SESでメール送信はできる状態。ただ、受信もしたかったので公式ドキュメント通り設定
ただし、その場合、S3に単純によくわからないファイル名で追加され続ける問題対応
ソース(Lambda)
キー (Key),値 (Value) の例
ADMIN_PREFIX,ses/admin
SVC_PREFIX,ses/svc
DYNAMO_TABLE,ReceivedEmails
重要なアドバイス:S3の無限ループに注意!
このLambdaを動かす際、S3のトリガー設定で注意点があります。
今の設定: ses/ フォルダ全体を監視してLambdaを動かす設定にしていると、
Lambdaがファイルを移動(新規作成)した際、その移動後のファイルに対してもLambdaが反応してしまい、
無限ループが発生します。
対策: S3のイベント通知設定(トリガー設定)で、「Prefix (プレフィックス)」に、
SESが最初にメールを書き込む場所(例: tmp/ など)を指定し、
Lambdaはその tmp/ から ses/admin/ や ses/svc/ へ
移動させるようにフォルダを分けるのが最も安全です。
import boto3
import email
import os
import xml.etree.ElementTree as ET
from datetime import datetime
from email.header import decode_header
# --- 環境変数から設定を取得 ---
# 設定されていない場合のデフォルト値も指定
ADMIN_PREFIX = os.environ.get('ADMIN_PREFIX', 'ses/admin')
SVC_PREFIX = os.environ.get('SVC_PREFIX', 'ses/svc')
DYNAMO_TABLE = os.environ.get('DYNAMO_TABLE', 'ReceivedEmails')
s3 = boto3.client('s3')
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(DYNAMO_TABLE)
def get_decode_subject(msg):
subject = msg.get('Subject', 'No Subject')
decoded = decode_header(subject)
subject_text = ""
for content, charset in decoded:
if isinstance(content, bytes):
subject_text += content.decode(charset or 'utf-8', errors='replace')
else:
subject_text += content
# ファイル名に使えない文字を置換
return subject_text.replace('/', '_').replace('\\', '_')
def lambda_handler(event, context):
bucket = event['Records'][0]['s3']['bucket']['name']
key = event['Records'][0]['s3']['object']['key']
# 1. S3からメール取得
response = s3.get_object(Bucket=bucket, Key=key)
raw_email = response['Body'].read()
msg = email.message_from_bytes(raw_email)
# 2. 基本情報抽出
to_address = msg.get('To', 'unknown')
subject = get_decode_subject(msg)
date_str = datetime.now().strftime('%Y-%m-%d')
# 3. 仕分けロジック
if 'admin@hoge.com' in to_address:
# DMARC用フォルダへ(adminフォルダ名を使用)
new_key = f"{ADMIN_PREFIX}/{date_str}/{os.path.basename(key)}.eml"
# ※ここに以前のDMARC XML解析ロジックを挿入可能
else:
# 一般メール用(svcフォルダ名を使用)
user_name = to_address.split('@')[0].replace('<', '').strip()
new_key = f"{SVC_PREFIX}/{date_str}/{user_name}/{subject}.eml"
# 4. S3での移動(コピー & 削除)
print(f"Moving {key} to {new_key}")
s3.copy_object(
Bucket=bucket,
CopySource={'Bucket': bucket, 'Key': key},
Key=new_key
)
s3.delete_object(Bucket=bucket, Key=key)
# 5. DynamoDBへの記録(簡易版)
table.put_item(
Item={
'MessageId': key, # SESのメッセージID
'ReceivedAt': datetime.now().isoformat(),
'Subject': subject,
'To': to_address,
'NewS3Path': new_key
}
)
return {'status': 'success', 'moved_to': new_key}
``