-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathsmtp.py
130 lines (112 loc) · 4.7 KB
/
smtp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import logging
import smtplib
import ssl
from shared.config import get_config
from helpers.email import Email
log = logging.getLogger(__name__)
class SMTPServiceError(Exception): ...
class SMTPService:
connection = None
@classmethod
def active(cls):
return cls.connection is not None
@property
def extra_dict(self):
return {"host": self.host, "port": self.port, "username": self.username}
def _load_config(self):
if get_config("services", "smtp", default={}) == {}:
return False
self.host = get_config("services", "smtp", "host", default="mailhog")
self.port = get_config("services", "smtp", "port", default=1025)
self.username = get_config("services", "smtp", "username", default=None)
self.password = get_config("services", "smtp", "password", default=None)
self.ssl_context = ssl.create_default_context()
return True
def tls_and_auth(self):
self.try_starttls()
if self.username and self.password:
self.try_login()
def try_starttls(self):
# only necessary if SMTP server supports TLS and authentication,
# for example mailhog does not need these two steps
try:
SMTPService.connection.starttls(context=self.ssl_context)
except smtplib.SMTPNotSupportedError:
log.warning(
"Server does not support TLS, continuing initialization of SMTP connection",
extra=dict(
host=self.host,
port=self.port,
username=self.username,
password=self.password,
),
)
except smtplib.SMTPResponseException as exc:
log.warning("Error doing STARTTLS command on SMTP", extra=self.extra_dict)
raise SMTPServiceError("Error doing STARTTLS command on SMTP") from exc
def try_login(self):
try:
SMTPService.connection.login(self.username, self.password)
except smtplib.SMTPNotSupportedError:
log.warning(
"Server does not support AUTH, continuing initialization of SMTP connection",
extra=self.extra_dict,
)
except smtplib.SMTPAuthenticationError as exc:
log.warning(
"SMTP server did not accept username/password combination",
extra=self.extra_dict,
)
raise SMTPServiceError(
"SMTP server did not accept username/password combination"
) from exc
def make_connection(self):
try:
SMTPService.connection.connect(self.host, self.port)
except smtplib.SMTPConnectError as exc:
raise SMTPServiceError("Error starting connection for SMTPService") from exc
self.tls_and_auth()
def __init__(self):
if not self._load_config():
log.warning("Unable to load SMTP config")
return
if SMTPService.connection is None:
try:
SMTPService.connection = smtplib.SMTP(
host=self.host,
port=self.port,
)
except smtplib.SMTPConnectError as exc:
raise SMTPServiceError(
"Error starting connection for SMTPService"
) from exc
self.tls_and_auth()
def send(self, email: Email):
if not SMTPService.connection:
self.make_connection()
else:
try:
SMTPService.connection.noop()
except smtplib.SMTPServerDisconnected:
self.make_connection() # reconnect if disconnected
try:
errs = SMTPService.connection.send_message(
email.message,
)
if len(errs) != 0:
err_msg = " ".join(
list(map(lambda err_tuple: f"{err_tuple[0]} {err_tuple[1]}", errs))
)
log.warning(f"Error sending email message: {err_msg}")
raise SMTPServiceError(f"Error sending email message: {err_msg}")
except smtplib.SMTPRecipientsRefused as exc:
log.warning("All recipients were refused", extra=self.extra_dict)
raise SMTPServiceError("All recipients were refused") from exc
except smtplib.SMTPSenderRefused as exc:
log.warning("Sender was refused", extra=self.extra_dict)
raise SMTPServiceError("Sender was refused") from exc
except smtplib.SMTPDataError as exc:
log.warning(
"The SMTP server did not accept the data", extra=self.extra_dict
)
raise SMTPServiceError("The SMTP server did not accept the data") from exc