Coverage for daklib/mail.py: 93%
25 statements
« prev ^ index » next coverage.py v7.6.0, created at 2026-01-04 16:18 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2026-01-04 16:18 +0000
1"""Mail handling
3@copyright: 2022 Ansgar <ansgar@debian.org>
4@license: GNU General Public License version 2 or later
5"""
7import email
8import email.message
9import email.policy
10from typing import cast
12import daklib.gpg
15def sign_mail(
16 msg: email.message.EmailMessage, *, digest_algorithm: str = "SHA256", **kwargs
17) -> email.message.EmailMessage:
18 """sign an email message using GnuPG.
20 This only handles non-multipart messages.
21 """
22 mime_data = email.message.MIMEPart()
23 mime_data.set_content(msg.get_payload())
24 # Copy Content-Transfer-Encoding from unsigned message
25 del mime_data["Content-Transfer-Encoding"]
26 mime_data["Content-Transfer-Encoding"] = msg["Content-Transfer-Encoding"]
27 data = mime_data.as_bytes(policy=email.policy.SMTP)
29 sig = daklib.gpg.sign(data, **kwargs, digest_algorithm=digest_algorithm)
30 assert sig is not None
31 mime_sig = email.message.MIMEPart()
32 mime_sig["Content-Type"] = "application/pgp-signature"
33 mime_sig.set_payload(sig)
35 msg.clear_content()
36 del msg["Content-Type"]
37 msg["Content-Type"] = (
38 f'multipart/signed; micalg="pgp-{digest_algorithm.lower()}"; protocol="application/pgp-signature"'
39 )
40 msg.set_payload([mime_data, mime_sig])
41 return msg
44# TODO [python3.10, pep604]:
45# def parse_mail(msg: bytes | str) -> email.message.EmailMessage:
46def parse_mail(msg) -> email.message.EmailMessage:
47 if isinstance(msg, str): 47 ↛ 55line 47 didn't jump to line 55 because the condition on line 47 was always true
48 # We need a cast as the return type depends on the `policy` argument.
49 return cast(
50 email.message.EmailMessage,
51 email.message_from_string(msg, policy=email.policy.SMTPUTF8), # type: ignore[arg-type]
52 )
53 else:
54 # We need a cast as the return type depends on the `policy` argument.
55 return cast(
56 email.message.EmailMessage,
57 email.message_from_bytes(msg, policy=email.policy.SMTPUTF8), # type: ignore[arg-type]
58 )