Sending E-mail Using Amazon SES With PDF Attachment

Sending E-mail Using Amazon SES With PDF Attachment

Doesn’t it look like the good old email is standing the test of time — tall and strong? Whether it’s sending a message to a colleague or writing down a well-worded business proposal to a client, the email never goes out of style! 

Even if you need to share an image with your recipient — that’s where email attachments, particularly sending a PDF document come in handy. Are you looking for a way to easily send high-volume emails for your business, without breaking the bank? Look no further than email using Amazon SES!  In this exciting blog, we'll dive into the world of Amazon SES and sending email with PDF attachment using Amazon SES.

Specifically, we'll be using AWS Lambda to create a script that will automatically send your emails when triggered. With this powerful combination of tools, you can streamline your email communication process and save time and effort. So buckle up and get ready to learn how to send professional-looking email using Amazon SES with ease!

 

What is Amazon SES?

Amazon ses logo

As a cloud-based email service provided by Amazon, SES enables businesses of all sizes to send transactional emails, marketing messages, and other types of communication with ease. But that's not all - SES is also scalable and reliable, ensuring that your messages get delivered to your recipients without fail. Additionally, sending email with PDF attachment using Amazon SES offers a seamless solution for sharing important documents with your customers or clients.

 

Implementation

In this blog, we will only focus on Amazon SES email sending with PDF attachment and not how to set up userpool.

Amazon SES is a cost-effective email service that charges only for the number of emails sent and received. If you’re wondering how to send bulk email with Amazon SES, know that it is designed to be highly scalable, which means it can handle a large volume of emails without any issues.
 

Step 1: Set up Amazon SES

  • To send email using Amazon SES, we will need to first set up SES from AWS console.
  •  Before sending an email, verify the email from which you will send the email.
  • To send emails using Amazon SES, verify your email address or domain. 
  • In the SES console, go to the "Email Addresses" or "Domains" section and click "Verify a New Email Address" or "Verify a New Domain", respectively.
  • Follow the instructions to verify ownership of the email address or domain you want to use. 

Now, you are a step closer to Amazon SES email sending with attached PDF.

 

Step 2: Create an IAM user for SES

We need to give  lambda role and policies to use cognito-idp services and ses services

    ## policy for allowing cognito-idp start ##

        lambda_role.add_to_policy(

            statement=iam.PolicyStatement(

                actions=['cognito-idp:*'],

                resources=['*']

            )

        )

        ## policy for allowing cognito-idp end ##

 

        ## policy to allow using ses start ##

        lambda_role.add_to_policy(

            statement=iam.PolicyStatement(

                actions=['ses:*'],

                resources=['*']

            )

        )

        ## policy to allow using ses end ##

 

These are the two services we are using and we are providing access to those resources for our lambda function.

 

Step 3: Creating Lambda Function for Sending Email 

Now, let’s move to sending email with Amazon SES using lambda function.

The next step is to create a lambda function that will send the email with the PDF attachment. Follow the steps below to create a lambda function:

  • Log in to your AWS Management Console and navigate to the Lambda service.
  • Click on the "Create function" button.
  • Select "Author from scratch" and enter a name for your function.
  • Select "Python 3.x" as the runtime.
  • Under "Permissions", select "Create a new role with basic Lambda permissions and define the role as given above.
  • Click on the "Create function" button.

 

Taking receiver email id from cognito user pool

  • To obtain the recipient's email address, we will retrieve it from the Cognito user pool. 
  • We will utilize the Cognito ID of the user, which will be passed from the front end. 
  • In order to fetch the user's email using their Cognito ID, it is necessary to establish a Cognito client using boto3.
  • Then we will use admin_get_user function of boto3 to get the information about the user stored in cognito user pool.
  • To obtain user information, we will require the user pool ID and user cognito ID.
  • Once we get the email of the user, we will send the email with pdf attachment using SES service.
     

Now for the Amazon SES email sending with PDF attachment, we will use the pdf file stored in s3 bucket, which we will attach to our email to send it as an attachment.

AWS SES offers two functions, namely send_email and send_raw_email, for sending emails. When it comes to sending an email with a PDF attachment, it is necessary to utilize the send_raw_email function to ensure successful delivery of the email along with the attached PDF file.
 

For the Amazon SES send email with attachment, here's the sample code that demonstrates how to send an email with a PDF attachment using Amazon SES:

 

from os import environ

import json

import boto3

import time

from datetime import datetime

from botocore.exceptions import ClientError  #added for email

from email.mime.multipart import MIMEMultipart

from email.mime.text import MIMEText

from email.mime.application import MIMEApplication

 

client = boto3.client('lambda')

cognito_client = boto3.client('cognito-idp')  #create cognito client

 

def lambda_handler(event, context):

    body = json.loads(event['body'])

    user_name = body['user_id']

 

    ##  get the user data from cognito start ##

    get_user_response = cognito_client.admin_get_user(

         UserPoolId ='enter your user pool id', Username=user_name

         )

 

    user_attributes = get_user_response['UserAttributes']

               

    print('userAttributes',user_attributes)

               

    user_email = get_user_response["UserAttributes"][3]["Value"]

    print('email of user is',user_email)

               

    ##  get the user data from cognito end ##

 

    print('reciver email',user_email)

 

    # create s3 client

    s3 = boto3.client('s3')

    #enter the file path where it is store in s3

    #s3_file_key = "path/to/my-file.pdf"

    s3_file_key = ""

 

    s3.download_file(environ["invoice_bucket_name"],s3_file_key,'/tmp/{}'.format(s3_file_key))

 

   

    # This address must be verified with Amazon SES.

    SENDER ="[email protected]"

 

    RECIPIENT =user_email

 

    # If necessary, replace us-west-2 with the AWS Region you're using for Amazon SES.

    AWS_REGION = "us-east-1"

 

    # The subject line for the email.

    SUBJECT = "Invoice Easy Shop"

 

    # The email body for recipients with non-HTML email clients.

    BODY_TEXT = (" Hi...\r\n"

                "This is invoice for order id  "

                "Please find the attached invoice below"

                "Thank you for shopping at Easy Shop"

                )

 

    # The HTML body of the email.

    BODY_HTML = """<html>

    <head></head>

    <body>

    <h3> Hi...</h3>

    <p>This is invoice for order id .</p>

    <p>Please find the attached invoice below</p>

    <p>Thank you for shopping at easy shop </p>

    </body>

    </html>

                """            

 

    CHARSET = "UTF-8"

 

    # Create a new SES resource and specify a region.

    client = boto3.client('ses',region_name=AWS_REGION)

 

    # Define the attachment to be send

    attachment = '/tmp/{}'.format(s3_file_key)

 

    # Create a multipart/mixed parent container.

    msg = MIMEMultipart('mixed')

    # Add subject, from and to lines.

    msg['Subject'] = SUBJECT

    msg['From'] = SENDER

    msg['To'] = RECIPIENT

 

    # Create a multipart/alternative child container.

    msg_body = MIMEMultipart('alternative')

 

    # Encode the text and HTML content and set the character encoding. This step is

    # necessary if you're sending a message with characters outside the ASCII range.

    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(attachment, 'rb').read())

 

    # 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=s3_file_key)

 

    # 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)

    print(msg)

 

    # Try to send the email.

    try:

        #Provide the contents of the email.

        response = client.send_raw_email(

            Destinations=[

                RECIPIENT

            ],

            RawMessage={

                'Data':msg.as_string(),

            },

            Source=SENDER

        )

        print('email res', response)

    # 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'])

 

Note: Replace ‘bucket-name’,’sender-email-address’,’aws-region’,’cognito-user-pool-id’ with your own values

In the above code, the required libraries are imported, including boto3 (the AWS SDK for Python), time, datetime, and various classes from the email.mime module.

  • Two AWS clients are created using boto3: a client for Lambda and a client for Cognito.
  • The lambda_handler function is defined. This function is the entry point for the Lambda function and is executed when the Lambda function is invoked.
  • The user_id is retrieved from the event object's body i.e is being passed to the lambda function from front end.
  • The user's email address is retrieved from Cognito using the admin_get_user method.
  • The user's email address is assigned to the RECIPIENT variable.
  • The S3 client is created, and you use that client to download the file from the S3 bucket.
  • The invoice file is downloaded from S3 to the /tmp directory using the download_file method.
  • The email message is sent using the send_raw_email method of the SES client.
  • If an error occurs during the sending of the email, the error message is printed.
  • If the email is sent successfully, the message ID is printed.


Note: As we will be using AWS SES service in testing environment, we need to verify the email address of receiver as well with SES.

In this blog, we have discussed Amazon SES sending email with attachment and how to send email with PDF attachment using Amazon SES and AWS Lambda. We have gone through the steps required to set up Amazon SES, create an IAM user for SES, and create a Lambda function that sends the email with the PDF attachment. We have also discussed how to get the receiver email from Cognito User Pool using Boto3, download the PDF file from an S3 bucket, and send the email with the PDF attachment using the send_raw_email function. 

 

By following these steps, businesses can easily send emails with PDF attachments to their customers or users. If you want further information on sending email with PDF attachment using Amazon SES, please contact our AWS experts today!

Author Profile Picture
Admin
Securing Your iOS App: How to Implement User Authentication with AWS Cognito

Securing Your iOS App: How to Implement User Authentication with AWS Cognito

Nayani Gaonkar
10 Key Instructions For Frontend Development

10 Key Instructions For Frontend Development

Amol Bhandari
Test Automation Frameworks: Choosing the Right Fit for Your Project

Test Automation Frameworks: Choosing the Right Fit for Your Project

Zahin Ahad