Unverified Commit 7596b877 authored by sand's avatar sand

prototype implementation for reading encrypted emails

parent b5443dd3
Pipeline #350 passed with stage
in 19 seconds
# https://github.com/leapcode/leap_mail/blob/develop/src/leap/mail/incoming/service.py
# should consider get_email_charset from:
# https://github.com/leapcode/leap_pycommon/blob/6efdee0a5bab59d90c915b44a65e798b4a426c4a/src/leap/common/mail.py
from email.utils import parseaddr
MULTIPART_ENCRYPTED = "multipart/encrypted"
MULTIPART_SIGNED = "multipart/signed"
PGP_BEGIN = "-----BEGIN PGP MESSAGE-----"
PGP_END = "-----END PGP MESSAGE-----"
class ReaderException(Exception):
pass
def extract_text_payload(msg):
if msg.is_multipart():
text = u''
for part in msg.walk():
if part.get_content_type() == 'text/plain':
text += unicode(part.get_payload(decode=True),
part.get_content_charset('utf-8'))
else:
text = unicode(msg.get_payload(decode=True),
msg.get_content_charset('utf-8'))
return text
def decrypt_multipart(msg, sender_address, gpg):
payload = msg.get_payload()
if (len(payload) != 2 or
payload[0].get_content_type() != 'application/pgp-encrypted' or
payload[1].get_content_type() != 'application/octet-stream'):
raise ReaderException("Invalid format for a multipart encrypted message")
enc_data = payload[1].get_payload()
data = str(gpg.decrypt(enc_data))
return data
def maybe_decrypt_inline(msg, sender_address, gpg):
"""Decrypt a inline PGP message or a normal plain text message"""
data = extract_text_payload(msg)
was_encrypted = False
if PGP_BEGIN in data and PGP_END in data:
begin = data.find(PGP_BEGIN)
end = data.find(PGP_END)
if begin > end:
raise ReaderException("Invalid inline PGP message")
pgp_message = data[begin:end + len(PGP_END)]
if len(pgp_message) == 0:
raise ReaderException("Empty inline PGP message")
was_encrypted = True
return (str(gpg.decrypt(pgp_message)), was_encrypted)
return (data, was_encrypted)
def read_encrypted_message(msg, gpg):
"""Return the body of a email message, wether it is encrypted or not."""
was_encrypted = False
content_type = msg.get_content_type()
from_header = msg.get('from', None)
sender_address = None
if from_header is not None and content_type in (MULTIPART_ENCRYPTED,
MULTIPART_SIGNED):
sender_address = parseaddr(from_header)[1]
if content_type == MULTIPART_ENCRYPTED:
was_encrypted = True
data = decrypt_multipart(msg, sender_address, gpg)
elif content_type == MULTIPART_SIGNED:
raise ReaderException("Signed but not encrypted messages are not supported yet")
else:
(data, was_encrypted) = maybe_decrypt_inline(msg, sender_address, gpg)
return (data, was_encrypted)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment