0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SESで受信設定済みのメール管理ETC

0
Posted at

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}
``
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?