forked from CGM_Public/pretix_original
Fix gaps in our email error handling
This commit is contained in:
@@ -15,6 +15,7 @@ import pytz
|
|||||||
import requests
|
import requests
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from celery import chain
|
from celery import chain
|
||||||
|
from celery.exceptions import MaxRetriesExceededError
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail import (
|
from django.core.mail import (
|
||||||
EmailMultiAlternatives, SafeMIMEMultipart, get_connection,
|
EmailMultiAlternatives, SafeMIMEMultipart, get_connection,
|
||||||
@@ -389,11 +390,25 @@ def mail_send_task(self, *args, to: List[str], subject: str, body: str, html: st
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
backend.send_messages([email])
|
backend.send_messages([email])
|
||||||
except smtplib.SMTPResponseException as e:
|
except (smtplib.SMTPResponseException, smtplib.SMTPSenderRefused) as e:
|
||||||
if e.smtp_code in (101, 111, 421, 422, 431, 442, 447, 452):
|
if e.smtp_code in (101, 111, 421, 422, 431, 442, 447, 452):
|
||||||
self.retry(max_retries=5, countdown=2 ** (self.request.retries * 3)) # max is 2 ** (4*3) = 4096 seconds = 68 minutes
|
# Most likely temporary, retry again (but pretty soon)
|
||||||
logger.exception('Error sending email')
|
try:
|
||||||
|
self.retry(max_retries=5, countdown=2 ** (self.request.retries * 3)) # max is 2 ** (4*3) = 4096 seconds = 68 minutes
|
||||||
|
except MaxRetriesExceededError:
|
||||||
|
if order:
|
||||||
|
order.log_action(
|
||||||
|
'pretix.event.order.email.error',
|
||||||
|
data={
|
||||||
|
'subject': 'SMTP code {}, max retries exceeded'.format(e.smtp_code),
|
||||||
|
'message': e.smtp_error.decode() if isinstance(e.smtp_error, bytes) else str(e.smtp_error),
|
||||||
|
'recipient': '',
|
||||||
|
'invoices': [],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
logger.exception('Error sending email')
|
||||||
if order:
|
if order:
|
||||||
order.log_action(
|
order.log_action(
|
||||||
'pretix.event.order.email.error',
|
'pretix.event.order.email.error',
|
||||||
@@ -405,10 +420,51 @@ def mail_send_task(self, *args, to: List[str], subject: str, body: str, html: st
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
raise SendMailException('Failed to send an email to {}.'.format(to))
|
||||||
|
except smtplib.SMTPRecipientsRefused as e:
|
||||||
|
smtp_codes = [a[0] for a in e.recipients.values()]
|
||||||
|
|
||||||
|
if not any(c >= 500 for c in smtp_codes):
|
||||||
|
# Not a permanent failure (mailbox full, service unavailable), retry later, but with large intervals
|
||||||
|
try:
|
||||||
|
self.retry(max_retries=5, countdown=2 ** (self.request.retries * 3) * 4) # max is 2 ** (4*3) * 4 = 16384 seconds = approx 4.5 hours
|
||||||
|
except MaxRetriesExceededError:
|
||||||
|
# ignore and go on with logging the error
|
||||||
|
pass
|
||||||
|
|
||||||
|
logger.exception('Error sending email')
|
||||||
|
if order:
|
||||||
|
message = []
|
||||||
|
for e, val in e.recipients.items():
|
||||||
|
message.append(f'{e}: {val[0]} {val[1].decode()}')
|
||||||
|
|
||||||
|
order.log_action(
|
||||||
|
'pretix.event.order.email.error',
|
||||||
|
data={
|
||||||
|
'subject': 'SMTP error',
|
||||||
|
'message': '\n'.join(message),
|
||||||
|
'recipient': '',
|
||||||
|
'invoices': [],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
raise SendMailException('Failed to send an email to {}.'.format(to))
|
raise SendMailException('Failed to send an email to {}.'.format(to))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if isinstance(e, (smtplib.SMTPServerDisconnected, smtplib.SMTPConnectError, ssl.SSLError, OSError)):
|
if isinstance(e, (smtplib.SMTPServerDisconnected, smtplib.SMTPConnectError, ssl.SSLError, OSError)):
|
||||||
self.retry(max_retries=5, countdown=2 ** (self.request.retries * 3)) # max is 2 ** (4*3) = 4096 seconds = 68 minutes
|
try:
|
||||||
|
self.retry(max_retries=5, countdown=2 ** (self.request.retries * 3)) # max is 2 ** (4*3) = 4096 seconds = 68 minutes
|
||||||
|
except MaxRetriesExceededError:
|
||||||
|
if order:
|
||||||
|
order.log_action(
|
||||||
|
'pretix.event.order.email.error',
|
||||||
|
data={
|
||||||
|
'subject': 'Internal error',
|
||||||
|
'message': 'Max retries exceeded',
|
||||||
|
'recipient': '',
|
||||||
|
'invoices': [],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
raise e
|
||||||
if order:
|
if order:
|
||||||
order.log_action(
|
order.log_action(
|
||||||
'pretix.event.order.email.error',
|
'pretix.event.order.email.error',
|
||||||
|
|||||||
Reference in New Issue
Block a user