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
|
from email.mime.application import MIMEApplication
from email.utils import getaddresses, parseaddr
from memoryhole.gpg import Gnupg
from memoryhole.rfc3156 import PGPEncrypted, MultipartEncrypted
def protect(msg, openpgp=Gnupg(), encrypt=True, obscure=True):
"""
Protect an email with memory hole. It will protect the PROTECTED_HEADERS
and if obscure=True will obscure the OBSCURED_HEADERS
:param msg: the email to be protected
:type msg: Message
:param openpgp: the implementation of openpgp to use for encryption and/or
signature
:type openpgp: OpenPGP
:param encrypt: should the message be encrypted
:type encrypt: bool
:param obscure: should the headers be obscured
:type obsucre: bool
:return: an encrypted and/or signed email
:rtype: Message
"""
if encrypt:
return _encrypt_mime(msg, openpgp)
raise NotImplementedError()
def _encrypt_mime(msg, openpgp):
encraddr = _recipient_addresses(msg)
signaddr = _from_address(msg)
newmsg = MultipartEncrypted('application/pgp-encrypted')
for hkey, hval in msg.items():
newmsg.add_header(hkey, hval)
del(msg[hkey])
encstr = openpgp.encrypt(msg.as_string(unixfrom=False),
encraddr, signaddr)
encmsg = MIMEApplication(
encstr, _subtype='octet-stream', _encoder=lambda x: x)
encmsg.add_header('content-disposition', 'attachment',
filename='msg.asc')
# create meta message
metamsg = PGPEncrypted()
metamsg.add_header('Content-Disposition', 'attachment')
# attach pgp message parts to new message
newmsg.attach(metamsg)
newmsg.attach(encmsg)
return newmsg
def _recipient_addresses(msg):
recipients = []
for header in ('to', 'cc', 'bcc'):
recipients += msg.get_all(header, [])
return [r[1] for r in getaddresses(recipients)]
def _from_address(msg):
frm = msg.get_all('From', [])
return parseaddr(frm)[1]
|