Sending S/MIME Signed Mails with Django

Viewed 335

Is there a way to use the wrappers provided by Django to send signed or even encrypted emails?
We use S/MIME in our company and it's required that all mails are signed.
I currently send emails via SendGrid:

EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_HOST_USER = 'apikey'
EMAIL_HOST_PASSWORD = "<email_password>"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
1 Answers

It's funny I just got the same assignment this week and came here hoping you or another member found a solution :)

I pulled of this one using the package M2Crypto, basically it's just adapted from this example provided in the docs/ folder of the package.

Please note that in my case I changed Cipher to aes_256_cbc and that sent email need to be both signed and encrypted or I'm not able to decrypt to theses mails in Outlook client because of some header issue.

from M2Crypto import BIO, SMIME, X509
import smtplib
from django.conf import settings

def sendsmime(from_addr, to_addrs, subject, msg, from_key, from_cert=None, to_certs=None):
    msg_bio = BIO.MemoryBuffer(msg)
    sign = from_key
    encrypt = to_certs

    s = SMIME.SMIME()
    if sign:
        s.load_key(from_key, from_cert)
        if encrypt:
            p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT)
        else:
            p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT | SMIME.PKCS7_DETACHED)
        msg_bio = BIO.MemoryBuffer(msg)  # Recreate coz sign() has consumed it.

    if encrypt:
        sk = X509.X509_Stack()
        for x in to_certs:
            sk.push(X509.load_cert(x))
        s.set_x509_stack(sk)
        s.set_cipher(SMIME.Cipher('aes_256_cbc'))
        tmp_bio = BIO.MemoryBuffer()
        if sign:
            s.write(tmp_bio, p7)
        else:
            tmp_bio.write(msg)
        p7 = s.encrypt(tmp_bio)

    out = BIO.MemoryBuffer()
    out.write('From: %s\r\n' % from_addr)
    out.write('To: %s\r\n' % ", ".join(to_addrs))
    out.write('Subject: %s\r\n' % subject)
    if encrypt:
        s.write(out, p7)
    else:
        if sign:
            s.write(out, p7, msg_bio, SMIME.PKCS7_TEXT)
        else:
            out.write('\r\n')
            out.write(msg)
    out.close()

    smtp = smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT)
    smtp.ehlo()
    smtp.sendmail(from_addr, to_addrs, out.read())
    smtp.quit()
Related