Tag Archives: AWS

Using Amazon Mail Manager SMTP to send email via Amazon Simple Email Service

Post Syndicated from Josephine Elea Schlage original https://aws.amazon.com/blogs/messaging-and-targeting/using-amazon-mail-manager-smtp-to-send-email-using-amazon-simple-email-service/

If you’re running applications or mail servers that need to send email over Simple Mail Transfer Protocol (SMTP), you may find that the classic Amazon Simple Email Service (Amazon SES) SMTP endpoint (email-smtp.<region>.amazonaws.com) is not available in every AWS Region.

This applies to some newer AWS Regions and partitions, including eusc-de-east-1 in the AWS European Sovereign Cloud (ESC). In these AWS Regions, services configured with a traditional SMTP hostname and credentials, such as Postfix relays, cannot use the classic SES SMTP integration pattern. Amazon SES Mail Manager provides an alternative: an authenticated SMTP ingress endpoint that accepts connections using a hostname, port, and credentials, just like any standard SMTP server.

In addition to SMTP connectivity, Mail Manager introduces a configurable email pipeline between acceptance and delivery. This pipeline gives you traffic filtering, message archiving, and rule-based routing that are not available with the classic SES SMTP endpoint.

In this post, you configure Amazon SES Mail Manager to send outbound email in a Region that does not offer the classic SES SMTP endpoint. This post uses eusc-de-east-1 (AWS European Sovereign Cloud) as an example, but the same steps apply to AWS Regions where Mail Manager is available and the classic SMTP endpoint is not. By the end, you have a working Mail Manager pipeline that can:

  • Control outbound email flow with traffic policies.
  • Archive outgoing messages for compliance.
  • Deliver messages to recipients through a managed SMTP pipeline.

This post walks through a practical setup in eusc-de-east-1 with step-by-step instructions for configuring each component.

Solution overview

In this walkthrough, you configure Amazon SES Mail Manager in eusc-de-east-1 with the following components:

  • Traffic policy: You create a traffic policy with a default action set to Deny. The policy includes two policy statements connected by an OR condition. Policy Statement 1 allows messages that use TLS protocol version 1.2 or higher. Policy Statement 2 allows messages where the recipient address ends with a specific domain, filtering outgoing mail to approved recipients only.
  • Rule set: You create a rule set containing a single rule with two actions that archive outgoing email and then deliver it to recipients.
  • Ingress endpoint: You create an authenticated Mail Manager ingress endpoint that receives, routes, and manages messages based on your configured traffic policy and rule set.

After setting up these components, you use sample Python code to send an email through the ingress endpoint. Optionally, you can integrate with Postfix for relay-based delivery. You also configure Amazon CloudWatch logging to monitor how each message flows through the pipeline. To verify functionality, you check the email archive to confirm that outgoing messages are stored and that the email is received in the intended inbox.

The following diagram shows the message flow: Application or Amazon Elastic Compute Cloud (Amazon EC2) instance → ingress endpoint → traffic policy (allow or deny) → rule set (archive, then send to internet) → recipient inbox.

Walkthrough

This walkthrough covers the prerequisites and the step-by-step setup. Before you create traffic policies and a rule set, you first set up email archiving and AWS Identity and Access Management (IAM) roles, which are needed when you create the traffic policies and rules.

Prerequisites

Before beginning, verify that you have completed domain verification in the eusc-de-east-1 (ESC) Region and moved out of the Amazon SES sandbox. Domain verification is a required first step that confirms your authority to send email through SES from your domain. In this tutorial, you use a sample Python program to send email programmatically through an ingress SMTP endpoint (ARecord). You can run this program on your local machine through the AWS Command Line Interface (AWS CLI).

  • An active AWS account in the AWS European Sovereign Cloud with access to the eusc-de-east-1 Region.
  • A domain to verify as a sending identity in Amazon SES.
  • The AWS CLI, installed and configured for eusc-de-east-1 (required for Amazon CloudWatch logging).
  • An AWS Secrets Manager secret to store ingress endpoint credentials.
  • (Optional) An Amazon Virtual Private Cloud (Amazon VPC) with at least two subnets and an Amazon EC2 instance, if you plan to configure VPC endpoint connectivity.
  • IAM permissions for Amazon SES, AWS Key Management Service (AWS KMS), AWS Secrets Manager, and CloudWatch for the user who is signed in to the AWS Management Console.

Step 1: Create and verify an identity

To create and verify a sending identity in Amazon SES:

  1. In the Amazon SES console, choose Configuration, and then select Identities.
  2. Create the identity (domain or email address). If you verify a domain identity, configure email authentication with Sender Policy Framework (SPF), DomainKeys Identified Mail (DKIM), and Domain-based Message Authentication and Reporting and Conformance (DMARC) to prevent email from being marked as spam or failing delivery. See the following guides:
    1. Authenticating Email with DKIM in Amazon SES.
    2. Authenticating Email with SPF in Amazon SES.
    3. Complying with DMARC authentication protocol in Amazon SES.

    If you verify an email address identity without also verifying the parent domain, your messages may be quarantined or rejected depending on the domain’s DMARC policy.

  3. Complete the verification process.

Note: For eusc-de-east-1, the Custom MAIL FROM Domain Name System (DNS) records use amazonses.eu instead of amazonses.com.

Step 2: Configure an email archive for compliance and retention

Create an email archive to store outgoing messages. You configure this archive as the first action in your rule. The archive serves as a repository for outgoing messages.

  1. In the Amazon SES console, choose Mail Manager, then Email Archiving.
  2. Under Manage archives, select Create archive.
    1. Enter a unique name in the Archive name field.
    2. (Optional) Select a retention period to override the default of 180 days (6 months).
    3. (Optional) Set up encryption by either entering your own AWS Key Management Service (AWS KMS) key in the AWS KMS key ARN field, or selecting Create new key.
  3. Choose Create archive.
  4. After it is created, this archive stores your email according to the rules you define in the next step.

Step 3: Create an IAM role permission policy for the send to internet rule action

Configure an IAM role that permits Mail Manager to send email to external domains. This role is referenced in the rule for the second action, “send to internet,” which delivers email to recipients.

  1. Go to the IAM console.
  2. Choose Roles, and then choose Create role.
  3. For trusted entity, select Custom trust policy and paste the following (replace XXXXXXXXXXX with your AWS EUSC account ID):
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "Statement1",
          "Effect": "Allow",
          "Principal": {
            "Service": "ses.amazonaws.com"
          },
          "Action": "sts:AssumeRole",
          "Condition": {
            "StringEquals": {
              "aws:SourceAccount": "XXXXXXXXXXX"
            },
            "ArnLike": {
              "aws:SourceArn": "arn:aws-eusc:ses:eusc-de-east-1:XXXXXXXX:mailmanager-rule-set/*"
            }
          }
        }
      ]
    }

  4. Skip add permissions, name review, and create your role.
  5. Open your newly created role and select Add permissions.
  6. From the menu, choose Create inline policy.
  7. Select JSON in the policy editor and paste the following (replace example.com with your verified domain, XXXXXXXXXXX with your AWS account ID, and my-configuration-set with your configuration set name if applicable). This policy grants the necessary permissions to send email to recipients on the internet, which is used in rule 2 of your rule set.
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "VisualEditor0",
          "Effect": "Allow",
          "Action": [
            "ses:SendEmail",
            "ses:SendRawEmail"
          ],
          "Resource": [
            "arn:aws-eusc:ses:eusc-de-east-1:XXXXXXXXXXX:identity/example.com",
            "arn:aws-eusc:ses:eusc-de-east-1:XXXXXXXXXXX:configuration-set/my-configuration-set"
          ],
          "Condition": {
            "StringEquals": {
              "ses:FromAddress": "example.com"
            }
          }
        }
      ]
    }

  8. Review and save the policy.

Your newly created role now has the custom trust policy in Trusted entities, and a customer-managed inline permission policy under Permissions.

Step 4: Create a traffic policy

Traffic policies act as security checkpoints for your email infrastructure. They control which messages can enter your system based on rules you define. To create a traffic policy that enforces security requirements for your email:

  1. Open the Amazon SES console.
  2. Go to Mail Manager and select Traffic policies.
  3. Choose Create traffic policy.
  4. Enter a unique name for your policy.
  5. Set Default action to Deny.
  6. In your traffic policy, select “add new policy statement.”
    1. For Allow or deny properties, select Allow.
    2. For Properties, select TLS protocol version.
    3. For Operator, select Minimum version or Is version.
    4. For Value, select TLS 1.2 (minimum) or TLS 1.3 (Is version).
  7. Now, add a second condition to the same policy statement to filter outgoing mail to *example.com domains:
    1. For Properties, select Recipient address.
    2. For Operator, select “Ends with” and for Value enter example.com.

    Configure your policy statements as you like.

  8. Choose Create traffic policy.

Traffic policies are evaluated in a specific sequence:

  1. Deny policy statements are evaluated in order. If any match, the email is immediately blocked and no further evaluation occurs.
  2. If no Deny statements match, all Allow policy statements are evaluated in order. Multiple statements within a policy are connected by OR logic. If any statement matches, the email is allowed.
  3. Within each individual policy statement, multiple conditions are connected by AND logic. Each condition must be true for the statement to match.
  4. If no policy statements match (neither Deny nor Allow), the default action of the traffic policy (either Allow or Deny) is applied.

This policy denies traffic by default and allows only messages that meet the TLS 1.2 minimum requirement and are addressed to approved recipient domains.

Default action: Deny by default. Email traffic is initially blocked unless explicitly allowed by the following policy statements.

Policy statement 1: Allows messages to be sent if the recipient’s address ends with *example.com AND meets the minimum TLS protocol version of TLS 1.2.

Step 5: Create a rule set

Rule sets define how your messages are processed after they pass through your traffic policy. In this example, the rule set establishes a sequential email processing workflow. First, you add the action for archiving outgoing messages, and then you add a second action to deliver messages to recipients.

To create a rule set:

  1. Open the Amazon SES console.
  2. Go to Mail Manager and select Rule sets.
  3. Choose Create rule set.
  4. Enter a unique name for your rule set.
  5. On the rule set’s overview page, select Edit, then select Create new rule.

Step 6: Create rules

In this step, you create rules within your rule set that define the actions performed on each email: archiving for compliance and delivering to recipients.

Email add-ons are optional: In your rule set, you can configure the Vade Advanced Email Security Add On for scanning or dropping messages, archiving for compliance, writing to Amazon Simple Storage Service (Amazon S3) for future analysis, and sending email out. Configure these rules accordingly. This guide covers email sending and archiving in the rule below.

  • Add conditions or exceptions as needed:
    • Select Add new condition to specify what messages the rule applies to.
    • Select EXCEPT in the case of and select Add new exception for exclusions.
  • Configure actions by choosing Add new action.
  • For multiple actions, use the up and down arrows to set the execution order.

Action 1: Archive outgoing email. Stores a copy of each outgoing email in a Mail Manager archive. Archived email can be searched and retrieved directly from the Amazon SES console under Email archiving, supporting compliance and audit requirements.

Action 2: Send to internet. Delivers the email to the intended recipient using Amazon SES.

After you create your rule set, add rules that define how email is processed. You create a rule set containing a single rule with two actions that execute in sequential order.

Follow these steps to create and configure your rules.

  1. In the created rule set’s overview page, select Edit, then choose Create new rule.
  2. In the Rule details sidebar, enter a unique name for your rule.
    1. In the rule details on the right side, select “add new action.”
    2. From the menu, choose “archive,” and choose the archive you created at Step 2.
    3. Then add another action: select “add new action” and from the menu, choose “Send to internet.”
    4. Choose the IAM role that you created in Step 3. This role grants SES Mail Manager access to your resource.
  3. When finished creating your rules, choose Save rule set to apply your changes.

Rule 1: Archive and send email to recipients

The rule processes messages that have successfully passed through the traffic policy. The archive action confirms that messages are archived and searchable. The send to internet action then forwards messages to their intended recipients, completing the email delivery workflow.

Step 7: Store password in AWS Secrets Manager for the ingress endpoint

Before you create an ingress endpoint, set up a password in AWS Secrets Manager and an AWS KMS customer managed key:

1. Create a customer managed key policy for your ingress endpoint.

  1. Open the AWS KMS console.
  2. Select Customer managed key (not AWS managed keys).
  3. Create the key.
  4. Define key administrative permissions.
  5. Define key usage permissions.
  6. In your key policy editor, when you review the key statements, paste the following (replace XXXXXXXXXXX with your AWS account ID):
    {
      "Sid": "Allow use of the key",
      "Effect": "Allow",
      "Principal": {
        "Service": "ses.amazonaws.com"
      },
      "Action": "kms:Decrypt",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "XXXXXXX",
          "kms:ViaService": "secretsmanager.eusc-de-east-1.amazonaws.com"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws-eusc:ses:eusc-de-east-1:XXXXXXXX:mailmanager-ingress-point/*"
        }
      }
    }

2. Set up a password in AWS Secrets Manager.

  1. Go to the AWS Secrets Manager console and select Store a new secret.
  2. Choose Other type of secret.
  3. Enter password as the key and your chosen password as the value.
  4. For encryption key, choose the customer managed key you created above.
  5. Choose Next to proceed to Configure secret.
  6. Enter a secret name and choose Edit permissions, then update the resource policy (replace XXXXXXXXXXX with your AWS account ID).
    {
      "Version": "2012-10-17",
      "Id": "Id",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "ses.amazonaws.com"
          },
          "Action": "secretsmanager:GetSecretValue",
          "Resource": "*",
          "Condition": {
            "StringEquals": {
              "aws:SourceAccount": "XXXXXXXXXXX"
            },
            "ArnLike": {
              "aws:SourceArn": "arn:aws-eusc:ses:eusc-de-east-1:XXXXXXXXXXX:mailmanager-ingress-point/*"
            }
          }
        }
      ]
    }

  7. Choose Next, then create and store your secret.

Step 8: Create an authenticated ingress endpoint (ARecord)

Now that you have created your traffic policy and rule set and stored your credentials, you can create the ingress endpoint:

  1. In the Amazon SES console, choose Mail Manager and then select Ingress endpoints.
  2. Choose Create ingress endpoint.
  3. Configure your endpoint:
    1. For type, select authenticated, then select the Secret ARN you created in Secrets Manager.
    2. Choose the traffic policy you created earlier.
    3. Choose the rule set you created earlier.
    4. Configure Network Type: Public Network (Standard Setup). If you select Private Network, follow Step 9 first in a new tab.
    5. Enter a unique name for your endpoint.
  4. Choose Create ingress endpoint.

After your ingress endpoint is created, note the following details from the General details section:

  • Amazon Resource Name (ARN): arn:aws-eusc:ses:eusc-de-east-1:XXXXXXXXXXX:mailmanager-ingress-point/inp-XXXXX
  • Username: inp-XXXXXXXXXXX
  • Host: XXXXXXXXXXX.mail-manager-smtp.eusc-de-east-1.amazonaws.eu (ARecord)

You need these details when configuring your email client or application to send email through this endpoint.

Step 9: Configure VPC endpoint for SES Mail Manager (optional enhanced security)

A VPC endpoint allows your Postfix EC2 instance to reach Mail Manager privately, without sending traffic over the public internet. To use this option, create the VPC endpoint in the same VPC as your Postfix instance. Configure security group rules to allow traffic on port 587.

  • VPC: The VPC endpoint must be created in the same VPC where your Postfix EC2 instance resides.
  • Security groups:
    • Postfix EC2 SG: Outbound rule to VPC endpoint SG on port 587.
    • VPC endpoint SG: Inbound rule from Postfix EC2 SG on port 587.
  • Subnets: The VPC endpoint should be in subnets that are routable from your EC2 instance’s subnet.

Create a security group for the VPC endpoint:

  1. Open the Amazon VPC console.
  2. Select Security groups.
  3. Choose Create security group.
    1. Name: mail-manager-vpce-sg (example).
    2. VPC: Choose the VPC where your Postfix EC2 instance resides.
  4. Add an inbound rule:
    1. Type: Custom TCP.
    2. Port: 587 (or 25 if using port 25).
    3. Source: Security Group ID of your Postfix EC2 instance (or create a placeholder, update later).
  5. Choose Create security group. Note the Security Group ID for the next step.
  6. Choose Endpoints in the VPC console.
  7. Choose Create endpoint.
    1. Name: mailmanager-ingress-endpoint (example).
    2. For Service category, select AWS services.
    3. For Service Name, select com.amazonaws.eusc-de-east-1.mail-manager-smtp.auth.
    4. For VPC, choose the VPC where your Postfix server resides.
    5. Subnets: Select at least 2 (private) subnets (for high availability).
    6. Security Groups: Choose the security group you created.
  8. Choose Create Endpoint.

Wait for the endpoint status to become Available. After the endpoint status becomes Available, note the DNS name from the endpoint details. Use the regional (non-AZ-specific) DNS name for your Postfix relay configuration:

auth.mail-manager-smtp.eusc-de-east-1.on.amazonwebservices.eu

Step 10: Mail Manager logging (AWS CLI)

Now that you have created your Mail Manager resources, you can configure log delivery through the AWS CLI to track message flow from ingress endpoints through rule set processing. After it is configured, you can view these logs in CloudWatch Log Groups.

  1. Open your terminal (CLI).
  2. Log in to your AWS account using the following command:
    aws configure

  3. Create a CloudWatch Log Group:
    aws logs create-log-group \
        --log-group-name /aws/mailmanager/ruleset-logs \
        --region eusc-de-east-1

    Before you proceed, copy the log group ARN for the step Create the Delivery Destination.

  4. Create the Log Delivery Source:Add your rule set ID to the resource-arn parameter below. You can find the resource ARN for the rule set when you click on the rule set name under rule sets in the SES console.
    aws logs put-delivery-source \
        --name rs-default \
        --resource-arn arn:aws-eusc:ses:eusc-de-east-1:XXXXXX:mailmanager-ruleset/YOUR-RULESET-ID \
        --log-type APPLICATION_LOGS

  5. Create the Log Delivery Destination:Add your log group ARN to the destinationResourceArn parameter below:
    aws logs put-delivery-destination \
        --name mailmanager-destination \
        --output-format json \
        --delivery-destination-configuration '{"destinationResourceArn":"arn:aws-eusc:logs:eusc-de-east-1:XXXXXX:log-group:/aws/mailmanager/ruleset-logs:*"}'

    Copy the delivery destination ARN for the step below.

  6. Link Log Delivery Source to Log Delivery Destination (Create Delivery):
    aws logs create-delivery \
        --delivery-source-name rs-default \
        --delivery-destination-arn arn:aws-eusc:logs:eusc-de-east-1:XXXXXX:delivery-destination:mailmanager-destination

    Verification commands:

    aws logs describe-log-groups --region eusc-de-east-1
    aws logs describe-delivery-sources --region eusc-de-east-1
    aws logs describe-delivery-destinations --region eusc-de-east-1
    aws logs describe-deliveries --region eusc-de-east-1

  7. Send an email and view your logs for your rule set:
    1. Open the Amazon CloudWatch console.
    2. Select Log Groups in the sidebar navigation.
    3. Select the log group you would like to view logs for.
    4. Select the log you would like to view under Log Streams.

Example output of an email that was sent successfully:

{
  "resource_arn": "arn:aws-eusc:ses:eusc-de-east-1:account-id:mailmanager-rule-set/ruleset-id",
  "event_timestamp": 3456789876,
  "message_id": "message-id",
  "rule_set_name": "send",
  "rule_name": "sendtointernet",
  "rule_index": 1,
  "recipients_matched": "[\"[email protected]\"]",
  "action_metadata": {
    "action_name": "SEND",
    "action_index": 1,
    "action_status": "SUCCESS"
  }
}

Step 11: Send email using an ingress endpoint

Code example with Python:

import smtplib
import ssl

# Your ingress endpoint and port
smtp_server = "*****.eusc-de-east-1.amazonaws.eu"
# Or for VPC: "vpce-xxxxx.mail-manager-smtp.auth.eusc-de-east-1.vpce.amazonaws.eu"
smtp_port = 587

# Your SMTP credentials retrieved from Secrets Manager
username = "****"
password = "[REDACTED_PASSWORD]"

sender_email = "[email protected]"  # Your verified identity
receiver_email = "[email protected]"

# Properly formatted email message with headers
message = f"""From: Firstname Lastname <{sender_email}>
To: Firstname Lastname <{receiver_email}>
Subject: Test Email from Python

This email was sent via the Mail Manager ingress endpoint and delivered
to the recipient through the "Send to Internet" rule action.
"""

server = None
try:
    print(f"Connecting to {smtp_server}:{smtp_port}...")
    server = smtplib.SMTP(smtp_server, smtp_port)
    server.set_debuglevel(1)

    print("\nStarting TLS...")
    context = ssl.create_default_context()
    server.starttls(context=context)

    print("\nLogging in...")
    server.login(username, password)

    print("\nSending email...")
    server.sendmail(sender_email, receiver_email, message)
    print("\nEmail sent successfully.")
except Exception as e:
    print(f"\nError: {e}")
    import traceback
    traceback.print_exc()
finally:
    if server:
        server.quit()

Step 12: Integrate with your existing email server

Use Postfix or SMTP clients on Amazon EC2 to relay outbound email through Mail Manager, which then forwards it through the “Send to internet” action configured in Step 3.

If you choose to integrate with Postfix in this guide, your relay host is the ingress endpoint or the VPC endpoint you created. Your port is typically 587.

relayhost = [<ARecord>]:<port>

Example with Postfix

/etc/postfix/main.cf:

relayhost = [xxxx.eusc-de-east-1.amazonaws.eu]:587 or 25
relayhost = [vpce-xxxxx.mail-manager-smtp.auth.eusc-de-east-1.vpce.amazonaws.eu]:587

Clean up

Clean up your AWS environment by removing all resources created during this walkthrough, including Mail Manager configurations, ingress endpoints, rule sets, traffic policies, archives, IAM roles, Secrets Manager secrets, AWS KMS keys, and CloudWatch log groups.

Conclusion

In this post, you configured Amazon SES Mail Manager in the eusc-de-east-1 Region of the AWS European Sovereign Cloud to send outbound email over SMTP. You created a traffic policy to enforce TLS and recipient filtering, a rule set to archive and deliver messages, and an authenticated ingress endpoint that serves as a compatible SMTP relay for your applications.

To learn more, see the Amazon SES Mail Manager documentation, open the Amazon SES console to start configuring your own pipeline, or visit the Amazon SES service page for additional features.

Additional references

For more information, see the following references:


About the authors

Shutdowns, power outages, and conflict: a review of Q1 2026 Internet disruptions

Post Syndicated from David Belson original https://blog.cloudflare.com/q1-2026-internet-disruption-summary/

In the first quarter of 2026, government-directed shutdowns figured prominently, with prolonged Internet blackouts in both Uganda and Iran, a stark contrast to the lack of observed government-directed shutdowns in the same quarter a year prior. This quarter, we also observed a number of Internet disruptions caused by power outages, including three separate collapses of Cuba’s national electrical grid. Military action continued to disrupt connectivity in Ukraine and also impacted hyperscaler cloud infrastructure in the Middle East. Severe weather knocked out Internet connectivity in Portugal, while cable damage disrupted connectivity in the Republic of Congo. A technical problem hit Verizon Wireless in the United States, and unknown issues briefly disrupted connectivity for customers of providers in Guinea and the United Kingdom.

This post is intended as a summary overview of observed and confirmed disruptions and is not an exhaustive or complete list of issues that have occurred during the quarter. A larger list of detected traffic anomalies is available in the Cloudflare Radar Outage Center. Note that both bytes-based and request-based traffic graphs are used within this post to illustrate the impact of the observed disruptions, with the choice of metric generally made based on which better illustrates the impact of the disruption.

Government-directed shutdowns

Uganda

In advance of the January 15 presidential election, Ugandan authorities ordered a nationwide Internet shutdown. The Uganda Communications Commission (UCC) instructed mobile network operators to suspend public Internet access, effective 18:00 local time (15:00 UTC) on January 13. The UCC reportedly defended the shutdown as necessary to “curb misinformation, disinformation, electoral fraud and related risks.” Domestic traffic at the Uganda Internet Exchange Point (UIXP) dropped from approximately 72 Gbps to 1 Gbps as a result of the action taken.

Similarly, Cloudflare data shows a near-complete loss of traffic from Uganda coincident with the start of the shutdown, with traffic remaining effectively at zero through 23:00 local time (20:00 UTC) on January 17, when Internet connectivity was partially restored after incumbent President Yoweri Museveni was declared winner of his seventh term. 

Full Internet restoration was announced by the UCC on January 26, with mobile network operators MTN Uganda and Airtel Uganda both confirming on social media that restrictions had been lifted. The shutdown prompted lawsuits against UCC and the telecoms companies and drew criticism from digital rights organizations including CIPESA.

Uganda also blocked Internet access during its 2021 election. Authorities had repeatedly promised this time would be different, stating as recently as January 5 that “claims suggesting otherwise are false, misleading.”

Iran

Iranian citizens spent a large part of Q1 2026 offline, or with severely limited connectivity, due to two nationwide Internet shutdowns. The first began around 20:00 local time (16:30 UTC) on January 8, and we explored the impact seen over the first few days in our What we know about Iran’s Internet shutdown blog post. Traffic from Iran remained near zero until January 21, when a small amount of traffic returned, only to disappear a little over 24 hours later. A similar brief restoration also occurred on January 25, before traffic recovered more aggressively starting on January 27.

A near-complete loss of announced IPv6 address space started several hours before the drop in traffic took place on January 8. Asiatech (AS43754) was by far the single largest contributor, losing 4.46 million /48-equivalents, accounting for ~9.4% of Iran’s entire IPv6 space loss on its own. RASANA (AS31549) was the second-largest, losing 4.19 million /48-equivalents (~8.8% of the country total). As would be expected, this resulted in the share of IPv6 traffic in Iran going to zero. Given the gap in timing between this change and the loss of traffic across the country, this may have been a leading indicator of what was about to happen, but likely not a direct cause of it. Some nominal shifts in announced IPv4 address space are visible during the shutdown, but levels remained fairly consistent during the shutdown period. These observations suggest that the shutdown was implemented by other means, such as filtering.

 

Cloudflare Radar social media posts (X, Bluesky, Mastodon) throughout January and into early February documented our observations about the state of connectivity in Iran over the course of that month.

On February 28, as military strikes on Iran escalated, a second nationwide Internet shutdown began. Cloudflare Radar observed a sharp drop in traffic from Iran beginning around 10:30 local time (07:00 UTC). Traffic levels fell to well under 1% of previous levels, with only small amounts of Web and DNS traffic egressing the country.

No significant shifts in announced IP address space were observed around the onset of this shutdown. IPv4 space remained fairly consistent, and IPv6 space remained consistently volatile, suggesting that route withdrawals were not the cause of this second shutdown.

The continued announcement of IP address space, and the presence of traffic from the country, even if just a small amount, supports reports that the shutdown was effectively achieved through aggressive filtering, with so-called “whitelists” and “white SIM cards” restricting access to only approved Internet sites by selected users.

Iran remained effectively offline through the end of the quarter. As of late April, this shutdown remains largely in place, making it one of the longest sustained Internet disruptions observed in recent years.

Republic of Congo

On March 15, as the Republic of Congo held a presidential election expected to extend President Denis Sassou Nguesso’s 42-year rule, a near-complete shutdown of Internet connectivity was observed in the country. Traffic from the country dropped precipitously around 06:30 local time (05:30 UTC), falling to near zero for approximately 60 hours through the election period and its immediate aftermath. Traffic began recovering around March 17 at 18:20 local time (17:20 UTC), rapidly returning to pre-shutdown levels. While Congolese authorities provided no official explanation for the drop in traffic, similar shutdowns were put into place during the 2021 and 2016 elections.

Military action

Ukraine (Dnipropetrovsk)

On January 7-8, Russian attacks on energy infrastructure in Ukraine caused power outages that disrupted Internet connectivity in Dnipropetrovsk and surrounding regions. Cloudflare Radar observed a significant drop in traffic from the region, reaching nearly 50% below the prior week’s levels, starting around 22:45 local time (20:45 UTC) on January 7. Recovery began approximately 06:00 local time (04:00 UTC) on January 8.

Ukraine (Kharkiv)

On January 26, Russia launched a drone and missile attack targeting energy infrastructure in Kharkiv. Cloudflare Radar observed an approximately 50% drop in traffic from the region beginning around 19:15 local time (17:15 UTC). Recovery progressed through January 27 as power was gradually restored.

Amazon Web Services Middle East (United Arab Emirates and Bahrain)

One of the most unusual disruptions of the quarter was the physical damage inflicted on Amazon Web Services data centers in the Middle East by drone strikes tied to the ongoing regional conflict. On the morning of March 1 (UTC), Amazon reported a fire started after objects hit a UAE data center. The following day, the company confirmed that two of its facilities in the United Arab Emirates (me-central-1 region) were “directly struck” by drones and that a facility in Bahrain (me-south-1 region) was also taken offline after being damaged by a nearby strike.

Cloudflare’s Cloud Observatory data showed elevated connection failure rates for the me-central-1 and me-south-1 regions beginning March 1-2 and remaining higher for multiple days. Connection failures occur when Cloudflare fails to successfully connect to an origin server when attempting to retrieve uncacheable content, or content not in/expired from cache. These graphs illustrate the increased rate of failures experienced when attempting to connect to servers in these impacted regions.

In a status post on the AWS Health Dashboard, Amazon acknowledged: “These strikes have caused structural damage, disrupted power delivery to our infrastructure, and in some cases required fire suppression activities that resulted in additional water damage.” The company warned that instability was likely to continue in the Middle East, making operations “unpredictable,” and urged customers with workloads in the affected regions to back up their data or migrate to other AWS regions.

The AWS me-south-1 region in Bahrain suffered an additional disruption on March 23, following further drone activity.

Power outages

Argentina (Buenos Aires)

On January 15, a power outage struck Buenos Aires during a summer heat wave. The outage caused nominal disruptions in Internet connectivity for customers of multiple providers in the Buenos Aires area, including Telecom Argentina (AS7303), Telecentro (AS27747), and IPLAN (AS16814), with traffic from these networks dropping between 17:30 and 19:30 local time (20:30 – 22:30 UTC). Traffic returned to expected levels approximately two hours after the outage began.

Moldova and Ukraine

An emergency power cut on Ukraine’s electricity grid on January 31 caused widespread power outages affecting Moldova and several Ukrainian regions including Kyiv and Kharkiv. Moldova was reportedly hit by widespread power cuts amid the Ukrainian grid problems, and the Ukrainian Energy Minister explained the cross-border impact, noting “Today at 10:42 a.m. (08:42 GMT), a technical malfunction occurred, causing a simultaneous shutdown of the 400 kilovolt line between the power grids of Romania and Moldova and the 750 kilovolt line between western and central Ukraine.” Traffic from Moldova, Kyiv, and Kharkiv began falling around 10:42 local time (08:42 UTC), reaching as much as 46% below the prior week, with recovery occurring around 14:00 local time (12:00 UTC).

Paraguay

On February 18, widespread power outages struck Paraguay after key transmission lines went out of service. The National Electricity Administration (ANDE) posted a series of updates on X documenting the incident and efforts to restore power. Internet traffic from Paraguay dropped as much as 72% compared to the prior week beginning around 15:15 local time (18:15 UTC), and the disruption lasted nearly three hours, with recovery occurring by approximately 18:30 local time (21:30 UTC).

Dominican Republic

A major failure in the Interconnected National Electric System (SENI) of the Dominican Republic caused a widespread power outage on February 23. The state-owned electric company Empresa de Transmisión Eléctrica Dominicana (ETED) posted updates on X documenting the failure and the recovery effort. Internet traffic from the country dropped sharply beginning around 10:50 local time (14:50 UTC), and recovered around midnight local time (04:00 UTC) on February 24, in line with a confirmation posted by ETED that “The authorities of the electric sector reported that the Interconnected National Electric System (SENI) was fully restored to 100% at 11:53 p.m. on this Monday…”.

Cuba

Cuba experienced three separate collapses of its National Electric System (SEN) during March, each causing widespread Internet disruption, reflecting the severe deterioration of the country’s electrical infrastructure. (Power outages also disrupted Internet connectivity in Cuba during September and March 2025, and October 2024.) 

The first collapse occurred on March 4, when a disconnection of Cuba’s National Electroenergy System cascaded from Camagüey to Pinar del Río, cutting power to the western half of the island, including Havana. OSDE/UNE (Cuba’s Electric Union) confirmed the failure on social media. Cloudflare Radar data showed traffic from the island dropping by nearly half beginning around 12:15 local time (17:15 UTC), with traffic recovering by approximately 05:01 local time (10:01 UTC) on March 5.

The second collapse occurred on March 16, when Cuba’s entire National Electric Power System was disconnected. EnergíaMinas Cuba posted updates on the situation on X. Cloudflare Radar data again shows a significant loss of traffic from Cuba beginning around 13:35 local time (17:35 UTC) on March 16, dropping approximately 65%. Traffic returned to expected levels by approximately 20:00 local time on March 17 (00:00 UTC on March 18), with the disruption lasting over 30 hours.

The third collapse (the second in just a week) happened just days later, on March 21-22. EnergíaMinas Cuba and OSDE/UNE again provided situation updates via X. Cloudflare Radar data shows another significant loss of traffic from Cuba beginning around 18:30 local time (22:30 UTC) on March 21, falling as much as 77% compared to the previous week. Traffic recovered around 21:39 local time on March 22 (01:39 UTC on March 23).

U.S. Virgin Islands

According to a Facebook post from the Virgin Islands Water and Power Authority (WAPA) on March 24, a loss of generation at the Richmond Power Plant combined with damage to an underground cable caused a power outage affecting St. Croix and St. Thomas in the U.S. Virgin Islands. Cloudflare Radar data shows traffic from local provider VI Powernet (AS14434), the primary ISP for the U.S. Virgin Islands, dropping to near zero beginning around 12:15 local time (16:15 UTC), with recovery occurring by approximately 14:45 local time (18:45 UTC). Although VI Powernet experienced a near-complete outage, traffic from St. Thomas only fell by around 60%, and approximately 40% from St. Croix due to the presence of other providers.

Severe weather

Portugal

Storm Kristin made landfall in Portugal on January 28, causing widespread damage and power outages across the country. Approximately 1,500 incidents were registered by Civil Protection between midnight and 08:00 local time (00:00 – 08:00 UTC), with the hardest-hit areas being the districts of Leiria and Coimbra. Significant infrastructure damage was reported, and by 07:00 local time (07:00 UTC), over 850,000 E-Redes customers were without electricity.

The associated power outages disrupted Internet connectivity across Portugal, which Cloudflare Radar observed primarily in the regions of Leiria, Santarém, and Coimbra beginning around 04:10 local time (04:10 UTC) on January 28. Internet traffic dropped as much as 70% in Leiria, and 52% in Coimbra.

Recovery was slow: over 290,000 customers remained without power as late as January 30, and Cloudflare continued tracking gradual recovery of regional traffic over the following weeks. (Coimbra returned to expected levels within the first several days after the storm.) More than three weeks after the storm, over 6,000 customers in Leiria reportedly remained without electricity.

Cable damage

Republic of Congo

Just after the New Year, Internet connectivity in the Republic of Congo was disrupted by an incident on the WACS (West Africa Cable System) submarine cable. Congo Telecom (AS37451) posted on X announcing “an international incident on the WACS cable” was causing Internet disruptions, and stating that backup solutions had been activated. Cloudflare Radar observed a significant drop in traffic from Congo beginning around 00:00 local time on January 2 (23:00 UTC on January 1), falling to 82% below expected levels. A follow-up post from Congo Telecom confirmed that repairs were ongoing, with users potentially experiencing slowdowns during peak hours. Traffic returned to expected levels by approximately 15:00 local time (14:00 UTC) on January 4.

Technical problems

Verizon Wireless (United States)

On January 14, a software issue impacted voice and data services for customers of Verizon Wireless (AS6167) across the United States. Verizon published an official statement acknowledging that the outage began January 14 and that by 22:15 ET (03:15 UTC on January 15) the issue had been resolved. Multiple updates on X from @VerizonNews kept subscribers informed throughout the evening. Cloudflare Radar data shows a minor drop in traffic beginning around 12:30 ET (17:30 UTC) on January 14, consistent with the reported onset of the outage.

Grenada

On February 9-10, customers of Flow Grenada (AS46650) – the primary Internet provider serving Grenada – experienced an island-wide service disruption lasting approximately 12 hours. The provider posted on Facebook acknowledging a service disruption, though no details about the root cause were provided. Cloudflare Radar data shows traffic from the network initially dropping around 11:30 local time (15:30) UTC on February 9, disappearing completely around 20:00 local time (midnight UTC on February 10), and recovering by approximately 23:30 local time (03:30 UTC on February 10). Routing data shows a complete loss of announced IPv4 space at the same time traffic dropped to zero. Major spikes in BGP announcements around the time the disruption initially started, and bookending the complete outage, suggest that the whole event may have been routing-related.

Unknown cause

Orange Guinée (Guinea)

Customers of Orange Guinée (AS37461) in Guinea were unable to make phone calls or access the Internet starting around 10:45 local time (10:45 UTC) on January 6. Orange Guinée subsequently confirmed an “exceptional breakdown” affecting mobile phone and Internet services due to a technical incident, with teams mobilized to restore service. Service was restored by approximately 14:00 local time (14:00 UTC) that same day. No further details on the root cause of the incident were publicly disclosed.

TalkTalk (United Kingdom)

On March 25, customers of UK broadband provider TalkTalk (AS13285) reported widespread service disruptions. TalkTalk acknowledged the issues on X but did not publicly disclose a root cause. Cloudflare Radar observed traffic from the provider drop nearly 50% as compared to the previous week beginning around 07:00 local time (07:00 UTC), with service restored by approximately 08:15 local time (08:15 UTC).

A quarter marked by major disruptions

The first quarter of 2026 was marked by an unusually high number of severe and prolonged Internet disruptions. The major government-directed shutdowns, particularly the extended blackouts in Uganda and Iran, underscore how Internet access continues to be weaponized as a tool of political control. Cuba’s three separate national grid collapses in a single month paint a troubling picture of infrastructure fragility with direct consequences for connectivity. And the drone strikes on AWS data centers in the Middle East represent an unprecedented escalation as active military conflict directly and physically damaged major cloud infrastructure, with disastrous consequences for the websites and applications hosted there.

The Cloudflare Radar team is constantly monitoring for Internet disruptions, sharing our observations on the Cloudflare Radar Outage Center, via social media, and in posts on blog.cloudflare.com. Follow us on social media at @CloudflareRadar(X), noc.social/@cloudflareradar (Mastodon), and radar.cloudflare.com (Bluesky), or contact us via email.

Meta Buys Tens of Millions of AWS Graviton Arm Cores in a CPU Land Grab

Post Syndicated from Patrick Kennedy original https://www.servethehome.com/meta-buys-tens-of-millions-of-aws-graviton-arm-cores-in-a-cpu-land-grab/

Meta is buying “tens of millions” of AWS Graviton CPU cores in a big move to bolster its agentic AI compute portfolio

The post Meta Buys Tens of Millions of AWS Graviton Arm Cores in a CPU Land Grab appeared first on ServeTheHome.

Upgrade business messaging with RCS on AWS

Post Syndicated from Brett Ezell original https://aws.amazon.com/blogs/messaging-and-targeting/upgrade-business-messaging-with-rcs-on-aws/

SMS remains a reliable workhorse for business-to-consumer reach, but it isn’t without its hurdles. Messages from unrecognized numbers are frequently ignored or flagged as spam, and the limitations of plain text can’t provide the interactive experiences modern customers expect. Rich Communication Services (RCS) on AWS End User Messaging addresses these challenges as the next generation of mobile messaging.

Before we get into the technical implementation, it is important to understand what RCS is, why it’s becoming the new standard for business-to-consumer (B2C) communication, and the strategic value it brings to your messaging stack.

The problem with traditional business messaging

Traditional SMS has long been confined to a “narrow lane” of one-directional alerts—think one-time passcodes (OTP) and basic shipment updates. Because these messages arrive from generic-looking short codes or long codes, recipients have no native way to verify the sender’s legitimacy. As a result, users often do the rational thing: they ignore the message or treat it with suspicion.

What is RCS?

RCS is the next-generation messaging protocol developed by the GSM Association (GSMA) to update traditional Short Message Service (SMS) and Multimedia Messaging Service (MMS). Unlike SMS, which relies on the cellular signaling channel, RCS is entirely IP-based, operating over data connectivity (Wi-Fi or mobile data). This shift allows RCS to bring high-resolution media and interactive capabilities directly to the default messaging application.

The core innovation is the RCS Agent—your verified sending identity. Instead of a random number, recipients see your brand name, logo, and a verified checkmark. This shift from “unknown sender” to “verified brand” transforms the recipient’s behavior from passive ignore to active engagement. When customers trust the sender, they stop only reading alerts and start completing workflows, asking questions, and engaging with AI-powered agents built on services like Amazon Bedrock.

The business case for RCS

We can see the future of RCS by looking at markets where over-the-top (OTT) apps like WhatsApp are dominant. In those regions, businesses use messaging for full-lifecycle order management, customer service, and complex scheduling. In markets without that OTT distribution, businesses have been stuck with one-way SMS notifications.

RCS levels this playing field. By bringing a branded, verified identity natively to the default messaging app, it opens up a range of interactive use cases previously reserved for dedicated apps or websites.

Where to start?

When evaluating RCS for your program, we recommend starting with your highest-volume transactional messages. These are often the easiest to migrate because they follow predictable templates. More importantly, they provide the most immediate ROI by maximizing the visibility of your verified identity across your largest customer touchpoints.

To illustrate the business impact across industries:

  • Ecommerce: Order confirmations arriving from a verified brand logo eliminate the “Is this legitimate?” hesitation customers have with SMS from generic numbers. Customers click tracking links confidently because they recognize the sender immediately.
  • Healthcare: Appointment reminders with verified provider identity reduce no-shows and eliminate verification calls. Patients respond more quickly to verified communications and handle appointment management through messaging rather than calling the office.
  • Financial services: Fraud alerts with verified bank identity increase response rates and reduce phishing confusion. Customers see their bank’s logo and verified badge and know the alert is legitimate — enabling faster fraud detection and prevention.

Prerequisites

Before you begin the registration process, make sure that you have the following prerequisites in place:

  • An active AWS account with billing configured.
  • Access to AWS End User Messaging.
  • AWS Identity and Access Management (IAM) permissions to create and manage RCS agents and origination identities.
  • Existing SMS infrastructure to serve as a fallback.
  • A planned timeline that accounts for carrier approval lead times, which vary by country and carrier.
  • A budget for registration and verification fees.

Timeline, planning, and costs

Adopting RCS requires careful planning for both timelines and budgets. Carrier approval timelines vary by country and carrier — approval is not instant. Plan and verify that your processes, such as opt-in consent collection and brand asset preparation, are in place well before your intended launch date.

Registration and usage fees also differ significantly by market. Currently, AWS End User Messaging supports RCS in the United States and Canada, with additional countries planned for future rollout.

  • United States: This market uses a per-segment (160-character) pricing model similar to SMS. It features a higher initial barrier to entry, including a one-time agent setup fee and an annual brand vetting fee.
  • Canada: Canada utilizes a distinct message-based model (“Basic” vs. “Single” messages) rather than segments. Notably, it currently lacks the one-time setup and annual vetting fees found in the US, though a monthly maintenance fee applies globally to all active agents.

Also note that RCS is billed only upon successful delivery, whereas SMS is charged at the time of the request. For the latest rates and a breakdown of carrier-specific content violation fees, see AWS End User Messaging pricing.

Note: You are charged only for successfully delivered messages, not delivery attempts. In the United States, long messages are billed per 160-character segment; however, for the Rest of the World (ROW), messages exceeding 160 characters are billed as a single ‘RCS Single’ message. When automatic fallback occurs, you are typically charged only for the successful SMS delivery. While rare, note that if both the RCS and SMS messages reach the device (dual-delivery), charges for both may apply. For more details, see the RCS billing and pricing model.

RCS and SMS: Better together

RCS works alongside SMS to create a reliable messaging solution with automatic SMS fallback. AWS End User Messaging ensures reliable delivery by intelligently handling three common scenarios where RCS may be unavailable, triggering an automatic fallback to SMS:

  • Carrier-specific availability — Your RCS agent may be approved on some carriers but still pending on others, or a carrier may not have deployed RCS infrastructure yet. AWS detects this upfront using carrier lookup data and automatically routes via SMS so that the message is delivered.
  • Device compatibility — Not all devices support RCS, even if the carrier does. This includes older Android models, devices with RCS disabled, or iPhones running versions earlier than iOS 18. AWS detects this compatibility upfront where possible and automatically routes the message via SMS so that it reaches the recipient.
  • Temporary connectivity — A device may support RCS but lack data connectivity at the moment of delivery (for example, traveling through a tunnel or with data roaming turned off). The device still has cellular coverage for SMS. AWS falls back to SMS so that the message is delivered.
SMS text message from short code 47205 showing a Verizon Call Filter trial activation notice in a dark-themed mobile messaging app, with no sender branding, a generic profile icon, and a "Report Spam" warning at the bottom.

Figure 1: A typical SMS business message often appears from an unrecognizable short code, making it difficult for customers to verify the sender before clicking a link or replying.

When RCS delivery falls back to SMS because of a lack of data connectivity or other availability reasons, AWS uses sticky sending. The service prioritizes the origination number that most recently delivered successfully to that destination—maintaining that preference for 24 hours before retrying RCS. This ensures consistent, recognizable delivery across various connectivity and compatibility scenarios.

Effective phone number management is the foundation for fallback behavior. AWS provides three ways to send messages, each with different fallback behavior:

  • Pool-based sending — AWS selects from identities in a specific pool containing your RCS agent and SMS phone numbers. This is the recommended approach for production deployments. Pools give you precise control over which identities are used while AWS handles automatic routing and fallback.
  • Account-level sending — AWS automatically selects the best identity from your entire account. This is similar to the default behavior in Amazon Simple Notification Service (SNS), where you cannot isolate traffic into specific pools. This approach is ideal for development, testing, or simple deployments where a single identity is used for all messaging use cases within a country.
  • Direct send — You specify an exact RCS agent as the origination identity. The message fails if RCS isn’t available. Use this for testing or when you want to handle fallback yourself.

For production messaging where delivery is critical, use pool-based or account-level sending for reliable delivery. Pools route your fallback SMS messages through consistent, recognizable numbers your customers trust.

RCS vs. SMS at a glance

For a detailed comparison of capabilities, see the following table.

Feature SMS RCS
Character limit 160 characters No practical limit
Media support MMS (compressed) High-resolution images, video, audio
Read receipts No Yes
Typing indicators No Yes
Interactive buttons No Yes
Branded identity Basic (Sender ID) Full (Verified Profile)
Delivery over internet No Yes
Verified RCS business profile for "Go Big or Go Home!" showing a branded hippo logo, purple banner, company tagline, and contact options for call, website, and email in a mobile messaging app.

Figure 2: The final result – A verified brand profile featuring your high-resolution logo, banner image, and custom brand colors—elements that significantly increase trust and click-through rates compared to standard SMS.

The recommended adoption path

Consider a phased approach to RCS adoption that aligns with your operational readiness. First, register your brand and get carrier approval. Next, move your existing SMS use cases to RCS. Finally, after you are comfortable with the channel, test and expand with advanced use cases.

How to register

Brand asset requirements

Before submitting your registration, prepare the following brand assets. Carriers reject assets that don’t meet exact specifications, so verify these requirements before submitting.

Asset Requirements
Logo 224×224 pixels, PNG with transparency, under 50 KB
Banner 1440×448 pixels, PNG or JPEG, under 200 KB
Brand Color Hex format (e.g. #1A73E8), minimum 4.5:1 contrast ratio

Note: A 4.5:1 contrast ratio means your brand color must be at least 4.5 times brighter (or darker) than its background. This threshold meets WCAG 2.1 Level AA standards, ensuring your brand name is legible for users with moderate vision loss or color blindness. To verify compliance, use a Contrast Checker to test your hex code against a solid white background.

Use case selection

Your use case determines what types of messages you can send in production. Select carefully before submitting — the use case does not affect approval timeline, but it does determine your message restrictions and how carriers perceive your traffic.

Use Case What you can send
OTP Authentication codes and security verification only
Transactional Order updates, shipping notifications, account alerts
Promotional Marketing campaigns and offers (requires opt-in consent)
Multi-use Combined transactional and promotional messaging

Why not just choose Multi-use for everything?

While Multi-use offers the most flexibility, it is often subject to stricter carrier scrutiny during the vetting process. Carriers prefer single-purpose agents (like OTP) because they provide a more predictable and trustworthy experience for the recipient. If you have a high-volume OTP use case, registering it separately can help protect your sender reputation from being impacted by the lower engagement rates typically associated with promotional marketing.

Important: Agents must be use-case specific. Sending message types that don’t match your registered use case could result in suspension.

Registration steps

To submit your registration, complete the following steps:

  1. Sign in to the AWS Management Console and open the AWS End User Messaging console.
  2. In the navigation pane, under Configurations, choose RCS agents.
  3. Choose Create RCS Agent. This creates an AWS RCS Agent and then immediately guides you through creating a testing registration in a single workflow.
RCS tester invitation from RBM Tester Management showing interactive "Make me a tester" and "Decline" buttons, user selection, and confirmation message for the "Go Big or Go Home!" RCS agent in a dark-themed mobile messaging app.

Figure 3: Once your agent is created in the AWS console, your registered test devices will receive an invitation like this one. Tapping ‘Make me a tester’ allows you to immediately see your branded content in action.

  1. The next screen shows an introduction to RCS and explains the setup process. Review the information and choose Next to continue.
  2. On the Agent details page, set the following:
    1. Friendly name — A console-only label for your AWS RCS Agent. This is an internal name for your reference (stored as a tag) and is not the name displayed on recipients’ phones. The friendly name is not available through the API.
    2. Deletion protection — (Optional) Enable to prevent accidental deletion of the agent.
    3. Tags — (Optional) Add tags to organize and identify your agent.
  3. In the Brand information section of the same page, enter the following:
    1. Display name — The brand name that recipients see alongside your RCS messages.
    2. Description — A brief description of your brand or business.
    3. Use case — Select the primary use case for your RCS messaging (for example, transactional notifications, marketing, or customer support).
  4. In the Brand assets section of the same page, upload the following:
    1. Logo — 224 × 224 pixels, PNG with transparency, under 50 KB.
    2. Banner image — 1440 × 448 pixels, PNG or JPEG, under 200 KB.
    3. Brand color — A hex color code (for example, #1A73E8) with a minimum contrast ratio of 4.5:1 against a white background.

Important: Some brand assets cannot be changed after the agent is submitted for registration. Prepare your final brand assets before creating the agent. If you want to experiment first, you can quickly create a test agent using this flow, then create a fresh AWS RCS Agent with finalized brand assets later.

  1. On the Compliance keywords page, configure your keywords and auto-response messages.
  2. On the Review page, verify all your settings.
  3. Choose Validate and submit to create the AWS RCS Agent and submit the testing registration.

Testing and production launch phases

Launching RCS follows a distinct path from testing to production:

  1. Testing Registration: The initial guided console flow creates your AWS RCS Agent and a testing agent, or RBM Agent(RCS Business Messaging Agents). This allows you to validate your integration immediately by sending messages to registered test devices without waiting for carrier approval.
  2. Country Launch Registrations: After testing is complete, you must submit separate country launch registrations for each production market.

Carrier review and approval

  • Independent Approval: Each country launch registration undergoes a separate review process by every carrier in that target country.
  • Partial Reach: Approval is per-carrier. You are considered “partially approved” as soon as at least one carrier approves your agent, allowing you to start sending production messages to recipients on that carrier’s network via the SendTextMessage API.
  • Timelines: For both the U.S. and Canada, expect the carrier approval process to take several months. To avoid delays, verify that all registration fields are accurate and, for U.S. launches, provide a clear screen recording demonstrating your intended use case.

Important considerations

Multi-level identity: Think of the AWS RCS Agent as your brand’s unified identity. Under this one resource, you will have multiple RCS for Business IDs: one for your testing agent and separate IDs for each country launch (e.g., one for the US and one for Canada).

Carrier approval is per-carrier, not all-at-once: You do not need to wait for every carrier to approve before you begin sending. As soon as an individual carrier approves your agent, you can reach that carrier’s subscribers.

Sandbox testing: Testing with sandbox agents does not require carrier approval and can begin immediately upon submission. Note that testing messages are charged at standard RCS rates.

Finality of configurations: Brand assets are defined on each specific registration and are final after submission. While minor updates are permitted through supporting documentation, significant structural changes require creating a new agent. Plan your configuration carefully before you submit.

Accuracy matters: Filling out registration forms incorrectly can result in lengthy delays or rejection. Double-check all information before submitting and verify that business documents are current and valid. In this early phase of RCS adoption, carriers have been approving recognizable brands more readily.

Managing costs and usage

Monitor your RCS message volume through Amazon CloudWatch metrics and set up billing alerts to track spending against your SMS baseline. For more information, see AWS End User Messaging pricing.

Conclusion

In this post, we showed you how RCS on AWS End User Messaging solves customer engagement challenges through verified branding, interactive features, and automatic SMS fallback. You get a branded messaging experience with the reliability of SMS built in. Evaluate your current SMS message volume and identify high-priority transactional messages that would benefit from verified branding. Consider migrating these high-impact use cases first to establish your brand presence and improve customer trust.

Get started today

Ready to implement RCS? Here are your next steps:

  • If you’re ready to register: Contact your AWS account team or AWS Support to begin the registration process.
  • If you want to learn more: Review the AWS End User Messaging and RCS documentation.
  • If you’re still evaluating: Start by auditing your current SMS message volume and identifying high-priority transactional messages that would benefit from verified branding.

About the authors

Building a Scalable Messaging API with AWS End User Messaging and SES

Post Syndicated from Tyler Holmes original https://aws.amazon.com/blogs/messaging-and-targeting/building-a-scalable-messaging-api-with-aws-end-user-messaging-and-ses/

Modern applications often need to send notifications across multiple channels either through email and/or SMS. However, building a reliable messaging system that manages templates, handles failures gracefully, scales, and maintains security can be challenging. Following this guide, you’ll learn how to build a template manager and messaging API using API Gateway with JWT authentication for secure access, Amazon SQS for reliable message queuing, AWS Lambda for serverless processing, AWS End User Messaging for SMS, and Amazon Simple Email Service (SES) for email.

Architecture overview

You deploy a decoupled architecture that separates message ingestion from processing, providing resilience and scalability.

Fig. 1 Message Template Manager Architecture

Fig. 1 Message Template Manager Architecture

Architecture flow

  1. Client Application sends authenticated requests with JWT tokens
  2. API Gateway validates requests using a Lambda Authorizer
  3. Lambda Authorizer retrieves the JWT secret from AWS Secrets Manager and validates the token
  4. API Gateway sends validated messages to the SQS Queue
  5. Lambda Processor polls messages from SQS in batches
  6. Lambda Processor retrieves message templates from DynamoDB (if needed)
  7. Lambda Processor sends emails through Amazon SES and SMS through AWS End User Messaging
  8. Failed messages (after 3 retries) move to the Dead Letter Queue
  9. CloudWatch Alarm triggers when messages arrive in the DLQ

If a message fails processing after three attempts, it moves to a Dead Letter Queue (DLQ) where it’s preserved for 14 days, and a CloudWatch alarm notifies you of the failure.

Key features

With this architecture, you get several important capabilities:

  • JWT Authentication: Secure API access using JSON Web Tokens stored in AWS Secrets Manager
  • Automatic Retries: Failed messages retry up to three times before moving to the DLQ
  • Partial Batch Failures: Only failed messages retry, not the entire batch
  • Template Management: Store reusable message templates in Amazon DynamoDB
  • Multi-Channel Support: Send email through Amazon SES and SMS through AWS End User Messaging
  • Configuration Set Support: Track delivery metrics and route events with per-message or deployment-level configuration sets
  • Monitoring: CloudWatch alarms alert you when messages fail

Implementation details

1. API Gateway with JWT authorization

The API Gateway uses a Lambda authorizer to validate JWT tokens before allowing requests through:

def lambda_handler(event, context):
    token = event.get('authorizationToken', '').replace('Bearer ', '')
    try:
        # Retrieve secret from AWS Secrets Manager
        jwt_secret = get_jwt_secret()
        
        # Validate JWT token
        payload = jwt.decode(
            token,
            jwt_secret,
            algorithms=['HS256'],
            issuer='messaging-api'
        )
        
        # Generate IAM policy to allow request
        return generate_policy(payload.get('sub'), 'Allow', event['methodArn'])
    except jwt.ExpiredSignatureError:
        raise Exception('Unauthorized: Token expired')
    except jwt.InvalidTokenError:
        raise Exception('Unauthorized: Invalid token')

The JWT secret is stored securely in AWS Secrets Manager and cached in the Lambda execution environment for performance.

2. SQS queue configuration

The SAM template defines two queues with appropriate settings:

MessagesQueue:
  Type: AWS::SQS::Queue
  Properties:
    QueueName: MessagesQueue
    VisibilityTimeout: 300  # 5 minutes
    MessageRetentionPeriod: 345600  # 4 days
    RedrivePolicy:
      deadLetterTargetArn: !GetAtt MessagesDeadLetterQueue.Arn
      maxReceiveCount: 3

MessagesDeadLetterQueue:
  Type: AWS::SQS::Queue
  Properties:
    QueueName: MessagesDeadLetterQueue
    MessageRetentionPeriod: 1209600  # 14 days

The visibility timeout of 5 minutes prevents duplicate processing while giving the Lambda function enough time to complete. Messages that fail three times automatically move to the DLQ.

3. Lambda message processor

The Lambda function processes messages from SQS and sends them through the appropriate channel:

def lambda_handler(event, context):
    failed_messages = []
    
    for record in event['Records']:
        message_id = record['messageId']
        try:
            message = json.loads(record['body'])
            
            # Process email if configured
            if 'EmailMessage' in message:
                send_emails(message)
            
            # Process SMS if configured
            if 'SMSMessage' in message:
                send_sms_messages(message)
                
        except Exception as e:
            print(f"Error processing message {message_id}: {str(e)}")
            failed_messages.append({"itemIdentifier": message_id})
    
    # Return failed messages for automatic retry
    return {"batchItemFailures": failed_messages}

Configuration Sets for tracking and analytics:

Configuration Sets enable you to track delivery metrics, monitor costs, and route events to analytics pipelines. You can set defaults at deployment time and override them per-message:

  • Deployment-level defaults: Set SMSConfigurationSet parameter during deployment to apply to all messages
  • Per-message override: Include ConfigurationSetName in the SMSMessage payload to use different tracking for specific messages

This flexibility lets you separate analytics by message type, campaign, or priority without requiring redeployment.

4. Template management with DynamoDB

Message templates are stored in DynamoDB for reusability:

def get_email_template_from_dynamodb(template_name, substitutions):
    response = templates_table.get_item(Key={'TemplateName': template_name})
    
    if 'Item' not in response:
        return build_default_email(), "Account Alert"
    
    template_body = response['Item']['MessageBody']
    subject = response['Item'].get('Subject', 'Notification')
    
    # Replace {variable} placeholders with actual values
    rendered_body = replace_variables(template_body, substitutions)
    rendered_subject = replace_variables(subject, substitutions)
    
    return rendered_body, rendered_subject

You can update message content without redeploying code.

Template size considerations:

DynamoDB has a 400 KB limit per item, which includes all attribute names and values. For message templates, this means:

  • Typical email templates (5-20 KB) fit comfortably
  • SMS templates (< 1 KB) have no practical constraints

If you need to store templates larger than 400 KB, consider storing them in Amazon S3 and referencing the S3 object key in DynamoDB. This hybrid approach provides unlimited template size while maintaining fast lookups.

Prerequisites

Before deploying this solution, ensure you have the following:

  • AWS End User Messaging SMS configured with a phone pool or origination identity for SMS sending
  • Amazon SES configured with verified email identities (sender and recipient for sandbox mode)
  • IAM permissions to create Lambda functions, API Gateway, SQS queues, DynamoDB tables, and Secrets Manager secrets
  • Python 3.9 or later installed locally
  • AWS SAM CLI installed (version 1.0 or later)
  • AWS CLI installed and configured with your credentials
  • An active AWS account with appropriate permissions

Deployment

You use AWS SAM for infrastructure as code. Deploy with these commands:

sam build
sam deploy --guided

During deployment, you’ll set a JWT secret that’s stored in AWS Secrets Manager. Use a strong, random secret for production:

python -c "import secrets; print(secrets.token_urlsafe(32))"

Usage example

Once deployed, send messages by making authenticated API requests:

curl -X POST "https://your-api-endpoint/dev/" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{
    "TraceId": "12345",
    "EmailMessage": {
      "FromAddress": "[email protected]",
      "Subject": "Low Balance Alert",
      "ConfigurationSetName": "email-analytics",
      "Substitutions": {
        "productName": "CHEQUING",
        "membershipNumber": "****5493",
        "accountBalance": "100.00"
      }
    },
    "SMSMessage": {
      "MessageType": "TRANSACTIONAL",
      "OriginationNumber": "your-pool-id",
      "TemplateName": "alert-template",
      "ConfigurationSetName": "sms-analytics"
    },
    "Addresses": {
      "[email protected]": {
        "ChannelType": "EMAIL"
      },
      "+16048621234": {
        "ChannelType": "SMS",
        "Substitutions": {
          "productName": "CHEQUING",
          "membershipNumber": "****7303",
          "accountBalance": "100.00"
        }
      }
    }
  }'

Using Configuration Sets:

The example above shows optional ConfigurationSetName parameters for both email and SMS. These enable:

  • Delivery tracking: Monitor delivery rates, failures, and bounce metrics
  • Cost monitoring: Track spending per campaign or message type
  • Event routing: Send delivery events to CloudWatch, Kinesis, or SNS for analytics
  • Segmented metrics: Separate analytics by use case, priority, or customer segment

If you don’t specify a ConfigurationSetName in the request, the system uses the deployment-level default (if configured).

Monitoring and operations

CloudWatch alarms

The solution includes a CloudWatch alarm that triggers when messages arrive in the DLQ:

DLQAlarm:
  Type: AWS::CloudWatch::Alarm
  Properties:
    AlarmName: !Sub ${AWS::StackName}-DLQ-Messages
    MetricName: ApproximateNumberOfMessagesVisible
    Namespace: AWS/SQS
    Statistic: Sum
    Period: 300
    EvaluationPeriods: 1
    Threshold: 1
    ComparisonOperator: GreaterThanOrEqualToThreshold

Handling failed messages

When messages fail, you can inspect them in the DLQ and redrive them back to the main queue after fixing the issue:

# Check DLQ depth
aws sqs get-queue-attributes \
  --queue-url YOUR_DLQ_URL \
  --attribute-names ApproximateNumberOfMessages

# Redrive messages from DLQ to main queue
aws sqs start-message-move-task \
  --source-arn YOUR_DLQ_ARN \
  --destination-arn YOUR_MAIN_QUEUE_ARN

Viewing logs

Lambda automatically logs to CloudWatch Logs:

aws logs tail /aws/lambda/MessageProcessor --follow

Cost considerations

For 1 million messages per month estimated costs are:

Service Usage Cost
API Gateway 1M requests $3.50
Amazon SQS 1M messages $0.40
AWS Lambda 1M invocations (128MB, 1s avg) $2.50
Amazon SES 1M emails $100.00
AWS End User Messaging SMS 1M SMS $ Varies based on destination

Note: The serverless architecture means you only pay for what you use, with no minimum fees or upfront costs.

Security best practices

This solution follows several security best practices:

  1. JWT Authentication: All API requests require valid JWT tokens
  2. Secrets Manager: JWT secrets are stored encrypted in AWS Secrets Manager
  3. IAM Least Privilege: Each Lambda function has only the permissions it needs
  4. HTTPS Only: API Gateway enforces HTTPS for all requests
  5. Token Caching: Authorization decisions are cached for 5 minutes to reduce latency

Clean up

To avoid incurring ongoing charges, delete the resources created by this solution when you no longer need them:

  1. If you configured AWS End User Messaging phone pools or origination identities for this solution, remove them from the End User Messaging console
  2. If you created Amazon SES email identities specifically for this solution, remove them from the SES console
  3. Verify that all resources (Lambda functions, API Gateway, SQS queues, DynamoDB table, Secrets Manager secret) have been removed in the AWS Management Console
  4. Delete the CloudFormation stack by running: sam delete --stack-name <your-stack-name>

Conclusion

With this architecture, you can build a production-ready messaging API using AWS serverless services. The decoupled design gives you resilience through automatic retries and dead letter queues, while the serverless approach eliminates infrastructure management and scales automatically.

The complete solution is deployable through AWS SAM and includes:

  • JWT authentication with AWS Secrets Manager
  • Multi-channel messaging (email and SMS)
  • Template management with DynamoDB
  • Configuration Set support for tracking and analytics
  • Comprehensive monitoring and alerting
  • Automatic retry and failure handling

You can extend this architecture by adding more channels (push notifications, webhooks), implementing message scheduling, or integrating with Amazon EventBridge for event-driven workflows.

Additional resources

The complete source code for this solution is available in the accompanying GitHub repository, including SAM templates, Lambda functions, and deployment scripts.


About the authors

Adding a voice layer to WhatsApp conversations with AWS End User Messaging

Post Syndicated from Pavlos Ioannou Katidis original https://aws.amazon.com/blogs/messaging-and-targeting/adding-a-voice-layer-to-whatsapp-conversations-with-aws-end-user-messaging/

Businesses around the world use WhatsApp as a primary channel to connect with customers. It’s familiar, trusted, and effective for everything from booking confirmations to customer support. But most of these conversations are still text-only. For many customers, text is fast and efficient. Yet there are times when typing is inconvenient, slow, or less effective at conveying nuance. In those moments, voice messages can transform the interaction — making it faster, more inclusive, and more human.

With AWS End User Messaging, businesses can now enable both voice note input and voice note responses on WhatsApp. Customers send a voice note, and a bot can respond with a natural-sounding voice note reply. Note: This solution processes asynchronous voice notes (recorded audio messages), not real-time voice calls. In this blog post, we explore why voice notes matter, where they make a difference, and how AWS helps you enable them through a sample voice note messaging solution.

Watch an end to end demo here.

Why voice notes matter in customer messaging

Text remains essential, but research shows that voice notes adds unique advantages:

  • Richer communication: Voice carries tone, urgency, and emotion — reducing misunderstandings and helping businesses respond more appropriately (Preply survey).
  • Natural and fast: Speaking is up to three times faster than typing on mobile devices, especially when users are on the go (Sherry Ruan, Jacob O. Wobbrock, Kenny Liou, Andrew Ng, and James A. Landay. 2018. Comparing Speech and Keyboard Text Entry for Short Messages in Two Languages on Touchscreen Phones. Proc. ACM Interact. Mob. Wearable Ubiquitous Technol. 1, 4, Article 159 (December 2017), 23 pages. https://doi.org/10.1145/3161187).
  • Accessibility and inclusivity: Voice lowers barriers for people with limited literacy or visual impairments. Elderly customers or those with difficulty reading long text messages benefit significantly.
  • Context-driven preference: A YouGov study across 17 markets found that while text is still preferred overall, a notable share of users choose both text and audio depending on situation (YouGov survey).

Where voice notes make a difference

Voice messaging is especially useful when speaking feels more natural than typing—helping customers communicate in ways that fit their situation and needs.

  • Elderly customers – easier to listen than to read.
  • Field workers or drivers – easier to speak than to type while working.
  • Healthcare – patients can describe symptoms naturally by voice.
  • Hospitality and reservations – “Book a table for 7 pm” is faster to say than to navigate online calendar.
  • Customer support escalation – complex issues are often resolved more quickly with a voice exchange.

Voice notes don’t replace text. It complements it — giving customers the flexibility to communicate in the way that best suits their context.

AWS End User Messaging and WhatsApp

AWS End User Messaging is a managed AWS service that enables businesses to send and receive messages across multiple channels, including WhatsApp, SMS, MMS (US only), outbound voice, and push notifications.

When you use AWS End User Messaging for WhatsApp, you benefit from AWS’s global scale, resilience, and security. Inbound WhatsApp messages are automatically published to an Amazon SNS topic, enabling the integration with other AWS services such as Amazon SQS queues, AWS Lambda functions or Amazon Bedrock for downstream processing.

This flexibility is also what makes voice-to-voice messaging possible. Businesses can process inbound voice messages with Lambda, apply speech-to-text and text-to-speech services like Amazon Transcribe and Amazon Polly, or integrate third-party models such as Whisper through the AWS Marketplace for Amazon Bedrock.

Voice notes messaging solution

To demonstrate how voice can be enabled on WhatsApp, check out the AWS CDK sample project:  GitHub – WhatsApp Voice Notes Messaging

The solution shows how to:

  • Receive a WhatsApp voice note through AWS End User Messaging.
  • Transcribe the voice input to text.
  • Process it with conversational bot logic.
  • Convert the response back into a natural-sounding voice note.
  • Send the reply to the user on WhatsApp.

You can enable inbound only, outbound only, or a full voice-to-voice  notes loop depending on your requirements.

Getting started

The complete solution is available as an open-source AWS CDK project. To get started, you’ll need:

Implementation

Clone the repository and deploy the solution:

git clone https://github.com/aws-samples/sample-whatsapp-voice-to-voice-messaging
cd sample-whatsapp-voice-to-voice-messaging
npm install

Before deploying, you’ll need to configure your WhatsApp phone number ID in the CDK context or parameters. The deployment will prompt you for this configuration, or you can set it in the cdk.json file. Once configured, deploy with:

cdk deploy

The CDK stack automatically provisions all required AWS resources including Lambda functions, SNS topics, S3 buckets, and IAM roles.

Clean up

To remove all resources and avoid ongoing charges:

cdk destroy

For detailed architecture diagrams, configuration options, and step-by-step setup instructions, visit the GitHub repository.

Conclusion

Customers are already using voice notes in their personal WhatsApp conversations. Bringing that same option into business communication makes customer interactions more natural, inclusive, and efficient.

With AWS End User Messaging and its WhatsApp channel, you can add voice alongside text without changing how customers connect to you. And with the sample CDK project, you can try it out today, experiment, and extend it for your own business needs.

Explore the project here: AWS Sample – WhatsApp Voice Notes Messaging


About the authors

Build an AI-powered course recommender using Amazon Bedrock and AWS End User Messaging

Post Syndicated from Ruchikka Chaudhary original https://aws.amazon.com/blogs/messaging-and-targeting/build-an-ai-powered-course-recommender-using-amazon-bedrock-and-aws-end-user-messaging/

Educational technology (EdTech) providers face the challenge of maintaining seamless, personalized communication and presenting the right recommendations to their diverse stakeholders. This post explores how combining Amazon Web Services (AWS) End User Messaging and WhatsApp Business API with the advanced AI capabilities of Amazon Bedrock can transform educational engagement.

In this post, we explore use cases that are reshaping the EdTech industry. We discover how application automation can streamline admissions and enrollment processes, making them more efficient and user-friendly. We demonstrate how instant student engagement can be achieved through AI-powered, personalized interactions that keep learners motivated and connected. We showcase how real-time course feedback mechanisms can help educators adapt and improve their teaching methods. We also examine how student support can be automated using intelligent assistants that provide continuous, all-day assistance while maintaining a personal touch.

We show you how to build an AI-powered course recommendation system. We explain how to set up WhatsApp Business API integration with Amazon Bedrock, implement smart search capabilities for course matching, and create a scalable serverless architecture. You’ll learn how to build meaningful analytics dashboards to track engagement and learn best practices for handling errors and maintaining system reliability. Whether you’re an EdTech professional or a cloud architect, this guide gives you practical insights into combining conversational AI with educational services.

Use cases

  • An AI-powered personalized learning pathway generator that automatically recommends customized content based on individual student performance metrics and learning requirements
  • Course improvement suggestions and real-time course feedback
  • A smart communication orchestrator that delivers role-specific, automated notifications and updates across multiple channels to enhance student and parent engagement
  • An early warning system using predictive analytics to identify at-risk students through real-time monitoring of engagement metrics and performance indicators
  • Student support automation with always available AI assistant support, FAQ handling, escalation management, and multilingual support

Prerequisites

  • An AWS account
  • AWS End User Messaging set up with WhatsApp channel enabled
  • A pre-existing WhatsApp Business account
  • Amazon Bedrock setup must be completed with preferred model
  • Amazon Quick Sight for the AWS Region must be enabled

Solution overview

With this solution, users can discover and order educational courses through WhatsApp conversations. Instead of navigating complex websites, the user can send a WhatsApp message saying, “I want to learn Python programming.” They’ll receive personalized course recommendations instantly. The architecture processes WhatsApp messages through AWS End User Messaging, uses Amazon Bedrock for AI-powered conversations, performs semantic search with Amazon OpenSearch Serverless, and captures analytics for business insights. (For step-by-step implementation and rollback guidelines, see the sample course recommendation system.) The following architectural diagram illustrates a modern AI-powered course recommendation system that uses multiple AWS services.

Figure 1: AI-powered course recommendation system

Message processing

When users send WhatsApp messages, AWS End User Messaging captures them and publishes events to an Amazon Simple Notification Service (Amazon SNS) topic. This creates a decoupled architecture where multiple services can process the same message events independently. AWS Lambda functions subscribe to these events, facilitating reliable message processing during high-traffic periods. The decoupled design provides several advantages:

  • If one component fails, others continue operating
  • You can add new message processors without affecting existing ones
  • The system automatically scales based on message volume without manual intervention

AI conversation engine

Amazon Bedrock with Claude 3 Haiku powers natural language understanding. It is configured specifically for WhatsApp with instructions for short paragraphs, relevant emoji, and mobile-optimized responses.

AI agents

The agent maintains conversation context and handles structured actions such as course search, detail retrieval, and booking through defined functions. The following workflow is the agent action flow and sample code:

Agent flow

  1. Greets user → Understands intent → Searches courses → Provides details → Facilitates booking
  2. Maintains context throughout the conversation
  3. Can switch between actions based on user responses
  4. Handles complex queries by combining multiple actions

Sample code

The following is sample code to create a Bedrock agent using AWS CDK:

    agent = bedrock.CfnAgent(foundation_model="anthropic.claude-3-haiku-20240307-v1:0",
     instruction="""
     Format for WhatsApp: short paragraphs,
        focus on technical courses only
       """,
      action_groups=[# Functions for search, details, booking]
)

Semantic search

Traditional keyword search can miss the user’s intent. The application uses Amazon Titan Embeddings in Amazon Bedrock to convert courses and queries into vectors, enabling semantic understanding. When users ask for “cloud computing courses,” the system can understand related terms such as “AWS” and “serverless” without exact matches. Amazon OpenSearch Serverless handles vector similarity matching combined with traditional filters for course price, level, and duration.

Analytics pipeline

Every WhatsApp message interaction generates business intelligence. Messages are stored in Amazon Simple Storage Service (Amazon S3) with date partitioning, catalogued through AWS Glue, and made queryable using Amazon Athena. Teams can analyze user behavior, popular topics, and conversion rates through Quick Sight dashboards. The following dashboard shows example widgets displaying pie-chart breakdown of message delivery status and count of messages per day.

Figure 2: Amazon Quick Sight dashboard

As shown in the following dashboard, Amazon Q in QuickSight enables you to explore and analyze your data using conversational AI capabilities.

Figure 3: Amazon Quick Sight dashboard showing chat window

Error handling and resilience

Such highly scalable and distributed solutions require robust error handling. The application has exponential backoff and retries for API calls, meaning the system can gracefully handle rate limits and temporary service unavailability.

The following is sample code for error handling and resilience:

python
def retry_with_backoff(func, max_retries=5):
retries = 0
backoff = 1
while retries < max_retries:
try:
return func()
except ThrottlingException:
sleep_time = backoff + random.uniform(0, 1)
time.sleep(sleep_time)
backoff = min(backoff * 2, 32)
retries += 1
raise Exception("Max retries exceeded")

Business impact

With the global EdTech market expected to reach $165 billion by 2026, educators and institutions are seeking solutions to prevent student dropouts, improve learning outcomes, and maintain their competitive advantage. Poor personalization can lead to decreased student engagement, lower course completion rates, and ultimately revenue loss.

Implementing AI-driven personalization and communication systems means institutions can significantly improve student retention rates, boost learning outcomes, and create a more engaging educational experience, which directly impacts their bottom line and reputation in an increasingly competitive educational landscape. This solution could transform educational delivery through intelligent personalization and operational excellence. A serverless architecture can help educational institutions focus on content quality rather than infrastructure management while potentially maintaining rapid response times for course searches. The system’s analytics capabilities could offer insights into student behavior and course preferences, helping shape future curriculum development.

With mobile optimization, institutions can better serve the growing population of digital-first learners. The combination of automated scaling and pay-per-use pricing could create opportunities for cost optimization, and real-time dashboards can be used to facilitate data-informed decision-making. Such improvements in user experience and operational efficiency could lead to enhanced student engagement and institutional growth in the evolving education environment.

Sample conversation

The following video shows how a user can interact with the generative AI-powered course recommendation system and receive course recommendations.

Future enhancements

We’re expanding to more messaging platforms, adding voice integration through Amazon Connect, and implementing predictive analytics for personalized recommendations. The serverless architecture makes these additions straightforward without infrastructure changes. Future scenarios could involve:

  • Educator and student support – This solution can be enhanced for student and educator experiences. For educators, it can automate administrative tasks. For students, it can create personalized engagement campaigns, a communication approach that could be significantly more effective than traditional methods.
  • Digital admission process flow – The solution integrates AWS Bedrock AI with WhatsApp Business API to streamline digital admissions. It can enable instant document verification, guide secure payments, and provide automated updates, all within the AWS End User Messaging WhatsApp channel. This AI-powered system could transform the complex admission process into an efficient, chat-based experience, benefiting both institutions and applicants.
  • Parental support and study material management – The system could intelligently distribute learning resources based on student needs, send automated schedule updates, and provide personalized progress reports to parents through WhatsApp. Parents could receive AI-curated study materials and real-time updates about their child’s academic performance, homework assignments, and upcoming assessments through familiar chat interactions. This integration could transform traditional parent-teacher communication into an efficient, automated system while providing timely access to relevant educational resources.

Conclusion

The WhatsApp course recommender agent demonstrates how modern AWS services can create sophisticated, AI-powered conversational experiences that scale automatically and provide rich business insights. The serverless architecture provides cost-effectiveness while maintaining enterprise-grade reliability. Key architectural principles that make this solution successful include event-driven design for scalability, AI integration for natural interactions, semantic search for superior user experience, customizable analytics for business intelligence, and infrastructure as code (IaC) for reliable deployments.

For organizations considering similar implementations, we recommend focusing on user experience optimization, robust error handling, comprehensive monitoring, and gradual feature rollout. The conversational AI environment is rapidly evolving, and solutions that prioritize user experience while maintaining technical excellence can drive the most business value. This implementation can serve as a reference architecture for building production-ready conversational AI systems on AWS, demonstrating patterns that can apply across industries and use cases.


About the authors

Threat Actors Using AWS WorkMail in Phishing Campaigns

Post Syndicated from Jan Blažek original https://www.rapid7.com/blog/post/dr-threat-actors-aws-workmail-phishing-campaigns

Introduction

At Rapid7, we track a wide range of threats targeting cloud environments, where a frequent objective is hijacking victim infrastructure to host phishing or spam campaigns. Beyond the obvious security risks, this approach allows threat actors to offload their operational costs onto the target company, often resulting in significant, unwanted bills for services the victim never intended to use.

Rapid7 recently investigated a cloud abuse incident in which threat actors leveraged compromised AWS credentials to deploy phishing and spam infrastructure using AWS WorkMail, bypassing the anti-abuse controls normally enforced by AWS Simple Email Service (SES). AWS SES is a general-purpose, API-driven email platform intended for application-generated email such as transactional notifications and marketing messages. This allows the threat actor to leverage Amazon’s high sender reputation to masquerade as a valid business entity, with the ability to send email directly from victim-owned AWS infrastructure. Generating minimal service-attributed telemetry also makes threat actor activity difficult to distinguish from routine activity. Any organization with exposed AWS credentials and permissive Identity and Access Management (IAM) policies are potentially at risk, particularly those without guardrails or monitoring around WorkMail and SES configuration.

In this post, we analyzed a real-world incident observed by our MDR team in which threat actors abused native AWS email services to build phishing and spam infrastructure inside a compromised cloud environment. We will reconstruct the attacker’s progression from credential validation and IAM reconnaissance to bypassing Amazon SES safeguards by pivoting to AWS WorkMail. Along the way, we highlight how legitimate service abstractions can be leveraged to evade detection, examine the resulting logging and attribution gaps, and outline practical detection and prevention strategies defenders can use to identify and disrupt similar cloud-native abuse.

Background: AWS WorkMail and its key components

AWS WorkMail is a fully managed business email and calendaring service that allows organizations to operate corporate mailboxes without deploying or maintaining their own mail servers. It supports standard email protocols such as IMAP and SMTP, as well as common desktop and mobile clients, making it a lightweight, pay-as-you-go alternative for teams already operating within AWS.

To understand the activities performed by threat actors in the incident, it’s important to first introduce several core concepts within AWS WorkMail.

Organization

An Organization is the top-level container in WorkMail. It represents an isolated email environment that holds all users, groups, and domains. Each WorkMail organization is region-specific and operates independently, which allows attackers to create disposable, self-contained email infrastructures with minimal setup.

Users

Users represent individual mail-enabled identities within a WorkMail organization. After a user is created using the “workmail:CreateUser” API call, a mailbox can be assigned via a “workmail:RegisterToWorkMail”API call. Once registered, the user can authenticate to the AWS WorkMail web client or connect via standard email protocols and immediately begin sending and receiving email.

Groups

Groups are collections of users that can receive email on behalf of multiple members. They are typically used for distribution lists or shared inboxes and can simplify bulk message delivery or internal coordination within a WorkMail organization.

Domains

Domains define the email address namespace used by a WorkMail organization ([email protected]). Before a domain can be used, ownership must be verified. This verification process leverages the standard domain verification mechanism of Amazon Simple Email Service, typically via DNS records. Once verified, the domain can be actively used for sending and receiving email, enabling threat actors to operate from attacker-controlled, but seemingly legitimate, domains.

Attack analysis

The diagram below contains a graphical representation of the key events carried out by the attackers throughout the attack, starting with initial access actions, continuing through privilege escalation, and ending with the achievement of objectives.

Graphical-visualization-of-AWS-workmail-phishing-attack.png
Figure 1: Graphical visualization of the attack

Initial access

The compromise began with the exposure of long-term AWS access keys. The first indication of malicious activity was an “sts:GetCallerIdentity” API call with the User-Agent set to TruffleHog Firefox. This strongly suggests the use of TruffleHog, a tool commonly leveraged by adversaries to discover and validate leaked credentials from sources such as GitHub, GitLab, and public S3 buckets. Rapid7 has frequently observed TruffleHog usage in active campaigns, including activity attributed to groups such as the Crimson Collective.

Several days after this initial credential validation, we observed suspicious activity involving a second IAM user authenticated via long-term access keys. While we cannot conclusively prove that both users were accessed by the same operator, multiple factors suggest they were part of the same intrusion activity. Notably, both authentications originated from the same geographic region, which was anomalous for the victim’s normal operating patterns. Throughout the incident window, access to both accounts was conducted through a rotating set of IP addresses associated primarily with cloud service providers such as Amazon and DigitalOcean. This infrastructure choice is consistent with common adversary tradecraft used to obfuscate true origin and blend into legitimate cloud-to-cloud traffic.

TruffleHog-output-discovered-credentials-for-Google-Cloud-Platform.png
Figure 2: Example TruffleHog output showing discovered credentials for Google Cloud Platform (GCP)

Discovery phase and privilege escalation

Following initial access, the first compromised user was used to perform basic environment discovery via native AWS APIs. These attempts repeatedly resulted in AccessDenied errors, indicating that the exposed credentials were constrained by limited permissions. The activity was conducted using the AWS command-line interface (CLI), suggesting hands-on, interactive exploration by the threat actor rather than automated tooling.

After encountering these limitations, the adversary shifted activity to the second set of compromised credentials, which possessed significantly broader permissions. With this user, enumeration became more deliberate and structured. The actor began with iam:ListUsers API calls to understand the identity landscape and then used a technique of intentionally triggering API errors to confirm specific permissions without making persistent changes.

As part of this broader discovery effort, the actor also queried Amazon SES to assess its current configuration and readiness for abuse. Specifically, they executed ses:GetAccount and ses:ListIdentities. These calls allowed the adversary to quickly map the operational status of SES within the account. The ses:ListIdentities API call was used to determine whether any verified identities (domains or email addresses) already existed that could be immediately leveraged for sending mail; none were present at the time. In parallel, ses:GetAccount was used to identify whether the account was operating in the SES sandbox, which would impose strict sending limits and require additional steps before large-scale email campaigns could be launched.

This SES-focused reconnaissance indicates early intent to abuse email-sending capabilities and demonstrates how attackers can efficiently evaluate service readiness using only a small number of low-noise management API calls.

For example, the actor attempted to create an IAM user that already existed. The resulting error response confirmed possession of iam:CreateUser permissions without successfully creating a new entity:

{
"userAgent": "aws-cli/1.22.34 Python/3.10.12 Linux/5.15.0-113-generic botocore/1.23.34",
"errorCode": "EntityAlreadyExistsException",
"errorMessage": "User with name xxxx already exists."
}

Listing 1: Part of the iam:CreateUser CloudTrail log

A similar validation was performed using iam:CreateLoginProfile. By supplying a password that violated the account’s password policy, the actor received a PasswordPolicyViolationException, confirming their ability to create console login profiles:

{
"userAgent": "aws-cli/1.22.34 Python/3.10.12 Linux/5.15.0-113-generic botocore/1.23.34",
"errorCode": "PasswordPolicyViolationException",
"errorMessage": "Password should have at least one uppercase letter"
}

Listing 2: Part of the iam:CreateLoginProfile CloudTrail log

After validating the scope of their privileges, the adversary created a new IAM user, attached the AWS managed policy “AdministratorAccess”, and established a login profile to enable AWS Management Console access. This marked a transition from CLI-based reconnaissance to full GUI-based control, providing unrestricted access and setting the stage for subsequent operational activity.

Action on objectives: Preparing email infrastructure for abuse

By the end of the discovery phase, the threat actor had established two critical facts:

  1. No verified identities existed in Amazon Simple Email Service (SES).

  2. The account remained restricted by the SES sandbox.

The SES sandbox is explicitly designed to limit fraud and abuse, and its restrictions effectively prevent meaningful phishing or spam campaigns. While an account remains in the sandbox, the following controls apply:

  • Emails can only be sent to verified identities (email addresses or domains) or the SES mailbox simulator.

  • A maximum of 200 messages per 24-hour period.

  • A maximum sending rate of 1 message per second.

These constraints made SES unsuitable for immediate abuse at scale. Rather than abandoning the service, the attacker initiated a process to legitimize higher-volume email sending.

First, they opened a support case with AWS requesting removal from the SES sandbox. In parallel, they requested a substantial increase to the daily sending quota— setting it to 100,000 emails per day —using the servicequotas:RequestServiceQuotaIncrease API call.

{
    "requestParameters": {
"serviceCode": "ses",
"quotaCode": "L-XXXXXX",
"desiredValue": 100000
	
}

Listing 3: Request parameters from RequestServiceQuotaIncrease API call

During this waiting period, the actor focused on persistence and stealth. Multiple IAM users were created.. These usernames were deliberately chosen to resemble region- or service-scoped automation accounts rather than human operators. To further reduce suspicion during IAM audits, the attacker attached narrowly scoped, SES-only policies to these users instead of broad administrative permissions. This approach allowed them to preserve operational access while minimizing obvious indicators of compromise such as over-privileged identities.

At this stage, the attacker had effectively prepared the account for large-scale email abuse-but they did not wait for AWS approval to proceed.

Bypassing SES controls by abusing AWS WorkMail

Rather than remaining idle while SES sandbox removal and quota increases were pending, the attacker pivoted to AWS WorkMail, which offers an alternative email-sending pathway with significantly fewer upfront restrictions.

Using the workmail:CreateOrganization API, the threat actor created multiple WorkMail organizations. They then initiated domain verification workflows for domains designed to appear legitimate and business-like, including:

  • cloth-prelove[.]me

  • ipad-service-london[.]com

Domain verification was performed through ses:VerifyDomainIdentity and ses:VerifyDomainDkim, with the calls originating from workmail.amazonaws.com. This highlights an important nuance for defenders: although SES APIs are involved, the activity is driven by WorkMail provisioning rather than traditional SES email campaigns.

Once domain verification was completed, the actor created multiple mailbox users directly within WorkMail, such as:

  • service@ipad-service-london[.]com

  • marketing@ipad-service-london[.]com

These accounts served two purposes. First, they established persistence at the application layer, independent of IAM. Second, they provided credible sender identities for phishing and spam operations, closely resembling legitimate corporate email addresses.

There were also AWS directory service events logged by CloudTrail that show new aliases created for the new sender domains, using the victim’s directory tenant:

CreateAlias

AuthorizeAppication

This pivot is particularly impactful because AWS WorkMail does not implement a sandbox model comparable to SES. Emails can be sent immediately to external, unverified recipients. Additionally, WorkMail supports significantly higher sending volumes than SES sandbox limits. While Rapid7 has not empirically validated the maximum throughput, AWS documentation cites a default upper limit of 100,000 external recipients per day per organization, aggregated across all users.

Email sending methods and logging gaps

The attacker had two viable options for sending email through WorkMail:

1. Web interface
Emails sent through the AWS WorkMail web client may surface indirectly in CloudTrail as “ses:SendRawEmail” events. These events are generated because WorkMail uses Amazon Simple Email Service (SES) as its underlying mail transport, even though the messages are composed and sent entirely through the WorkMail application.

While these events are not attributed to an IAM principal, they do expose several pieces of valuable metadata within the “requestParameters” field — most notably the sender’s email address and associated SES identity. This allows defenders to link outbound email activity to specific WorkMail users and recently verified domains, even in the absence of traditional application or message-level logs.

One notable limitation of these “ses:SendRawEmail” events is the absence of a true client source IP address. Because emails sent via the WorkMail web interface are executed by an AWS-managed service on behalf of the mailbox user, CloudTrail records the “sourceIPAddress” as “workmail.<region>.amazonaws.com” rather than the originating IP address of the actor’s browser session. This effectively obscures the attacker’s true network origin and prevents defenders from correlating email-sending activity with suspicious IP ranges, TOR exit nodes, or previously observed intrusion infrastructure.

{
"eventVersion": "1.11",
"userIdentity": {
"type": "AWSService",
"invokedBy": "workmail.us-east-1.amazonaws.com"
    },
"eventTime": "2025-12-20T11:26:59Z",
"eventSource": "ses.amazonaws.com",
"eventName": "SendRawEmail",
"awsRegion": "us-east-1",
"sourceIPAddress": "workmail.us-east-1.amazonaws.com",
"userAgent": "workmail.us-east-1.amazonaws.com",
"requestParameters": {
"sourceArn": "arn:aws:ses:us-east-1:123456789012:identity/malicious-organiation[.]com",
"destinations": [
"HIDDEN_DUE_TO_SECURITY_REASONS"
        ],
"source": "=?UTF-8?Q?Malicious_User?= <marketing@malicious-organiation[.]com>",
"fromArn": "arn:aws:ses:us-east-1:123456789012:identity/malicious-organiation[.]com",
"configurationSetName": "gcp-iad-prod-workmail-default-configuration-set",
"rawMessage": {
"data": "HIDDEN_DUE_TO_SECURITY_REASONS"
        }
    },
"responseElements": null,
"additionalEventData": {
"SignatureVersion": "4",
"sesMessageId": "0100019b3c4a8bb7-50af951c-fbd4-4610-bc94-c7fc35733699-000000"
    },
"requestID": "aff61405-04bd-4969-802a-7ce4d5946949",
"eventID": "c34ed12d-5bec-3fdd-aef9-57ae4313ca88",
"readOnly": true,
"resources": [
        {
"accountId": "123456789012",
"type": "AWS::SES::ConfigurationSet",
"ARN": "arn:aws:ses:us-east-1:123456789012:configuration-set/gcp-iad-prod-workmail-default-configuration-set"
        },
        {
"accountId": "123456789012",
"type": "AWS::SES::EmailIdentity",
"ARN": "arn:aws:ses:us-east-1:123456789012:identity/malicious-organiation[.]com"
        }
    ],
"eventType": "AwsApiCall",
"managementEvent": false,
"recipientAccountId": "123456789012",
"sharedEventID": "xxx",
"eventCategory": "xxx"}

Listing 4: SendRawEmail event logged after an email is sent via AWS WorkMail web interface

While limited, this telemetry can still be valuable for correlating suspicious sending behavior with recently created WorkMail users or newly verified domains.

2. SMTP access
Alternatively, the attacker can authenticate directly to WorkMail’s SMTP endpoint and send messages programmatically. Emails sent via SMTP do not generate CloudTrail events, even when SES data events are enabled, creating a significant blind spot for defenders.

An example Python script used to send email through WorkMail SMTP is shown below:

import smtplib
from email.message import EmailMessage

# Configuration
SMTP_SERVER = "smtp.mail.us-east-1.awsapps.com"
SMTP_PORT = 465
EMAIL_ADDRESS = "[email protected]"
EMAIL_PASSWORD = "****"

# Create the message
msg = EmailMessage()
msg["Subject"] = "WorkMail SMTP"
msg["From"] = EMAIL_ADDRESS
msg["To"] = "<unverified_email>"
msg.set_content("Email Delivered to an Unverified Email via AWS WorkMail")

# Send the email
try:
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as smtp:
smtp.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
smtp.send_message(msg)
print("Email sent successfully!")
except Exception as e:
print(f"Error: {e}")

Listing 5: Example script sending messages via AWS WorkMail via SMTP

From an attacker’s perspective, this method is ideal: higher volume, immediate external reach, and minimal centralized logging. From a defender’s perspective, it underscores the importance of monitoring WorkMail organization creation, domain verification events, and mailbox provisioning, as these actions often precede phishing activity that will never be visible in CloudTrail.

Conclusion

This incident illustrates how threat actors can abuse higher-level AWS services to deploy phishing and spam infrastructure closely resembling legitimate enterprise usage. While AWS WorkMail is not designed to support bulk email operations, attackers can still leverage it as an interim capability alongside Amazon SES. By abusing WorkMail’s authenticated mailboxes and relaxed upfront controls, adversaries can begin sending lower volumes of email immediately — well before SES is moved out of the sandbox and higher sending quotas are approved. This staged approach allows attackers to establish sender reputation, validate infrastructure, and maintain operational momentum while bypassing many of the friction points intentionally built into SES.

To mitigate this class of abuse, organizations should combine preventive guardrails with focused detection. Where AWS WorkMail is not required, its use should be explicitly blocked using AWS Organizations Service Control Policies (SCPs) to prevent organization creation and mailbox provisioning. In environments where WorkMail is needed, IAM policies should enforce strict least-privilege access and treat WorkMail and SES administration as privileged operations subject to monitoring and approval. Finally, organizations should reduce the likelihood of initial access by implementing secure development and operational practices — such as secret scanning in code repositories, regular key rotation, and minimizing long-term access keys — to limit the impact of credential leakage and prevent attackers from converting compromised credentials into scalable email abuse.

MITRE ATT&CK techniques

Tactic

Technique

Details

Initial Access

Valid Accounts: Cloud Accounts (T1078.004)

The attacker authenticated to AWS using exposed long-term access keys validated with sts:GetCallerIdentity

Persistence

Create Account: Cloud Account (T1136.003)

The attacker created multiple IAM users and AWS WorkMail mailbox users to maintain persistent access

Privilege Escalation

Account Manipulation: Additional Cloud Roles (T1098.003)

The attacker attached the AdministratorAccess managed policy to a newly created IAM user

Discovery

Cloud Infrastructure Discovery (T1580)

The attacker enumerated IAM users and assessed Amazon SES configuration and sandbox status via API calls

Impact

Resource Hijacking: Cloud Service Hijacking (T1496.004)

The attacker abused AWS WorkMail and SES to send high-volume phishing and spam emails from the victim account

Indicators of compromise (IOCs)

139.59.117[.]125

3.0.205[.]202

54.151.176[.]0

Note: IP addresses 3.0.205[.]202 and 54.151.176[.]0 are Amazon owned IP addresses so care should be taken when applying IP blocks.

Rapid7 customers

InsightIDR and Managed Detection and Response (MDR) customers have existing detection coverage through Rapid7’s expansive library of detection rules. These detections are deployed and will alert on the behaviors described in this technical analysis.

Cable cuts, storms, and DNS: a look at Internet disruptions in Q4 2025

Post Syndicated from David Belson original https://blog.cloudflare.com/q4-2025-internet-disruption-summary/

In 2025, we observed over 180 Internet disruptions spurred by a variety of causes – some were brief and partial, while others were complete outages lasting for days. In the fourth quarter, we tracked only a single government-directed Internet shutdown, but multiple cable cuts wreaked havoc on connectivity in several countries. Power outages and extreme weather disrupted Internet services in multiple places, and the ongoing conflict in Ukraine impacted connectivity there as well. As always, a number of the disruptions we observed were due to technical problems – with some acknowledged by the relevant providers, while others had unknown causes. In addition, incidents at several hyperscaler cloud platforms and Cloudflare impacted the availability of websites and applications. 

This post is intended as a summary overview of observed and confirmed disruptions and is not an exhaustive or complete list of issues that have occurred during the quarter. These anomalies are detected through significant deviations from expected traffic patterns observed across our network. Check out the Cloudflare Radar Outage Center for a full list of verified anomalies and confirmed outages. 

Government-directed

Tanzania

The Internet was shut down in Tanzania on October 29 as violent protests took place during the country’s presidential election. Traffic initially fell around 12:30 local time (09:30 UTC), dropping more than 90% lower than the previous week. The disruption lasted approximately 26 hours, with traffic beginning to return around 14:30 local time (11:30 UTC) on October 30. However, that restoration proved to be quite brief, with a significant decrease in traffic occurring around 16:15 local time (13:15 UTC), approximately two hours after it returned. This second near-complete outage lasted until November 3, when traffic aggressively returned after 17:00 local time (14:00 UTC). Nominal drops in announced IPv4 and IPv6 address space were also observed during the shutdown, but there was never a complete loss of announcements, which would have signified a total disconnection of the country from the Internet. (Autonomous systems announce IP address space to other Internet providers, letting them know what blocks of IP addresses they are responsible for.)

Tanzania’s president later expressed sympathy for the members of the diplomatic community and foreigners residing in the country regarding the impact of the Internet shutdown. Internet and social media services were also restricted in 2020 ahead of the country’s general elections.

Cable cuts

Digicel Haiti

Digicel Haiti is unfortunately no stranger to Internet disruptions caused by cable cuts, and the network experienced two more such incidents during the fourth quarter. On October 16, traffic from Digicel Haiti (AS27653) began to fall at 14:30 local time (18:30 UTC), reaching near zero at 16:00 local time (20:00 UTC). A translated X post from the company’s Director General noted: “We advise our clientele that @DigicelHT is experiencing 2 cuts on its international fiber optic infrastructure.” Traffic began to recover after 17:00 local time (21:00 UTC), and reached expected levels within the following hour. At 17:33 local time (21:34 UTC), the Director General posted that “the first fiber on the international infrastructure has been repaired” and service had been restored. 

On November 25, another translated X post from the provider’s Director General stated that its “international optical fiber infrastructure on National Road 1” had been cut. We observed traffic dropping on Digicel’s network approximately an hour earlier, with a complete outage observed between 02:00 – 08:00 local time (07:00 – 13:00 UTC). A follow-on X post at 08:22 local time (13:22 UTC) stated that all services had been restored.

Cybernet/StormFiber (Pakistan)

At 17:30 local time (12:30 UTC) on October 20, Internet traffic for Cybernet/StormFiber (AS9541) dropped sharply, falling to a level approximately 50% the same time a week prior. At the same time, the network’s announced IPv4 address space dropped by over a third. The cause of these shifts was damage to the PEACE submarine cable, which suffered a cut in the Red Sea near Sudan. 

PEACE is one of several submarine cable systems (including IMEWE and SEA-ME-WE-4) that carry international Internet traffic for Pakistani providers. The provider pledged to fully restore service by October 27, but traffic and announced IPv4 address space had recovered to near expected levels by around 02:00 local time on October 21 (21:00 UTC on October 20).

Camtel, MTN Cameroon, Orange Cameroun

Unusual traffic patterns observed across multiple Internet providers in Cameroon on October 23 were reportedly caused by problems on the WACS (West Africa Cable System) submarine cable, which connects countries along the west coast of Africa to Portugal. 

A (translated) published report stated that MTN informed subscribers that “following an incident on the WACS fiber optic cable, Internet service is temporarily disrupted” and Orange Cameroun informed subscribers that “due to an incident on the international access fiber, Internet service is disrupted.” An X post from Camtel stated “Cameroon Telecommunications (CAMTEL) wishes to inform the public that a technical incident involving WACS cable equipment in Batoke (LIMBE) occurred in the early hours of 23 October 2025, causing Internet connectivity disruptions throughout the country.” 

Traffic across the impacted providers originally fell just at around  05:00 local time (04:00 UTC) before recovering to expected levels around 22:00 local time (21:00 UTC). Traffic across these networks was quite volatile during the day, dropping 90-99% at times. It isn’t clear what caused the visible spikiness in the traffic pattern—possibly attempts to shift Internet traffic to other submarine cable systems that connect to Cameroon. Announced IP address space from MTN Cameroon and Orange Cameroon dropped during this period as well, although Camtel’s announced IP address space did not change.

Connectivity in the Central African Republic and Republic of Congo was also reportedly impacted by the WACS issues.

Claro Dominicana

On December 9, we saw traffic from Claro Dominicana (AS6400), an Internet provider in the Dominican Republic, drop sharply around 12:15 local time (16:15 UTC). Traffic levels fell again around 14:15 local time (18:15 UTC), bottoming out 77% lower than the previous week before quickly returning to expected levels. The connectivity disruption was likely caused by two fiber optic outages, as an X post from the provider during the outage noted that they were “causing intermittency and slowness in some services.” A subsequent post on X from Claro stated that technicians had restored Internet services nationwide by repairing the severed fiber optic cables.

Power outages

Dominican Republic

According to a (translated) X post from the Empresa de Transmisión Eléctrica Dominicana (ETED), a transmission line outage caused an interruption in electrical service in the Dominican Republic on November 11. This power outage impacted Internet traffic from the country, resulting in a nearly 50% drop in traffic compared to the prior week, starting at 13:15 local time (17:15 UTC). Traffic levels remained lower until approximately 02:00 local time (06:00 UTC) on December 12, with a later (translated) X post from ETED noting “At 2:20 a.m. we have completed the recovery of the national electrical system, supplying 96% of the demand…

A subsequent technical report found that “the blackout began at the 138 kV San Pedro de Macorís I substation, where a live line was manually disconnected, triggering a high-intensity short circuit. Protection systems responded immediately, but the fault caused several nearby lines to disconnect, separating 575 MW of generation in the eastern region from the rest of the grid. The imbalance caused major power plants to trip automatically as part of their built-in safety mechanisms.

Kenya

On December 9, a major power outage impacted multiple regions across Kenya. Kenya Power explained that the outage “was triggered by an incident on the regional Kenya-Uganda interconnected power network, which caused a disturbance on the Kenyan side of the system” and claimed that “[p]ower was restored to most of the affected areas within approximately 30 minutes.” However, impacts to Internet connectivity lasted for nearly four hours, between 19:15 – 23:00 local time (16:15 – 20:00 UTC). The power outage caused traffic to drop as much as 18% at a national level, with the traffic shifts most visible in Nakuru County and Kaimbu County.

Military action

Odesa, Ukraine

Russian drone strikes on the Odesa region in Ukraine on December 12 damaged warehouses and energy infrastructure, with the latter causing power outages in parts of the region. Those outages disrupted Internet connectivity, resulting in traffic dropping by as much as 57% as compared to the prior week. After the initial drop at midnight on December 13 (22:00 UTC on December 12), traffic gradually recovered over the following several days, returning to expected levels around 14:30 local time (12:30 UTC) on December 16.

Weather

Jamaica

Hurricane Melissa made landfall on Jamaica on October 28 and left a trail of damage and destruction in its path. Associated power outages and infrastructure damage impacted Internet connectivity, causing traffic to initially drop by approximately half, starting around 06:15 local time (11:15 UTC), ultimately reaching as much as 70% lower than the previous week. Internet traffic from Jamaica remained well below pre-hurricane levels for several days, and ultimately started to make greater progress towards expected levels during the morning of November 4. It can often take weeks or months for Internet traffic from a country to return to “normal” levels following storms that cause massive and widespread damage – while power may be largely restored within several days, damage to physical infrastructure takes significantly longer to address.

Sri Lanka & Indonesia

On November 26, Cyclone Senyar caused catastrophic floods and landslides in Sri Lanka and Indonesia, killing over 1,000 people and damaging telecommunications and power infrastructure across these countries. The infrastructure damage resulted in disruptions to Internet connectivity, and resultant lower traffic levels, across multiple regions.

In Sri Lanka, regions outside the main Western Province were the most affected, and several provinces saw traffic drop between 80% and 95% as compared to the prior week, including North Western, Southern, Uva, Eastern, Northern, North Central, and Sabaragamuwa.

In Indonesia, Aceh and the Sumatra regions saw the biggest Internet disruptions. In Aceh, traffic initially dropped over 75% as compared to the previous week. In Sumatra, North Sumatra was the most affected, with an early 30% drop as compared to the previous week, before starting to recover more actively the following week.

Known or unspecified technical problems

Smartfren (Indonesia)

On October 3, subscribers to Indonesian Internet provider Smartfren (AS18004) experienced a service disruption. The issues were acknowledged by the provider in an X post, which stated (in translation), “Currently, telephone, SMS and data services are experiencing problems in several areas.” Traffic from the provider fell as much as 84%, starting around 09:00 local time (02:00 UTC). The disruption lasted for approximately eight hours, as traffic returned to expected levels around 17:00 local time (10:00 UTC). Smartfren did not provide any additional information on what caused the service problems.

Vodafone UK

Major British Internet provider Vodafone UK (AS5378 & AS25135) experienced a brief service outage on October 23. At 15:00 local time (14:00 UTC), traffic on both Vodafone ASNs dropped to zero. Announced IPv4 address space from AS5378 fell by 75%, while announced IPv4 address space from AS25135 disappeared entirely. Both Internet traffic and address space recovered two hours later, returning to expected levels around 17:00 local time (16:00 UTC). Vodafone did not provide any information on their social media channels about the cause of the outage, and their network status checker page was also unavailable during the outage.

Fastweb (Italy)

According to a published report, a DNS resolution issue disrupted Internet services for customers of Italian provider Fastweb (AS12874) on October 22, causing observed traffic volumes to drop by over 75%. Fastweb acknowledged the issue, which impacted wired Internet customers between 09:30 – 13:00 local time (08:30 – 12:00 UTC).

Although not an Internet outage caused by connectivity failure, the impact of DNS resolution issues on Internet traffic is very similar. When a provider’s DNS resolver is experiencing problems, switching to a service like Cloudflare’s 1.1.1.1 public DNS resolver will often restore connectivity.

SBIN, MTN Benin, Etisalat Benin

On December 7, a concurrent drop in traffic was observed across SBIN (AS28683), MTN Benin (AS37424), and Etisalat Benin (AS37136). Between 18:30 – 19:30 local time (17:30 – 18:30 UTC), traffic dropped as much as 80% as compared to the prior week at a country level, nearly 100% at Etisalat and MTN, and over 80% at SBIN.

While an attempted coup had taken place earlier in the day, it is unclear whether the observed Internet disruption was related in any way. From a routing perspective, all three impacted networks share Cogent (AS174) as an upstream provider, so a localized issue at Cogent may have contributed to the brief outage.  

Cellcom Israel

According to a reported announcement from Israeli provider Cellcom (AS1680), on December 18, there was “a malfunction affecting Internet connectivity that is impacting some of our customers.” This malfunction dropped traffic nearly 70% as compared to the prior week, and occurred between 09:30 – 11:00 local time (07:30 – 09:00 UTC). The “malfunction” may have been a DNS failure, according to a published report.

Partner Communications (Israel)

Closing out 2025, on December 30, a major technical failure at Israeli provider Partner Communications (AS12400) disrupted mobile, TV, and Internet services across the country. Internet traffic from Partner fell by two-thirds as compared to the previous week between 14:00 – 15:00 local time (12:00 – 13:00 UTC). During the outage, queries to Cloudflare’s 1.1.1.1 public DNS resolver spiked, suggesting that the problem may have been related to Partner’s DNS infrastructure. However, the provider did not publicly confirm what caused the outage.

Cloud Platforms

During the fourth quarter, we launched a new Cloud Observatory page on Radar that tracks availability and performance issues at a region level across hyperscaler cloud platforms, including Amazon Web Services, Microsoft Azure, Google Cloud Platform, and Oracle Cloud Infrastructure.

Amazon Web Services

On October 20, the Amazon Web Services us-east-1 region in Northern Virginia experienced “increased error rates and latencies” that affected multiple services within the region. The issues impacted not only customers with public-facing Web sites and applications that rely on infrastructure within the region, but also Cloudflare customers that have origin resources hosted in us-east-1.

We began to see the impact of the problems around 06:30 UTC, as the share of error (5xx-class) responses began to climb, reaching as high as 17% around 08:00 UTC. The number of failures encountered when attempting to connect to origins in us-east-1 climbed as well, peaking around 12:00 UTC.

The impact could also be clearly seen in key network performance metrics, which remained elevated throughout the incident, returning to normal levels just before the end of the incident, around 23:00 UTC. Both TCP and TLS handshake durations got progressively worse throughout the incident—these metrics measure the amount of time needed for Cloudflare to establish TCP and TLS connections respectively with customer origin servers in us-east-1. In addition, the amount of time elapsed before Cloudflare received response headers from the origin increased significantly during the first several hours of the incident, before gradually returning to expected levels.

Microsoft Azure

On October 29, Microsoft Azure experienced an incident impacting Azure Front Door, its content delivery network service. According to Azure’s report on the incident, “A specific sequence of customer configuration changes, performed across two different control plane build versions, resulted in incompatible customer configuration metadata being generated. These customer configuration changes themselves were valid and non-malicious – however they produced metadata that, when deployed to edge site servers, exposed a latent bug in the data plane. This incompatibility triggered a crash during asynchronous processing within the data plane service.

The incident report marked the start time at 15:41 UTC, although we observed the volume of failed connection attempts to Azure-hosted origins begin to climb about 45 minutes prior. The TCP and TLS handshake metrics also became more volatile during the incident period, with TCP handshakes taking over 50% longer at times, and TLS handshakes taking nearly 200% longer at peak. The impacted metrics began to improve after 20:00 UTC, and according to Microsoft, the incident ended at 00:05 UTC on October 30.

Cloudflare

In addition to the outages discussed above, Cloudflare also experienced two disruptions during the fourth quarter. While these were not Internet outages in the classic sense, they did prevent users from accessing Web sites and applications delivered and protected by Cloudflare when they occurred.

The first incident took place on November 18, and was caused by a software failure triggered by a change to one of our database systems’ permissions, which caused the database to output multiple entries into a “feature file” used by our Bot Management system. Additional details, including a root cause analysis and timeline, can be found in the associated blog post.

The second incident occurred on December 5, and impacted a subset of customers, accounting for approximately 28% of all HTTP traffic served by Cloudflare. It was triggered by changes being made to our request body parsing logic while attempting to detect and mitigate a newly disclosed industry-wide React Server Components vulnerability. A post-mortem blog post contains additional details, including a root cause analysis and timeline.

For more information about the work underway at Cloudflare to prevent outages like these from happening again, check out our blog post detailing “Code Orange: Fail Small.”

Conclusion

The disruptions observed in the fourth quarter underscore the importance of real-time data in maintaining global connectivity. Whether it’s a government-ordered shutdown or a minor technical issue, transparency allows the technical community to respond faster and more effectively. We will continue to track these shifts on Cloudflare Radar, providing the insights needed to navigate the complexities of modern networking. We share our observations on the Cloudflare Radar Outage Center, via social media, and in posts on blog.cloudflare.com. Follow us on social media at @CloudflareRadar (X), noc.social/@cloudflareradar (Mastodon), and radar.cloudflare.com (Bluesky), or contact us via email.

As a reminder, while these blog posts feature graphs from Radar and the Radar Data Explorer, the underlying data is available from our API. You can use the API to retrieve data to do your own local monitoring or analysis, or you can use the Radar MCP server to incorporate Radar data into your AI tools.

How to improve email sender reputation with Amazon SES Email Validation

Post Syndicated from Zip Zieper original https://aws.amazon.com/blogs/messaging-and-targeting/how-to-improve-email-sender-reputation-with-amazon-ses-email-validation/

If you’re sending emails at scale with Amazon Simple Email Service (Amazon SES), maintaining high deliverability depends on more than the content you send. It’s about who receives those emails. Mailbox providers like Gmail, Yahoo, and Outlook assign reputation scores based on your sending practices, domain and IP authentication records, message quality, and recipient engagement. These providers use their own algorithms to decide whether your emails reach the inbox, are filtered as spam, or aren’t delivered at all. For more information about managing your email reputation, see The Four Pillars of Managing Email Reputation. In this post, we show you how the Amazon SES Email Validation feature can help you to protect your sender reputation.

The email bounce rate is the percentage of emails that fail to deliver and is one of the most critical factors affecting your sender reputation. Every bounce damages your sender reputation. Mailbox providers like Gmail and Outlook closely monitor bounce rates, and accounts that bounce over 5% trigger warnings. If your account bounce rate exceeds 10%, the email services providers might throttle, or completely block sending. For customers sending email at scale with Amazon SES, a high bounce rate may trigger immediate consequences: damaged sender reputation, blocked deliverability, and ISP penalties that can throttle or suspend your entire email program. Traditional approaches to email quality are reactive, because you will only discover problems after bounces have damaged your reputation. While account suppression lists protect against known problematic addresses, they can’t protect you from the normal decay of email address quality that occurs because of job changes, abandoned mailboxes, domain expirations, or bots and bad actors looking to damage your email reputation.

Use Amazon SES Email Validation to help you protect your sender reputation

Amazon SES Email Validation shifts bounce management from reactive to proactive, helping you detect problems before they damage your sender reputation. The feature provides two validation approaches: the Email Validation API for timely checks during registration and Auto Validation to automatically review all outbound email addresses before sending and only deliver messages to recipients that meet your selected validation threshold. Both methods are intended to catch problem addresses before they become bounces, helping to protect your sender reputation.

In this post, we guide you through implementing both validation approaches using AnyCompany—a fictitious ecommerce website—as our example. You will see how AnyCompany might use the Email Validation API for timely registration checks on address acquisition and Auto Validation at time of sending. You’ll learn how to protect your sender reputation proactively and integrate validation into existing workflows with minimal disruption. We also show you how to use Amazon CloudWatch metrics to improve email list health over time. After you’re done reading and experimenting, you’ll understand how Amazon SES Email Validation can help transform your email operations from reactive bounce management to proactive quality assurance.

Solution overview – how to use the Email Validation API to avoid ingesting invalid email addresses

You can use the Email Validation API to validate email addresses through synchronous API calls to check addresses at the point of collection. This method gives you immediate feedback about address validity and helps prevent invalid addresses from entering your database. You control when validation occurs and how to handle the results. The Email Validation API costs $0.01 per validation using the API or the AWS Management Console for Amazon SES. See Amazon SES pricing for details.

The Amazon SES console uses the Email Validation API to manually validate up to 10 email addresses at a time. The results are shown in the console—shown in the following screenshot—and you can export the results to a CSV file.

The Email Validate API can be used in your code or using the AWS Command Line Interface (AWS CLI) to validate individual email addresses through synchronous API calls. This method is well-suited for validating addresses at the point of collection—during user registration, subscription form submission, or during an email list import to help prevent invalid addresses from entering your database. The following is an example using the AWS CLI.

aws sesv2 get-email-address-insights \
    --email-address [email protected] \
    --region us-east-1

The API returns a response structure similar to the following example:

{
  "MailboxValidation": {
    "IsValid": {
      "ConfidenceVerdict": "HIGH"
    },
    "Evaluations": {
      "HasValidSyntax": {
        "ConfidenceVerdict": "HIGH"
      },
      "HasValidDnsRecords": {
        "ConfidenceVerdict": "MEDIUM"
      },
      "MailboxExists": {
        "ConfidenceVerdict": "MEDIUM"
      },
      "IsRoleAddress": {
        "ConfidenceVerdict": "LOW"
      },
      "IsDisposable": {
        "ConfidenceVerdict": "LOW"
      },
      "IsRandomInput": {
        "ConfidenceVerdict": "LOW"
      }
    }
  }
}

Understanding Email Validation API verdicts

For each email, the Email Validation API returns an overall validity confidence with three possible aggregate verdicts:

  • HIGH – The email address passed all critical validation checks and is highly likely to be deliverable. These addresses can be accepted without additional scrutiny.
  • MEDIUM – The email address passed basic validation but has characteristics that might affect deliverability (such as being a role address or having uncertain mailbox existence). Your use case and bounce risk tolerance should be used to determine whether to accept these addresses.
  • LOW – The email address failed one or more critical validation checks and is unlikely to be deliverable. Your use case and bounce risk tolerance will most likely cause you to reject these addresses.

To reach the overall validity confidence, the Email Validation API performs six detailed checks on each email address:

  • Syntax validation (HasValidSyntax) – Confirms the address follows RFC 5321 and RFC 5322 standards for email address formatting. This catches obvious errors such as missing @ symbols or invalid characters.
  • DNS verification (HasValidDnsRecords) – Validates that the domain exists and has proper mail exchange (MX) records and corresponding A records configured. This helps confirm that the domain can receive email.
  • Mailbox existence (MailboxExists) – Predicts whether the specific mailbox exists and can receive messages.
  • Role address detection (IsRoleAddress) – Identifies generic addresses like [email protected] or [email protected] that typically represent shared mailboxes rather than individual recipients.
  • Disposable email detection (IsDisposable) – Checks temporary email services like mailinator.com or guerrillamail.com that users often employ to avoid providing real contact information.
  • Random input detection (IsRandomInput) – Checks randomly generated patterns.

For more information about response values and data types, see the MailboxValidation data type in the Amazon SES API v2 reference.

The Email Validation API provides a dashboard in the Amazon SES console that you can use to view email address verification results over time, with the ability to look back for up to one month, as shown in the following screenshot.

Use auto validation to help prevent bounces when sending from Amazon SES

Amazon SES Auto Validation automatically performs comprehensive address validation through multiple checks such as syntax validation, DNS records, and others before each message is sent. When auto validation is enabled, Amazon SES will only deliver messages to recipients that meet your selected validation threshold. This helps you protect your sender reputation by preventing sends to addresses that have a high probability of being invalid or risky without requiring manual intervention or API integration. Auto Validation must be enabled separately for each AWS region in your account. For example, if you enable it in us-east-1, it will not be active in us-west-2 unless you explicitly enable it there as well. You can enable it at the account level for an entire region, or selectively within configuration sets. Auto validation costs $0.01 per 1,000 validations. Be aware that sends suppressed by Auto Validation count towards your daily send quota, and you will be charged the standard outgoing message fee for suppressed sends (in addition to the fee for auto validation). See Amazon SES pricing for more information.

When enabled at the AWS account level, you set the Validation threshold to determine which email addresses to suppress based on their validity confidence, as shown in the following screenshot.

  • Amazon SES managed threshold (recommended) – Amazon SES automatically manages the threshold to suppress invalid addresses based on your sending patterns and reputation. This option allows Amazon SES to optimize the validation threshold dynamically. Use this threshold when you want AWS to handle validation decisions based on your account’s specific characteristics.
  • Custom threshold –
    • High – Delivers emails only to addresses with high delivery likelihood. This provides maximum protection for your sender reputation but might suppress some legitimate addresses with medium delivery confidence. Use this threshold for critical transactional emails or when protecting sender reputation is your top priority.
    • Medium – Delivers emails to addresses with medium or high delivery likelihood. This balances reputation protection with delivery reach by allowing addresses with moderate deliverability scores. Use this threshold for marketing campaigns where you want to maximize reach while still filtering obviously invalid addresses.

You will usually find that using the recommended Amazon SES managed threshold works best for the bulk of your sending, however for certain use cases you might want to override the account setting and use a custom threshold in your configuration set. If you choose High or Medium thresholds instead of Amazon SES managed (as shown in the following screenshot), it’s important that you monitor your delivery metrics and validation results regularly.

Auto Validation applies to all outbound emails sent through your account. Addresses that don’t meet your threshold will be suppressed with the bounceSubType of EmailValidationSuppressed. Suppressed sends count towards your daily send quota, and you will be charged the standard outgoing message fee for suppressed sends in addition to the fee for auto validation.

{
  "Type": "Notification",
  "MessageId": "0ded6fd6-4e59-5ae0-9782-0e68faa886e7",
  "TopicArn": "arn:aws:sns:us-east-1:252640393490:ses-auto-validate",
  "Subject": "Amazon SES Email Event Notification",
  "Message": "{\"**eventType**\":\"**Bounce**\",\"bounce\":{\"feedbackId\":\"0100019b345a05a0-95e3062a-9594-499f-aafc-dc2dc9647cb6-000000\",\"**bounceType**\":\"**Permanent**\",\"**bounceSubType**\":\"**EmailValidationSuppressed**\",\"bouncedRecipients\":"
}

How AnyCompany might use the Email Validation API and auto validation

AnyCompany runs an ecommerce platform for both business and consumer office supplies. The company’s website hosts various web-forms for customers to create accounts and sign up to receive newsletters and discount offers. When they place orders through the platform, AnyCompany’s system sends order confirmations and delivery tracking emails. Today, when a new user registers through one of the web forms, AnyCompany sends a verification email to confirm the user’s email address, contact details, and opt-in to the company’s emails. If a user misspells their email address, they will never receive this verification email. Frustrated, they might move on to another provider. Similarly, if a bot or bad actor deliberately submits invalid addresses to the web form, verification emails will bounce. Both scenarios cost AnyCompany money with no return; at scale, a high bounce rate might cause email service providers to throttle or block future sends. AnyCompany previously investigated various third-party email validation services, but the engineering work, security reviews, and costs outweighed the expected benefits. This necessitated the cloud team’s constant and careful vigilance over the company’s bounce rate and reputation, diverting resources that the company would prefer to deploy elsewhere. As an ecommerce company, AnyCompany needs to be highly protective of its sender reputation. With email validation now built directly into Amazon SES, AnyCompany can bypass the complexity and cost of third-party tools and directly benefit from proactive bounce prevention across all email use cases. In the following section, we guide you through the simple steps AnyCompany might take to implement Amazon SES Email Validation.

Prerequisites

Before implementing Email Validation, you’ll need:

AWS account :

  • An AWS account with Amazon SES enabled in your desired AWS Region
  • AWS CLI version 2.0 or later installed and configured

Required IAM permissions:

Your IAM user or role needs the following permissions to configure Email Validation:

  • ses:PutAccountSuppressionAttributes – To enable and configure Email Validation at the account level
  • ses:GetAccount to verify Email Validation configuration
  • ses:CreateConfigurationSet when creating a new configuration set
  • ses:PutConfigurationSetSuppressionOptionsto override validation settings for specific configuration sets
  • ses:GetEmailAddressInsights to call the Email Validation API
  • iam:CreateServiceLinkedRole  creates an IAM service-linked role that is used by Amazon SES to publish CloudWatch metrics
  • cloudwatch:GetMetricStatistics – To retrieve validation metrics

Development environment:

  • Familiarity with AWS CLI commands and JSON configuration files
  • For API integration, SDK support for Amazon SES API v2 in your preferred programming language
  • Access to your application’s user registration code

Existing Amazon SES configuration:

  • At least one verified email address or domain in Amazon SES

While the Email Validation API works with an AWS account that is in the Amazon SES sandbox, auto validation is best demonstrated after your AWS account has been granted production access.

  • (Optional) Configuration sets created for different email types (transactional, marketing, and so on)

Validating email addresses at acquisition with the Email Validation API

To prevent bad addresses from entering their customer database at time of acquisition, AnyCompany will integrate the Email Validation API directly into their registration form. When a user submits their contact details, including email address, the Email Validation API is used. Results arrive within 100 milliseconds, with the overall validity confidence and six detailed checks of the email address. AnyCompany will then use the results and custom business logic they designed for their different use cases. For example, for their B2B business, they might allow registrations with high overall confidences and a role address, such as [email protected]. For the consumer business, they might accept registrations with medium overall confidences, but always reject emails that the API identifies as disposable, such as [email protected] or random, such as [email protected].

Sample code snippets

The code snippets in this section are examples only and are not intended for production use.

Step 1: Validate email address on form submission

When a user submits the registration form, AnyCompany’s application calls the Email Validation API before creating the account:

import boto3

ses_client = boto3.client('sesv2', region_name='us-east-1')

def validate_registration_email(email_address):
    try:
        response = ses_client.get_email_address_insights(
            EmailAddress=email_address
        )
        return response
    except Exception as e:
        # Handle API errors gracefully
        print(f"Validation error: {e}")
        return None

Step 2: Apply business rules based on verdict

AnyCompany’s business logic handles different validation outcomes:

def should_accept_email(validation_response, registration_type):
    if not validation_response:
        # API error - accept email but flag for manual review
        return True, "accepted_with_warning"

    overall_verdict = validation_response['MailboxValidation']['IsValid']['ConfidenceVerdict']
    checks = validation_response['MailboxValidation']['Evaluations']

    # Always reject FAIL verdicts
    if overall_verdict == 'LOW':
        return False, "rejected_invalid"

    # Always accept PASS verdicts
    if overall_verdict == 'HIGH':
        return True, "accepted"

    # Handle NEUTRAL verdicts based on registration type
    if overall_verdict == 'MEDIUM':
        # Reject disposable emails for all registration types
        if checks['IsDisposable']['ConfidenceVerdict'] == 'HIGH':
            return False, "rejected_disposable"

        # Accept role addresses for B2B, reject for consumer
        if checks['IsRoleAddress']['ConfidenceVerdict'] == 'HIGH':
            if registration_type == 'b2b':
                return True, "accepted_role_address"
            else:
                return False, "rejected_role_address"

        # Accept other NEUTRAL cases with warning
        return True, "accepted_with_warning"

Step 3: Provide user-friendly error messages

When validation fails, AnyCompany provides specific, actionable feedback (you can add more conditions based on your requirements):

def get_user_error_message(validation_response):
    checks = validation_response['Evaluations']

    if checks['HasValidSyntax']['ConfidenceVerdict'] == 'LOW':
        return "Please check your email address for typos. It appears to have formatting errors."

    if checks['HasValidDnsRecords']['ConfidenceVerdict'] == 'LOW':
        return "The domain in your email address doesn't appear to exist. Please verify you entered it correctly."

    if checks['IsDisposable']['ConfidenceVerdict'] == 'HIGH':
        return "Temporary email addresses are not accepted. Please use a different email address."

    if checks['IsRoleAddress']['ConfidenceVerdict'] == 'HIGH':
        return "Please use a personal email address rather than a shared mailbox like support@ or admin@."

    return "We couldn't verify this email address. Please check for typos and try again."

Step 4: Suggest corrections for common mistakes

For addresses that fail DNS validation, AnyCompany suggests common corrections to popular domain typos.

def suggest_email_correction(email_address):
    common_domains = {
        'gmial.com': 'gmail.com',
        'gmai.com': 'gmail.com',
        'yahooo.com': 'yahoo.com',
        'hotmial.com': 'hotmail.com',
        'outlok.com': 'outlook.com'
    }

    # Extract domain from email
    if '@' in email_address:
        local, domain = email_address.split('@', 1)

        # Check for common misspellings
        if domain.lower() in common_domains:
            suggested_domain = common_domains[domain.lower()]
            return f"{local}@{suggested_domain}"

    return None

Key benefits of the Email Validation API

The Email Validation API provide proactive quality control by preventing invalid addresses from entering AnyCompany’s database, preventing the reputation damage that occurs when they send to addresses that bounce.

  • Immediate user feedback – Because validation results return within milliseconds, AnyCompany can provide real-time feedback during registration without impacting user experience.
  • Flexible policy enforcement – AnyCompany can use individual check results to define custom validation policies that match their various business requirements, accepting or rejecting addresses based on use case-specific risk tolerance.
  • Cost-effective validation – AnyCompany pays only for the addresses they validate, with no infrastructure to provision or manage and no license fees. Preventing a single bounce might save more than the cost of validation.

By integrating the Email Validation API into their registration workflow, AnyCompany can transform their approach from reactive bounce management to proactive quality assurance. Invalid addresses are prevented from entering their database, legitimate customers receive verification emails reliably, and their sender reputation remains protected with little to no ongoing effort.

Set up a CloudWatch alarm for high rates of LOW verdicts

You can configure CloudWatch alarms to notify you when validation patterns indicate a consistently high rate of LOW verdicts. This might indicate malicious bots attempting to sign up through a web-form or other mechanism.

The following example creates a CloudWatch alarm that fires when the rate of LOW verdicts exceeds 20%.

aws cloudwatch put-metric-alarm \
  --region us-east-1 \
  --alarm-name "EmailInsights-LOW-Rate-Above-20-Percent" \
  --alarm-description "Alarm when LOW confidence verdict rate exceeds 20%" \
  --comparison-operator GreaterThanThreshold \
  --threshold 20 \
  --evaluation-periods 2 \
  --treat-missing-data notBreaching \
  --metrics '[
    {
      "Id": "low",
      "MetricStat": {
        "Metric": {
          "MetricName": "EmailAddressInsights.ConfidenceVerdict.LOW",
          "Namespace": "AWS/SES"
        },
        "Period": 300,
        "Stat": "Sum"
      },
      "ReturnData": false
    },
    {
      "Id": "medium",
      "MetricStat": {
        "Metric": {
          "MetricName": "EmailAddressInsights.ConfidenceVerdict.MEDIUM",
          "Namespace": "AWS/SES"
        },
        "Period": 300,
        "Stat": "Sum"
      },
      "ReturnData": false
    },
    {
      "Id": "high",
      "MetricStat": {
        "Metric": {
          "MetricName": "EmailAddressInsights.ConfidenceVerdict.HIGH",
          "Namespace": "AWS/SES"
        },
        "Period": 300,
        "Stat": "Sum"
      },
      "ReturnData": false
    },
    {
      "Id": "e1",
      "Expression": "IF((low+medium+high)>0, low/(low+medium+high)*100, 0)",
      "Label": "LOW Rate Percentage",
      "ReturnData": true
    }
  ]'

How AnyCompany uses validation metrics

AnyCompany monitors their Email Validation dashboard in the Amazon SES console to track list quality trends. For example, if they notice an increase in disposable email failures, they can add additional client-side validation to their registration forms to discourage this behavior. When Auto Validation blocks a spike of invalid addresses from a specific partner marketing campaign, they avoid the problems associated with a spike in bounces while being better informed when investigating the list source and removing or cleaning it for future campaigns.

Validating email addresses at send time with Auto Validation

AnyCompany has been operating its online platform for many years without a way to validate email addresses. The company also makes frequent acquisitions and partnerships that regularly introduce new email addresses into their sending. This means that no matter how well the new registration for with the Email Validation API performs, they will always have some invalid email addresses in their outbound sends.

This is one of the scenarios that can be addressed with no code or process changes by using Auto Validation. When enabled at the AWS account level, Auto Validation checks each address before sending, automatically suppressing the send of invalid addresses, adding those addresses to the account suppression list, and generating bounce notification events. These bounce events appear in Amazon SES event publishing and can be monitored using Amazon CloudWatch, Amazon Simple Notification Service (Amazon SNS), or Amazon EventBridge or written to an Amazon Simple Storage Service (Amazon S3) bucket. Auto Validation bounce events appear as:

  • Bounce type: Permanent for addresses that will never be deliverable
  • Bounce subtypeEmailValidationSuppressed indicating Auto Validation blocked the send

Because it’s implemented in Amazon SES events, AnyCompany can handle address validation failures the same way they currently handle actual bounces from mailbox providers, maintaining consistency in their email processing workflows.

Conclusion

Amazon SES Email Validation addresses critical needs for organizations sending email at scale: preventing invalid addresses at registration and automatically filtering risky recipients before sending. The feature’s two complementary approaches—the Email Validation API for real-time checks and Auto Validation for automatic send-time filtering—give you flexibility to implement validation where it makes the most sense for your workflows.

Use the Email Validation API to:

  • Validate at point of collection (registration, imports)
  • Receive immediate user feedback
  • Build custom validation workflows
  • Validate before database entry
  • Validate up to 10 addresses

Use Auto Validation to:

  • Automatically protect ongoing campaigns automatically
  • Avoid code changes to sending logic
  • Provide consistent quality across all sends
  • Set organization-wide quality standards

By implementing both features of Amazon SES Email Validation, you can better protect your sender reputation by proactively preventing bounces, reducing the possibility of high bounce rates that can damage your deliverability.

Next steps

Start improving your email deliverability today:

  1. Enable Email Validation in your AWS account using the Amazon SES console or the AWS CLI
  2. Implement API validation at your registration points to improve data quality from the start
  3. Configure Auto Validation policies to protect your sender reputation across all campaigns
  4. Set up CloudWatch dashboards to track validation performance and identify list quality trends
  5. Review validation metrics weekly to refine your validation policies based on actual patterns

For more information about Amazon SES Email Validation, see the Amazon SES Developer Guide.


About the authors

Establishing finops management: Integrating AWS Budgets with WhatsApp using AWS End User Messaging

Post Syndicated from Ruchikka Chaudhary original https://aws.amazon.com/blogs/messaging-and-targeting/establishing-finops-management-integrating-aws-budgets-with-whatsapp-using-aws-end-user-messaging/

Managing cloud costs effectively is a critical concern for organizations of all sizes. While AWS Budgets provides powerful tools to set spending thresholds and receive notifications, these alerts traditionally arrive through email or through AWS Management Console notifications. These traditional notification methods face several challenges when managing cloud costs:

  • Email notifications might not be seen immediately
  • Important budget alerts can get lost in crowded inboxes
  • Team members might not have immediate access to their email or the console
  • Global teams need accessible alerting mechanisms that work across time zones

Today, we’re sharing a solution that brings AWS Budgets alerts directly to your WhatsApp using AWS End User Messaging—enabling real-time cost awareness and faster response to budget thresholds wherever you are.

Overview of solution

Our solution integrates AWS Budgets with WhatsApp messaging using AWS End User Messaging, AWS Lambda, and Amazon Simple Notification Service (Amazon SNS). When a budget threshold is crossed, the alert is processed and delivered as a formatted WhatsApp message to designated recipients.

The architecture, shown in the following figure, consists of four main AWS services to deliver budget alerts. AWS Budgets tracks expenses against your defined thresholds. When expenses exceed these thresholds, Amazon SNS receives an alert. An AWS Lambda function processes this alert and sends it through AWS End User Messaging to WhatsApp. Users then receive actionable budget notifications directly on their WhatsApp.

Billing and Cost Management data, which AWS Budgets uses to monitor resources, is updated at least once per day. Keep in mind that budget information and associated alerts are updated and sent according to this data refresh cadence. In a budget period,

notifications are triggered every time the notification state goes from OK to Exceeded (when the threshold is exceeded). If the budget stays in Exceeded state in the same budget period, AWS Budgets doesn’t send an additional alert.

Prerequisites

Implementation requires an AWS account with appropriate permissions for AWS CloudFormation, Lambda, Amazon SNS, and AWS Budgets. You must also have a WhatsApp Business Account integrated with AWS End User Messaging Social and the WhatsApp phone number ID from the AWS End User Messaging console. For instructions to locate this information, see View a phone number’s ID in AWS End User Messaging Social.

For more information about how to set up WhatsApp using AWS End User Messaging Social, see Automate workflows with WhatsApp using AWS End User Messaging Social.

Before you deploy this solution, create an approved utility template in your Meta account named aws_budgets_notification_template(as shown in the following screenshot). Alternatively, use your preferred template name and modify the Lambda function code accordingly.

The preceding figure shows variable samples that can be used while creating a message template. You can also use the following AWS Command Line Interface (AWS CLI) command to create the messaging template-

aws socialmessaging create-whatsapp-message-template \
  --region <region> \
  --id <waba-id> \
  --template-definition "$(echo '{
    "name": "aws_budgets_notification_template",
    "language": "en",
    "category": "UTILITY",
    "parameter_format": "named",
    "components": [
      {
        "type": "HEADER",
        "format": "TEXT",
        "text": "{{emoji}} Budget Alert",
        "example": {
          "header_text_named_params": [
            {"param_name": "emoji", "example": "💰"}
          ]
        }
      },
      {
        "type": "BODY",
        "text": "Subject: {{subject}}\\nDetails: {{notification_title}}\\nAWS Account {{account_info}}\\n\\n{{notification_msg}}\\n\\nBudget Name: {{budget_name}}\\nBudget Type: {{budget_type}}\\nBudgeted Amount: {{budgeted_amount}}\\nAlert Type: {{alert_type}}\\nAlert Threshold: {{alert_threshold}}\\nFORECASTED Amount: {{forecasted_amount}}\\n\\nAWS Console: {{console_link}}\\n\\nTime: {{time}}\\n\\nTip: Check your AWS Billing Dashboard for detailed cost breakdown",
        "example": {
          "body_text_named_params": [
            {"param_name": "subject", "example": "AWS Budgets: Budget-Cloudwatch-budget-dev has exceeded your alert threshold"},
            {"param_name": "notification_title", "example": "AWS Budget Notification Oct 19, 2025"},
            {"param_name": "account_info", "example": "AWS Account 12345"},
            {"param_name": "notification_msg", "example": "You requested that we alert you when the FORECASTED Cost associated with your Budget-Cloudwatch-dev Budget is greater"},
            {"param_name": "budget_name", "example": "Budget-Cloudwatch-budget-dev"},
            {"param_name": "budget_type", "example": "Cost"},
            {"param_name": "budgeted_amount", "example": "$1"},
            {"param_name": "alert_type", "example": "Cost"},
            {"param_name": "alert_threshold", "example": "> 1"},
            {"param_name": "forecasted_amount", "example": "$2"},
            {"param_name": "console_link", "example": "https://console.aws.amazon.com/billing/home#/budgets"},
            {"param_name": "time", "example": "2025-10-19 12:38:52 UTC"}
          ]
        }
      }
    ]
  }' | base64)"

You can confirm the template approval status and type in the Meta portal.

Solution walkthrough

The core component consists of a Python-based Lambda function that processes Budget alerts and formats them for WhatsApp delivery. The function receives SNS events containing budget alerts data, extracts relevant information, formats contextual messages, and delivers notifications through AWS End User Messaging Social.The following function shows an example to parse the SNS message content:

 def process_notification(record):
"""Process SNS notification and send WhatsApp message"""
sns_message = record['Sns']
subject = sns_message.get('Subject', 'AWS Notification')
message_body = sns_message.get('Message', '')

logger.info(f"Processing notification - Subject: {subject}")
process_budget_notification(subject, message_body)

The following example demonstrates how to format alert information—including subject, details, and timestamp—and deliver the message to WhatsApp.

#Create template message with parsed values
template_name = "aws_budgets_notification_template"
template_message = {
    "name": template_name,
    "language": {
        "code": "en"
    },
    "components": [
        {
            "type": "header",
            "parameters": [{
                "type": "text",
                "parameter_name": "emoji",
                "text": "💰"
            }]
        },
        {
            "type": "body",
            "parameters": [
                {
                    "type": "text",
                    "parameter_name": "subject",
                    "text": subject
                },
                {
                    "type": "text",
                    "parameter_name": "notification_title",
                    "text": notification_title
                },
                {
                    "type": "text",
                    "parameter_name": "account_info",
                    "text": f"AWS Account {account_number}"
                },
                {
                    "type": "text",
                    "parameter_name": "notification_msg",
                    "text": notification_msg + "."
                },
                {
                    "type": "text",
                    "parameter_name": "budget_name",
                    "text": budget_details.get('Budget Name', '')
                },
                {
                    "type": "text",
                    "parameter_name": "budget_type",
                    "text": budget_details.get('Budget Type', '')
                },
                {
                    "type": "text",
                    "parameter_name": "budgeted_amount",
                    "text": budget_details.get('Budgeted Amount', '')
                },
                {
                    "type": "text",
                    "parameter_name": "alert_type",
                    "text": budget_details.get('Alert Type', '')
                },
                {
                    "type": "text",
                    "parameter_name": "alert_threshold",
                    "text": budget_details.get('Alert Threshold', '')
                },
                {
                    "type": "text",
                    "parameter_name": "forecasted_amount",
                    "text": budget_details.get('FORECASTED Amount', '')
                },
                {
                    "type": "text",
                    "parameter_name": "console_link",
                    "text": "https://console.aws.amazon.com/billing/home#/budgets"
                },
                {
                    "type": "text",
                    "parameter_name": "time",
                    "text": datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')
                }
            ]
        }
    ]
}
send_whatsapp_message(template_message)

The send_whatsapp_message function uses AWS End User Messaging Social to deliver formatted messages through the socialmessaging client, as shown in the following example:

def send_whatsapp_message(message):
  client = boto3.client('socialmessaging')
  # Get environment variables
  phone_number_id = os.environ.get('WHATSAPP_PHONE_NUMBER_ID')
  recipient = os.environ.get('ALERT_RECIPIENT')
                    
# Prepare message object
  message_object = {
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": recipient,
"type": "template",
"template": message
}
  # Send message
response = client.send_whatsapp_message(
originationPhoneNumberId=phone_number_id,
metaApiVersion="v20.0",
message=bytes(json.dumps(message_object), "utf-8")  
)

Deploying the solution

The solution uses AWS CloudFormation for infrastructure as code (IaC) deployment. The main template creates an SNS topic for alert notifications, a Lambda function for message processing, and required AWS Identity and Access Management (IAM) roles with least-privilege permissions.

The CloudFormation template requires a recipient number with an active WhatsApp account to receive alert notifications as messages. The template also requires the WhatsApp phone number ID retrieved from the AWS End User Messaging Social console, as noted in the prerequisites. The template must be deployed in the same AWS Region as AWS End User Messaging Social. See the following code:

aws cloudformation deploy \
  --template-file <> \
  --stack-name budget-eum-whatsapp-alerts \
  --parameter-overrides \
    ActualSpendThreshold= \
    AlertRecipient=<+1234567890> \
    BudgetAmount=<Budget Amount e.g. 3000> \
    Environment= \
    ForecastedSpendThreshold= \
    WhatsAppPhoneNumberId= \
  --capabilities CAPABILITY_NAMED_IAM \
  --region <EUM-region>

Testing the solution

The solution can be tested and validated using the SNS topic created by the CloudFormation stack. Use the following AWS CLI command to publish a test message to the SNS topic:

aws sns publish \
  --topic-arn arn:aws:sns:<region>:<account>:<topic-name> \
  --subject "[Test] AWS Budget Alert: Budget-Alert-EUM has exceeded 80% of your budgeted amount" \
  --message "AWS Budget Notification - Your budget has exceeded the alert threshold
AWS Account 123456789012
Budget Name: Budget-Alert-EUM
Budget Type: Cost
Budgeted Amount: $100.00
Alert Type: ACTUAL
Alert Threshold: 80%
FORECASTED Amount: $85.00
You have exceeded 80% of your budget for this period" \
  --region <region>

The SNS message triggers the Lambda function, which sends the alert to your configured WhatsApp recipient, as shown in the following screenshot.

Clean up

Use the following steps to clean up your resources when you no longer need this solution:

  1. Delete the CloudFormation stack deployed in this solution: budget-eum-whatsapp-alerts
  2. Delete the template in your Meta account.

Conclusion

Integrating AWS Budgets alerts with WhatsApp notifications represents a significant step forward in modern cost monitoring. By using AWS End User Messaging Social, you can send teams critical alerts through their preferred communication channel while maintaining the reliability and scalability of AWS services. The solution’s modular architecture, basic yet effective security model, and cost-effective design make it suitable for organizations of various sizes.


About the authors

Automate sender ID registration in AWS End User Messaging

Post Syndicated from Sarath Kumar Kallayil Sreedharan original https://aws.amazon.com/blogs/messaging-and-targeting/automate-sender-id-registration-in-aws-end-user-messaging/

AWS End User Messaging makes it possible to send SMS, MMS, push notifications, WhatsApp messages, and text to voice globally. When you send SMS, MMS, and voice messages with AWS End User Messaging, you must use a specific origination identity that supports sending these messages. Messaging options vary by country and include toll-free numbers (TFN), 10-digit long codes (US 10DLC), long codes, short codes, and sender IDs. To check a country’s available options, refer to Supported countries and regions for SMS messaging with AWS End User Messaging SMS.

This post explains how to programmatically register sender IDs, which can be used in many countries around the globe. The registration process makes it possible for businesses and organizations to send messages using an alphanumeric identifier instead of a phone number, making communications more professional and recognizable to recipients. For example, a fictitious company Example Corp could use the sender ID EXAMPLECO to send SMS. To learn more about sender ID registration, refer to Sender IDs in AWS End User Messaging SMS.

This post explores the AWS End User Messaging APIs required for programmatically registering sender IDs for the Indonesia and India. These sample scripts serve as a reference for sender ID registration in other countries. This automation approach simplifies the registration process, saving time and effort for businesses using AWS End User Messaging for their communication needs.

AWS End User Messaging APIs for sender ID registration

The AWS End User Messaging V2 API contains a set of actions that focus on sender ID registration management:

  • DescribeRegistrationTypeDefinitions – Retrieves registration type details for different countries. You can use DescribeRegistrationFieldDefinitions to view the requirements for creating, filling out, and submitting each registration type.
  • CreateRegistration – Creates a new registration. The RegistrationType field controls whether this is a registration for toll-free, 10DLC, or sender ID. This post will use a sender ID.
  • DescribeRegistrationFieldDefinitions – Retrieves field requirements for a specific registration type (retrieved by DescribeRegistrationTypeDefinitions).
  • PutRegistrationFieldValue – This action must be repeated for all required fields (retrieved by DescribeRegistrationFieldDefinitions).
  • CreateRegistrationAttachment – Uploads a required attachment (for example, a letter of authorization) for registration based on country-specific requirements.
  • SubmitRegistrationVersion – Submits the specified registration for review and approval. Make sure to verify all data is accurate before submitting the registration. The review process consists of the following steps:
    • After your script submits the registration, the initial status appears as CREATED and typically changes to REVIEWING within 24 hours.
    • After submission, your sender ID registration can’t be modified or deleted until the third-party registrar completes their review process.
    • If the status remains CREATED for over 24 hours after you’ve submitted your registration, open a support case for assistance.

Available actions for sender ID registration

As you manage your messaging campaigns in AWS End User Messaging SMS, several APIs are available to help you handle sender ID registrations efficiently:

  • CreateRegistrationVersion – Creates a new version of the registration and increases the VersionNumber. The previous version of the registration becomes read-only. This is useful for updating registration information while maintaining historical records.
  • DescribeRegistrationAttachments – Retrieves the specified registration attachments or all registration attachments associated with your AWS account. This helps in managing and reviewing documents linked to your registrations.
  • DescribeRegistrationFieldValues – Retrieves the specified registration field values. You can use this API to review current registration details for a specific version.
  • DescribeRegistrations – Retrieves the specified registrations and provides an overview of all your sender ID registrations, which is useful for multi-campaign management.
  • DescribeRegistrationSectionDefinitions – Retrieves the specified registration section definitions. You can use DescribeRegistrationSectionDefinitions to view the requirements for creating, filling out, and submitting each registration type. This API helps you understand the structure and requirements of different registration sections.
  • DescribeRegistrationVersions – Retrieves the specified registration version. You can use this API to track changes and view historical versions of a registration.

The following are important considerations for registration:

  • Most registration submissions undergo review by an independent third-party organization. This is a standard industry practice across SMS providers.
  • AWS does not review your registrations. It is important to complete this registration process with the understanding that AWS merely facilitates the submission process. AWS does not participate in or influence the third-party review process.
  • Each country has its own review process and timeline. Each registration is examined on a first-in/first-out basis by the registrar for each country. The registration review is conducted by external personnel unfamiliar with your company or use case. Therefore, it is crucial to provide clear and concise responses in your application.
  • After submitting your registration, the status begins as CREATED and typically transitions to REVIEWING within 24 hours
  • If AWS is able to provide you with a sender ID, AWS sends you an estimated time frame required for its provisioning. In many countries, AWS can provide you with a sender ID within 2–4 weeks. However, in some countries, it can take several weeks to obtain a sender ID.

AWS End User Messaging API usage flow for sender ID registration

The API flow consists of the following steps:

  1. Call DescribeRegistrationTypeDefinitions to understand available registration types.
  2. Use CreateRegistration to initiate the registration process.
  3. To obtain details about the required fields, call DescribeRegistrationFieldDefinitions.
  4. Use PutRegistrationFieldValue multiple times to populate all required fields.
  5. If needed, use CreateRegistrationAttachment to upload supporting documents.
  6. Finally, call SubmitRegistrationVersion to submit the registration for review.
  7. Use DescribeRegistrations periodically to check the status of the registration.

This API flow enables a fully automated sender ID registration process for supported countries. Businesses can efficiently manage registrations across various regulatory environments and geographical locations.

Registration field format

The AWS End User Messaging API uses a specific format to define the registration fields:

  • SectionPath – Represents the hierarchical location of a field within the registration form’s structure. For example, "SectionPath": "companyInfo".
  • FieldPath – The complete path to a specific field, combining the SectionPath with the field name. For example, "FieldPath": "companyInfo.companyName".
  • FieldType – Specifies the data type of the field (such as TEXT, SELECT, or ATTACHMENT). For example, "FieldType": "TEXT".
  • FieldRequirement – Indicates whether the field is REQUIRED, OPTIONAL, or CONDITIONAL. For example, "FieldRequirement": "REQUIRED".

Understanding these attributes is crucial for effective API interaction during the registration process. They define both the structure of your API calls and the necessary data inputs.

The following code is the subset of the response of DescribeRegistrationFieldDefinitions for the United Kingdom registration type (RegistrationType):

{
            "SectionPath": "companyInfo",
            "FieldPath": "companyInfo.companyName",
            "FieldType": "TEXT",
            "FieldRequirement": "REQUIRED",
            "TextValidation": {
                "MinLength": 1,
                "MaxLength": 100,
                "Pattern": "^(?=\\s*\\S)[\\s\\S]+$"
            },
            "DisplayHints": {
                "Title": "Company name",
                "ShortDescription": "Legal name which your company is registered under.",
                "ExampleTextValue": "Example Corp"
            }
        }
        
     {
            "SectionPath": "senderIdInfo",
"FieldPath": "senderIdInfo.senderIdDescription",
            "FieldType": "TEXT",
            "FieldRequirement": "OPTIONAL",
            "TextValidation": {
                "MinLength": 1,
                "MaxLength": 500,
                "Pattern": "^(?=\\s*\\S)[\\s\\S]+$"
            },
            "DisplayHints": {
                "Title": "Sender ID description",
                "ShortDescription": "If it is not obvious, explain the connection between your company name and this sender ID."
            }
        }
        
        {
            "SectionPath": "senderIdInfo",
            "FieldPath": "senderIdInfo.letterOfAuthorization",
            "FieldType": "ATTACHMENT",
            "FieldRequirement": "CONDITIONAL",
            "DisplayHints": {
                "Title": "Letter of authorization image",
                "ShortDescription": "Image of your signed letter of authorization (LOA)"
            }
        }
        {
            "SectionPath": "messagingUseCase",
            "FieldPath": "messagingUseCase.monthlyMessageVolume",
            "FieldType": "SELECT",
            "FieldRequirement": "REQUIRED",
            "SelectValidation": {
                "MinChoices": 1,
                "MaxChoices": 1,
                "Options": [
                    "10",
                    "100",
                    "1,000",
                    "10,000",
                    "100,000",
                    "250,000",
                    "500,000",
                    "750,000",
                    "1,000,000",
                    "5,000,000",
                    "10,000,000+"
                ]
            },
            "DisplayHints": {
                "Title": "Monthly SMS volume",
                "ShortDescription": "Estimated number of SMS messages which will be sent from this sender ID each month."
            }
        }

Prerequisites

Before running either script, you must have the following:

Automate sender ID registration for Indonesia

The Indonesia registration process involves several additional requirements that vary based on your company’s location and business type. All companies must submit XL Axiata’s Letter of Authorization (LOA). Indonesian companies need additional LOAs from Telkomsel, IOH, and Smartfren, plus NIB and NPWP documents. Apply IDR9K and the company stamp to each LOA. For sample documents, refer to Indonesia sender ID registration in AWS End User Messaging SMS. Businesses operating in the money lending sector are required to provide an operating license issued by the Financial Services Authority (Otoritas Jasa Keuangan—OJK).

In this section, we break down the Python script for Indonesia registration.

Before running the registration script, you must first set the necessary variables, with your company actual data. The following is a sample file with the variables required for Indonesia local sender ID registration. Provide the correct path for LOA files (telkomsel_loa.png,ioh_loa.png, xl_axiata_loa.png, smartfren_loa.png,regulatory_licence.png, proof_of_sender_id.png, nomor_pokokWajib_pajak_document.png, and nomor_induk_berusaha_document.png).

Save the following file as indonesia_config.py:

# =============================================================================
# INDONESIA SENDER ID REGISTRATION CONFIGURATION
# =============================================================================
#AWS Region Details
# ---------------------
REGION_NAME='us-west-2'
# Registration Settings
# ---------------------
REGISTRATION_TYPE = 'ID_SENDER_ID_REGISTRATION'  # Registration type for Indonesia
REGISTRATION_NAME = 'INDONESIA_TEST_SENDER_ID'    # Name tag for this registration
# Sender ID Information
# --------------------
# The sender ID to register. Must be between 3 and 11 alphanumeric characters.
# Must contain at least one letter. Example: 'EXAMPLE'
SENDER_ID = 'DEMO'
# Company Information
# ------------------
# Legal name of your company
COMPANY_NAME = 'Example Corp'
# Legal identification number of your company (such as EIN or VAT)
# Must be alphanumeric, 1-30 characters
COMPANY_ID = '123456789'
# Full URL of your company's website
COMPANY_WEBSITE = 'https://www.example.com'
# Select the vertical which most closely aligns with your company's area of business
# Options: Agriculture, Communication, Construction, Education, Energy, Entertainment,
# Financial, Government, Healthcare, Hospitality, Insurance, Manufacturing,
# Real estate, Retail, Technology, Other
AREA_OF_BUSINESS = ['Other']
# Company Address
# ---------------
# Physical street address associated with your company
COMPANY_ADDRESS = '123 Main Street'
# City where the physical address is located
COMPANY_CITY = 'Jakarta'
# Two-digit ISO country code where the physical address is located
COUNTRY_CODE = 'ID'
# Contact Information
# ------------------
# Email address of your company's point of contact
CONTACT_EMAIL = '[email protected]'
# Phone number of your company's point of contact
CONTACT_PHONE = '+6281234567890'
# Messaging Use Case
# -----------------
# Description of your use case for sending SMS messages with this sender ID
USE_CASE_DESCRIPTION = 'For One Time Messages'
# Select the category which most closely aligns with your use case
# Options: One-time passcodes, Account or security alerts, Purchase or delivery notifications,
# Public service announcements, Polling and surveys, Info on demand, Promotions and marketing, Other
USE_CASE_CATEGORY = ['One-time passcodes']
# Estimated number of SMS messages which will be sent from this sender ID each month
# Options: 10, 100, 1,000, 10,000, 100,000, 1,000,000, 10,000,000+
MONTHLY_MESSAGE_VOLUME = ['10,000']
# At least one sample is required of an SMS message which will be sent from this sender ID
# Maximum 306 characters
MESSAGE_SAMPLE = 'Your OTP is XXX'
# Document Paths
# --------------
# Update these paths to point to your actual document files
DOCUMENT_PATHS = {
    # Letter of authorization for Telkomsel (CONDITIONAL - required if company is local to Indonesia)
    # Download, complete, and attach the LOA from AWS documentation
    'TELKOMSEL_LOA': 'telkomsel_loa.png',
    
    # Letter of authorization for IOH (CONDITIONAL - required if company is local to Indonesia)
    # Download, complete, and attach the LOA from AWS documentation
    'IOH_LOA': 'ioh_loa.png',
    
    # Letter of authorization for XL Axiata (REQUIRED for all companies)
    # Download, complete, and attach the LOA from AWS documentation
    'XL_AXIATA_LOA': 'xl_axiata.png',
    
    # Letter of authorization for Smartfren (CONDITIONAL - required if company is local to Indonesia)
    # Download, complete, and attach the LOA from AWS documentation
    'SMARTFREN_LOA': 'smartfren_loa.png',
    
    # Regulatory agency license (OPTIONAL - required only if company's area of business is money lending)
    # Provide operating license from OJK (Otoritas Jasa Keuangan)
    'REGULATORY_LICENSE': 'regulatory_license.png',

Save the following file as indonesia_senderid_registration.py:

import boto3
from typing import Dict, Union, List
import logging
import importlib.util
import argparse
import time
# Set up logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def load_config(config_file):
    """Load configuration from a Python file"""
    spec = importlib.util.spec_from_file_location("config", config_file)
    config = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(config)
    return config
class EndUserMessagingRegistrationIndonesia:
    def __init__(self, config):
        self.client = boto3.client('pinpoint-sms-voice-v2',region_name=config.REGION_NAME)
        self.registration_id = None
        self.config = config
        self.max_retries = 5
        self.retry_delay = 2
    def create_registration(self) -> str:
        """Create a new Sender ID registration"""
        try:
            response = self.client.create_registration(RegistrationType=self.config.REGISTRATION_TYPE,
                                                       Tags=[{'Key': 'Name', 'Value': self.config.REGISTRATION_NAME}])
            self.registration_id = response['RegistrationId']
            logger.info(f"Registration created with ID: {self.registration_id}")
            return self.registration_id
        except Exception as e:
            logger.error(f"Failed to create registration: {str(e)}")
            raise


    def create_attachment(self, file_path: str) -> str:
        """Create and upload attachments"""
        try:
            with open(file_path, 'rb') as file:
                response = self.client.create_registration_attachment(
                    AttachmentBody=file.read()
                )
            attachment_id = response['RegistrationAttachmentId']
            logger.info(f"Created attachment with ID: {attachment_id}")
            return attachment_id
        except Exception as e:
            logger.error(f"Failed to create attachment: {str(e)}")
            raise
    def wait_for_attachment(self, attachment_id: str) -> bool:
        """Wait for attachment upload to complete"""
        for attempt in range(self.max_retries):
            try:
                response = self.client.describe_registration_attachments(
                    RegistrationAttachmentIds=[attachment_id]
                )
                status = response['RegistrationAttachments'][0]['AttachmentStatus']
                if status == 'UPLOAD_COMPLETE':
                    return True
                logger.info(f"Attachment status: {status}, waiting...")
                time.sleep(self.retry_delay)
            except Exception as e:
                logger.error(f"Error checking attachment status: {str(e)}")
                time.sleep(self.retry_delay)
        return False
def update_registration_fields(self, fields: Dict[str, Union[str, List[str], Dict[str, str]]]):
        """Update registration fields with provided values"""
        if not self.registration_id:
            raise ValueError("Registration ID not set. Create registration first.")
        for field_path, value in fields.items():
            try:
                if isinstance(value, dict) and 'attachmentId' in value:
                    self.client.put_registration_field_value(
                        RegistrationId=self.registration_id,
                        FieldPath=field_path,
                        RegistrationAttachmentId=value['attachmentId']
                    )
                elif isinstance(value, list):
                    self.client.put_registration_field_value(
                        RegistrationId=self.registration_id,
                        FieldPath=field_path,
                        SelectChoices=value
                    )
                else:
                    self.client.put_registration_field_value(
                        RegistrationId=self.registration_id,
                        FieldPath=field_path,
                        TextValue=value
                    )
                logger.info(f"Updated field: {field_path}")
            except Exception as e:
                logger.error(f"Failed to update field {field_path}: {str(e)}")
                raise
    def submit_registration(self):
        """Submit the registration for review"""
        if not self.registration_id:
            raise ValueError("Registration ID not set. Create registration first.")
        try:
            self.client.submit_registration_version(RegistrationId=self.registration_id)
            logger.info("Registration submitted successfully")
        except Exception as e:
            logger.error(f"Failed to submit registration: {str(e)}")
            raise
def main():
    parser = argparse.ArgumentParser(description='Indonesia SMS Registration Tool')
    parser.add_argument('--config', required=True, help='Path to config file')
    args = parser.parse_args()
  config = load_config(args.config)
    registration = EndUserMessagingRegistrationIndonesia(config)
    registration.create_registration()
    # Document mappings
    document_mapping = {
        'TELKOMSEL_LOA': 'idSidSpecificInfo.letterOfAuthorization1',
        'IOH_LOA': 'idSidSpecificInfo.letterOfAuthorization2',
        'XL_AXIATA_LOA': 'idSidSpecificInfo.letterOfAuthorization3',
        'SMARTFREN_LOA': 'idSidSpecificInfo.letterOfAuthorization4',
        'REGULATORY_LICENSE': 'idSidSpecificInfo.regulatoryAgencyLicense',
        'PROOF_OF_SENDER_ID': 'senderIdInfo.proofOfSenderIdConnection',
        'NOMOR_POKOK_WAJIB_PAJAK_Document': 'idSidSpecificInfo.nomorPokokWajibPajakDocument',
        'NOMOR_INDUK_BERUSAHA_DOCUMENT': 'idSidSpecificInfo.nomorIndukBerusahaDocument',
    }
    # Process documents
    document_fields = {}
    for doc_type, file_path in config.DOCUMENT_PATHS.items():
        try:
            attachment_id = registration.create_attachment(file_path)
            if registration.wait_for_attachment(attachment_id):
                if doc_type in document_mapping:
                    field_path = document_mapping[doc_type]
                    document_fields[field_path] = {'attachmentId': attachment_id}
                    logger.info(f"Successfully processed {doc_type}")
        except Exception as e:
            logger.error(f"Failed to process {doc_type}: {str(e)}")
            raise
    # Text fields
    text_fields = {
        'senderIdInfo.senderId': config.SENDER_ID,
        'companyInfo.companyId': config.COMPANY_ID,
        'companyInfo.companyName': config.COMPANY_NAME,
        'companyInfo.website': config.COMPANY_WEBSITE,
        'companyInfo.areaOfBusiness': config.AREA_OF_BUSINESS,
        'companyAddress.address1': config.COMPANY_ADDRESS,
        'companyAddress.city': config.COMPANY_CITY,
        'companyAddress.isoCountryCode': config.COUNTRY_CODE,
        'contactInfo.emailAddress': config.CONTACT_EMAIL,
        'contactInfo.phoneNumber': config.CONTACT_PHONE,
        'messagingUseCase.useCaseCategory': config.USE_CASE_CATEGORY,
        'messagingUseCase.useCaseDescription': config.USE_CASE_DESCRIPTION,
        'messagingUseCase.monthlyMessageVolume': config.MONTHLY_MESSAGE_VOLUME,
        'messagingUseCase.optInDescription': config.USE_CASE_DESCRIPTION,
        'messageSamples.messageSample1': config.MESSAGE_SAMPLE
    }
    # Combine all fields
    all_fields = {**text_fields, **document_fields}
    registration.update_registration_fields(all_fields)
    registration.submit_registration()
if __name__ == "__main__":
    main()

Run the script: python indonesia_senderid_registration.py --config indonesia_config.py

Automate sender ID registration for India

Starting April 30, 2025, AWS will offer India sender ID registration through two Regions: Asia Pacific (Mumbai) and Asia Pacific (Hyderabad).

The sender ID registration process for India differs slightly; it doesn’t require an LOA attachment and includes additional fields specific to the Indian regulatory environment.

Before running the registration script, you must first set the necessary variables with your company’s actual data. The following is a sample file with the variables required for India sender ID registration. Modify and save the file as india_config.py:

# =============================================================================
# INDIA SENDER ID REGISTRATION CONFIGURATION
# =============================================================================
#AWS Region Details
# ---------------------
REGION_NAME='ap-south-1'
# Registration Settings
# ---------------------
REGISTRATION_TYPE = 'IN_SENDER_ID_REGISTRATION'  # Registration type for India
REGISTRATION_NAME = 'INDIA_TEST_SENDERID'        # Name tag for this registration
# Sender ID Information
# --------------------
# The sender ID to register. India sender IDs must be 3-6 alphabetic characters.
# Must exactly match the sender ID registered with TRAI (Telecom Regulatory Authority of India)
SENDER_ID = 'DEMO'
# Principal Entity ID (PEID) - REQUIRED
# The PEID received after completing registration with TRAI
ENTITY_ID = '123'
# Chain IDs (India Specific) - ALL REQUIRED
# ----------------------------------------
# Provide approved chain IDs from your DLT platform after creating telemarketer chains
# Chain ID for ROUTE LEDGER TECHNOLOGIES PRIVATE LIMITED
CHAIN_ID_1 = '456'
# Chain ID for Karix Mobile Pvt Ltd  
CHAIN_ID_2 = '789'
# Chain ID for Sinch Cloud Communication Services India Private Limited
CHAIN_ID_3 = '910'
# Chain ID for Infobip India Private Limited
CHAIN_ID_5 = '912'
# Company Information
# ------------------
# Legal name of your company
COMPANY_NAME = 'Example Corp'
# Legal identification number of your company (such as EIN or VAT)
# Must be alphanumeric, 1-30 characters
COMPANY_ID = '123456789'
# Full URL of your company's website
COMPANY_WEBSITE = 'https://www.example.com'
# Select the vertical which most closely aligns with your company's area of business
# Options: Agriculture, Communication, Construction, Education, Energy, Entertainment,
# Financial, Government, Healthcare, Hospitality, Insurance, Manufacturing,
# Real estate, Retail, Technology, Other
AREA_OF_BUSINESS = ['Other']
# Company Address
# ---------------
# Physical street address associated with your company
COMPANY_ADDRESS = '123 Main Street'
# City where the physical address is located
COMPANY_CITY = 'Any Town'
# Two-digit ISO country code where the physical address is located
COUNTRY_CODE = 'IN'
# Contact Information
# ------------------
# Email address of your company's point of contact
CONTACT_EMAIL = '[email protected]'
# Phone number of your company's point of contact
CONTACT_PHONE = '+12605550100'
# Messaging Use Case
# -----------------
# Description of your use case for sending SMS messages with this sender ID
USE_CASE_DESCRIPTION = 'For One Time Messages'
# Select the category which most closely aligns with your use case
# Options: One-time passcodes, Account or security alerts, Purchase or delivery notifications,
# Public service announcements, Polling and surveys, Info on demand, Other
# Note: India does not support 'Promotions and marketing' category
USE_CASE_CATEGORY = ['One-time passcodes']
# Estimated number of SMS messages which will be sent from this sender ID each month
# Options: 10, 100, 1,000, 10,000, 100,000, 1,000,000, 10,000,000+
MONTHLY_MESSAGE_VOLUME = ['10,000']
# At least one sample is required of an SMS message which will be sent from this sender ID
# Maximum 306 characters
MESSAGE_SAMPLE = 'Your OTP is XXX'
# India Specific Settings
# ----------------------
# Acknowledgement that you will specify Entity ID and Template ID when sending messages
# This is REQUIRED and must be 'Yes'
SENDING_PARAMETERS_ACKNOWLEDGMENT = ['Yes']

The following script handles the creation of the registration, updating of India-specific fields, and submission of the registration. Save the following file as india_senderid_registration.py:

import boto3
from typing import Dict, Union, List
import logging
import importlib.util
import argparse
# Set up logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def load_config(config_file):
    """Load configuration from a Python file"""
    spec = importlib.util.spec_from_file_location("config", config_file)
    config = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(config)
    return config
class EndUserMessagingRegistrationIndia:
    def __init__(self, config):
        self.client = boto3.client('pinpoint-sms-voice-v2',region_name=config.REGION_NAME)
        self.registration_id = None
        self.config = config
    def create_registration(self) -> str:
        """Create a new Sender ID registration"""
        try:
            response = self.client.create_registration(RegistrationType=self.config.REGISTRATION_TYPE,
                                                       Tags=[{'Key': 'Name', 'Value': self.config.REGISTRATION_NAME}])
            self.registration_id = response['RegistrationId']
            logger.info(f"Registration created with ID: {self.registration_id}")
            return self.registration_id
        except Exception as e:
            logger.error(f"Failed to create registration: {str(e)}")
            raise
    def update_registration_fields(self, fields: Dict[str, Union[str, List[str]]]):
        """Update registration fields with provided values"""
        if not self.registration_id:
            raise ValueError("Registration ID not set. Create registration first.")
for field_path, value in fields.items():
            try:
                if isinstance(value, list):
                    self.client.put_registration_field_value(
                        RegistrationId=self.registration_id,
                        FieldPath=field_path,
                        SelectChoices=value
                    )
                else:
                    self.client.put_registration_field_value(
                        RegistrationId=self.registration_id,
                        FieldPath=field_path,
                        TextValue=value
                    )
                logger.info(f"Updated field: {field_path}")
            except Exception as e:
                logger.error(f"Failed to update field {field_path}: {str(e)}")
                raise
    def submit_registration(self):
        """Submit the registration for review"""
        if not self.registration_id:
            raise ValueError("Registration ID not set. Create registration first.")
        try:
            self.client.submit_registration_version(RegistrationId=self.registration_id)
            logger.info("Registration submitted successfully")
        except Exception as e:
            logger.error(f"Failed to submit registration: {str(e)}")
            raise
def main():
    parser = argparse.ArgumentParser(description='SMS Registration Tool')
    parser.add_argument('--config', required=True, help='Path to config file')
    args = parser.parse_args()
    
    config = load_config(args.config)
    registration = EndUserMessagingRegistrationIndia(config)
    registration.create_registration()
    fields = {
        'senderIdInfo.senderId': config.SENDER_ID,
        'inSidSpecificInfo.principalEntityId': config.ENTITY_ID,
        'inSidSpecificInfo.chainId1': config.CHAIN_ID_1,
        'inSidSpecificInfo.chainId2': config.CHAIN_ID_2,
        'inSidSpecificInfo.chainId3': config.CHAIN_ID_3,
        'inSidSpecificInfo.chainId5': config.CHAIN_ID_5,
        'inSidSpecificInfo.sendingParametersAcknowledgement': config.SENDING_PARAMETERS_ACKNOWLEDGMENT,
        'companyInfo.companyId': config.COMPANY_ID,
        'companyInfo.companyName': config.COMPANY_NAME,
        'companyInfo.website': config.COMPANY_WEBSITE,
        'companyInfo.areaOfBusiness': config.AREA_OF_BUSINESS,
        'companyAddress.address1': config.COMPANY_ADDRESS,
        'companyAddress.city': config.COMPANY_CITY,
        'companyAddress.isoCountryCode': config.COUNTRY_CODE,
        'contactInfo.emailAddress': config.CONTACT_EMAIL,
        'contactInfo.phoneNumber': config.CONTACT_PHONE,
        'messagingUseCase.useCaseCategory': config.USE_CASE_CATEGORY,
        'messagingUseCase.useCaseDescription': config.USE_CASE_DESCRIPTION,
        'messagingUseCase.monthlyMessageVolume': config.MONTHLY_MESSAGE_VOLUME,
        'messagingUseCase.optInDescription': config.USE_CASE_DESCRIPTION,
        'messageSamples.messageSample1': config.MESSAGE_SAMPLE
    }
    registration.update_registration_fields(fields)
    registration.submit_registration()
if __name__ == "__main__":
    main()

Run the script: python india_senderid_registration.py --config india_config.py

After submission, you can monitor the registration status. Upon approval, the status will show as Complete, as shown in the following screenshot.

The following screenshot shows that the registration requires updates before it can be approved.

The error occurred because the registration code was run in an Region other than AP-SOUTH-1 or AP-SOUTH-2. To resolve this issue, delete the current registration and rerun the process in one of the supported Regions.

As mentioned earlier, DescribeRegistrationFieldDefinitions varies by country, because each has unique registration requirements and field specifications. You must modify this script according to your target country’s specific requirements. Refer to the API documentation for country-specific registration types and field definitions.

Check registration status

Check the status of your registration using either the AWS End User Messaging console or the DescribeRegistrations API. To use the console, choose Registrations under Configurations in the navigation pane.

The registration status for each request will initially display CREATED and will change to REVIEWING within 24 hours after submission. For more information about registration statuses, refer to Check a registration’s status in AWS End User Messaging SMS. If your registration status shows REQUIRES_UPDATES, the registration needs more information. You can edit and resubmit the request with the required information.

As noted earlier, third-party reviewers evaluate registrations. Expect 2-4 weeks for approval, and longer for sender IDs in some countries.

SMS program registrations for ISVs

Independent software vendors (ISVs) are positioned between AWS End User Messaging and the ISV’s end business customers. Though they might operate differently or offer different services, their requirements for SMS program registrations are largely the same. End business refers to your ISV customers. This is generally the entity that creates the messaging content, distributes it through your platform, and interacts with their end-users (message recipients).

SMS program registrations require end-user business information, not ISV information. This means the ISV must provide a mechanism for their end businesses to provide their information to be submitted for registration. ISVs and aggregators must provide information representing the customer entity sending messages to opted-in recipients. Amazon uses this information in accordance with all applicable obligations, and to verify the end-user is a legitimate business. Amazon will not contact the end-business user with the information provided.

Conclusion

In this post, we showed how to automate the sender ID registration process using Python scripts and AWS End User Messaging APIs. Using these APIs can significantly improve efficiency and reduce manual errors. For additional guidance, refer to automating AWS End User Messaging US Toll-Free Number registrations, Automate AWS End User Messaging US toll-free Number Registrations, How to Register a Sender ID Using APIs with AWS End User Messaging, and the AWS End User Messaging V2 API Reference.


About the authors

Enhance email security using VPC endpoints with Amazon SES Manager

Post Syndicated from Gabrielle Zhou original https://aws.amazon.com/blogs/messaging-and-targeting/enhance-email-security-using-vpc-endpoints-with-amazon-ses-manager/

Organizations managing on-premises email infrastructure face a critical challenge: how to modernize email systems while maintaining strict security and compliance standards. For healthcare providers, financial institutions, and government agencies, email messages often contain sensitive data that must remain on private networks throughout processing.

The virtual private cloud (VPC) endpoint feature of Amazon Simple Email Service (Amazon SES) Mail Manager addresses this challenge by enabling SMTP messages to remain on your private network throughout processing, routing, and compliance logging before final delivery. This post walks you through implementing this solution to securely modernize your email infrastructure.

Consider this scenario: You’re responsible for a healthcare organization’s email infrastructure that processes thousands of patient communications daily. Your on-premises Exchange servers are aging, maintenance costs are climbing, and your organization is moving workloads to AWS. Your security team requires that email processing for sensitive patient communications—including workflow processing, temporary storage, rule-based routing, and compliance logging—remain within private, controlled networks until ready for final delivery. The Amazon SES Mail Manager VPC endpoint feature addresses this requirement by maintaining network-level isolation for email operations from generation through processing, minimizing data exposure, meeting compliance requirements, and providing defense-in-depth security before final message delivery.

This post demonstrates how to implement VPC endpoints with Amazon SES Mail Manager using exercises from the Amazon SES Mail Manager workshop. We show how to configure VPC endpoints, security groups, and ingress endpoints to maintain private network connectivity for your email processing workflows.

Solution overview

Our approach combines AWS services to create a secure, private email infrastructure:

This solution requires your applications to run within a VPC or have established connectivity between your on-premises network and Amazon VPC through AWS Direct Connect or VPN. For guidance on connecting on-premises networks to AWS, refer to Hybrid network connections.

The following diagram illustrates the solution architecture.

The workflow consists of the following steps:

  1. Amazon Elastic Compute Cloud (Amazon EC2) instances running the sender email application on subnet 10.0.0.0/18 connect to the Amazon SES Mail Manager ingress endpoint through a VPC endpoint.
  2. Sender credentials are retrieved securely from Secrets Manager.
  3. AWS KMS decrypts credentials using your managed encryption keys.
  4. Authenticated email traffic flows securely to SES Amazon SES Mail Manager.

Prerequisites

Before beginning your migration, ensure you have the following:

  • AWS account – Use an AWS account with appropriate permissions for creating and managing a VPC, Secrets Manager, AWS KMS, and Amazon SES. Make sure AWS Identity and Access Management (IAM) policies follow least privilege principles.
  • Existing VPC infrastructure – Use a VPC that hosts your applications in the same AWS account and AWS Region as Amazon SES. For more information, see Plan your VPC.
  • Amazon SES configured – Configure Amazon SES in the same Region and AWS account.
  • Network connectivity – Deploy application servers either on premises with network connectivity to your VPC using Direct Connect or VPN, or already running within the VPC.

For this example, we use Linux SMTP commands from an EC2 instance in the VPC to connect to the Amazon SES Mail Manager ingress endpoint through a VPC endpoint on port 587.

Create traffic policy

Create an Amazon SES Mail Manager traffic policy to filter incoming messages by a combination of recipient address, sender IP address range, and TLS protocol version (1.2 or 1.3). For more details about Amazon SES Mail Manager traffic policies, refer to Traffic policies and policy statements. In this example, we use a traffic policy with minimum TLS version of 1.2.

Complete the following steps:

  1. Open the Amazon SES console in the target Region.
  2. In the navigation pane, under SES Mail Manager, choose Traffic policies.
  3. Choose Create traffic policy.
  4. For Policy name, enter a descriptive name, such as first-traffic-policy.
  5. For Default action, choose Deny.
  6. Choose Add new policy statement.
  7. For Allow or deny properties, choose Allow.
  8. For Properties, choose TLS protocol version.
  9. For Operator, choose Minimum version.
  10. For Value, choose TLS 1.2.
  11. Choose Create traffic policy.

Create rule set

Rule sets are containers for an ordered set of rules that determine how the messages are processed. For more information, see Rule sets and rules. In this example, we use the archive rule to archive all emails processed by Amazon SES Mail Manager.

Complete the following steps:

  1. On the Amazon SES console, under Amazon SES Mail Manager in the navigation pane, choose Rule sets.
  2. Choose Create rule set.
  3. Name the rule (for example, first-rule-set) and choose Create rule set.
  4. Choose Create new rule, then choose Create new rule again.
  5. Under Rule settings, name the rule (for example, archive_all).
  6. Under Actions, choose Add new action.
  7. Chose Archive.
  8. Choose Create archive.
  9. Give the archive a name, such as archive_all.
  10. Set a retention period (3 months for testing).
  11. Choose Create archive.

  1. For Archive resource name, choose archive_all.
  2. Choose Save rule set.

Create security group

Complete the following steps to create a security group:

  1. On the Amazon VPC console, under Security in the navigation pane, choose Security groups.
  2. Choose Create security group.
  3. For Security group name, provide a name that uniquely identifies the security group. For this example, we name the security group my-sg-mail-manager.
  4. For Description, describe the purpose of this security group.
  5. For VPC, choose the VPC that hosts your applications.
  6. For Inbound rules, choose Add rule.
  7. For Type, choose SMTP.
  8. For Source, enter the IP range of your private subnet.
  9. Choose Add rule again.
  10. For Port range, enter 587 and the IP range of your private subnet.
  11. Choose Create security group.

Create VPC endpoint

VPC endpoints make it possible to keep your email traffic within your private AWS network. Complete the following steps to create a VPC endpoint:

  1. Open the Amazon VPC console in the target Region.
  2. Under PrivateLink and Lattice in the navigation pane, choose Endpoints.
  3. Choose Create endpoint.
  4. For Name tag, enter an optional tag, such as mm-vpce-auth-ingress-endpoint.
  5. Select AWS services.
  6. For Services, enter mail-manager to search for Amazon SES Mail Manager VPC endpoints.
  7. Select com.amazonaws.us-east-1.mail-manager-smtp.auth.fips.

  1. For VPC, choose the VPC that hosts your applications.
  2. For DNS name, select Enable DNS name
  3. For DNS record IP type, select IPv4.
  4. Under Subnets, select all Availability Zones and choose the subnet ID for each subnet.
  5. For IP type, select IPv4.

  1. For Security groups, select the group my-sg-mail-manager.
  2. Choose Create endpoint.

Create ingress endpoint

Complete the following steps to create an authenticated ingress endpoint using Secrets Manager and AWS KMS:

  1. On the Amazon SES console, under Amazon SES Mail Manager in the navigation pane, choose Ingress endpoints.
  2. Choose Create ingress endpoint.
  3. For Ingress endpoint name, enter a unique name for the ingress endpoint. For this example, we use my-authenticated-ingress-endpoint.
  4. For Type, choose Authenticated.
  5. For Authentication type, choose Secret.
  6. Choose Create new, which will open a new tab.
  7. For Secret type, choose Other type of secret.
  8. Under Key/value pairs, enter password as the key (anything else will cause authentication to fail), then enter a password as the value.
  9. For Encryption Key, choose Add new key, which will open a new tab.
  10. Choose Create key.
  11. Keep the default values for Key type and Key usage and choose Next.

  1. For Alias, enter a unique name for your custom managed key. For this example, we use my-mail-manager-key.
  2. For Description, describe the purpose of the key.
  3. Choose Next.

  1. For Key administrators, choose any users (other than yourself) or roles you want to permit to administer the key, then choose Next.
  2. For Key users, choose any users (other than yourself) or roles you want to permit to use the key, then choose Next.
  3. For Key policy, choose Edit, then enter the following KMS key policy into the key policy JSON text editor at the "statement" level by adding it as an additional statement separated by a comma. Replace the Region and account number with your own.
{
    "Effect": "Allow",
    "Principal": {
        "Service": "ses.amazonaws.com"
    },
    "Action": "kms:Decrypt",
    "Resource": "*",
    "Condition": {
        "StringEquals": {
           "kms:ViaService": "secretsmanager.us-east-1.amazonaws.com",
            "aws:SourceAccount": "000000000000"
        },
        "ArnLike": {
            "aws:SourceArn": "arn:aws:ses:us-east-1:000000000000:mailmanager-ingress-point/*"
        }
    }
}
  1. Choose Next.
  2. Review and choose Finish.
  3. Switch to the Secrets Manager tab and choose the refresh icon.
  4. Choose the KMS key you just created, then choose Next.

  1. For Secret name, provide a unique name for the secret. For this example, we use my-mail-manager-secret.
  2. For Description, describe the purpose for the secret.
  3. For Resource permissions, replace the example JSON code in the editor with the following policy. Replace the Region and the account number with your own.
{
    "Version": "2012-10-17",
    "Id": "Id",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ses.amazonaws.com"
            },
            "Action": "secretsmanager:GetSecretValue",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "000000000000"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:ses:us-east-1:000000000000:mailmanager-ingress-point/*"
                }
            }
        }
    ]
}
  1. Choose Save, then choose Next.
  2. Configuring automatic rotation is optional. We skip this step and choose Next.
  3. Review and choose Store.
  4. Switch back to the Amazon SES console tab to finish creating the ingress endpoint.
  5. For Secret ARN, choose Refresh list, then choose the secret you just created.
  6. For Rule set, choose first-rule-set.
  7. For Traffic policy, choose first-traffic-policy.
  8. For Network type, select Private.
  9. For VPC endpoint ID, choose mm-vpce-auth-ingress-endpoint.
  10. Choose Create ingress endpoint.

Test configuration

Complete the following steps to test your configuration:

  1. Open the Amazon VPC console in the target Region.
  2. Under PrivateLink and Lattice in the navigation pane, choose Endpoints.
  3. Choose the VPC endpoint ID of mm-vpce-auth-ingress-endpoint to open the details page.
  4. Find the DNS names for the VPC endpoint. The first DNS name on this list is the Regional DNS name of the VPC endpoint; copy this DNS name and save it on a notepad for later use.

  1. Open the Amazon SES console in the target Region.
  2. Under Amazon SES Mail Manager in the navigation pane, choose Ingress endpoints.
  3. Choose my-authenticated-ingress-endpoint.
  4. In the Authentication section, locate the SMTP user name (typically starts with inp-).

  1. Connect to your EC2 instance using SSH.
  2. Use the command line to send an email using the Amazon SES SMTP interface to test the connectivity. Replace the endpoint with the DNS name of the VPC endpoint you copied earlier.

The message 250 OK esllb73q6bd94cnq004ujd544f169sog39bc9ug1 indicates the message was successfully accepted by Amazon SES Mail Manager.

Clean up

When you’re done with this solution, clean up the resources you created including Mail Manager configurations, security groups, VPC endpoints, KMS keys, and Secrets Manager secrets to avoid additional charges.

Conclusion

In this post, we showed how to enhance email security by implementing Amazon SES Mail Manager with VPC endpoints. This solution can help you modernize your email infrastructure while maintaining network-level isolation and meeting enterprise compliance requirements.

To learn more about Amazon SES, see the Amazon SES Developer Guide. For additional security best practices, refer to AWS Best Practices for Security, Identity, & Compliance. To get started using Amazon SES Mail Manager, participate in an Amazon SES Mail Manager workshop event, explore the advanced workflow features of Amazon SES Mail Manager, and consider integrating with your existing monitoring and alerting systems.


About the authors

Implement Tenants in your Amazon SES environment, Part 3: Implementation guide

Post Syndicated from Rommel Sunga original https://aws.amazon.com/blogs/messaging-and-targeting/implement-tenants-in-your-amazon-ses-environment-part-3-implementation-guide/

This is part 3 in a series covering the new tenants feature in Amazon Simple Email Service (SES). The first post in this series discussed how users can improve email deliverability with tenant management in Amazon SES. Part 2 covered key aspects involved in planning the migration of existing Amazon SES infrastructure to use tenant-based reputation isolation.

With Amazon SES tenants, users can:

  • Manage individual tenant onboardings and their reputations in isolation
  • Provision isolated tenants within a single SES account
  • Apply automated reputation policies to manage email sending
  • Detect and isolate deliverability issues within isolated email streams
  • Preserve sender reputation and improve inbox placement with mailbox providers

This post provides a step-by-step migration guide to Tenants for key AWS components like AWS Identity and Access Management (IAM) permissions, Amazon CloudWatch logging and Amazon EventBridge monitoring. Additionally, we provide several code examples that show how to programmatically provision tenants in real time as customers are onboarded. The goal is to demonstrate how to use the Tenants feature to achieve reputation isolation between customers or business units (BUs), get more control over sending policies, and enable the automatic pause mechanism to limit the damage from problematic senders.

Step-by-step migration guide

Having completed the inventory and configuration planning prescribed in part 2 of this series, we are ready to start the 4-step migration (or implementation) of the tenants feature in the AWS SES account.

The Amazon SES Tenants Migration process is as follows:

  1. Preparation
    1. Verify SES V2 API usage
    2. Update SDK versions
  2. Create Your First Tenant
    1. Create Tenant API calls
    2. Implement in onboarding workflow
    3. Verify tenant creation
  3. Associating Resources
    1. Link verified domains to tenants
    2. Associate configuration sets
    3. Connect IP pools
  4. Updating Your Sending Code
    1. Add Tenant/Name parameter to API calls
    2. Add X-SES-TENANT header for SMTP
    3. Update application sending code
    4. Test email sending functionality

Preparation

When sending email through a tenant, be sure to specify the tenant in the API calls or SMTP headers and ensure that all resources used are associated with that tenant. Before getting started, keep in mind that there’s an additional charge per tenant per month based on the number of emails. For more detailed information, see the SES Pricing page.

For applications that use SMTP, see the SMTP Implementation section later in this document.

For applications that use the SES API, confirm that the latest Amazon SES V2 API is being used, as tenant management capabilities are only available in this version (see SES V2 API migration guide). We also recommend verifying that the AWS SDK version being used supports these operations, otherwise you may need to update to a version that supports them.

The SES V2 API includes the seven essential operations for managing the tenant architecture that the application will need to leverage throughout the migration (or implementation) and tenant lifecycle:

  1. CreateTenant for establishing new tenant containers
  2. CreateTenantResourceAssociation for linking resources like domains and configuration sets to tenants
  3. DeleteTenant for removing tenants when workloads offboard
  4. DeleteTenantResourceAssociation to unlink resources from tenants
  5. GetTenant retrieves specific tenant details
  6. ListTenants provides an overview of all tenants in an account
  7. ListTenantResources shows which resources are associated with each tenant

Implementation Steps

Creating the tenant(s)

The following Python code example uses the AWS SDK for Python (Boto3) and CreateTenant to demonstrate tenant creation. We’ve added optional tags to better organize the tenant resource for billing or logging purposes.

import boto3
from botocore.exceptions import ClientError

def setup_ses_tenant():
    ses_client = boto3.client('sesv2')
    
    # Create a new tenant with descriptive tags
    tenant_response = ses_client.create_tenant(
        TenantName='MyTenant',
        Tags=[
            {
                'Key': 'Environment',
                'Value': 'Production'
            },
            {
                'Key': 'CustomerID',
                'Value': '[customer_id]'
            }
        ]
    )
    
    # Verify tenant creation
    tenants = ses_client.list_tenants()
    print(f"Total tenants in account: {len(tenants['Tenants'])}")
    
    return tenant_response['TenantName']


if __name__ == "__main__":
    try:
        tenant_name = setup_ses_tenant()
        print(f"Successfully created tenant: {tenant_name}")
    except ClientError as e:
        print(f"AWS error: {e}")
    except Exception as e:
        print(f"Unexpected error: {e}")

This example code can be used when a customer first onboards onto the platform to send email. By creating a tenant for this customer, resources under that tenant will be associated together whenever the tenant is used as explained in the next steps.

Associating resources with the tenant

Each tenant needs appropriate resources—configuration sets, sending identities, and potentially dedicated IP pools—to begin sending email. The association process should align with the resource sharing strategy as established during the migration planning phase.

The following Python code example uses the AWS SDK for Python (Boto3) and CreateTenantResourceAssociation to associate resources to the tenant that was created in the previous step.

import boto3
from botocore.exceptions import ClientError

def associate_resources_with_tenant():
    ses_client = boto3.client('sesv2')
    
    try:
        # Associate verified domain identity
        ses_client.create_tenant_resource_association(
            TenantName='MyTenant',
            ResourceArn='arn:aws:ses:[aws_region]:[account_id]:identity/[domain_name]'
        )
        print("Successfully associated email identity with tenant")

        # Associate configuration set for tracking
        ses_client.create_tenant_resource_association(
            TenantName='MyTenant',
            ResourceArn='arn:aws:ses:[aws_region]:[account_id]:configuration-set/MyTenantConfigurationSet'
        )
        print("Successfully associated configuration set with tenant")

    except ClientError as e:
        print(f"Error: {e.response['Error']['Message']}")
        raise

if __name__ == "__main__":
    associate_resources_with_tenant()

Consider implementing batch association for email streams with multiple domains or configuration sets. This approach reduces API calls and improves provisioning efficiency. Remember that resources can be shared across multiple tenants if the architecture requires it, allowing flexible resource allocation strategies.

Update the applications

The transition to tenant-based sending requires minimal code changes in the apps, namely adding the TenantName and ConfigurationSetName to the sending process.

API Implementations

For applications that use the SES V2 API, add the tenant and configuration set parameters to the send calls as demonstrated below using the AWS SDK for Python (Boto3) :

import boto3

def send_email_from_tenant():
    ses_client = boto3.client('sesv2')
    
    response = ses_client.send_email(
        FromEmailAddress='sender@[domain_name]',
        Destination={
            'ToAddresses': ['[recipient_email]']
        },
        Content={
            'Simple': {
                'Subject': {
                    'Data': 'Test email from SES tenant'
                },
                'Body': {
                    'Text': {
                        'Data': 'This is a test email sent from an SES tenant'
                    }
                }
            }
        },
        ConfigurationSetName='MyTenantConfigurationSet',
        TenantName='MyTenant'  # Critical addition for tenant routing
    )
    
    print(f"Message sent! Message ID: {response['MessageId']}")
    return response

if __name__ == "__main__":
    send_email_from_tenant()

SMTP Implementations

For sending applications that use SMTP, add the X-SES-TENANT and the ConfigurationSetName header parameters to every message. In the code block that follows, we demonstrate the proper header configuration for SMTP sending using Python:

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib

def send_smtp_email_with_tenant():
    sender = 'smtp-sender@[domain_name]'
    sender_name = 'Sender Name'
    recipient = '[recipient_email]'
    username_smtp = '[smtp_username]'
    configuration_set = 'MyTenantConfigurationSet'
    host = 'email-smtp.[aws_region].amazonaws.com'
    port = 587
    
    subject = 'Amazon SES test (SMTP interface accessed using Python)'
    body_text = """Email Test
    This email was sent through the Amazon SES SMTP interface using Python."""
    body_html = """<h1>Email Test</h1>
        <p>This email was sent through the 
        <a href="https://aws.amazon.com/ses">Amazon SES</a> SMTP
        interface using Python."</p>"""
    
    msg = MIMEMultipart('alternative')
    msg['Subject'] = subject
    msg['From'] = f"{sender_name} <{sender}>"
    msg['To'] = recipient
    msg['X-SES-CONFIGURATION-SET'] = configuration_set
    
    # Critical: Specify tenant for SMTP sending
    msg['X-SES-TENANT'] = 'MyTenant'
    
    part1 = MIMEText(body_text, 'plain')
    part2 = MIMEText(body_html, 'html')
    msg.attach(part1)
    msg.attach(part2)
    
    try:
        server = smtplib.SMTP(host, port)
        server.ehlo()
        server.starttls()
        server.ehlo()
        server.login(username_smtp, fetch_smtp_password_from_secure_storage())
        server.sendmail(sender, recipient, msg.as_string())
        print("Email sent successfully!")
        
    except Exception as e:
        print(f"Error: {str(e)}")
    
    finally:
        server.quit()

def fetch_smtp_password_from_secure_storage():
    # Implement secure password retrieval from AWS Secrets Manager
    # or your preferred secret storage solution
    return '[smtp_password]'


if __name__ == "__main__":
    send_smtp_email_with_tenant()

Configuring IAM policies and permissions for tenants

This section explains how to configure IAM permissions for SES tenants, including how to set up different permission levels for tenant management, email sending, and monitoring while following security best practices to control access based on organizational roles. Remember that IAM policies for tenants follow the principle of least privilege. Start with minimal permissions and expand as needed, regularly reviewing and removing unused permissions to maintain security.

Tenant management permissions

SES Tenants can be controlled through specific IAM permissions that determine who can create, modify, and use specific tenant(s) in the organization. The tenant management system’s core API actions discussed previously can be granted with granular access through IAM policies for administrative operations. The Service Authorization Reference for Amazon Simple Email Service v2 page contains the latest documentation for the service-specific actions used below for Amazon Simple Email Service.

We recommend limiting each IAM role’s permission based on the minimum capabilities required by that role. This helps mitigate the potential for negative effects if an SMTP credential is misused. What follows is a basic IAM policy that demonstrates full tenant management capabilities; this is NOT demonstrating the principle of least privilege (yet):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ses:CreateTenant",
                "ses:DeleteTenant",
                "ses:GetTenant",
                "ses:ListTenants",
                "ses:CreateTenantResourceAssociation",
                "ses:DeleteTenantResourceAssociation",
                "ses:ListTenantResources",
                "ses:ListResourceTenants"
            ],
            "Resource": "*"
        }
    ]
}

Configuring sending permissions with tenants

Applications that send emails through tenants need different permissions than those managing tenants. The key distinction is using the ses:TenantName condition to restrict which tenants an application can use for sending.

The IAM policy below allows sending emails only through the specified CustomerA-Tenant tenant, ensuring applications can’t accidentally or maliciously send through other customers’ tenants.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ses:SendEmail",
                "ses:SendBulkEmail"
            ],
            "Resource": [
                "arn:aws:ses:[aws_region]:[account_id]:identity/*",
                "arn:aws:ses:[aws_region]:[account_id]:configuration-set/*"
            ],
            "Condition": {
                "StringEquals": {
                    "ses:TenantName": "CustomerA-Tenant"
                }
            }
        }
    ]
}

Separating administrative and operational access

Production environments implement role separation between tenant management and email sending operations. Administrative roles handle tenant creation and resource association during customer onboarding, while application roles can only send emails through assigned tenants. The IAM policy below is an example of an administrative role; it allows creating and configuring tenants for use during customer onboarding but does not allow the tenant deletion action to prevent accidental deletions.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ses:CreateTenant",
                "ses:ListTenants"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ses:CreateTenantResourceAssociation",
                "ses:GetTenant"
            ],
            "Resource": "arn:aws:ses:[aws_region]:[account_id]:tenant/*/tn-*"
        },
        {
            "Effect": "Deny",
            "Action": "ses:DeleteTenant",
            "Resource": "*"
        }
    ]
}

Resource-level permissions

Tenants support resource-level permissions using Amazon Resource Names (ARNs), enabling fine-grained access control. Grant access to specific tenants by specifying the tenant name and tenant id (ex. CustomerA-Tenant/tn-1a2b3c4d5e6f7890abcdef1234567890) rather than granting blanket permissions using the “*/tn-*” wildcard as above. To obtain the tenant id you can use the list-tenants command of the AWS SESv2 CLI.

The IAM policy below grants access only to tenants CustomerA-Tenant and CustomerB-Tenant where the following tenant id is a placeholder that should be replaced by the correct tenant id that you obtained from list-tenants.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ses:GetTenant",
            "Resource": [
                "arn:aws:ses:[aws_region]:[account_id]:tenant/CustomerA-Tenant/tn-1a2b3c4d5e6f7890abcdef1234567890",
                "arn:aws:ses:[aws_region]:[account_id]:tenant/CustomerB-Tenant/tn-9876543210fedcba0987654321abcdef"
            ]
        }
    ]
}

Monitoring and compliance access

Security and compliance teams often need read-only access to monitor tenant usage. The following IAM policy grants read-only access to all tenants, but does not permit modifications or deletions of any tenants:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ses:GetTenant",
                "ses:ListTenants",
                "ses:ListTenantResources"
            ],
            "Resource": "*"
        }
    ]
}

Monitoring Tenants with EventBridge and CloudWatch

Amazon SES integrates with Amazon EventBridge to deliver comprehensive monitoring capabilities for tenant management, providing real-time visibility into reputation changes and enabling automated response workflows. EventBridge is a serverless service that uses JSON-formatted events to connect application components, making it straightforward to build scalable event-driven applications. Amazon SES’s tenant feature’s integration with EventBridge enables organizations to track tenant-specific metrics and other metrics, such as reputation findings and reputation status changes, and tenant status changes.

Understanding EventBridge Integration with SES

EventBridge operates as a router that receives events from SES and delivers them to one or many destinations (aka targets). When SES features experience state changes or status updates, they automatically send events to the EventBridge default event bus. Rules associated with the event bus evaluate events as they arrive, checking whether each event matches the rule’s pattern before routing to specified targets. For SES tenant management, organizations can receive real-time alerts through Amazon EventBridge when tenant reputation findings are detected or when tenant status changes occur. These events are delivered on a best-effort basis; they might be delivered out of order, requiring users to deploy processing logic to handle such scenarios gracefully.

The code block that follows can guide users through the basic EventBridge integration with the SES tenant feature. For more extensive documentation on integrating with EventBridge please consult AWS documentation.

Setting up EventBridge integration

Create an EventBridge rule using the AWS SDK for Python (Boto3) to capture tenant status changes and reputation findings:

# Create rule for monitoring tenant status changes
aws events put-rule \
    --name "SESTenantStatusMonitor" \
    --description "Monitor SES tenant status changes" \
    --event-pattern '{
        "source": ["aws.ses"],
        "detail-type": [
            "Sending Status Enabled",
            "Sending Status Disabled",
            "Advisor Recommendation Status Open",
            "Advisor Recommendation Status Closed"
        ]
    }'

Routing events from EventBridge to CloudWatch Logs

CloudWatch provides the capability to collect raw data and process it into readable, near real-time metrics. Follow these steps to set up a CloudWatch log group for SES tenant events and configure the appropriate IAM permissions:

  1. Create a CloudWatch log group for tenant events:

aws logs create-log-group --log-group-name "/aws/ses/tenants"

  1. Add resource-based policy to CloudWatch Logs:
aws logs put-resource-policy \
    --policy-name EventBridgeToCloudWatchLogsPolicy \
    --policy-document '{
        "Version": "2012-10-17",
        "Statement": [{
            "Sid": "TrustEventsToStoreLogEvent",
            "Effect": "Allow",
            "Principal": {
                "Service": ["events.amazonaws.com", "delivery.logs.amazonaws.com"]
            },
            "Action": ["logs:CreateLogStream", "logs:PutLogEvents"],
            "Resource": "arn:aws:logs:[aws_region]: [account_id]:log-group:/aws/ses/tenants:*"
        }]
    }'
  1. Add the EventBridge target:

aws events put-targets \
    --rule "SESTenantStatusMonitor" \
    --targets '[{
        "Id": "SendToCloudWatchLogs",
        "Arn": "arn:aws:logs:[aws_region]:[account_id]:log-group:/aws/ses/tenants"
    }]'

An example event of a paused (“disabled”) tenant is shown below for reference:

{
    "version": "0",
    "id": "3cc76530-9842-03a9-fdef-e4e4f667cf4e",
    "detail-type": "Sending Status Disabled",
    "source": "aws.ses",
    "account": "[account_id]",
    "time": "2025-10-01T03:37:17Z",
    "region": "[aws_region]",
    "resources": [
        "arn:aws:ses:[aws_region]::tenant/CustomerA-Tenant/tn-2a8c678ec0000fdaf76cc1f127b40"
    ],
    "detail": {
        "version": "1.0.0",
        "data": {
            "origin": "CUSTOMER_MANAGED",
            "record": {
                "status": "DISABLED",
                "cause": "Status manually updated.",
                "lastUpdatedTimestamp": [
                    2025,
                    10,
                    1,
                    3,
                    37,
                    17,
                    671000000
                ]
            }
        }
    }
}

Managing tenant reputation with key Tenants features

Reputation management for individual tenants is one of the core benefits of using Amazon SES’s tenant feature, providing automated protection against deliverability issues that could damage overall account reputation. This section demonstrates how to configure reputation policies that can automatically pause tenants when they experience high bounce rates or reputation issues, as well as how to manually control tenant sending status for custom workflows.

Setting reputation policies

Amazon SES provides three reputation policy enforcement levels that determine how the system responds to reputation findings.

  • The Standard policy (recommended) pauses sending only for high-impact findings, providing a balance between protection and operational flexibility.
  • The Strict policy pauses sending for any reputation finding, offering maximum protection for sensitive environments.
  • The None option disables automated pausing while continuing to track findings, useful for manual monitoring scenarios.

Reputation findings are generated in two severity levels—low and high—based on metrics like bounce rates and complaint rates. When these metrics indicate a potential deliverability issue, SES creates findings that can trigger automatic pausing based on a chosen policy.

In the following code block, we demonstrate how to set a reputation policy on the CustomerA-Tenant

import boto3
from botocore.exceptions import ClientError

def update_tenant_reputation_policy(tenant_arn, policy_arn):
    ses_client = boto3.client('sesv2')
    
    ses_client.update_reputation_entity_policy(
        ReputationEntityType='RESOURCE',
        ReputationEntityReference=tenant_arn,
        ReputationEntityPolicy=policy_arn
    )
    print(f"Tenant policy_arn updated to: {policy_arn}")

# Example usage
if __name__ == "__main__":
    tenant_arn = "arn:aws:ses:[aws_region]:[account_id]:tenant/CustomerA-Tenant/tn-2a8c678ec0000fdaf76cc1f127b40"
    
    # Enable normal sending
    update_tenant_reputation_policy(tenant_arn, 'arn:aws:ses:[aws_region]:aws:reputation-policy/standard')
    
    # Disable/pause sending
    update_tenant_reputation_policy(tenant_arn, 'arn:aws:ses:[aws_region]:aws:reputation-policy/strict')
    
    # Reinstate with monitoring
    update_tenant_reputation_policy(tenant_arn, 'arn:aws:ses:[aws_region]:aws:reputation-policy/none')

Our recommendation is to choose the Standard policy for most production tenants, as this policy provides automatic protection against severe reputation issues while avoiding unnecessary disruptions. Reserve the Strict policy for new or untrusted tenants where maximum caution is warranted. Use the None option during initial monitoring periods or when implementing custom reputation management logic.

Handling paused tenants

When a tenant is paused, either automatically through reputation policies or manually, the sending status prevents any emails from being sent through that tenant. The system derives this aggregate status from both customer-managed and AWS-managed statuses; if either is set to DISABLED, the tenant cannot send emails.

Amazon SES publishes notifications to EventBridge when tenant status changes occur or new reputation findings are detected, enabling real-time response to reputation events. After investigating and resolving the underlying issues, the tenant’s sending capabilities can be reinstated. During reinstatement (REINSTATED status), the tenant can continue sending while metrics are monitored to verify improvement.

def update_tenant_status(tenant_arn, status):
    ses_client = boto3.client('sesv2')
    
    ses_client.update_reputation_entity_customer_managed_status(
        ReputationEntityType='RESOURCE',
        ReputationEntityReference=tenant_arn,
        SendingStatus=status
    )
    print(f"Tenant status updated to: {status}")

# Example usage
if __name__ == "__main__":
    tenant_arn = "arn:aws:ses:[aws_region]:[account_id]:tenant/CustomerA-Tenant/tn-2a8c678ec0000fdaf76cc1f127b40"
    
    # Enable normal sending
    update_tenant_status(tenant_arn, 'ENABLED')
    
    # Disable/pause sending
    update_tenant_status(tenant_arn, 'DISABLED')
    
    # Reinstate with monitoring
    update_tenant_status(tenant_arn, 'REINSTATED')

The REINSTATED status allows the tenant to continue sending even with active reputation findings. Once metrics return to healthy levels, the tenant automatically transitions back to ENABLED status. This approach ensures minimal disruption while protecting the overall account reputation from problematic email streams.

Managing tenant lifecycle

When customers modify a service tier or leave the platform, proper cleanup ensures resource efficiency and maintains account organization.

Removing resource associations

Before deleting a tenant, remove all resource associations to prevent orphaned configurations:

import boto3
from botocore.exceptions import ClientError

def remove_resource_from_tenant():
    ses_client = boto3.client('sesv2')
    
    try:
        # Remove identity association
        ses_client.delete_tenant_resource_association(
            TenantName='MyTenant',
            ResourceArn='arn:aws:ses:[aws_region]:[account_id]:identity/[domain_name]'
        )
        print("Successfully removed identity association")
        
        # Remove configuration set association
        ses_client.delete_tenant_resource_association(
            TenantName='MyTenant',
            ResourceArn='arn:aws:ses:[aws_region]:[account_id]:configuration-set/MyTenantConfigurationSet'
        )
        print("Successfully removed configuration set association")
    
    except ClientError as e:
        print(f"Error: {e.response['Error']['Message']}")
        raise


if __name__ == "__main__":
    remove_resource_from_tenant()

Deleting tenants

Once all resources are disassociated, remove the tenant entirely:

import boto3
from botocore.exceptions import ClientError

def delete_tenant(tenant_name):
    ses_client = boto3.client('sesv2')
    
    try:
        # Delete the tenant
        ses_client.delete_tenant(TenantName=tenant_name)
        print(f"Successfully deleted tenant: {tenant_name}")
        return True
        
    except ClientError as e:
        print(f"Error deleting tenant: {e.response['Error']['Message']}")
        raise

# Example usage with error handling
if __name__ == "__main__":
    try:
        delete_tenant("MyTenant")
    except ClientError as e:
        print(f"Cleanup failed: {e}")

Tenant lifecycle management ensures clean transitions when customers change service tiers or leave the platform. Implement these operations in customer offboarding workflows to maintain optimal account organization and resource utilization.

Resource Management

Resource Sharing Capabilities

Resources can be assigned to multiple tenants simultaneously. This enables sharing common resources between tenants while maintaining separate reputation tracking. For example, the reputation for marketing and transactional email could be tracked separately across independent tenants while using the same sending domain. SES validates tenant-resource associations at send time, rejecting requests if the specified tenant lacks access to the requested resources.

Resource Migration Between Tenants

Resource migration involves two API calls. First, remove the association from the current tenant using DeleteTenantResourceAssociation, then create a new association with the target tenant using CreateTenantResourceAssociation. This process can be automated for bulk migrations during reorganizations.

Reputation Management

Tenant Isolation Protection

Each tenant maintains independent reputation metrics and sending status. When one tenant experiences deliverability issues, it can be automatically paused without affecting other tenants’ ability to send, protecting both shared resources and account-level reputation.

Tenant Pausing Triggers

Tenants can either be paused manually using the UpdateReputationEntityCustomerManagedStatus API or paused automatically based on the reputation policy assigned to the tenant. Reputation policies pause tenants based on reputation findings generated from bounce rates, complaint rates, and third-party feedback reports. The Standard policy (recommended) pauses only for high-severity findings (bounce rate > 15%, complaint rate > 1%), while Strict pauses even for low severity findings (bounce rate > 10%, complaint rate > 0.5%).

Tenant Reactivation Process

For tenants paused by automated reputation policies, use the UpdateReputationEntityCustomerManagedStatus API to reinstate sending after addressing root causes. Tenants paused by AWS Trust & Safety require case resolution through AWS Support.

Migrating Existing Customers

Creating tenants for existing email streams can be completed with no disruption to email sending. Start by creating tenants for each customer or business unit, then associate existing resources like email identities, configuration sets, and templates using the tenant association APIs. Once those steps are complete, update the application, or inform the customer or BU they now need to specify the tenant name and configuration set in their SES SendEmail API calls or SMTP headers which enables SES to route emails through the appropriate tenant.

Reputation Metrics Transition

New reputation metrics will be tracked separately for each tenant from the point of creation and use. Historical metrics from before tenant implementation are not available. Tenant metrics contribute to the overall account-level reputation. For example, if tenant-a, tenant-b, and tenant-c each send 1,000 emails and:

  • Tenant-a receives 150 bounce notifications over 1,000 emails (for a bounce rate of 15%), tenant reputation protection will pause this tenant before the issue escalates.
  • Tenant-b receives 0 bounces over 1,000 emails, for a bounce rate of 0%
  • Tenant-c receives 0 bounces over 1,000 emails, for a bounce rate of 0%

The SES Account Level Bounce Rate (all tenants) is 150 out of 3,000, or 5%

Account Activation Requirements

No account-level activation is required to configure and use the Tenant feature, it is immediately available through the SES V2 API or the AWS SES Console. Users can also start using the tenant management APIs (CreateTenant, CreateTenantResourceAssociation, DeleteTenant, etc.) without any account modifications or support requests.

Conclusion

This post covered detailed migration steps, monitoring setup, practical implementation examples and troubleshooting steps. From running a SaaS platform, to managing multiple brands, to operating separate business units, tenant-based reputation isolation ensures Amazon SES email infrastructure scales reliably as an organization grows.

Additional resources


About the authors

Implement Tenants in your Amazon SES environment, Part 2: Assessment and planning

Post Syndicated from Rommel Sunga original https://aws.amazon.com/blogs/messaging-and-targeting/implement-tenants-in-your-amazon-ses-environment-part-2-assessment-and-planning/

Running multiple users or business units (BUs) on a shared email infrastructure often creates deliverability and compliance risks. The tenant-based reputation isolation feature in Amazon Simple Email Service (Amazon SES) solves these challenges by separating email reputation by customer, BU, or workload. This is part 2 in a series covering the new tenants feature in Amazon Simple Email Service (SES). The first post in this series discussed how users can improve email deliverability with tenant management in Amazon SES (for more details, see the blog post).

In this post, we provide an overview of the tenants feature and guidance for planning the implementation to or migration of your existing Amazon SES infrastructure to use tenant-based reputation isolation.

Part 3 covers practical implementation steps for the tenants feature, including configuration steps for key components like Identity and Access Management (IAM) permissions, Amazon CloudWatch logging, and Amazon EventBridge monitoring. We also provide code examples using the Amazon SES v2 APIs that show how to provision tenants in real time as you onboard downstream customers or business divisions onto your Amazon SES account. Key outcomes include complete reputation isolation between customers, control over sending policies, and automated pause mechanisms for problematic senders.

Solution overview

Amazon SES now offers tenant management capabilities that enable isolated email sending environments within a single AWS account. This provides granular reputation management across different email streams. You can assign dedicated configuration sets, sending identities, and templates to each tenant. Each tenant functions as a logical container that maintains its own sending reputation independently. This tenant-based reputation isolation makes sure deliverability issues with one tenant won’t affect your other tenants. You also get real-time visibility into tenant-level metrics, including messages sent, bounce rates, and complaint rates.

The following diagram illustrates the solution architecture.

Tenants are a best practice for those who want visibility, isolation, and control over their email reputation, from large-scale platforms to smaller teams:

  • Independent software vendors (ISVs) with multiple customers, and marketing and software as a service (SaaS) solutions using a central AWS SES account – You can provision a tenant for each customer to segregate email sending and prevent one client’s sending from negatively affecting deliverability for other clients.
  • Enterprises and other large organizations with multiple BUs – You can maintain separate reputation profiles for different BUs, departments, or brands within the same AWS account.
  • Organizations with distinct mail streams – You can separate transactional and marketing mail, or keep product notifications distinct from internal communications, to make sure issues with one tenant’s email stream don’t affect the other tenants.
  • Single-stream senders – Even if you currently only operate one email stream, you can future-proof your SES account by assigning a tenant from day one. This provides visibility into reputation findings and helps you apply proactive policies to stay ahead of deliverability issues before they impact sending.

In the following sections, we outline how to plan and execute your migration to Amazon SES tenants. We show how to assess your current setup, choose the right tenant structure for your organization, and implement a gradual rollout that minimizes disruption to your existing email operations.

Pre-migration assessment

If you are already using Amazon SES, the transition to tenant-based architecture begins with understanding your current email infrastructure. Start by creating an inventory of your existing sending identities (domains) and identify what, if any, Amazon SES configuration set is assigned. This will help you understand how each customer or BU is currently distributed across your Amazon SES infrastructure. Review each configuration set to identify and track the various configuration options, such as the sending IP pool and archive option. The information you uncover in this phase will serve as the blueprint for your tenant associations and help you make sure each tenant has access to the appropriate resources, while maintaining proper isolation boundaries.

Recommended tenant structure: Individual tenants per customer

For most implementations, we recommend creating one or more tenants per customer or BU so you can achieve complete tenant-level isolation of email workloads. With this approach, you can supply dedicated SMTP or API credentials per tenant to provide secure access to allocated resources. You can apply different reputation policies per tenant as needed and automatically pause any tenant that conflicts with the reputation policy. Additionally, the shared tenant monitoring tools in Amazon SES help you automatically monitor and enforce reputation-based policies at the tenant level, so that problematic email sending behavior from one tenant doesn’t impact the deliverability of others.

The following diagram shows an example of an ISV that operates a SaaS platform on AWS that sends emails on behalf of its many customers from a single Amazon SES account. They have followed the recommended approach by implementing a 1:1 mapping between tenants and customers. This strategy provides complete reputation isolation for each customer and makes sure the ISV operating the Amazon SES account can automatically prevent deliverability issues from one customer from impacting others. This architecture minimizes the reputation damage a single tenant can cause to the ISV’s Amazon SES account’s shared resources like IP pools and domains, making it the optimal choice for maintaining high deliverability standards.

Resource sharing strategies

Your resource allocation strategy depends on your business model and customer segmentation. Consider the following recommended approaches:

  • Complete resource isolation – Each customer, brand, BU, or workload is assigned to individual, dedicated resources using the tenant configuration. This approach offers the simplest migration path: associate each customer’s dedicated resources (identities, IP addresses) with their corresponding tenant and continue operations with enhanced isolation. This model works well for enterprise customers and ISVs who deploy dedicated IPs for customers and require complete separation.
  • Tiered resource sharing – Organizations and ISVs with service tiers (such as free, pro, and VIP) can align tenants and resource sharing with these tiers. Free-tier customers might use the free-tier tenant and share basic resources, pro customers access the pro-tier tenant that maps to enhanced shared resources, and VIP customers receive dedicated resources, often using VIP customer-specific tenants. This balances cost-efficiency with appropriate isolation levels for each customer segment.
  • Extensive resource sharing – Even when email streams share most resources in the Amazon SES account, such as sending identities and IP pools, tenant isolation tenant isolation allows you to protect the sender reputation for independent email streams you send through the shared resources. Consider grouping similar types of customers or email streams into a single tenant or assigning a certain number of customers to each tenant. Although the grouping might be varied, the Amazon SES tenant feature can still minimize the effect of problematic email streams in any one tenant from affecting other tenants by pausing the offending tenant. This helps avoid Amazon SES account-level reputation damage to shared resources, protecting customers and stakeholders using those resources.

Tenant limits and quotas

Amazon SES provides tenant limits to accommodate various organizational scales. The default limit supports 10,000 tenants per account, which is sufficient for most organizations. Qualifying accounts can request increases for more tenants as needed through the Service Quotas console.

Importantly, implementing tenants doesn’t impact your account-level sending quotas or transactions per second (TPS) limits; these remain unchanged and continue to apply across the tenants within your account.

Low-friction adoption

Amazon SES tenants are designed for low-friction adoption, providing isolated containers for your existing Amazon SES email infrastructure. With tenants, you can continue sending emails using your current domains, configuration sets, and IP pools while progressively associating them with appropriate tenants. If you use them, your senders can continue targeting their assigned configuration set. After you’ve configured your Amazon SES account with tenants, instruct your customers or event buses to add a new Amazon SES API call or SMTP header specifying their unique tenant ID. If you aren’t yet using configuration sets, we’ve found that the introduction of the Amazon SES tenants feature often serves as a compelling reason for ISVs and large organizations to adopt configuration sets. If your organization has been looking for ways to offer enhanced email services to existing customers, you might want to use this opportunity to review customer accounts and offer dedicated IPs or email archiving to important email workloads. The ability to gradually roll out the Amazon SES tenants feature facilitates selective adoption, starting with a subset of customers, brands, event buses, or workloads before expanding to your entire customer base. This phased approach enables testing and refinement of your tenant strategy without disrupting existing email operations. Organizations can validate their tenant configuration with low-risk customers before rolling out to critical segments, providing a smooth transition to enhanced reputation management.

Conclusion

In this post, we discussed key aspects of the migration process to Amazon SES tenants, from initial assessment to tenant structure planning. Part 3 of this series will cover details of IAM configuration, monitoring setup, and practical implementation examples. Whether you’re running a SaaS platform, managing multiple brands, operating separate BUs, or just starting to use Amazon SES for your organization, the tenant feature provides simple reputation isolation, boosts efficiency, and helps create better experiences for users.

To learn more, refer to the following resources:


About the authors

Learning email deliverability with Amazon SES

Post Syndicated from Alaa Hammad original https://aws.amazon.com/blogs/messaging-and-targeting/learning-email-deliverability-with-amazon-ses/

Emails landing in spam folders? Facing account suspension warnings? This blog post walks you through seven targeted video tutorials that address the most common Amazon Simple Email Service (Amazon SES) deliverability challenges our customers encounter. Each video in this series provides actionable insights which will allow you to gain knowledge on every aspect of email deliverability, improve your email performance and increase your inbox placement rates.

Why email deliverability matters

Poor deliverability can lead to emails landing in spam folders, increase bounce rates, and can trigger account suspension. Email deliverability directly impacts:

  • Your sender reputation
  • Inbox placement rates
  • Customer engagement
  • Business revenue
  • Compliance with email service provider policies.

Our video series will help you avoid these pitfalls and build a robust email delivery strategy, including onboarding to Amazon SES, choosing your IP, monitoring feedback, reputation, and how to handle unsubscribes, bounces, and complaints.

Onboarding your email solution to Amazon SES

Watch: SES Deliverability learning series: Onboarding your email solution to Amazon SES

What you’ll learn: This video provides a complete migration roadmap for moving your email system to Amazon SES, including domain verification and authentication setup through DKIM, SPF, and DMARC protocols. You’ll learn how to move the account to the production access, acquire and configure dedicated IPs, create and manage configuration sets, and set up Virtual Deliverability Manager for email monitoring. The video also covers the difference between SMTP and API sending methods to explain bulk sender requirements and how to comply with them for successful email delivery.

How this helps with email deliverability: Following SES best practices when onboarding your email system to Amazon SES will help protect your emails from being spoofed, with proactive monitoring using Virtual Deliverability Manager, you can identify issues before they impact delivery, maintaining strong sender reputation and sustained email delivery success.

Choosing the right Amazon SES IP

Watch: SES Deliverability learning series: Choosing the Right Amazon SES IP for Your Email Needs

What you’ll learn: Key differences between shared IPs, dedicated IPs (Managed and Standard), How to choose the right IP environment based on your sending volume and use case, best practices for managing IP reputation, the IP warm-up process and its importance, and shared responsibilities between you and Amazon SES when using dedicated IPs. This video shows you how to rebuild trust with mailbox providers through proper IP management.

How this helps with email deliverability: If your account’s reputation was impacted due to poor sending practices, switching to dedicated IPs can help isolate your reputation and provide better control over your sending environment.

Monitoring email feedback

Watch: Mastering email deliverability: Monitoring email feedback

What you’ll learn: Discover how Amazon SES feedback loops can prevent account pause by alerting you to rising complaint, understanding and analyzing complaint data, utilizing mailbox provider postmaster tools, setting up comprehensive monitoring dashboards, tracking deliverability and engagement metrics, and strategies for emails to reach intended recipients. This video teaches you how to set up systems that alert you to rising complaint rates, bounce rates, and other warning signs before they started to impact your account’s ability to send emails.

How this helps with email deliverability: Proper monitoring is essential for preventing further complaints or bounces that could put your AWS account at risk of termination.

Email reputation with Amazon SES

Watch: Mastering email deliverability: Email Reputation with Amazon SES

What you’ll learn: What email reputation is and why it matters, how email providers evaluate sender reputation, best practices for isolating and managing your reputation, authentication methods to protect your reputation, and effective monitoring techniques for reputation management.

How this helps with email deliverability: Understanding email reputation is important for maintaining a good reputation with mailbox providers.

Handling email unsubscribes

Watch: Mastering email deliverability: Handling email unsubscribes

What you’ll learn: The importance of proper unsubscribe handling, how to remove unsubscribes from your SES mailing lists, the connection between unsubscribes and deliverability rates, strategies to maintain clean email lists, how to identify and prevent mass unsubscribe events, what to do when you see high unsubscribe rates. This video shows you how to properly handle unsubscribes and reduce rates that might trigger spam complaints by mailbox providers or impact your account’s ability to send emails.

How this helps with email deliverability: High unsubscribe rates often indicate content quality issues, sending emails to users who don’t want or expect, list hygiene issue, not having a proper confirmed opt-in, and sending too frequently.

How to handle bounces and boost inbox success

Watch: Mastering Email Deliverability: How to Handle Bounces and Boost Inbox Success

What you’ll learn: Different types of email bounces (soft and hard bounces), What each bounce type indicates about your campaign health, practical strategies to manage and reduce bounce rates, best practices for cleaning your email lists, how to implement effective bounce monitoring systems, steps to identify and address unusual bounce trends, and actionable solutions for common bounce-related challenges. This video provides specific strategies to clean your lists and reduce bounce rates that could impact your account’s ability to send emails, helping you demonstrate improved sending practices with SES.

How this helps with email deliverability: High bounce rates often indicate that a sender is sending unsolicited email to their recipients.

Understanding and handling email complaints

Watch: Mastering Email Deliverability: Understanding and Handling Email Complaints

What you’ll learn: What email complaints are and why they matter, different types of complaints (spam reports, unsubscribe requests), how complaints directly impact your deliverability rates, the correlation between complaint rates and spam folder placement , strategies to keep complaint rates within ideal ranges, practical tips to proactively reduce email complaints, and best practices for content creation and opt-out options. This video helps you understand how to maintain a healthy sender reputation by implementing best practices that align with email service provider guidelines and minimize potential risks to the email system.

How this helps with email deliverability: Mailbox providers may reject emails received from senders based on the complaints they received from their recipients.

Take action today

Don’t let deliverability issues impact your business success. Each video in this series provides practical, actionable guidance that you can implement immediately. Whether you’re dealing with account suspensions issue or simply want to optimize your email performance, these videos will help you establish reliable email delivery that meets mailbox provider requirements.

Ready to get started? Begin with the video that addresses your most pressing challenge, then work through the complete series to learn more about all aspects of email deliverability with Amazon SES.

Have questions about implementing these strategies? The AWS Support team is here to help you optimize your email deliverability and resolve any challenges you may be facing.


About the author

Onboard at Cloud Speed with Rapid7 and AWS IAM Delegation

Post Syndicated from Rapid7 original https://www.rapid7.com/blog/post/cds-onboard-at-cloud-speed-with-rapid7-aws-iam-delegation

Every great product experience starts with a smooth beginning. But in the world of cloud security, onboarding can sometimes feel like an obstacle course. Detailed fine-grained Identity and Access Management (IAM) configurations, lengthy deployment steps, and manual permission setups can turn what should be an exciting first impression into a tedious chore.

That’s changing. Rapid7 has enhanced the onboarding experience for Exposure Command and InsightCloudSec by integrating with AWS IAM temporary delegation – a new AWS capability that lets customers approve deployment access directly in the AWS console. The result? A faster, simpler, and more secure path to getting up and running in the cloud.

Why onboarding matters – and why it often fails  

The first minutes with a new platform matter. It’s the difference between “this is amazing” and “I’ll come back to it later.”

In cloud environments, setup usually involves multiple AWS services – compute, storage, networking, access management – all of which must be configured precisely to maintain security. Traditionally, customers have had to manually create IAM roles, adjust trust relationships, and fine-tune permissions just to let a partner solution like Rapid7 deploy resources.

It’s not just time-consuming; it’s error-prone. Misconfigured roles can cause deployment failures or unnecessary security risk. Support teams spend hours walking customers through the process, and the friction delays time-to-value. When scaling across dozens or hundreds of AWS accounts, those delays multiply fast.

Meet AWS IAM temporary delegation: What it is and why it matters

AWS IAM temporary delegation simplifies the entire setup journey. It allows trusted partners like Rapid7 to automate deployment securely – but only after the customer grants explicit, time-bound approval.

Here’s how it works: When you initiate onboarding from within Rapid7’s interface, you’re redirected to the AWS console. There, you can review the exact permissions Rapid7 is requesting and how long access will last. Once approved, AWS provides Rapid7 with temporary credentials to complete the setup. After the time window expires, that access ends automatically.

No long-term IAM keys, no manual role creation, and no guesswork. Customers stay in control, with full visibility and auditability. It’s automation with accountability built in.

How Rapid7 is putting this into action

With the latest release, Rapid7 has integrated this capability directly into Exposure Command and InsightCloudSec, creating a guided onboarding experience that happens almost entirely inside the Rapid7 interface.

Here’s the new flow:

  1. Customers configure deployment options in Rapid7’s InsightCloudSec environment.
  2. A temporary delegation request appears via an AWS console pop-up.
  3. An authorized AWS user reviews and approves the request.
  4. Rapid7 automatically deploys the necessary resources on the customer’s behalf.

This streamlined workflow eliminates dozens of manual steps and reduces onboarding time from hours to minutes. It’s faster, simpler, and still fully aligned with AWS’s strict security model. 

Speed, simplicity, and security

This integration hits the sweet spot between automation and trust:

  • Speed: Customers can start realizing value from Rapid7’s cloud security solutions in minutes instead of days.

  • Simplicity: The UI-driven process means no wrestling with IAM policies or JSON templates.

  • Security: Access is temporary and permission-scoped. Customers retain complete oversight through the AWS console and CloudTrail logs.

For organizations with compliance or security governance requirements, this is the ideal balance: operational efficiency without compromising control.

Beyond onboarding: What this says about Rapid7 and AWS alignment

This update isn’t just about faster onboarding. It’s a glimpse into Rapid7’s broader partnership with AWS. Rapid7 has long been an AWS Advanced Tier Partner, building integrations that help customers manage security across cloud-native environments. From leveraging AWS telemetry in MXDR to integrating with AWS services like CloudTrail and GuardDuty, Rapid7’s platform has been designed to meet customers where they already operate within AWS.

By adopting AWS IAM temporary delegation early, Rapid7 reinforces its commitment to cloud-first innovation and shared responsibility principles. Customers get the assurance that their onboarding, deployment, and operations all align with AWS security best practices. 

What this means for customers

If you’re deploying Rapid7 Exposure Command (Advanced or Ultimate) or InsightCloudSec on AWS, here’s what to expect:

  • A guided onboarding experience that automates AWS resource setup.
  • A faster, less error-prone workflow that still keeps you in control.
  • The ability for authorized users to approve temporary access requests directly in the AWS console.

Before onboarding, make sure someone in your organization has the permissions to approve delegation requests. After deployment, review your CloudTrail logs as part of normal governance;  you’ll see every action logged and time-bounded.

Value from day one

Onboarding shouldn’t be a hurdle. And now with AWS IAM Temporary Delegation and Rapid7’s enhanced experience, it no longer is. Together, AWS and Rapid7 have reimagined what “getting started” looks like in the cloud – faster, more intuitive, and just as secure as you need it to be.

It’s one more way Rapid7 is helping organizations unlock value from day one, while staying aligned with AWS’s best practices for identity, access, and automation.

See how easy secure onboarding can be.Explore Rapid7’s listings for Exposure Command and InsightCloudSec straight from the AWS Marketplace.

Introducing Rapid7 Curated Intelligence Rules for AWS Network Firewall

Post Syndicated from Rapid7 original https://www.rapid7.com/blog/post/cds-rapid7-curated-intelligence-rules-aws-network-firewall

Outsmart attackers with smarter rules

Managing network security in a dynamic cloud environment is a constant challenge. As traffic volume grows and threat actors evolve their tactics, organizations need protection that can scale effortlessly while delivering robust, intelligent defense. That’s where a service like AWS Network Firewall becomes essential, and we’re excited to partner with AWS to make it even more powerful.

What is AWS Network Firewall?

AWS Network Firewall (AWS NWF) is a managed service that provides essential, auto-scaling network protections for Amazon Virtual Private Clouds (VPCs). While its flexible rules engine offers granular control, defining and maintaining the right rules to defend against evolving threats is a complex and resource-intensive task.

Manually creating and updating rules often leads to coverage gaps and creates significant operational overhead. To simplify this process and empower teams to act with confidence, Rapid7 is proud to announce the availability of Curated Intelligence Rules for AWS Network Firewall. As an AWS partner, we convert our curated intelligence on Indicators of Compromise (IOCs) from into high-quality rule groups, delivering expert-vetted threat intelligence directly within your native AWS experience.

Harnessing industry-leading threat intelligence

In the world of threat intelligence, more isn’t always better. Too many low-fidelity alerts generate noise, distract analysts, and leave teams chasing false positives. At Rapid7, our approach is different. We focus on delivering high-fidelity intelligence, enabling customers to zero in on the threats most relevant to their unique environments. 

Rapid7 Curated Intelligence Rules embody this same approach, and are built on three key principles:


Focus on quality over quantity – Rules emphasize meaningful, low-noise detection directly aligned with current, real-world threats, significantly reducing alert fatigue.

Curated global intelligence – Rule sets are powered by high-quality, region-specific data from unique sources, providing unparalleled visibility and context for actionable detections.

Dynamic and self-cleaning rule sets – Threat intelligence is not static. Using Rapid7’s proprietary , rules are automatically retired when an IOC passes a certain threshold, ensuring the delivered intelligence is always fresh, relevant, and current.

We’re launching with two distinct rule sets, each designed to address today’s most pressing threats:

  • Advanced Persistent Threat (APT) campaigns: Targets the subtle and persistent techniques used by state-sponsored and sophisticated threat actors.

  • Ransomware & cybercrime: Focuses on the tools, infrastructure, and indicators associated with financially motivated attacks.

These rule sets are updated daily to ensure you have the most current protections. Furthermore, our intelligence is dynamic. When an IOC passes a certain threshold in our proprietary Decay Scoring system, we remove it from the rule set. This process guarantees that the intelligence you receive is always current and actionable, significantly reducing alert fatigue.

The operational advantage

These Curated Intelligence Rules deliver immediate and tangible value, allowing your team to:

  • Automate threat protection: Reduce overhead with curated, continuously updated detections delivered natively within AWS Network Firewall.

  • Adopt protections faster: Deploy protections powered by Rapid7 Labs intelligence with just a few clicks in the console.

  • Maintain predictable operations: Rely on AWS-validated updates, clear rule group metadata, and transparent per-GB metering.

Common use cases addressed

Our rule sets provide practical defense against a wide range of attack scenarios. You can:

  • Block command and control (C2) communication from known malware families

  • Detect network reconnaissance activity associated with advanced persistent threats

  • Prevent data exfiltration to malicious domains linked to cybercrime groups

  • Identify and stop the download of malware payloads from compromised websites

  • Alert on traffic to newly registered domains used in malicious activities

Get started with Curated Intelligence Rules for AWS NFW today

Ready to enhance your cloud security with curated, actionable intelligence? Add our rule sets to your and strengthen your organization’s defenses in minutes.
››› Visit the listing in the AWS Marketplace to learn more.

How to register for a US toll-free number with AWS End User Messaging

Post Syndicated from Tyler Holmes original https://aws.amazon.com/blogs/messaging-and-targeting/how-to-register-for-a-us-toll-free-number-with-aws-end-user-messaging/

As businesses increasingly use SMS messaging to engage with customers at scale, having the right origination identity is crucial. Toll-free numbers (TFNs) are the quickest way to begin sending to the United States and offer a trusted, high-visibility option that can drive greater response and brand recognition. This post is for every company that wants to send to the US or internationally.

Obtaining and properly registering a US toll-free number requires a registration process and adhering to requirements set forth by mobile carriers. This comprehensive guide walks you through the step-by-step procedure for registering a US toll-free number through AWS End User Messaging, which provides robust SMS capabilities to AWS customers.

The benefits of using a US toll-free number

TFNs offer several key advantages over other SMS origination types in the US market:

Toll-free facts

  • The opt-out flow for US TFNs is managed at a network level and enforced by US Carriers. If a user sends the word stopor any of the other supported keywords—to the TFN, the carrier sends the following outbound message to the user: NETWORK MSG: You replied with the word "stop" which blocks all texts sent from this number.
    Text back unstop or start to receive messages again. This behavior cannot be changed.
  • Toll-free numbers have a throughput of three Message Parts per Second (MPS).
  • International toll-free numbers are two-way capable in the US and Canada but are one-way only in all other supported countries. Depending on the country being sent to, if not the US or Canada, your end-user can receive your message from an originator other than your TFN. This feature can be turned on before or after registration.

The TFN registration process

To get started, you need to create a US toll-free number registration in the AWS Management Console for AWS End User Messaging or use the API.

  1. Company information: Provide details about your business, including the company name, website, and headquarters address.
  2. Contact information: Enter the name, email, and phone number of the individual who will serve as the main point of contact for your TFN program. This email address should match the domain of the company being registered and cannot be a distribution list, contact group, or mailing list. This information will be used for verification or in the event of something needing to be communicated to you about your TFN. It will not be public knowledge.
  3. Messaging use case: Describe how you intend to use the TFN, including your estimated monthly SMS volume, and select the Use Case Category (such as two-factor authentication, notifications, or marketing).
  4. Use case details: It’s critical that the Use Case Details field and all message templates are consistent with the Use Case Category you selected in the previous step.

For example, if you select two-factor authentication or one-time passwords, your Use Case Details should explain how you plan to use your TFN for that use case, who you will interact with, and why. Answers must be written in English, and it is very important to be clear and concise in this section. Humans are reviewing these, so make sure that everything you write can be understood without prior knowledge of your company or your use case.

  1. Opt-in Workflow Description: This has several boiler-plate components that must be present at the point of opt-in and are discussed in depth in this blog post. If you have a verbal opt-in, you can include the script in this field. If you have a publicly available form, you can supply the URL in the description. Regardless of the format, you must include the following elements at the point of opt in:
    1. Program (brand) name.
    2. Explicitly state the purpose of the SMS program that your end-users are opting into.
    3. Have no prefilled checkboxes, radio buttons, or other fields.
    4. Message frequency disclosure. For example: Message frequency varies or One message per login.
    5. Customer care contact information. For example, Text HELP or call 1-800-111-2222 for support.
    6. Opt-out information. For example: Text STOP to opt-out of future messages.
    7. Include Message and data rates may apply disclosure.
    8. Link to a publicly accessible terms and conditions page.
        • Note: See this post on opt-in processes for terms that must be included.
        • If you are unable to include a public link to your terms, you can include them in the Opt-in workflow image field or alternatively attach them to the registration form or another method like an Amazon S3 presigned URL. Make sure to keep it separate from the actual opt-in screenshots.
    9. Link to a publicly accessible privacy policy page.
        • Note: Carriers are primarily concerned with data sharing of opt-in information to third parties. It’s recommended to have a specific SMS section that addresses that no data gathered during opt-in is shared. See this post on opt-in processes for more details on creating a compliant privacy policy.
        • If you’re unable to include a public link, you can include the full terms in the Opt-in workflow image field or alternatively attach them to the registration form or another method like an Amazon S3 presigned URL. Make sure to keep it separate from the actual opt-in screenshots.
  2. Opt-in workflow image: Upload an image showing how users consent to receiving messages.
    • The maximum file size is 500 KB, and valid file extensions are PDF, JPEG, and PNG.
    • This could be a screenshot of a non-public form, a written consent form, or other evidence of a compliant explicit opt-in that includes all the elements detailed previously.
    • Make sure that the screenshot is clear and readable; degraded image quality will likely be rejected regardless of compliance.
  3. Message samples: Each sample message should reflect actual messages to be sent, should match the Use Case Category you indicated previously, and should follow these best practices:

    • Indicate any variable fields with brackets and make sure to be clear what information can be replaced.
    • Example: Hi, [FirstName] this is AnyCompany letting you know that your delivery is ready.
    • Each sample message must be at least 20 characters. If you plan to use multiple message templates, include them too.
    • Ensure that all messages include your brand name and that it’s consistent with the previously entered information.
    • Make sure your messaging doesn’t involve prohibited content such as cannabis, hate speech, and so on; and that your use case is compliant with AWS Messaging Policy.
  4. Review and submit: Verify that all information is accurate before submitting your registration for approval. There are no exceptions to an explicit opt-in—this includes one-time password use cases, so make sure that your registration includes all the required elements.

The TFN provisioning process

After your TFN registration is submitted it will be reviewed by the same third-party as all other SMS vendors across the globe, not by AWS. You can find current registration time estimates in the number registration process. While waiting, you can monitor your registration status for rejection or acceptance. This AWS blog post has an example of using AWS Lambda to monitor status changes.

If your registration is rejected, the status will change to REQUIRES_UPDATES and should have at least one rejection reason that needs to be reviewed and updated before resubmitting. Follow these instructions to update a rejected registration.

Sending SMS messages and monitoring delivery receipts

After your TFN is activated, you can begin sending SMS messages through AWS End User Messaging. It’s important to monitor your program closely and maintain compliance, because carriers might filter or block your messages if there are issues with your program. This blog post reviews best practices for how to monitor deliverability of SMS messages.

Conclusion

Make sure to follow each step carefully and answer each question completely. There are humans reviewing these so it’s important that your answers are succinct and clear.

As an AWS customer, you have access to powerful messaging capabilities through AWS End User Messaging. By following the steps outlined in this guide, you can quickly register for a US toll-free number to start your SMS outreach. Maintaining compliance is key, and with a TFN in place, you’ll be well on your way to delivering highly effective, compliant SMS messaging that drives real business impact. If you have other questions about AWS End User Messaging, see the comprehensive API specs, the User Guide, or reach out to AWS Support.


About the authors