Login

S/MIME Encrypted E-mail

Author:
bthomas
Posted:
July 30, 2009
Language:
Python
Version:
1.1
Score:
1 (after 1 ratings)

Requires the M2Crypto module. See http://sandbox.rulemaker.net/ngps/m2/howto.smime.html for more information on using M2Crypto to create S/MIME email. This could also be adapted to allow signing, or sign+encrypt, but currently only encrypts.

Use just like EmailMessage, except takes an extra parameter cert, which is the path to the recipient's public X.509 certificate.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
from email.MIMEBase import MIMEBase
from email.Utils import formatdate
from email.message import Message
from M2Crypto import BIO, SMIME, X509, Rand

from django.utils.encoding import smart_str
from django.core.mail import EmailMessage, SafeMIMEText, SafeMIMEMultipart, make_msgid, forbid_multi_line_headers
from django.conf import settings

class SafeMessage(Message):
    def __setitem__(self, name, val):
        name, val = forbid_multi_line_headers(name, val)
        Message.__setitem__(self, name, val)

class SecureEmailMessage(EmailMessage):
    cert = 'recipient.pem'
    
    def __init__(self, *args, **kwargs):
        if 'cert' in kwargs:
            self.cert = kwargs['cert']
            del kwargs['cert']
        super(SecureEmailMessage, self).__init__(*args, **kwargs)
    
    def message(self):
        encoding = self.encoding or settings.DEFAULT_CHARSET
        msg = SafeMIMEText(smart_str(self.body, settings.DEFAULT_CHARSET),
                           self.content_subtype, encoding)
        if self.attachments:
            body_msg = msg
            msg = SafeMIMEMultipart(_subtype=self.multipart_subtype)
            if self.body:
                msg.attach(body_msg)
            for attachment in self.attachments:
                if isinstance(attachment, MIMEBase):
                    msg.attach(attachment)
                else:
                    msg.attach(self._create_attachment(*attachment))
        
        buf = BIO.MemoryBuffer(msg.as_string())
        # Seed the PRNG.
        Rand.load_file('randpool.dat', -1)
    
        # Instantiate an SMIME object.
        s = SMIME.SMIME()
        
        # Load target cert to encrypt to.
        x509 = X509.load_cert(self.cert)
        sk = X509.X509_Stack()
        sk.push(x509)
        s.set_x509_stack(sk)
        
        # Set cipher: 3-key triple-DES in CBC mode.
        s.set_cipher(SMIME.Cipher('des_ede3_cbc'))
        
        # Encrypt the buffer.
        p7 = s.encrypt(buf)
        
        out = BIO.MemoryBuffer()
        s.write(out, p7)
        headers, body = out.read().split('\n\n', 1)
        for line in headers.splitlines():
            key, value = line.split(': ')
            self.extra_headers[key] = value
        
        # Save the PRNG's state.
        Rand.save_file('randpool.dat')
        
        msg = SafeMessage()
        msg.set_payload(body)
        msg['Subject'] = self.subject
        msg['From'] = self.from_email
        msg['To'] = ', '.join(self.to)

        # Email header names are case-insensitive (RFC 2045), so we have to
        # accommodate that when doing comparisons.
        header_names = [key.lower() for key in self.extra_headers]
        if 'date' not in header_names:
            msg['Date'] = formatdate()
        if 'message-id' not in header_names:
            msg['Message-ID'] = make_msgid()
        for name, value in self.extra_headers.items():
            msg[name] = value
        return msg

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 6 months ago

Comments

Please login first before commenting.