SonofaBleepBloop
SonofaBleepBloop

Reputation: 49

ClientError: An error occurred (AccessDenied) when calling the SendEmail operation:

I want to use lambda to send automated emails whenever a file hits a specific region of an s3-bucket. When I place the file in the bucket at the given location and it attempts to run I receive the following error in cloudwatch logs:

[ERROR] ClientError: An error occurred (AccessDenied) when calling the SendEmail operation: User `arn:aws:sts::123456789012:assumed-role/my-bot-role-abcdefg/my-bot' is not authorized to perform `ses:SendEmail' on resource `arn:aws:ses:eu-west-1:123456789012:identity/[email protected]'
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 44, in lambda_handler
    Message = message   )
  File "/var/runtime/botocore/client.py", line 316, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/var/runtime/botocore/client.py", line 626, in _make_api_call
    raise error_class(parsed_response, operation_name)

I have written the following permissions into the json policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "logs:*"
            ],
            "Effect": "Allow",
            "Resource": "*"
        },
        {
            "Action": [
                "ses:SendEmail"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:ses:eu-west-1:123456789012:identity/*"
        }
    ]
}

The basis of the code I am using within the lambda handle before I plan to modify it for specific purposes is not my own:

import json
import boto3

email_defaults = {
    "port" : 465,  # For SSL
    "smtp_server" : "smtp.gmail.com",
    "sender_email" : "[email protected]", #replace as needed in testing
    "receiver_email" : "[email protected]" #replace as needed in testing
    }

def lambda_handler(event, context):

    for i in event["Records"]:
        action = i["eventName"]
        ip = i["requestParameters"]["sourceIPAddress"]
        bucket_name = i["s3"]["bucket"]["name"]
        object = i["s3"]["object"]["key"]

    client = boto3.client("ses")

    subject = str(action) + 'Event from ' + bucket_name
    body = """
        <br>
        This email is to notify you regarding {} event.
        The object {} has been uploaded.
        Source IP: {}
    """.format(action, object, ip)

    message = {"Subject": {"Data": subject}, "Body": {"Html": {"Data": body}}}

    response = client.send_email(   Source = email_defaults["sender_email"], 
                                    Destination = {"ToAddresses": [email_defaults["receiver_email"]]}, 
                                    Message = message   )

    return "Hello world"

Any guidance on anything I may have overlooked would be appreciated, but I'm quite stumped currently.

Upvotes: 3

Views: 5874

Answers (1)

Fidel Duque
Fidel Duque

Reputation: 72

you have to add the policy that enables the email sending to your role.

in the console, go to your IAM service IAM Service

then, on the left side choose roles:

choose roles

select your role: select role

then add inline policy inline policy

choose SES as service, then all SES Actions, and all resources (you can reduce this permissions if needed)

then review and save. and done! you're ready to send emails via lambda

Upvotes: 1

Related Questions