Create PGP signed message with EmailMessage class

277 views Asked by At

I struggle to re-create a script using Python's legacy email API with the current API. The working code replicates this example:

from email.message import Message
from email.mime.multipart import MIMEMultipart

def messageFromSignature(signature):
    message = Message()
    message['Content-Type'] = 'application/pgp-signature; name="signature.asc"'
    message['Content-Description'] = 'OpenPGP digital signature'
    message.set_payload(signature)
    return message

def send_message(subject, body):
    basemsg = Message()
    basemsg.set_payload(body)
    basemsg.set_charset('utf-8')

    gpg = gnupg.GPG()
    basetext = basemsg.as_string().replace('\n', '\r\n')
    signature = str(gpg.sign(basetext, keyid='xxxxxxxxxxxxxxxx', detach=True))
    if signature:
        signmsg = messageFromSignature(signature)
        msg = MIMEMultipart(_subtype="signed", micalg="pgp-sha512", protocol="application/pgp-signature")
        msg.attach(basemsg)
        msg.attach(signmsg)
    else:
        print('Warning: failed to sign the message!')

With the new code –

from email.message import EmailMessage, MIMEPart

def messageFromSignature(signature):
    message = MIMEPart()
    message.set_content(signature)
    message.replace_header('Content-Type', 'application/pgp-signature; name="signature.asc"')
    message['Content-Description'] = 'OpenPGP digital signature'
    return message

def send_message(subject, body):
    basemsg = EmailMessage()
    basemsg.set_content(body)
    basemsg.set_charset('utf-8')

    gpg = gnupg.GPG()
    basetext = basemsg.as_string().replace('\n', '\r\n')
    signature = str(gpg.sign(basetext, keyid='xxxxxxxxxxxxxxxx', detach=True))
    if signature:
        signmsg = messageFromSignature(signature)
        msg = basemsg
        msg.make_mixed()
        msg.add_attachment(signmsg)
        msg.replace_header('Content-Type', 'multipart/signed; micalg="pgp-sha512"; protocol="application/pgp-signature";')
    else:
        print('Warning: failed to sign the message!')

signmsg receives an additional set of headers when being attached to the multipart message:

--===============0054553979676888393==
Content-Type: message/rfc822
Content-Transfer-Encoding: 8bit
MIME-Version: 1.0
Content-Disposition: attachment

Content-Type: application/pgp-signature; name="signature.asc"
Content-Transfer-Encoding: 7bit
Content-Description: OpenPGP digital signature

-----BEGIN PGP SIGNATURE-----

iHUEABYKAB0WIQQTeptvPezKETGQAId81GVnkrOh+QUCYqWYUAAKCRB81GVnkrOh
+SJSAQCre0cbhMf6frI9jILwc0XXGkByXUgiBkexcpYnXN/HzAD/WaPZA5hTutMg
5lPOQdZGaeVpsApYDL/fmbH6SniTvAg=
=xuOv
-----END PGP SIGNATURE-----

--===============0054553979676888393==--

How can I add the signature as a MIME message subpart without creating headers (similar to the legacy attach method), and why is a MIME version header created by add_attachment, even though the MIMEPart class does not create this header, because

sub-parts do not need their own MIME-Version headers

according to the docs?

Thanks, Jan

0

There are 0 answers