Email S3 Objects as Attachment

Rishi Raj Singh
3 min readMay 2, 2020

The following post will help you to email objects (files, images etc.) from s3 as soon as they are uploaded. We will be using S3 events to triggers Lambda function which will download and email the file using SES.

If the S3 buckets doesn’t exist already, create a bucket and an IAM role with below permissions, for this demo we are using permissions which are wide open, these should be restricted.

Naviagte to SES and verify an email address, this will be used in Lambda function to send emails. Click on to verify a new Email Addres and follow the instructions.

Navigate to Lambda and create a function, use python 3.7 and assign the role we created earlier which had s3, ses and cloudwatch logs permissions to the lambda function. Use the below code in the function, add the TO email addresses.

import os.path
import boto3
import email
from botocore.exceptions import ClientError
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
s3 = boto3.client("s3")def lambda_handler(event, context):

SENDER = "abc@abc.com"
RECIPIENT = "efg@efg.com"
AWS_REGION = "us-west-2"
SUBJECT = "Email From S3"
FILEOBJ = event["Records"][0]
BUCKET_NAME = str(FILEOBJ['s3']['bucket']['name'])
KEY = str(FILEOBJ['s3']['object']['key'])
FILE_NAME = os.path.basename(KEY)TMP_FILE_NAME = '/tmp/' + FILE_NAMEs3.download_file(BUCKET_NAME, KEY, TMP_FILE_NAME)
ATTACHMENT = TMP_FILE_NAME
BODY_TEXT = "The Object file was uploaded to S3"client = boto3.client('ses',region_name=AWS_REGION)msg = MIMEMultipart()
# Add subject, from and to lines.
msg['Subject'] = SUBJECT
msg['From'] = SENDER
msg['To'] = RECIPIENT
textpart = MIMEText(BODY_TEXT)
msg.attach(textpart)
att = MIMEApplication(open(ATTACHMENT, 'rb').read())
att.add_header('Content-Disposition','attachment',filename=ATTACHMENT)
msg.attach(att)
print(msg)
try:
response = client.send_raw_email(
Source=SENDER,
Destinations=['abc@abc.com','xyz@xyz.com'],
RawMessage={ 'Data':msg.as_string() }
)
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:",response['MessageId'])

Go back to S3 bucket -> Properties -> Events -> Add notifications

Give a Name, select PUT in events , select lambda in Send to and from the drop down select the lambda function. These changes will trigger the lambda function as soon as there is a PUT (object upload to S3).

The trigger will send an email to the TO address defined in the function, to check logs navigate to Cloudwatch logs and search for “/aws/lambda/functionname”.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Rishi Raj Singh
Rishi Raj Singh

Written by Rishi Raj Singh

Monk who wants to buy back his Ferrari

Responses (5)

Write a response

Note that this will not work if the filename contains special characters (e.g. spaces). Can fix this this by adding `from urllib.parse import unquote_plus` and using it when getting the key `KEY = unquote_plus(str(FILEOBJ['s3']['object']['key']))`

why we are using '/tmp/' there and i have use same code but it is not working

Thanks for the post Rishi Raj Singh. Could you also please help me in clarifying if in this way the attachment will be encrypted while being sent as mail from lambda? Any help would be greatly appreciated.
Thanks in advance!