diff --git a/email_api/email_api/app.py b/email_api/email_api/app.py index 2006c1f..7d2809c 100644 --- a/email_api/email_api/app.py +++ b/email_api/email_api/app.py @@ -175,6 +175,7 @@ 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') for page in paginator.paginate(Bucket=bucket): @@ -182,33 +183,64 @@ def retry_domain_emails(domain): head = s3_client.head_object(Bucket=bucket, Key=obj['Key']) if head.get('Metadata', {}).get('processed') != 'true': unprocessed.append(obj['Key']) - + request_id = f"retry-{domain}-{int(time.time())}" - logger.info(f"[{request_id}] RETRY processing for domain={domain}, keys={unprocessed}") - + logger.info(f"[{request_id}] RETRY for domain={domain}, keys={unprocessed}") + results = {'processed': [], 'failed': []} + for key in unprocessed: try: + # E-Mail laden und 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', []))] + 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', []))] recipients = to_addrs + cc_addrs + bcc_addrs - with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as smtp: - smtp.sendmail(from_addr, recipients, body) + if not recipients: + # keine Empfänger → nichts markieren + results['failed'].append(f"{key}: no recipients") + continue - if mark_email_as_processed(bucket, key): + try: + # Versuch, die Mail zuzustellen + with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as smtp: + smtp.sendmail(from_addr, recipients, body) + + # bei Erfolg → processed=true + mark_email_as_processed(bucket, key, 'true') results['processed'].append(key) - else: - results['failed'].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' + + mark_email_as_processed(bucket, key, status) + results['processed'].append(key) + results['failed'].append({key: refused}) + + except Exception as e: + # andere SMTP-/Verbindungs-Fehler → nicht markieren + results['failed'].append(f"{key}: {e}") + except Exception as e: + # Fehler beim Laden/Parsen der Objekte results['failed'].append(f"{key}: {e}") return jsonify(results), 200 + @app.route('/health', methods=['GET']) def health_check(): return jsonify({'status': 'OK'}), 200