LambdaからSESで画像付きのメールを送信する

2019.06.04

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、サーバーレス開発部の岡です。 最近はチャットでのコミュニケーションが主流ですが実際の業務ではまだまだEメールも使いますよね。 今回はLambdaでS3から画像をダウンロードLambdaにファイルを保存、SESで送信までの実装方法をご紹介したいと思います。

boto3で添付ファイルを送信する場合はsend_raw_emailを使います。

ちなみに添付ファイルなしの場合はboto3のsend_emailで送信することができます。 こちらのブログで紹介していますので参考にしてください。

LambdaからSESを呼んでメール送信をサクッと実装してみた

環境

  • Lambdaランタイム Python3.7(boto3)
  • Region: us-east-1(SES)

SESが東京リージョンで使えない為、SESのみバージニアリージョンを使います。

SESの設定

  • sandboxの解除申請(本番環境の場合)
  • 送信元アドレスorドメインをSESに登録

画像のダウンロード

添付する画像ファイルの情報はeventで渡せるようにします。 ダウンロード元のS3の環境は以下の通りです。

バケット名: attached_file_store S3キー: 201906/angular.png

ダウンロード先は以下にします。 Lambda内の画像ダウンロード先: /tmp/img/201906

eventの中身

{
"subject": "テスト",
"text": "=========================\n\nテスト\n\n=========================",
"file": {
"path": "201906",
"file_name": "angular.png"
}
}

実行コード

import os
import logging
import boto3
from botocore.exceptions import ClientError
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication

# log
LOGGER = logging.getLogger()
LOGGER.setLevel(logging.INFO)

os.environ['TZ'] = 'Asia/Tokyo'
SRC_MAIL = 'from@test.email'
DST_MAIL = 'to@test.email'
SES_REGION = "us-east-1"
ses = boto3.client('ses', region_name=SES_REGION)
s3 = boto3.resource('s3')
BUCKET_NAME = 'attached_file_store'
bucket = s3.Bucket(BUCKET_NAME)

def send_raw_email(source, to, subject, body, img_absolute_path):
LOGGER.info('send_raw_email: START')

msg = MIMEMultipart()

msg['Subject'] = subject
msg['From'] = SRC_MAIL
msg['To'] = DST_MAIL
body_msg = MIMEText(body, 'plain')
msg.attach(body_msg)

att = MIMEApplication(open(img_absolute_path, 'rb').read())
att.add_header('Content-Disposition','attachment',filename=os.path.basename(img_absolute_path))
msg.attach(att)

try:
response = ses.send_raw_email(
Source=source,
Destinations=[to],
RawMessage={
'Data':msg.as_string()
}
)
return response

except ClientError as e:
LOGGER.error(e.response['Error']['Message'])
else:
LOGGER.info("Email sent! Message ID:"),
LOGGER.info(response['MessageId'])

def mkdir(path):
img_path = f'/tmp/img/{path}/'

if os.path.exists(img_path) == False:
os.makedirs(img_path)
else:
pass

def download_s3_file(s3_key):
download_dst = f'/tmp/img/{s3_key}'
bucket.download_file(s3_key, download_dst)
return download_dst

def lambda_handler(event, context):
print(event)
subject = event.get('subject')
image = event.get('file')
message = event.get('text')
try:
path = image['path']
file_name = image['file_name']

# 画像ファイル置き場を作成
mkdir(path)

# S3から対象ファイルをダウンロード
img_absolute_path = download_s3_file(path + '/' + file_name)

# メール送信
response = send_raw_email(SRC_MAIL, DST_MAIL, subject, message, img_absolute_path)

return response
except Exception as error:
LOGGER.error(error)
raise error
  • mkdir()でダウンロード先のディレクトリを作成
  • download_s3_file()でeventのfileで指定したファイルをダウンロード
  • SESのsend_raw_email()でメール送信

という流れになります。

参考

AWS SDKs を使用して raw E メールを送信する