Managing MX Records for Your Email Domain Using AWS




Managing MX Records for Your Email Domain Using AWS
 
Problem

You need to configure MX (Mail Exchange) records for your domain to receive email, and you're wondering how AWS services—like Route 53 and Amazon Simple Email Service (SES)—can help.


Clarifying the Issue

To accept incoming mail at your domain (like support@example.com), you need to create an MX record in DNS that points to a service capable of receiving email. AWS provides exactly that through SES, but the setup involves a few moving parts: DNS, SES configuration, and optional automation through S3, Lambda, or SNS.


Why It Matters

Misconfigured MX records will block your domain from receiving email. Using AWS for email gives you a highly reliable and flexible system, where incoming email can be stored, processed, or reacted to using event-driven services—all without running a traditional mail server.


Key Terms
  • MX Record: DNS record that routes incoming email to a mail server.
  • Amazon Route 53: AWS’s DNS service, used to publish MX records.
  • Amazon Simple Email Service (SES): Email platform used to receive and process messages.
  • S3: AWS storage service for storing raw email content.
  • Lambda: AWS function service to process messages.
  • SNS: Notification service for alerts or downstream integration.

Steps at a Glance
  1. Create an S3 bucket for storing incoming emails.
  2. Publish an MX record in Route 53 pointing to SES.
  3. Verify your domain with SES.
  4. Attach a bucket policy to allow SES to write to S3.
  5. Create an SES receipt rule to handle incoming email.
  6. Deploy a Lambda function (optional) to process the email.

Detailed Steps

Step 1: Create an S3 Bucket 

Bash
aws s3api create-bucket --bucket my-ses-inbox --region us-west-2

Pitfall to avoid: Make sure the bucket name is globally unique. If you get an error, try a longer name like my-ses-inbox-aaron-dev.


Step 2: Publish an MX Record in Route 53


Bash
aws route53 change-resource-record-sets --hosted-zone-id ZONE_ID \
  --change-batch '{
    "Changes": [{
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "example.com.",
        "Type": "MX",
        "TTL": 300,
        "ResourceRecords": [{
          "Value": "10 inbound-smtp.us-west-2.amazonaws.com"
        }]
      }
    }]
  }'


Pitfall to avoid: Don’t forget the priority number (10). SES requires it. Omitting it or formatting the value incorrectly (e.g., missing whitespace) will silently break mail routing.


Step 3: Verify Your Domain with SES 

Bash
aws ses verify-domain-identity --domain example.com

AWS will return a TXT record that you must publish in Route 53 to confirm ownership.

Pitfall to avoid: SES email receiving is only supported in certain regions. Double-check that the region you're using (e.g., us-west-2) supports inbound email.


Step 4: Attach a Bucket Policy to S3

Save the policy below as ses-policy.json, replacing 123456789012 with your AWS account ID: 

JSON
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "ses.amazonaws.com" },
    "Action": "s3:PutObject",
    "Resource": "arn:aws:s3:::my-ses-inbox/*",
    "Condition": {
      "StringEquals": {
        "aws:Referer": "123456789012"
      }
    }
  }]
}


Apply it: 

Bash
aws s3api put-bucket-policy 
    --bucket my-ses-inbox 
    --policy file://ses-policy.json

Pitfall to avoid: If SES can’t write to your bucket, this policy is almost always the issue. Make sure the AWS account ID is correct and that the principal is ses.amazonaws.com.


Step 5: Create an SES Receipt Rule 

Bash
aws ses create-receipt-rule-set --rule-set-name "myRuleSet"

aws ses create-receipt-rule --rule-set-name "myRuleSet" --rule '{
  "Name": "StoreAndProcess",
  "Enabled": true,
  "Recipients": ["support@example.com"],
  "Actions": [
    {
      "S3Action": {
        "BucketName": "my-ses-inbox",
        "ObjectKeyPrefix": "emails/"
      }
    }
  ],
  "ScanEnabled": true
}'


Activate the rule set: aws ses set-active-receipt-rule-set --rule-set-name "myRuleSet"


Bash
aws ses set-active-receipt-rule-set --rule-set-name "myRuleSet"

Pitfall to avoid: Creating a rule set doesn’t activate it. You must explicitly call set-active-receipt-rule-set or activate it in the console—or email won’t flow.


Step 6: Deploy a Lambda Function (Optional)

Here’s a sample function to read and log email content from S3: 

Python
import boto3
import email

s3 = boto3.client('s3')

def lambda_handler(event, context):
    record = event['Records'][0]
    bucket = record['s3']['bucket']['name']
    key = record['s3']['object']['key']
    
    response = s3.get_object(Bucket=bucket, Key=key)
    raw_email = response['Body'].read()
    
    msg = email.message_from_bytes(raw_email)
    subject = msg.get('Subject', 'No subject')
    
    print(f"Email subject: {subject}")


Pitfall to avoid: Make sure Lambda has the AmazonS3ReadOnlyAccess policy (or finer-grained access) and that SES is allowed to invoke it if added to the rule.


Conclusion

By publishing an MX record in Route 53 and routing mail through Amazon Simple Email Service, you gain total control over your domain’s email. Combine it with S3, Lambda, and SNS, and you’re no longer dealing with traditional inboxes—you’re building smart, event-driven workflows.


Need AWS Expertise?

If you're looking for guidance on AWS or any cloud challenges, feel free to reach out! We'd love to help you tackle your projects. 🚀

Email us at: info@pacificw.com



Image: Gemini

Comments

Popular posts from this blog

The New ChatGPT Reason Feature: What It Is and Why You Should Use It

Raspberry Pi Connect vs. RealVNC: A Comprehensive Comparison

The Reasoning Chain in DeepSeek R1: A Glimpse into AI’s Thought Process