> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mailofly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrating from Amazon SES

> Eliminate complex SNS/SQS/Lambda bounce pipelines and low-level AWS SDK boilerplate by migrating from Amazon SES to Mailofly.

# Migrating from Amazon SES to Mailofly

Amazon Simple Email Service (SES) is inexpensive raw infrastructure, but it forces developers to build and maintain their own email platform. Tracking simple bounces or opens with SES typically requires setting up:

* **Amazon SNS topics** for bounce and complaint notifications
* **Amazon SQS queues** or **AWS Lambda functions** to process payloads
* **Custom database tables** to store suppression blacklists
* **CloudWatch metrics and alarms** for deliverability health
* Complex IAM policies and SigV4 authentication headers

Mailofly delivers an end-to-end email platform where deliverability, suppression handling, real-time analytics, and webhooks are **fully managed** out of the box.

***

## Infrastructure Architecture Comparison

```mermaid theme={null}
flowchart TD
    subgraph "Amazon SES Architecture (Heavy Infrastructure)"
        A[Your App] -->|SendRawEmail| B[AWS SES]
        B -->|Event Destination| C[Amazon SNS]
        C -->|Trigger| D[AWS Lambda]
        D -->|Write Blacklist| E[(Database / DynamoDB)]
        B -->|Metrics| F[CloudWatch Alarms]
    end

    subgraph "Mailofly Architecture (Zero Infrastructure)"
        G[Your App] -->|emails.send| H[Mailofly Engine]
        H -.->|Real-time Webhook| G
        H -->|Automatic Suppression| I[(Built-in Suppression List)]
        H -->|Live Telemetry| J[Mailofly Real-time Dashboard]
    end
```

***

## Why Teams Migrate from AWS SES

* **Zero Infrastructure Overhead**: No more maintaining Lambda functions, IAM roles, and SNS topics just to record a bounced email.
* **Automatic Suppressions**: Bounces and spam complaints are automatically suppressed by Mailofly to protect your domain reputation.
* **Readable Code**: Send rich emails with attachments in 5 lines of code instead of 40 lines of AWS SDK v3 MIME assembly.
* **Native Inbound Webhooks**: Receive and parse inbound emails without setting up SES → S3 → Lambda pipelines.

***

## 1. Code Comparison

### Node.js / TypeScript

<CodeGroup>
  ```ts Before: AWS SES (AWS SDK v3) theme={null}
  import { SESClient, SendEmailCommand } from "@aws-sdk/client-ses";

  const ses = new SESClient({ region: "us-east-1" });

  const command = new SendEmailCommand({
    Source: "Acme <hello@acme.com>",
    Destination: {
      ToAddresses: ["customer@example.com"],
    },
    Message: {
      Subject: {
        Data: "Welcome to Acme",
        Charset: "UTF-8",
      },
      Body: {
        Html: {
          Data: "<p>Welcome to our platform!</p>",
          Charset: "UTF-8",
        },
        Text: {
          Data: "Welcome to our platform!",
          Charset: "UTF-8",
        },
      },
    },
  });

  const response = await ses.send(command);
  console.log("Message ID:", response.MessageId);
  ```

  ```ts After: Mailofly (@mailofly/node) theme={null}
  import { Mailofly } from "@mailofly/node";

  const mailofly = new Mailofly({
    apiKey: process.env.MAILOFLY_API_KEY!,
  });

  const { id } = await mailofly.emails.send({
    from: "Acme <hello@acme.com>",
    to: ["customer@example.com"],
    subject: "Welcome to Acme",
    html: "<p>Welcome to our platform!</p>",
    text: "Welcome to our platform!",
  });

  console.log("Message ID:", id);
  ```
</CodeGroup>

***

### Python

<CodeGroup>
  ```python Before: AWS SES (Boto3) theme={null}
  import boto3

  client = boto3.client("ses", region_name="us-east-1")

  response = client.send_email(
      Source="Acme <hello@acme.com>",
      Destination={"ToAddresses": ["customer@example.com"]},
      Message={
          "Subject": {"Data": "Welcome to Acme"},
          "Body": {
              "Html": {"Data": "<p>Welcome to our platform!</p>"},
              "Text": {"Data": "Welcome to our platform!"},
          },
      },
  )
  print("SES MessageId:", response["MessageId"])
  ```

  ```python After: Mailofly theme={null}
  from mailofly import Mailofly
  import os

  client = Mailofly(api_key=os.environ["MAILOFLY_API_KEY"])

  response = client.emails.send(
      sender="Acme <hello@acme.com>",
      to=["customer@example.com"],
      subject="Welcome to Acme",
      html="<p>Welcome to our platform!</p>",
      text="Welcome to our platform!",
  )
  print("Mailofly ID:", response.id)
  ```
</CodeGroup>

***

## 2. DNS & DKIM Verification

AWS SES uses **Easy DKIM** with three `CNAME` records pointing to `*.amazonses.com`. Mailofly uses modern 2048-bit DKIM records.

1. In Mailofly, go to **[Domains](https://www.mailofly.com/user/domains)** → **Add Domain**.
2. Add the DKIM and SPF records generated by Mailofly to Route 53 or your DNS host:
   * **DKIM**: `mailofly._domainkey.yourdomain.com` (TXT or CNAME)
   * **SPF**: Update your existing SPF TXT record:
     ```dns theme={null}
     # During coexistence
     v=spf1 include:amazonses.com include:mailofly.com ~all

     # After complete cutover
     v=spf1 include:mailofly.com ~all
     ```
3. Mailofly will verify your records and enable sending within minutes.

***

## 3. Retiring the SNS/SQS Bounce Pipeline

In SES, if you do not handle bounce events, AWS will shut down your sending account when bounce rates cross 5%. With Mailofly:

1. **Automatic Suppression**: When an address hard-bounces or marks your email as spam, Mailofly automatically flags it. Future sends to that address will be blocked instantly at the API level without burning sending credits or impacting ISP reputation.
2. **Simplified Webhooks**: Instead of setting up an SNS topic, SQS queue, and Lambda worker, simply paste your app's webhook URL in **[Mailofly Webhooks](https://www.mailofly.com/user/webhooks)**.
3. You can safely decommission your AWS SNS topics and Lambda bounce processors once you finish migration.

***

## 4. SMTP Relay Configuration

If you send via SES SMTP credentials:

```env theme={null}
# Before: AWS SES SMTP
# SMTP_HOST=email-smtp.us-east-1.amazonaws.com
# SMTP_PORT=587
# SMTP_USER=AKIA...
# SMTP_PASS=B...

# After: Mailofly SMTP
SMTP_HOST=smtp.mailofly.com
SMTP_PORT=587
SMTP_USER=mailofly
SMTP_PASS=mf_live_xxxxxxxxxxxxxxxxxxxxxxxx
```

***

## Migration Checklist

* [ ] Add domain to Mailofly and configure DNS records.
* [ ] Update SPF TXT record to include `include:mailofly.com`.
* [ ] Export existing suppression lists from SES (via AWS CLI or your database) and import into Mailofly.
* [ ] Replace `@aws-sdk/client-ses` or `boto3` calls with `@mailofly/node` or `mailofly`.
* [ ] Configure Mailofly webhooks to notify your backend of delivery events.
* [ ] Tear down unused AWS SNS topics, SQS queues, and Lambda bounce processors.
* [ ] Remove `include:amazonses.com` from your SPF record once migration is verified.


## Related topics

- [Index](/changelog/index.md)
- [Introduction](/identities/introduction.md)
- [How Identities Send](/identities/how-it-sends.md)
- [Managing Identities](/identities/managing-identities.md)
- [Send without a domain (Identities)](/getting-started/identities.md)
