diff --git a/email_api/email_api/app.py b/email_api/email_api/app.py index 7d2809c..33bbdb9 100644 --- a/email_api/email_api/app.py +++ b/email_api/email_api/app.py @@ -175,9 +175,10 @@ def retry_domain_emails(domain): return jsonify({'error': 'Unauthorized'}), 401 bucket = domain.replace('.', '-') + '-emails' - # 1) Sammle alle Keys, die noch nicht processed=true sind - unprocessed = [] paginator = s3_client.get_paginator('list_objects_v2') + + # keys, die noch nicht processed='true' sind + unprocessed = [] for page in paginator.paginate(Bucket=bucket): for obj in page.get('Contents', []): head = s3_client.head_object(Bucket=bucket, Key=obj['Key']) @@ -191,56 +192,66 @@ def retry_domain_emails(domain): for key in unprocessed: try: - # E-Mail laden und parsen + # Datei und E-Mail parsen body = s3_client.get_object(Bucket=bucket, Key=key)['Body'].read() msg = BytesParser(policy=default).parsebytes(body) + from_addr = ( getaddresses(msg.get_all('from', []))[0][1] if msg.get_all('from') else f'retry@{domain}' ) - to_addrs = [addr for _n, addr in getaddresses(msg.get_all('to', []))] - cc_addrs = [addr for _n, addr in getaddresses(msg.get_all('cc', []))] - bcc_addrs = [addr for _n, addr in getaddresses(msg.get_all('bcc', []))] + to_addrs = [a for _n, a in getaddresses(msg.get_all('to', []))] + cc_addrs = [a for _n, a in getaddresses(msg.get_all('cc', []))] + bcc_addrs = [a for _n, a in getaddresses(msg.get_all('bcc', []))] recipients = to_addrs + cc_addrs + bcc_addrs if not recipients: - # keine Empfänger → nichts markieren - results['failed'].append(f"{key}: no recipients") + # keine Empfänger → nur als failed markieren + results['failed'].append({'key': key, 'error': 'no recipients'}) continue try: - # Versuch, die Mail zuzustellen + # Zustellen with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as smtp: smtp.sendmail(from_addr, recipients, body) - # bei Erfolg → processed=true + # Erfolg mark_email_as_processed(bucket, key, 'true') results['processed'].append(key) except smtplib.SMTPRecipientsRefused as e: - # bei abgelehnten Adressen → unknownUser vs unknownDomain - refused = e.recipients # dict: {addr: (code, msg), ...} - # check, ob eine abgelehnte Adresse zur eigenen Domain gehört - if any(addr.split('@')[-1] == domain for addr in refused): - status = 'unknownUser' - else: - status = 'unknownDomain' + # Einzelne Adressen abgelehnt + refused = e.recipients # dict { addr: (code, msg_bytes) } + # bestimme Status + status = ( + 'unknownUser' + if any(addr.split('@')[-1] == domain for addr in refused) + else 'unknownDomain' + ) + # bytes → string + clean = {} + for addr, (code, msg) in refused.items(): + msg_str = msg.decode('utf-8', errors='ignore') if isinstance(msg, bytes) else str(msg) + clean[addr] = {'code': code, 'message': msg_str} mark_email_as_processed(bucket, key, status) results['processed'].append(key) - results['failed'].append({key: refused}) + results['failed'].append({'key': key, 'refused': clean}) except Exception as e: - # andere SMTP-/Verbindungs-Fehler → nicht markieren - results['failed'].append(f"{key}: {e}") + # andere SMTP-Fehler + mark_email_as_processed(bucket, key, 'unknownDomain') + results['processed'].append(key) + results['failed'].append({'key': key, 'error': str(e)}) except Exception as e: - # Fehler beim Laden/Parsen der Objekte - results['failed'].append(f"{key}: {e}") + # Fehler beim Laden/Parsen + results['failed'].append({'key': key, 'error': str(e)}) return jsonify(results), 200 + @app.route('/health', methods=['GET']) def health_check(): return jsonify({'status': 'OK'}), 200