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
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Please login first before commenting.