0

My Lambda function creates a text file in /tmp location within in lambda environment.

I am failing to send the file as an attachment using Lambda SES Python

I am following code from below AWS documentation to send RAW email with attachment using SES Python3.6

https://docs.aws.amazon.com/ses/latest/DeveloperGuide/examples-send-raw-using-sdk.html

def send_mail_with_attach_ses(sender, recipient, aws_region, subject, file_name):
    # The email body for recipients with non-HTML email clients.
    BODY_TEXT = "Hello,\r\nPlease find the attached file."

    # The HTML body of the email.
    BODY_HTML = """\
    <html>
    <head></head>
    <body>
    <h1>Hello!</h1>
    <p>Please find the attached file.</p>
    </body>
    </html>
    """

    CHARSET = "utf-8"
    client = boto3.client('ses',region_name=aws_region)

    msg = MIMEMultipart('mixed')
    # Add subject, from and to lines.
    msg['Subject'] = subject 
    msg['From'] = sender 
    msg['To'] = recipient    

    msg_body = MIMEMultipart('alternative')
    textpart = MIMEText(BODY_TEXT.encode(CHARSET), 'plain', CHARSET)
    htmlpart = MIMEText(BODY_HTML.encode(CHARSET), 'html', CHARSET)

    # Add the text and HTML parts to the child container.
    msg_body.attach(textpart)
    msg_body.attach(htmlpart)

    # Define the attachment part and encode it using MIMEApplication.
    att = MIMEApplication(open(file_name, 'rb').read())

    att.add_header('Content-Disposition','attachment',filename=os.path.basename(file_name))

    if os.path.exists(file_name):
        print("File exists")
    else:
        print("File does not exists")

    # Attach the multipart/alternative child container to the multipart/mixed
    # parent container.
    msg.attach(msg_body)

    # Add the attachment to the parent container.
    msg.attach(att)

    try:
        #Provide the contents of the email.
        response = client.send_raw_email(
            Source=msg['From'],
            Destinations=[
                msg['To']
            ],
            RawMessage={
                'Data':msg.as_string(),
            },
            ConfigurationSetName="ConfigSet"
        )
    # Display an error if something goes wrong. 
    except ClientError as e:
        print(e.response['Error']['Message'])
    else:
        print("Email sent! Message ID:"),
        print(response['MessageId'])


    # Add a header to tell the email client to treat this part as an attachment,
    # and to give the attachment a name.
    att.add_header('Content-Disposition','attachment',filename=os.path.basename(ATTACHMENT))

    # Attach the multipart/alternative child container to the multipart/mixed
    # parent container.
    msg.attach(msg_body)

    # Add the attachment to the parent container.
    msg.attach(att)

After trigger the lambda the function is reaching to response = client.send_raw_email and never returning until the lambda timesout. My lambda timeout is configured for 3 minutes.

{
  "errorMessage": "2019-07-30T10:14:45.180Z fc3ca995-58f9-4f89-8a35-114d941ee063 Task timed out after 180.06 seconds"
}

Can anyone help to send email with attachment using Lambda SES Python?

LG555
  • 145
  • 1
  • 2
  • 8
  • Where is the file located and what is the size of it? – Abdullah Khawer Jul 30 '19 at 11:53
  • Can your lambda reach ses endpoint. Are you running in VPC? – titogeo Jul 30 '19 at 12:00
  • @abdullahkhawer the file size is tiny, it's around 10KB – LG555 Jul 30 '19 at 12:54
  • @titogeo - Yes, my lambda is in vpc, my vpc has route table with internet gateway and attached to all subnets in the vpc. How to check the connectivity between lambda and ses endpoint? – LG555 Jul 30 '19 at 12:56
  • @user3276214 and where is the file located? – Abdullah Khawer Jul 30 '19 at 13:01
  • @user3276214 you can test the connectivity by creating a smallest EC2 instance (e.g., t2.micro or t2.nano) with the same VPC, Subnet and Security Group as that of the Lambda function and running AWS SES CLI command for send raw email. – Abdullah Khawer Jul 30 '19 at 13:04
  • @abdullahkhawer the file is located within the lambda container in /tmp location. The file is getting created with the other function in the same lambda. – LG555 Jul 30 '19 at 13:15
  • Make a simple code with boto3. For example, list instances or describe any services. If this is not working then the internet connection might be a problem. – Lamanus Jul 30 '19 at 13:39

2 Answers2

1

Your Lambda is timing out after 180 seconds. For what you're looking to achieve it shouldn't take this long.

Instead of increasing the timeout you should work out where the bottleneck is in your code and fix that.

John H
  • 47
  • 1
  • 7
0

you just have to extend the timeout value under basic settings of the function. It can go up to 15 mins.