Отправка писем с подписью S/MIME с помощью Django

#python #django #sendgrid #sign #smime

Вопрос:

Есть ли способ использовать обертки, предоставляемые Django, для отправки подписанных или даже зашифрованных электронных писем?
Мы используем S/MIME в нашей компании, и все письма должны быть подписаны.
В настоящее время я отправляю электронные письма через SendGrid:

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

Ответ №1:

Забавно, что я только что получил то же задание на этой неделе и пришел сюда в надежде, что вы или другой участник нашли решение 🙂

Я вытащил этот , используя пакет M2Crypto , в основном он просто адаптирован из этого примера, приведенного в папке docs/ пакета.

Пожалуйста, обратите внимание, что в моем случае я изменил шифр на aes_256_cbc и что отправленное электронное письмо должно быть подписано и зашифровано, иначе я не смогу расшифровать эти письма в клиенте Outlook из-за какой-то проблемы с заголовком.

 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: %srn' % from_addr)
    out.write('To: %srn' % ", ".join(to_addrs))
    out.write('Subject: %srn' % subject)
    if encrypt:
        s.write(out, p7)
    else:
        if sign:
            s.write(out, p7, msg_bio, SMIME.PKCS7_TEXT)
        else:
            out.write('rn')
            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()
 

Комментарии:

1. Не могли бы вы пояснить, пожалуйста, почему электронное письмо должно быть одновременно подписано и зашифровано? Когда я шифрую и подписываю, кажется, что все работает, но когда я хочу только подписать, Outlook утверждает, что сообщение было изменено, и я не могу понять, почему это так. Это то же самое поведение, с которым вы столкнулись?