Search code examples
pythonemaildigital-signaturegnupgpgp

PGP-signing multipart e-mails with Python


I'm currently trying to add PGP signing support to my small e-mail sending script (which uses Python 3.x and python-gnupg module).

The code that signs message is:

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

(Here basemsg is of email.message.Message type.)

And messageFromSignature function is:

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

Then I add all the needed headers to the message (msg) and send it.

This works well for non-multipart messages, but fails when basemsg is multipart (multipart/alternative or multipart/mixed).

Manually verifying the signature against the corresponding piece of text works, but Evolution and Mutt report that the signature is bad.

Can anybody please point me to my mistake?


Solution

  • The problem is that Python's email.generator module doesn't add a newline before the signature part. I've reported that upstream as http://bugs.python.org/issue14983.

    (The bug was fixed in Python2.7 and 3.3+ in 2014)