This commit is contained in:
2025-11-15 12:48:20 -06:00
parent a3e86add49
commit df0d92ba27
2 changed files with 159 additions and 4 deletions

View File

@@ -11,10 +11,21 @@ sqs = boto3.client('sqs', region_name='us-east-2')
# AWS Region
AWS_REGION = 'us-east-2'
# Dynamo Table
dynamo = boto3.resource('dynamodb', region_name=AWS_REGION)
msg_table = dynamo.Table('ses-outbound-messages')
# Metadata Keys
PROCESSED_KEY = 'processed'
PROCESSED_VALUE = 'true'
def is_ses_autoresponse(parsed):
from_h = (parsed.get('From') or '').lower()
auto_sub = (parsed.get('Auto-Submitted') or '').lower()
return (
'mailer-daemon@us-east-2.amazonses.com' in from_h
and 'auto-replied' in auto_sub
)
def domain_to_bucket(domain: str) -> str:
"""Konvertiert Domain zu S3 Bucket Namen"""
@@ -323,19 +334,91 @@ def lambda_handler(event, context):
# E-Mail laden um Subject zu extrahieren
subject = '(unknown)'
raw_bytes = b''
parsed = None
modified = False
try:
print(f"\n📖 Reading email for metadata...")
obj = s3.get_object(Bucket=bucket, Key=key)
raw_bytes = obj['Body'].read()
# Nur Headers parsen (schneller)
metadata = obj.get('Metadata', {}) or {}
# Header parsen
parsed = BytesParser(policy=SMTPPolicy).parsebytes(raw_bytes)
subject = parsed.get('subject', '(no subject)')
print(f" Subject: {subject}")
# 🔁 SES Auto-Response erkennen
if is_ses_autoresponse(parsed):
print(" Detected SES auto-response (out-of-office)")
# Message-ID der ursprünglichen Mail aus In-Reply-To / References holen
in_reply_to = (parsed.get('In-Reply-To') or '').strip()
if not in_reply_to:
refs = (parsed.get('References') or '').strip()
# nimm die erste ID aus References
in_reply_to = refs.split()[0] if refs else ''
lookup_id = ''
if in_reply_to.startswith('<') and '>' in in_reply_to:
lookup_id = in_reply_to[1:in_reply_to.find('>')]
else:
lookup_id = in_reply_to
original = None
if lookup_id:
try:
res = msg_table.get_item(Key={'MessageId': lookup_id})
original = res.get('Item')
print(f" Dynamo lookup for {lookup_id}: {'hit' if original else 'miss'}")
except Exception as e:
print(f"⚠ Dynamo lookup failed: {e}")
if original:
orig_from = original.get('source', '')
destinations = original.get('destinations', []) or []
# einfache Variante: nimm den ersten Empfänger
orig_to = destinations[0] if destinations else ''
# Domain hast du oben bereits aus recipients[0] extrahiert
display = f"Out of Office from {orig_to}" if orig_to else "Out of Office"
# ursprüngliche Infos sichern
parsed['X-SES-Original-From'] = parsed.get('From', '')
parsed['X-SES-Original-Recipient'] = orig_to
# From für den User "freundlich" machen
parsed.replace_header('From', f'"{display}" <no-reply@{domain}>')
# Antworten trotzdem an den Absender deiner ursprünglichen Mail
if orig_from:
parsed['Reply-To'] = orig_from
subj = parsed.get('Subject', 'out of office')
if not subj.lower().startswith('out of office'):
parsed.replace_header('Subject', f"Out of office: {subj}")
# geänderte Mail zurück in Bytes
raw_bytes = parsed.as_bytes()
modified = True
print(" Auto-response rewritten for delivery to user inbox")
else:
print(" No original send record found for auto-response")
# Wenn wir die Mail verändert haben, aktualisieren wir das S3-Objekt
if modified:
s3.put_object(
Bucket=bucket,
Key=key,
Body=raw_bytes,
Metadata=metadata
)
print(" Updated S3 object with rewritten auto-response")
except Exception as e:
print(f" ⚠ Could not parse email (continuing): {e}")
# In Queue einreihen (EINE Message mit ALLEN Recipients)
try: