INTEXT-6 - Add AWS SES Samples
* Add SES JavaMailSender Sample * Add SES Spring Integration Sample * Refactor DefaultAmazonSESMailSender to implement JavaMailSender and delegate to JavaMailSenderImpl rather than extending it * Cleanup
This commit is contained in:
@@ -23,7 +23,7 @@ import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHa
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class AWSNamespaceHandler extends
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.w3c.dom.Element;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractAWSOutboundChannelAdapterParser extends
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.w3c.dom.Element;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public final class AmazonWSParserUtils {
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.amazonaws.AmazonWebServiceClient;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public interface AWSClientFactory<T extends AmazonWebServiceClient> {
|
||||
|
||||
@@ -20,7 +20,7 @@ package org.springframework.integration.aws.core;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public interface AWSCredentials {
|
||||
|
||||
@@ -20,7 +20,7 @@ package org.springframework.integration.aws.core;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class AWSOperationException extends RuntimeException {
|
||||
|
||||
@@ -34,7 +34,7 @@ import com.amazonaws.AmazonWebServiceClient;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractAWSClientFactory<T extends AmazonWebServiceClient> implements AWSClientFactory<T> {
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
package org.springframework.integration.aws.core;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* The basic implementation class holding the Access key and the secret
|
||||
* key for the AWS account .
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class BasicAWSCredentials implements AWSCredentials {
|
||||
@@ -45,12 +47,15 @@ public class BasicAWSCredentials implements AWSCredentials {
|
||||
}
|
||||
|
||||
/**.
|
||||
* The constructor accepting the access and secret key
|
||||
* @param accessKey
|
||||
* @param secretKey
|
||||
* The constructor accepting the access and secret key.
|
||||
*
|
||||
* @param accessKey Must not be null or empty
|
||||
* @param secretKey Must not be null or empty
|
||||
*/
|
||||
public BasicAWSCredentials(String accessKey, String secretKey) {
|
||||
super();
|
||||
Assert.hasText(accessKey, "The accessKey parameter must not be null or empty.");
|
||||
Assert.hasText(secretKey, "The secretKey parameter must not be null or empty.");
|
||||
|
||||
this.accessKey = accessKey;
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
@@ -68,6 +73,7 @@ public class BasicAWSCredentials implements AWSCredentials {
|
||||
* @param accessKey
|
||||
*/
|
||||
public void setAccessKey(String accessKey) {
|
||||
Assert.hasText(accessKey, "The accessKey parameter must not be null or empty.");
|
||||
this.accessKey = accessKey;
|
||||
}
|
||||
|
||||
@@ -84,6 +90,7 @@ public class BasicAWSCredentials implements AWSCredentials {
|
||||
* @param secretKey
|
||||
*/
|
||||
public void setSecretKey(String secretKey) {
|
||||
Assert.hasText(secretKey, "The secretKey parameter must not be null or empty.");
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ package org.springframework.integration.aws.core;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class InvalidAWSCredentialsException extends RuntimeException {
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Properties;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -30,7 +31,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class PropertiesAWSCredentials extends BasicAWSCredentials implements InitializingBean {
|
||||
@@ -44,11 +45,13 @@ public class PropertiesAWSCredentials extends BasicAWSCredentials implements Ini
|
||||
private String propertyFileName;
|
||||
|
||||
/**.
|
||||
* Constructor accepting the properties file
|
||||
* @param propertyFileName
|
||||
* Constructor accepting the properties file.
|
||||
*
|
||||
* @param propertyFileName Must not be null or empty
|
||||
*/
|
||||
public PropertiesAWSCredentials(String propertyFileName) {
|
||||
super();
|
||||
Assert.hasText(propertyFileName, "The propertyFileName parameter must not be null or empty.");
|
||||
this.propertyFileName = propertyFileName;
|
||||
}
|
||||
|
||||
@@ -95,10 +98,12 @@ public class PropertiesAWSCredentials extends BasicAWSCredentials implements Ini
|
||||
}
|
||||
|
||||
/**.
|
||||
* Sets the name of the file that will hold the AW credentials
|
||||
* @param propertyFileName
|
||||
* Sets the name of the file that will hold the AW credentials.
|
||||
*
|
||||
* @param propertyFileName Must not be null or empty
|
||||
*/
|
||||
public void setPropertyFileName(String propertyFileName) {
|
||||
Assert.hasText(propertyFileName, "The propertyFileName parameter must not be null or empty.");
|
||||
this.propertyFileName = propertyFileName;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.springframework.mail.javamail.JavaMailSender;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class AmazonSESMessageHandler extends MailSendingMessageHandler {
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.springframework.integration.core.MessageHandler;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class AmazonSESOutboundAdapterParser extends
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.integration.aws.core.AWSOperationException;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class AmazonSESMailSendException extends AWSOperationException {
|
||||
|
||||
@@ -15,94 +15,107 @@
|
||||
*/
|
||||
package org.springframework.integration.aws.ses.core;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.mail.NoSuchProviderException;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Transport;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
|
||||
import org.springframework.integration.aws.core.AWSCredentials;
|
||||
import org.springframework.integration.aws.core.AWSOperationException;
|
||||
import org.springframework.mail.MailException;
|
||||
import org.springframework.mail.SimpleMailMessage;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
import org.springframework.mail.javamail.MimeMessagePreparator;
|
||||
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClient;
|
||||
import com.amazonaws.services.simpleemail.model.RawMessage;
|
||||
import com.amazonaws.services.simpleemail.model.SendRawEmailRequest;
|
||||
import com.amazonaws.services.simpleemail.AWSJavaMailTransport;
|
||||
|
||||
/**
|
||||
* The implementation class for sending mail using the Amazon SES service
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @author Gunnar Hillert
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class DefaultAmazonSESMailSender extends JavaMailSenderImpl {
|
||||
|
||||
/**.
|
||||
* The API class used for sending email using Amazon SES
|
||||
*/
|
||||
private final AmazonSimpleEmailServiceClient emailService;
|
||||
|
||||
private final AWSCredentials credentials;
|
||||
public class DefaultAmazonSESMailSender implements JavaMailSender {
|
||||
|
||||
public DefaultAmazonSESMailSender(AWSCredentials credentials) {
|
||||
if(credentials == null)
|
||||
|
||||
if(credentials == null) {
|
||||
throw new AWSOperationException(null, "Credentials cannot be null, provide a non null valid set of credentials");
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup JavaMail to use the Amazon Simple Email Service by specifying
|
||||
* the "aws" protocol.
|
||||
*/
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("mail.transport.protocol", "aws");
|
||||
|
||||
properties.setProperty(AWSJavaMailTransport.AWS_ACCESS_KEY_PROPERTY, credentials.getAccessKey());
|
||||
properties.setProperty(AWSJavaMailTransport.AWS_SECRET_KEY_PROPERTY, credentials.getSecretKey());
|
||||
|
||||
javaMailSender.setJavaMailProperties(properties);
|
||||
|
||||
emailService = new AmazonSimpleEmailServiceClient(
|
||||
new BasicAWSCredentials(credentials.getAccessKey(),
|
||||
credentials.getSecretKey()));
|
||||
}
|
||||
|
||||
private JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl() {
|
||||
|
||||
@Override
|
||||
protected Transport getTransport(Session session)
|
||||
throws NoSuchProviderException {
|
||||
return new AWSJavaMailTransport(session, null);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The Actual implementation of the sending of the mail message using the AWS SES
|
||||
* SDK
|
||||
*/
|
||||
@Override
|
||||
protected void doSend(MimeMessage[] mimeMessages, Object[] originalMessages)
|
||||
public void send(SimpleMailMessage simpleMessage) throws MailException {
|
||||
javaMailSender.send(simpleMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(SimpleMailMessage[] simpleMessages) throws MailException {
|
||||
javaMailSender.send(simpleMessages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimeMessage createMimeMessage() {
|
||||
return javaMailSender.createMimeMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimeMessage createMimeMessage(InputStream contentStream)
|
||||
throws MailException {
|
||||
Map<Object, Exception> failedMessageMap = new HashMap<Object, Exception>();
|
||||
if(mimeMessages != null && mimeMessages.length > 0) {
|
||||
int index = 0;
|
||||
for(MimeMessage mailMessage:mimeMessages) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
mailMessage.writeTo(baos);
|
||||
RawMessage rawMessage = new RawMessage(ByteBuffer.wrap(baos.toByteArray()));
|
||||
SendRawEmailRequest rawMail = new SendRawEmailRequest(rawMessage);
|
||||
emailService.sendRawEmail(rawMail);
|
||||
index++;
|
||||
} catch (Exception e) {
|
||||
failedMessageMap.put(originalMessages != null? originalMessages[index]:mailMessage, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!failedMessageMap.isEmpty()) {
|
||||
throw new AmazonSESMailSendException(credentials.getAccessKey(),
|
||||
"Exception while sending one or more messages, see failedMessages for more details",
|
||||
failedMessageMap);
|
||||
}
|
||||
return javaMailSender.createMimeMessage(contentStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPort(int port) {
|
||||
throw new UnsupportedOperationException("AWS SES Implementation of mail " +
|
||||
"sender does not allow setting the port number");
|
||||
public void send(MimeMessage mimeMessage) throws MailException {
|
||||
javaMailSender.send(mimeMessage);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setHost(String host) {
|
||||
throw new UnsupportedOperationException("AWS SES Implementation of mail " +
|
||||
"sender does not allow setting the host name. It is already configured with an endpoint");
|
||||
public void send(MimeMessage[] mimeMessages) throws MailException {
|
||||
javaMailSender.send(mimeMessages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(MimeMessagePreparator mimeMessagePreparator)
|
||||
throws MailException {
|
||||
javaMailSender.send(mimeMessagePreparator);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(MimeMessagePreparator[] mimeMessagePreparators)
|
||||
throws MailException {
|
||||
javaMailSender.send(mimeMessagePreparators);
|
||||
}
|
||||
|
||||
//Should we disallow setSession?
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import com.amazonaws.services.sqs.AmazonSQSClient;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class AWSClientFactoryTest {
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.util.Properties;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public abstract class BaseTestCase {
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.integration.test.util.TestUtils;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractAWSOutboundChannelAdapterParserTests<T extends MessageHandler> {
|
||||
|
||||
@@ -30,7 +30,7 @@ import com.amazonaws.AmazonWebServiceClient;
|
||||
* The abstract test class for Amazon WebService client factory tests
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractAWSClientFactoryTests<T extends AmazonWebServiceClient> {
|
||||
|
||||
@@ -48,7 +48,7 @@ import org.springframework.mail.javamail.JavaMailSender;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class AmazonSESMessageHandlerTests {
|
||||
|
||||
@@ -15,22 +15,25 @@
|
||||
*/
|
||||
package org.springframework.integration.aws.ses.config.xml;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.aws.core.AWSCredentials;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
|
||||
import com.amazonaws.services.simpleemail.AWSJavaMailTransport;
|
||||
|
||||
/**
|
||||
* The test class for the AmazonSESOutboundAdapterParser
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class AmazonSESOutboundAdapterParserTests {
|
||||
@@ -79,10 +82,11 @@ public class AmazonSESOutboundAdapterParserTests {
|
||||
Assert.assertNotNull("Expected a non null EventDrivenConsumer", consumer);
|
||||
MessageHandler handler = TestUtils.getPropertyValue(consumer, "handler", MessageHandler.class);
|
||||
Assert.assertNotNull("Expected a non null messagehandler", handler);
|
||||
AWSCredentials credentials = TestUtils.getPropertyValue(handler, "mailSender.credentials", AWSCredentials.class);
|
||||
Assert.assertNotNull("Expected a non null instance of credentials", credentials);
|
||||
Assert.assertEquals("dummy", credentials.getAccessKey());
|
||||
Assert.assertEquals("dummy", credentials.getSecretKey());
|
||||
|
||||
Properties properties = TestUtils.getPropertyValue(handler, "mailSender.javaMailSender.javaMailProperties", Properties.class);
|
||||
Assert.assertNotNull("Expected a non null instance of credentials", properties);
|
||||
Assert.assertEquals("dummy", properties.getProperty(AWSJavaMailTransport.AWS_ACCESS_KEY_PROPERTY));
|
||||
Assert.assertEquals("dummy", properties.getProperty(AWSJavaMailTransport.AWS_SECRET_KEY_PROPERTY));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.integration.aws.ses.core;
|
||||
|
||||
import javax.mail.Session;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
@@ -38,7 +37,7 @@ import org.springframework.mail.javamail.MimeMessageHelper;
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 1.0
|
||||
* @since 0.5
|
||||
*
|
||||
*/
|
||||
public class DefaultAmazonSESMailSenderAWSTests {
|
||||
@@ -96,8 +95,7 @@ public class DefaultAmazonSESMailSenderAWSTests {
|
||||
*/
|
||||
@Test
|
||||
public void sendMimeMessage() throws Exception {
|
||||
Session session = sender.getSession();
|
||||
MimeMessageHelper helper = new MimeMessageHelper(new MimeMessage(session));
|
||||
MimeMessageHelper helper = new MimeMessageHelper(sender.createMimeMessage());
|
||||
helper.setText("Some HTML Text", true);
|
||||
helper.setTo(TO_EMAIL_ID);
|
||||
helper.setFrom(TO_EMAIL_ID);
|
||||
@@ -111,16 +109,15 @@ public class DefaultAmazonSESMailSenderAWSTests {
|
||||
*/
|
||||
@Test
|
||||
public void sendMimeMessageArray() throws Exception {
|
||||
Session session = sender.getSession();
|
||||
MimeMessage[] messages = new MimeMessage[2];
|
||||
MimeMessageHelper helper = new MimeMessageHelper(new MimeMessage(session));
|
||||
MimeMessageHelper helper = new MimeMessageHelper(sender.createMimeMessage());
|
||||
helper.setText("Some HTML Text One", true);
|
||||
helper.setTo(TO_EMAIL_ID);
|
||||
helper.setFrom(TO_EMAIL_ID);
|
||||
helper.setSubject("Some HTML Message's Subject Line One");
|
||||
MimeMessage message = helper.getMimeMessage();
|
||||
messages[0] = message;
|
||||
helper = new MimeMessageHelper(new MimeMessage(session));
|
||||
helper = new MimeMessageHelper(sender.createMimeMessage());
|
||||
helper.setText("Some HTML Text Two", true);
|
||||
helper.setTo(TO_EMAIL_ID);
|
||||
helper.setFrom(TO_EMAIL_ID);
|
||||
|
||||
Reference in New Issue
Block a user