Package com.amazonaws.services.simpleemail

Source Code of com.amazonaws.services.simpleemail.AWSJavaMailTransport

/*
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
*  http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amazonaws.services.simpleemail;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.URLName;
import javax.mail.event.TransportEvent;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import com.amazonaws.AmazonWebServiceRequest;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.simpleemail.model.RawMessage;
import com.amazonaws.services.simpleemail.model.SendRawEmailRequest;
import com.amazonaws.util.VersionInfoUtils;

/**
* A transport implementation using Amazon Web Service's E-mail Service. For
* JavaMail purposes this transport implementation uses the "aws" protocol. In
* order to send messages through the E-mail Service your AWS Credentials
* (http://aws.amazon.com/security-credentials) need to be either in the
* JavaMail Session's Properties (mail.aws.user and mail.aws.password), passed
* into the connect() method, or set in the Session's setPasswordAuthentication
* method. Parameters passed into the connect method as well as
* PasswordAuthentication information supersedes the properties field for a
* particular session. When connecting your AWS Access Key is your username and
* your AWS Secret Key is your password.
* <p>
* This transport implementation only accepts MIME encoded messages (see
* MimeMessage class) and RFC822 E-mail addresses (see InternetAddress class).
*/
public class AWSJavaMailTransport extends Transport {

  public static final String AWS_EMAIL_SERVICE_ENDPOINT_PROPERTY = "mail.aws.host";
    public static final String AWS_SECRET_KEY_PROPERTY = "mail.aws.password";
    public static final String AWS_ACCESS_KEY_PROPERTY = "mail.aws.user";
   
    private AmazonSimpleEmailServiceClient emailService;
  private final String accessKey;
  private final String secretKey;
  private final String httpsEndpoint;

  public AWSJavaMailTransport(Session session, URLName urlname) {
    super(session, urlname);
    this.accessKey = session.getProperty(AWS_ACCESS_KEY_PROPERTY);
    this.secretKey = session.getProperty(AWS_SECRET_KEY_PROPERTY);
    this.httpsEndpoint = session.getProperty(AWS_EMAIL_SERVICE_ENDPOINT_PROPERTY);
  }

  /**
   * Sends a MIME message through Amazon's E-mail Service with the specified
   * recipients. Addresses that are passed into this method are merged with
   * the ones already embedded in the message (duplicates are removed).
   *
   * @param msg
   *            A Mime type e-mail message to be sent
   * @param addresses
   *            Additional e-mail addresses (RFC-822) to be included in the
   *            message
   */
  @Override
  public void sendMessage(Message msg, Address[] addresses)
      throws MessagingException, SendFailedException {

    checkConnection();
    checkMessage(msg);
    checkAddresses(msg, addresses);
    collateRecipients(msg, addresses);
   
    SendRawEmailRequest req = prepareEmail(msg);

    sendEmail(msg, req);
  }

  /**
   * Asserts a valid connection to the email service.
   */
    private void checkConnection() {
        if (emailService == null || !super.isConnected()) {
      throw new IllegalStateException("Not connected");
    }
    }

    /**
     * Checks that the message can be sent using AWS Simple E-mail Service.
     */
    private void checkMessage(Message msg) throws MessagingException {
        if (msg == null) {
      throw new MessagingException("Message is null");
    }
    if (!(msg instanceof MimeMessage)) {
      throw new MessagingException(
          "AWS Mail Service can only send MimeMessages");
    }
    }

  /**
   * Checks to ensure at least one recipient is present (either in the Message
   * or Address[]) and all addresses that are passed in using the Address
   * array are of type InternetAddress.
   */
  private void checkAddresses(Message m, Address[] addresses)
      throws MessagingException, SendFailedException {
      
        if ( isNullOrEmpty((Object[]) addresses)
                && isNullOrEmpty((Object[]) m.getRecipients(Message.RecipientType.TO))
                && isNullOrEmpty((Object[]) m.getRecipients(Message.RecipientType.CC))
                && isNullOrEmpty((Object[]) m.getRecipients(Message.RecipientType.BCC)) ) {
            throw new SendFailedException("No recipient addresses");
        }

        // Make sure all addresses are internet addresses
        Set<Address> invalid = new HashSet<Address>();
        for ( Address[] recipients : new Address[][] {
                m.getRecipients(Message.RecipientType.TO),
                m.getRecipients(Message.RecipientType.CC),
                m.getRecipients(Message.RecipientType.BCC),
                addresses } ) {
            if ( !isNullOrEmpty(recipients) ) {
                for ( Address a : recipients ) {
                    if ( !(a instanceof InternetAddress) ) {
                        invalid.add(a);
                    }
                }
            }
        }
       
        if ( !invalid.isEmpty() ) {
            Address[] sent = new Address[0];
            Address[] unsent = new Address[0];
            super.notifyTransportListeners(TransportEvent.MESSAGE_NOT_DELIVERED, sent, unsent,
                    invalid.toArray(new Address[invalid.size()]), m);
            throw new SendFailedException("AWS Mail Service can only send to InternetAddresses");
        }
    }

  /**
   * Collates any addresses into the message object.  All addresses in the Address array
     * become of type TO unless they already exist in the Message header. If
     * they are in the Message header they will stay of the same type. Any
     * duplicate addresses are removed. Type BCC and then CC takes precedence
     * over TO when duplicates exist.  If any address is invalid an exception is
     * thrown.
   */
    private void collateRecipients(Message m, Address[] addresses) throws MessagingException {

        if ( !isNullOrEmpty(addresses) ) {
            Hashtable<Address, Message.RecipientType> addressTable = new Hashtable<Address, Message.RecipientType>();

            for ( Address a : addresses ) {
                addressTable.put(a, Message.RecipientType.TO);
            }

            if ( !isNullOrEmpty(m.getRecipients(Message.RecipientType.TO)) ) {
                for ( Address a : m.getRecipients(Message.RecipientType.TO) ) {
                    addressTable.put(a, Message.RecipientType.TO);
                }
            }
            if ( !isNullOrEmpty(m.getRecipients(Message.RecipientType.CC)) ) {
                for ( Address a : m.getRecipients(Message.RecipientType.CC) ) {
                    addressTable.put(a, Message.RecipientType.CC);
                }
            }
            if ( !isNullOrEmpty(m.getRecipients(Message.RecipientType.BCC)) ) {
                for ( Address a : m.getRecipients(Message.RecipientType.BCC) ) {
                    addressTable.put(a, Message.RecipientType.BCC);
                }
            }

            // Clear the original recipients for collation
            m.setRecipients(Message.RecipientType.TO, new Address[0]);
            m.setRecipients(Message.RecipientType.CC, new Address[0]);
            m.setRecipients(Message.RecipientType.BCC, new Address[0]);
           
            Iterator<Address> aIter = addressTable.keySet().iterator();

            while ( aIter.hasNext() ) {
                Address a = aIter.next();
                m.addRecipient(addressTable.get(a), a);
            }
           
            // Simple E-mail needs at least one TO address, so add one if there isn't one
            if ( m.getRecipients(Message.RecipientType.TO) == null ||
                    m.getRecipients(Message.RecipientType.TO).length == 0 ) {
                m.setRecipient(Message.RecipientType.TO, addressTable.keySet().iterator().next());
            }
        }
    }

  /**
   * Prepares the email to be sent using the JavaMail service. Wraps up the
   * message into a RawEmailRequest object to be processed by AWS's
   * sendRawEmail().
   *
   * @param m
   *            A JavaMail message to be converted to a request
   * @return A Raw Email Request for AWS E-mail Service
   */
  private SendRawEmailRequest prepareEmail(Message m)
      throws MessagingException {

    try {
      OutputStream byteOutput = new ByteArrayOutputStream();
      m.writeTo(byteOutput);
      SendRawEmailRequest req = new SendRawEmailRequest();
      byte[] messageByteArray = ((ByteArrayOutputStream) byteOutput)
          .toByteArray();
      RawMessage message = new RawMessage();
      message.setData(ByteBuffer.wrap(messageByteArray));
      req.setRawMessage(message);
      return req;
    } catch (Exception e) {
        Address[] sent = new Address[0];
        Address[] unsent = new Address[0];
        Address[] invalid = m.getAllRecipients();
      super.notifyTransportListeners(
          TransportEvent.MESSAGE_NOT_DELIVERED, sent, unsent,
          invalid, m);
      throw new MessagingException("Unable to write message: "
          + m.toString(), e);
    }
  }

  /**
   * Sends an email using AWS E-mail Service and notifies listeners
   *
   * @param m
   *            Message used to notify users
   * @param req
   *            Raw email to be sent
   */
  private void sendEmail(Message m, SendRawEmailRequest req)
      throws SendFailedException, MessagingException {

    Address[] sent = null;
    Address[] unsent = null;
    Address[] invalid = null;

    try {
        appendUserAgent(req, USER_AGENT);
      this.emailService.sendRawEmail(req);
      sent = m.getAllRecipients();
      unsent = new Address[0];
      invalid = new Address[0];
      super.notifyTransportListeners(TransportEvent.MESSAGE_DELIVERED,
          sent, unsent, invalid, m);
    } catch (Exception e) {
      sent = new Address[0];
      unsent = m.getAllRecipients();
      invalid = new Address[0];
      super.notifyTransportListeners(
          TransportEvent.MESSAGE_NOT_DELIVERED, sent, unsent,
          invalid, m);
      throw new SendFailedException("Unable to send email", e, sent,
          unsent, invalid);
    }
  }

  /**
   * Sets up a new AmazonSimpleEmailServiceClient. This method is typically called
   * indirectly from the connect() method and should only be called on
   * instantiation or to reopen after a close(). If a non-null or empty User
   * and Password passed in session properties are overridden while user
   * remains connected (mail.aws.user and mail.aws.password). The default
   * https endpoint is specified by the mail client; however, it can be
   * overridden by either passing in a value or setting mail.aws.host. Like
   * the user and password, the variable that is passed in takes preference
   * over the properties file.
   *
   * @param host
   *            Optional - host specifies the AWS E-mail endpoint
   * @param awsAccessKey
   *            Optional - AWS Access Key (otherwise must specify through
   *            properties file)
   * @param awsSecretKey
   *            Optional - AWS Secret key (otherwise must specify through
   *            properties file)
   * @return Returns true if non-empty credentials are given
   */
  @Override
  protected boolean protocolConnect(String host, int port, String awsAccessKey,
      String awsSecretKey) {
    if (isConnected())
      throw new IllegalStateException("Already connected");

    if (isNullOrEmpty(awsAccessKey) || isNullOrEmpty(awsSecretKey)) {
      if (isNullOrEmpty(accessKey) || isNullOrEmpty(secretKey)) {
        return false;
      }
      awsAccessKey = this.accessKey;
      awsSecretKey = this.secretKey;
    }

        this.emailService = new AmazonSimpleEmailServiceClient(new BasicAWSCredentials(awsAccessKey, awsSecretKey));
    if (!isNullOrEmpty(host)) {
      this.emailService.setEndpoint(host);
    } else if (this.httpsEndpoint != null) {
      this.emailService.setEndpoint(this.httpsEndpoint);
    }
    super.setConnected(true);
    return true;
  }

  @Override
  public void close() throws MessagingException {
    super.close();
    this.emailService = null;
  }

  private static boolean isNullOrEmpty(String s) {
    return (s == null || s.length() == 0);
  }

  private static boolean isNullOrEmpty(Object[] o) {
    return (o == null || o.length == 0);
  }
 
    public <X extends AmazonWebServiceRequest> X appendUserAgent(X request, String userAgent) {
        request.getRequestClientOptions().addClientMarker(USER_AGENT);
        return request;
    }
 
    private static final String USER_AGENT = AWSJavaMailTransport.class.getName() + "/" + VersionInfoUtils.getVersion()

}
TOP

Related Classes of com.amazonaws.services.simpleemail.AWSJavaMailTransport

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.