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
|
"""Handle sending emails. Uses Python3's `smtplib`."""
import logging
import smtplib
import mimetypes
from typing import Optional
from email.message import EmailMessage
from email.headerregistry import Address
def __read_mime__(filepath) -> dict:
"""Read mimetype for attachments"""
_mime,_extras = mimetypes.guess_type(filepath)
if bool(_mime):
return dict(zip(("maintype", "subtype"),
_mime.split("/")))# type: ignore[union-attr]
return {}
def build_email_message(# pylint: disable=[too-many-arguments]
from_address: str,
to_addresses: tuple[Address, ...],
subject: str,
txtmessage: str,
htmlmessage: str = "",
attachments: tuple[str, ...] = tuple()
) -> EmailMessage:
"""Build an email message."""
msg = EmailMessage()
msg["From"] = Address(display_name="GeneNetwork Automated Emails",
addr_spec=from_address)
msg["To"] = to_addresses
msg["Subject"] = subject
msg.set_content(txtmessage)
if bool(htmlmessage):
msg.add_alternative(htmlmessage, subtype="html")
for _path in attachments:
with open(_path, "rb") as _file:
msg.add_attachment(_file.read(), **__read_mime__(_path))
return msg
def send_message(# pylint: disable=[too-many-arguments]
smtp_user: str,# pylint: disable=[unused-argument]
smtp_passwd: str,# pylint: disable=[unused-argument]
message: EmailMessage,
host: str = "",
port: int = 587,
local_hostname: Optional[str]=None,
timeout: int = 200,
source_address: Optional[tuple[tuple[str, int], ...]] = None
):
"""Set up a connection to a SMTP server and send a message."""
logging.debug("Email to send:\n******\n%s\n******\n", message.as_string())
with smtplib.SMTP(host, port, local_hostname, timeout, source_address) as conn:
conn.ehlo()
conn.send_message(message)
|