【问题标题】:Sending S/MIME Signed Mails with Django使用 Django 发送 S/MIME 签名邮件
【发布时间】:2021-10-18 08:55:25
【问题描述】:

有没有办法使用 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

【问题讨论】:

    标签: python django sendgrid sign smime


    【解决方案1】:

    很有趣,我这周刚接到同样的任务,来到这里希望你或其他成员找到解决方案:)

    我使用包M2Crypto 提取了这个,基本上它只是改编自包的docs/ 文件夹中提供的this example

    请注意,在我的情况下,我将 Cipher 更改为 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: %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()
    

    【讨论】:

    • 您能否详细说明为什么电子邮件需要签名和加密?当我加密并签名时,一切似乎都可以工作,但当我只想签名时,Outlook 声称邮件已被更改,我无法弄清楚为什么会这样。这与您遇到的行为相同吗?
    猜你喜欢
    • 2017-03-02
    • 1970-01-01
    • 2017-08-07
    • 2021-03-08
    • 2018-08-08
    • 2012-02-18
    • 2018-05-21
    • 2017-10-31
    • 2012-05-15
    相关资源
    最近更新 更多