AWS: SQS,SNS,SES - 2
Use Case
Overview
graph LR
Sender_Email("test@test.com")
Email_Failed
Email_Delivered
SNS_Subscriptions --> Email_Failed
SNS_Subscriptions --> Email_Delivered
Bounce_Notification --> Email_Failed
Complaint_Notification --> Email_Failed
Delivery_Notification --> Email_Delivered
subgraph SQS
subgraph Email_Status_Queue
SNS_Subscriptions
end
end
subgraph SNS
subgraph Topics
Email_Failed
Email_Delivered
end
end
subgraph SES
Sender_Email
subgraph Notifications
Bounce_Notification
Complaint_Notification
Delivery_Notification
end
end
SNS Setup
Create a topic for failed email, e.g. bounce or spam complaint
- It is named Email_Failed in the diagram above
Create a topic for delivered email
- It is named Email_Delivered in the diagram above
SES Setup
Create a new domain for sender email, e.g. test@test.com
Setup the notifications
- Bounce Notification maps to Email_Failed
- Complaint Notification maps to Email_Failed
- Delivery Notification maps to Email_Delivered
Verify the domain - test.com
Verify the DKIM - *.domainkey.test.com
SQS Setup
- Create a new queue named Email_Status_Queue
- Add SNS subscriptions Email_Failed and Email_Delivered to the queue
Integration
- Sender code of sample
package email.sample;
// import ....
public class SesSample {
static final String FROM = "sender@test.com";
static final String TO = "recipient@test.com";
static final String CONFIGSET = "ConfigSet";
// The subject line for the email.
static final String SUBJECT = "SES test";
// The email body for recipients with non-HTML email clients.
static final String TEXTBODY = "This email was sent through Amazon SES "
public static void main(String[] args) throws IOException {
try {
AmazonSimpleEmailService client =
AmazonSimpleEmailServiceClientBuilder.standard()
// Replace the AWS Region
.withRegion(Regions.US_WEST_2).build();
SendEmailRequest request = new SendEmailRequest()
.withDestination(
new Destination().withToAddresses(TO))
.withMessage(new Message()
.withBody(new Body()
.withText(new Content()
.withCharset("UTF-8").withData(TEXTBODY)))
.withSubject(new Content()
.withCharset("UTF-8").withData(SUBJECT)))
.withSource(FROM);
client.sendEmail(request);
System.out.println("Email sent!");
} catch (Exception ex) {
System.out.println("Error message: " + ex.getMessage());
}
}
}
- Sample of SQS code
// .....
public class SqsConsumer {
public void receive(Object message) throws Exception {
if (message instanceof CamelMessage) {
String body = ((CamelMessage) message).getBodyAs(String.class, camelContext());
JsonNode envelope = Json.parse(body);
if (envelope.has("Message")) {
JsonNode notification = Json.parse(envelope.get("Message").asText());
String notificationType = notification.get("notificationType").asText();
log.debug("Processing email notification: " + notificationType);
switch (notification.get("notificationType").asText()) {
case "Received":
received.tell(new EmailActorProtocol.EmailReceived(notification), self());
break;
case "Bounce":
response.tell(new EmailActorProtocol.EmailBounced(notification), self());
break;
case "Delivery":
response.tell(new EmailActorProtocol.EmailDelivered(notification), self());
break;
case "Complaint":
response.tell(new EmailActorProtocol.EmailComplaintReceived(notification), self());
break;
default:
throw new RuntimeException(String.format("Notification type %s not supported", notificationType));
}
}
}
}
}
// EmailActorProtocol
// public class EmailActorProtocol {
// public interface EmailResponse {
// }
// @Data
// static public class EmailReceived {
// private final JsonNode body;
// }
// @Data
// static public class EmailDelivered implements EmailResponse {
// private final JsonNode body;
// }
// @Data
// static public class EmailBounced implements EmailResponse {
// private final JsonNode body;
// }
// @Data
// static public class EmailComplaintReceived implements EmailResponse {
// private final JsonNode body;
// }
// static public class GetHealth {
// }
// @Data
// static public class Health {
// private final boolean healthy;
// }
// }