AWS SES
Lambda function
Access Denied error
Email sending issue
Cloud troubleshooting

Access Denied while sending email from AWS SES in Lambda function

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

An AccessDenied error from SES inside Lambda usually means one of three things: the Lambda execution role is missing SES permissions, the SES identity is not allowed in that region, or the account is still constrained by SES sandbox rules. The fix becomes much easier once you separate IAM permission failures from SES identity and account-state problems.

Start With the Lambda Execution Role

The Lambda function needs permission to call SES. For a basic send operation, the role usually needs ses:SendEmail or ses:SendRawEmail.

A minimal IAM policy looks like this:

json
1{
2  "Version": "2012-10-17",
3  "Statement": [
4    {
5      "Effect": "Allow",
6      "Action": [
7        "ses:SendEmail",
8        "ses:SendRawEmail"
9      ],
10      "Resource": "*"
11    }
12  ]
13}

Attach that policy to the Lambda execution role, not to your personal user account. A common mistake is testing with broad permissions in the console and then forgetting that Lambda runs under a different role.

Make Sure the SES Client Uses the Right Region

SES identities and permissions are region-specific in common setups. If the Lambda function creates an SES client in a different region from the verified sender, the call can fail even when the IAM policy looks correct.

A clean boto3 example:

python
1import boto3
2
3ses = boto3.client("ses", region_name="us-east-1")
4
5response = ses.send_email(
6    Source="[email protected]",
7    Destination={"ToAddresses": ["[email protected]"]},
8    Message={
9        "Subject": {"Data": "Hello"},
10        "Body": {"Text": {"Data": "Sent from Lambda"}}
11    }
12)
13
14print(response["MessageId"])

Make the region explicit so the code and the SES setup are clearly aligned.

Check the Sender Identity

SES may deny the send because the Source address or domain is not verified in the region you are using. That is not the same problem as missing IAM permissions, but it often appears during the same debugging session.

If you send from [email protected], verify either:

  • that exact email address
  • or the domain that covers it

If the identity is not verified, SES rejects the message even when Lambda is allowed to call the API.

Sandbox Restrictions Still Matter

In SES sandbox mode, you can usually send only to verified recipients. That often surprises people because the error shows up during a permission-related workflow, but the root cause is actually account state rather than IAM.

So a good debugging checklist is:

  1. does the Lambda role have SES send permissions
  2. is the sender verified in the same SES region
  3. is the recipient allowed under current SES sandbox rules

You need all three to be true.

Logging the Failure Properly

Log the exact AWS error message from the exception rather than only printing "send failed." That makes the difference between IAM, identity, and sandbox issues visible:

python
1import boto3
2from botocore.exceptions import ClientError
3
4ses = boto3.client("ses", region_name="us-east-1")
5
6try:
7    ses.send_email(
8        Source="[email protected]",
9        Destination={"ToAddresses": ["[email protected]"]},
10        Message={
11            "Subject": {"Data": "Hello"},
12            "Body": {"Text": {"Data": "Sent from Lambda"}}
13        }
14    )
15except ClientError as error:
16    print(error.response["Error"]["Code"])
17    print(error.response["Error"]["Message"])
18    raise

That output often tells you directly whether you are dealing with AccessDenied, a verification problem, or sandbox limitations.

Common Pitfalls

The most common mistake is updating the wrong IAM principal. The Lambda execution role needs permission, not just the developer account.

Another issue is region mismatch. SES setup in one region does not automatically make another region work.

Teams also verify the sender but forget that sandbox mode can still block unverified recipients. That can look like a mysterious policy problem until you check the account state.

Summary

  • Check the Lambda execution role first for ses:SendEmail or ses:SendRawEmail.
  • Use the SES client in the same region where your sender identity is verified.
  • Verify the sender address or domain before sending.
  • Remember that SES sandbox mode can still restrict recipients.
  • Log the exact AWS error code and message so IAM and SES configuration issues do not get mixed together.

Course illustration
Course illustration

All Rights Reserved.