Amazon SES Plugin

Overview

Amazon Simple Email Service provides an API for outbound-only email delivery. It is an excellent API for managing email campaigns, as its API include delivery of bounce and spam ("complaint") notifications to an endpoint.

The qbo.Message.Amazon plugin includes:
  • SES.cs: a "plain" IMailOutbound wrapper around the SES API; use this for outbound emails when you do not need to programatically track bounce or spam notifications
  • SESValidator.cs: a "value-added" IMailOutbound wrapper that works with SES to track bounce and spam notifications, and to minimize bounces

Email Campaigns: Handling Bounce and Spam Notifications

Part of the SES terms of service attempt to manage "spammers".  Two strong indicators that an entity is a "spammer" is bounce rate and complaint rate.  A "bounce" is an attempt to email an address that does not (currently) exist.  A complaint is an email that is marked as spam by an end-user, or by an email provider based on a set of rules (e.g. Viagra ads).

qbo.Message.Amazon can assist with managing bounce and spam as follows:
  • The SESValidator class will check recipients against a list of ContactMethods in a QBO database prior to delivering the email to SES; if a recipient (To, Cc, or Bcc) is part of this list, the recipient will automatically be removed
    • the list of ContactMethods is delivered by the QBO Message/InvalidRecipientList operation
    • any removed recipients will be logged to a logging sink under the category "EmailAddressValidation" (configured by Properties.Settings.Default.LogCategoriesAddressValidation)
    • if the ErrorOnInvalidRecipient message is set to true and a recipient is removed, none of the email will be delivered, and an error will be raised (default value is false)
  • The SES.ashx handle provide three key pieces of functionality:
    • SES.ashx/Bounce: parses SES bounce notifications (JSON format) and added any bounce recipients as a ContactMethod using Message/InvalidRecipientAdd
    • SES.ashx/Spam: parses SES complaint notifications (JSON format) and added any complaint recipients as a ContactMethod using Message/InvalidRecipientAdd
    • SES.ashx/*: any inbound Amazon SNS topic requiring subscription confirmation will be automatically confirms
  • From the Amazon SES console, an SNS topic should be create to handle bounces and complaints
    • add an HTTPS endpoint to both of these topcis; by default, point them to https://{site}/Notification/SES.ashx/Bounce for bounces; SES.ashx/Spam for complaints
    • note the site's web.config file was modified to allow anonymous access to Notification/SES.ashx; the sns@quandis.net user determine the security context under which this is run
Review SES Best Practices for more context.

Spam Feedback Unit Test

You can unit test the feedback loop with Fiddler as follows:
  • Open Fiddler's Composer window
  • POST to https://qrm.quandis.net/Notification/SES.ashx/Spam
  • Use the JSON below as the Request Body:
{
"Type" : "Notification",
"MessageId" : "8bc02f2f-d890-52dd-80ad-62b3180696a2",
"TopicArn" : "arn:aws:sns:us-east-1:724166662639:Email-Complaint",
"Message" : "{\"notificationType\":\"Complaint\",\"complaint\":{\"complainedRecipients\":[{\"emailAddress\":\"not.eric.patrick@hotmail.com\"}],\"timestamp\":\"2015-04-06T17:11:49.000Z\",\"feedbackId\":\"0000014c8fb7806f-03891f38-dc80-11e4-b188-51db004b08f2-000000\"},\"mail\":{\"timestamp\":\"2015-04-06T17:07:26.000Z\",\"source\":\"\\\"QRM Notification\\\" <no-reply@quandis.net>\",\"messageId\":\"0000014c8fb37c0b-931e62da-507f-4a9b-b9ce-6e3081a83ccd-000000\",\"destination\":[\"bradandresen@hotmail.com\"]}}",
"Timestamp" : "2015-04-06T17:11:50.333Z",
"SignatureVersion" : "1",
"Signature" : "xnwIWPLR2KSrhfoBWpnZDgZxyyRG7ehhbzDZhIZu9Gh6X/y1RhwTq0n5O4tPmIuAFCT43upsF51GV8rB6HL4ZE3zXiZF4JDhlx/TuTCLh5XiRkhf1dRKewd97PYoTE7/lizQyYorZuRzUl71CT8C35xvmnHqYNeZo4a4lrWIN9SC5IJNwvgzUm3NANZwCBi8/sTUtHan5eoSPDpeSLC2PMO7l9vwimyF27kApmIRlE/+plfqEBfVm4iKdWxyjJR/bFZGuJRFU6mIkZnV4OEiwR5EPPxeOR5HclFdHBkH3Bzyw1xgBnW1+iHgzeNCJ6+Ytf9y7n8rleG763VckVI68w==",
"SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-d6d679a1d18e95c2f9ffcf11f4f9e198.pem",
"UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:724166662639:Email-Complaint:3800bc5f-30a1-4d46-9021-802ae23343f3"
}

Bounce Feedback Unit Test

You can unit test the feedback loop with Fiddler as follows:
  • Open Fiddler's Composer window
  • POST to https://qrm.quandis.net/Notification/SES.ashx/Bounce
  • Use the JSON below as the Request Body:
{
"Type" : "Notification",
"MessageId" : "22351349-0958-5d97-bc62-5ed5c9c11128",
"TopicArn" : "arn:aws:sns:us-east-1:724166662639:Email-Bounce",
"Message" : "{\"notificationType\":\"Bounce\",\"bounce\":{\"bounceSubType\":\"General\",\"bounceType\":\"Permanent\",\"reportingMTA\":\"dsn; a8-39.smtp-out.amazonses.com\",\"bouncedRecipients\":[{\"action\":\"failed\",\"emailAddress\":\"not.eric.patrick@yahoo.com\",\"status\":\"5.3.0\",\"diagnosticCode\":\"smtp; 554 delivery error: dd This user doesn't have a yahoo.com account (not.eric.patrick@yahoo.com) [0] -mta1415.mail.gq1.yahoo.com\"}],\"timestamp\":\"2015-04-06T17:11:53.642Z\",\"feedbackId\":\"0000014c8fb78dbf-a7388d60-19fd-41ac-8335-8ad48fece34e-000000\"},\"mail\":{\"timestamp\":\"2015-04-06T17:11:52.000Z\",\"messageId\":\"0000014c8fb7897c-cd0ce951-81be-4b6e-9af5-83b43c012ecc-000000\",\"source\":\"\\\"QRM Notification\\\" <no-reply@quandis.net>\",\"destination\":[\"not.eric.patrick@yahoo.com\"]}}",
"Timestamp" : "2015-04-06T17:11:53.657Z",
"SignatureVersion" : "1",
"Signature" : "oaCax3gYZPx5usDyIKnopdosz0I6x1dce9zDuGMa3oqZhL4nLlfQQ143JgBPf3MyjQ4S2mkmVz1WZ3/PSJ7W6TTiN7Kp6oreTcsqgQvmB841BkxVAvsAT1LCI2tvme0kAvih3iJZHthNkY2n6sLRh+wX2ataALobwJ9qXG+FKMVVD5CY8wdSJ0XQ88USuo44b0b++jcfmUKBde9AGFzHBzLyIThfDneFufiC038JVIOh7VrOPLGA/DIi8Jv1QSwMjjy4FLLOD573BwOHuuMtbFrh7i1PQGfm26Af3bQuDDXKtvy6BBhbnls2QYkBcVUnZzyf2jcC3PccdO2kbjxkLw==",
"SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-d6d679a1d18e95c2f9ffcf11f4f9e198.pem",
"UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:724166662639:Email-Bounce:243310cd-5cbd-4033-b97c-1a798289256c"
}

Data Tier Considerations

Rather than having each QBO client maintain their own bounce / spam list, a common database should be used to maintain the ContactMethods that have been reported as bounces or complaints. For AWS-based QBO installations, the 'master' database for this list should be the QRM database.

Setting up an SES account requires adding one or more domains (quandis.net, mycompany.info, etc.) to route mail from. It is not reasonable to create a dedicated SES account for each Quandis client site; instead all Quandis client sites that use SES will typically route through a single SES account / domain.  

Comments