change retry method
This commit is contained in:
parent
68f5f0c3f4
commit
3a528b37a1
|
|
@ -226,9 +226,15 @@ def retry_domain_emails(domain):
|
||||||
if auth != f'Bearer {API_TOKEN}':
|
if auth != f'Bearer {API_TOKEN}':
|
||||||
return jsonify({'error': 'Unauthorized'}), 401
|
return jsonify({'error': 'Unauthorized'}), 401
|
||||||
|
|
||||||
|
# 1) Domain-Check ganz am Anfang
|
||||||
|
if not domain_exists(domain):
|
||||||
|
logger.info(f"Retry aborted: unknown domain '{domain}'")
|
||||||
|
return jsonify({'error': f"Unknown domain '{domain}'"}), 404
|
||||||
|
|
||||||
bucket = domain.replace('.', '-') + '-emails'
|
bucket = domain.replace('.', '-') + '-emails'
|
||||||
paginator = s3_client.get_paginator('list_objects_v2')
|
paginator = s3_client.get_paginator('list_objects_v2')
|
||||||
|
|
||||||
|
# 2) alle unprocessed Keys sammeln
|
||||||
unprocessed = []
|
unprocessed = []
|
||||||
for page in paginator.paginate(Bucket=bucket):
|
for page in paginator.paginate(Bucket=bucket):
|
||||||
for obj in page.get('Contents', []):
|
for obj in page.get('Contents', []):
|
||||||
|
|
@ -245,24 +251,30 @@ def retry_domain_emails(domain):
|
||||||
try:
|
try:
|
||||||
body = s3_client.get_object(Bucket=bucket, Key=key)['Body'].read()
|
body = s3_client.get_object(Bucket=bucket, Key=key)['Body'].read()
|
||||||
msg = BytesParser(policy=default).parsebytes(body)
|
msg = BytesParser(policy=default).parsebytes(body)
|
||||||
|
|
||||||
from_addr = (
|
from_addr = (
|
||||||
getaddresses(msg.get_all('from', []))[0][1]
|
getaddresses(msg.get_all('from', []))[0][1]
|
||||||
if msg.get_all('from') else f'retry@{domain}'
|
if msg.get_all('from') else f'retry@{domain}'
|
||||||
)
|
)
|
||||||
to_addrs = [a for _n, a in getaddresses(msg.get_all('to', []))]
|
|
||||||
cc_addrs = [a for _n, a in getaddresses(msg.get_all('cc', []))]
|
# Sammle alle To/Cc/Bcc
|
||||||
bcc_addrs = [a for _n, a in getaddresses(msg.get_all('bcc', []))]
|
recipients = []
|
||||||
recipients = to_addrs + cc_addrs + bcc_addrs
|
for hdr in ('to', 'cc', 'bcc'):
|
||||||
|
recipients += [addr for _n, addr in getaddresses(msg.get_all(hdr, []))]
|
||||||
|
|
||||||
if not recipients:
|
if not recipients:
|
||||||
results['failed'].append({'key': key, 'error': 'no recipients'})
|
# gar keine Adressen → überspringen
|
||||||
|
mark_email_as_processed(bucket, key, 'unknownDomain')
|
||||||
|
results['processed'].append(key)
|
||||||
|
results['failed'].append({
|
||||||
|
'key': key,
|
||||||
|
'status': 'unknownDomain',
|
||||||
|
'reason': 'no recipients'
|
||||||
|
})
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# **Neu: Domain-Match prüfen**
|
# 3) Domain-Match: nur Mails, die an die angefragte Domain adressiert sind
|
||||||
domains = {addr.split('@')[-1].lower() for addr in recipients}
|
domains_in_mail = {addr.split('@')[-1].lower() for addr in recipients if '@' in addr}
|
||||||
if domain.lower() not in domains:
|
if domain.lower() not in domains_in_mail:
|
||||||
# niemals zur eigenen Domain adressiert → unknownDomain
|
|
||||||
mark_email_as_processed(bucket, key, 'unknownDomain')
|
mark_email_as_processed(bucket, key, 'unknownDomain')
|
||||||
results['processed'].append(key)
|
results['processed'].append(key)
|
||||||
results['failed'].append({
|
results['failed'].append({
|
||||||
|
|
@ -273,48 +285,66 @@ def retry_domain_emails(domain):
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# mindestens ein passender Empfänger → Sendeversuch
|
# 4) Inbox-Check: nur existierende Postfächer zulassen
|
||||||
|
valid_recipients = []
|
||||||
|
for addr in recipients:
|
||||||
|
try:
|
||||||
|
local, dom = addr.split('@', 1)
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
if dom.lower() == domain.lower() and inbox_exists(domain, local):
|
||||||
|
valid_recipients.append(addr)
|
||||||
|
else:
|
||||||
|
logger.info(f"Skipping non-existent inbox: {addr}")
|
||||||
|
|
||||||
|
if not valid_recipients:
|
||||||
|
mark_email_as_processed(bucket, key, 'unknownUser')
|
||||||
|
results['processed'].append(key)
|
||||||
|
results['failed'].append({
|
||||||
|
'key': key,
|
||||||
|
'status': 'unknownUser',
|
||||||
|
'from': from_addr,
|
||||||
|
'to': recipients
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 5) Versand an die validierten Adressen
|
||||||
try:
|
try:
|
||||||
with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as smtp:
|
with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as smtp:
|
||||||
smtp.sendmail(from_addr, recipients, body)
|
smtp.sendmail(from_addr, valid_recipients, body)
|
||||||
mark_email_as_processed(bucket, key, 'true')
|
mark_email_as_processed(bucket, key, 'true')
|
||||||
results['processed'].append(key)
|
results['processed'].append(key)
|
||||||
|
|
||||||
except smtplib.SMTPRecipientsRefused as e:
|
except smtplib.SMTPRecipientsRefused as e:
|
||||||
refused = e.recipients
|
# falls Mailcow einzelne Adressen ablehnt
|
||||||
status = (
|
mark_email_as_processed(bucket, key, 'unknownUser')
|
||||||
'unknownUser'
|
refused = {
|
||||||
if any(addr.split('@')[-1].lower() == domain.lower() for addr in refused)
|
addr: {'code': code, 'message': msg.decode('utf-8','ignore') if isinstance(msg, bytes) else str(msg)}
|
||||||
else 'unknownDomain'
|
for addr, (code, msg) in e.recipients.items()
|
||||||
)
|
}
|
||||||
# bytes → str
|
|
||||||
clean = {addr: {'code': code, 'message': (msg.decode('utf-8', 'ignore')
|
|
||||||
if isinstance(msg, bytes) else str(msg))}
|
|
||||||
for addr, (code, msg) in refused.items()}
|
|
||||||
|
|
||||||
mark_email_as_processed(bucket, key, status)
|
|
||||||
results['processed'].append(key)
|
results['processed'].append(key)
|
||||||
results['failed'].append({
|
results['failed'].append({
|
||||||
'key': key,
|
'key': key,
|
||||||
'status': status,
|
'status': 'unknownUser',
|
||||||
'from': from_addr,
|
'from': from_addr,
|
||||||
'to': recipients,
|
'to': valid_recipients,
|
||||||
'refused': clean
|
'refused': refused
|
||||||
})
|
})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# andere SMTP-Fehler behandeln wie unknownDomain
|
# alle anderen SMTP-Fehler behandeln wir als unknownDomain
|
||||||
mark_email_as_processed(bucket, key, 'unknownDomain')
|
mark_email_as_processed(bucket, key, 'unknownDomain')
|
||||||
results['processed'].append(key)
|
results['processed'].append(key)
|
||||||
results['failed'].append({
|
results['failed'].append({
|
||||||
'key': key,
|
'key': key,
|
||||||
'status': 'unknownDomain',
|
'status': 'unknownDomain',
|
||||||
'from': from_addr,
|
'from': from_addr,
|
||||||
'to': recipients,
|
'to': valid_recipients,
|
||||||
'error': str(e)
|
'error': str(e)
|
||||||
})
|
})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# Parsing- oder S3-Fehler
|
||||||
results['failed'].append({'key': key, 'error': str(e)})
|
results['failed'].append({'key': key, 'error': str(e)})
|
||||||
|
|
||||||
return jsonify(results), 200
|
return jsonify(results), 200
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue