AWS Blog

New – Receive and Process Incoming Email with Amazon SES

We launched the Amazon Simple Email Service (SES) way back in 2011, with a focus on deliverability — getting mail through to the intended recipients. Today, the service is used by Amazon and our customers to send billions of transactional and marketing emails each year.

Today we are launching a much-requested new feature for SES. You can now use SES to receive email messages for entire domains or for individual addresses within a domain. This will allow you to build scalable, highly automated systems that can programmatically send, receive, and process messages with minimal human intervention.

You use sophisticated rule sets and IP address filters to control the destiny of each message. Messages that match a rule can be augmented with additional headers, stored in an S3 bucket, routed to an SNS topic, passed to a Lambda function, or bounced.

Receiving and Processing Email
In order to make use of this feature you will need to verify that you own the domain of interest. If you have already done this in order to use SES to send email, then you are already good to go.

Now you need to route your incoming email to SES for processing. You have two options here. You can set the domain’s MX (Mail Exchange) record to point to the SES SMTP endpoint in the region where you want to process incoming email. Or, you can configure your existing mail handling system to forward mail to the endpoint.

The next step is to figure out what you want to do with the messages. To do this, you need to create some receipt rules. Rules are grouped into rule sets (order matters within the set) and can apply to multiple domains. Like most aspects of AWS, rules and rule sets are specific to a particular region. You can have one active rule set per AWS region; if you have no such set, then all incoming email will be rejected.

Rules have the following attributes:

  • Enabled – A flag that enables or disables the rule.
  • Recipients – A list of email addresses and/or domains that the rule applies to. If this attribute is not supplied, the rule matches all addresses in the domain.
  • Scan – A flag to request spam and virus scans (default is true).
  • TLS – A flag to require that mail matching this rule is delivered over a connection that is encrypted with TLS.
  • Action List -An ordered list of actions to perform on messages that match the rule.

When SES receives a message, it performs several checks before it accepts the message for further processing. Here’s what happens:

  • The source IP address is checked against an internal list maintained by SES, and rejected if so (this list can be overridden using an IP address filter that explicitly allows the IP address).
  • The source IP address is checked against your IP address filters, and rejected if so directed by the filter.
  • The message is checked to see if it matches any of the recipients specified in a rule, or if there’s a domain level match, and accepted if so.

Messages that do not match a rule do not cost you anything. After a message has been accepted, SES will perform the actions associated with the matching rule.  The following actions are available:

  • Add a header to the message.
  • Store the message in a designated S3 bucket, with optional encryption using a key stored in AWS Key Management Service (KMS). The entire message (headers and body) must be no larger than 30 megabytes in size for this action to be effective.
  • Publish the message to a designated SNS topic. The entire message (headers and body) must be no larger than 150 kilobytes in size for this action to be effective.
  • Invoke a Lambda function. The invocation can be synchronous or asynchronous (the default).
  • Return a specified bounce message to the sender.
  • Stop processing the actions in the rule.

The actions are run in the order specified by the rule. Lambda actions have access to the results of the spam and virus scans and can take action accordingly. If the Lambda function needs access to the body of the message, a preceding action in the rule must store the message in S3.

A Quick Demo
Here’s how I would create a rule that passes incoming email messages to a Lambda function (MyFunction) notifies an SNS topic (MyTopic), and then stores the messages in an S3 bucket (MyBucket) after encrypting them with a KMS key (aws/ses):

I can see all of my rules at a glance:

Here’s a Lambda function that will stop further processing if a message fails any of the spam or virus checks. In order for this function to perform as expected, it must be invoked in synchronous (RequestResponse) fashion.

exports.handler = function(event, context) {
    console.log('Spam filter');
    
    var sesNotification = event.Records[0].ses;
    console.log("SES Notification:\n", JSON.stringify(sesNotification, null, 2));
 
    // Check if any spam check failed
    if (sesNotification.receipt.spfVerdict.status      === 'FAIL'
        || sesNotification.receipt.dkimVerdict.status  === 'FAIL'
        || sesNotification.receipt.spamVerdict.status  === 'FAIL'
        || sesNotification.receipt.virusVerdict.status === 'FAIL')
    {
        console.log('Dropping spam');
        // Stop processing rule set, dropping message
        context.succeed({'disposition':'STOP_RULE_SET'});
    }
    else
    {
        context.succeed();   
    }
};

To learn more about this feature, read Receiving Email in the Amazon SES Developer Guide.

Pricing and Availability
You will pay $0.10 for every 1000 emails that you receive. Messages that are 256 KB or larger are charged for the number of complete 256 KB chunks in the message, at the rate of $0.09 per 1000 chunks. A 768 KB message counts for 3 chunks. You’ll also pay for any S3, SNS, or Lambda resources that you consume. Refer to the Amazon SES Pricing page for more information.

This new feature is available now and you can start using it today. Amazon SES is available in the US East (Northern Virginia), US West (Oregon), and EU (Ireland) regions.

— Jeff;