diff options
author | Yann Rouillard <yann@pleiades.fr.eu.org> | 2013-12-08 17:40:33 +0100 |
---|---|---|
committer | Patrick Totzke <patricktotzke@gmail.com> | 2014-08-02 17:29:33 +0200 |
commit | 1912b7cdedc3ffb88ba953e4e8877fdec6c38893 (patch) | |
tree | d80fc9c459d25ddfc57735a49d80cb0951908c4a /alot/helper.py | |
parent | 6e1990f019fee1cf01af1c63e6f18607da672296 (diff) |
Move email_as_string function from crypto to helper module
The email_as_string function, and the related RFC3156_canonicalize
function, are now used by the ForwardCommand and are not specific
anymore to the crypto routine. So we move them to the global helper
module.
fix an import removal mistake while moving email_as_string function: StringIO was not only used by email_as_string
Diffstat (limited to 'alot/helper.py')
-rw-r--r-- | alot/helper.py | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/alot/helper.py b/alot/helper.py index 6eceeed9..fb95f706 100644 --- a/alot/helper.py +++ b/alot/helper.py @@ -11,16 +11,18 @@ import email import mimetypes import os import re +from email.generator import Generator from email.mime.audio import MIMEAudio from email.mime.base import MIMEBase from email.mime.image import MIMEImage from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart import urwid import magic from twisted.internet import reactor from twisted.internet.protocol import ProcessProtocol from twisted.internet.defer import Deferred -import StringIO +from cStringIO import StringIO import logging @@ -337,8 +339,8 @@ def call_cmd_async(cmdlist, stdin=None, env=None): class _EverythingGetter(ProcessProtocol): def __init__(self, deferred): self.deferred = deferred - self.outBuf = StringIO.StringIO() - self.errBuf = StringIO.StringIO() + self.outBuf = StringIO() + self.errBuf = StringIO() self.outReceived = self.outBuf.write self.errReceived = self.errBuf.write @@ -589,3 +591,54 @@ def mailto_to_envelope(mailto_str): from alot.db.envelope import Envelope headers, body = parse_mailto(mailto_str) return Envelope(bodytext=body, headers=headers) + + +def RFC3156_canonicalize(text): + """ + Canonicalizes plain text (MIME-encoded usually) according to RFC3156. + + This function works as follows (in that order): + + 1. Convert all line endings to \\\\r\\\\n (DOS line endings). + 2. Ensure the text ends with a newline (\\\\r\\\\n). + 3. Encode all occurences of "From " at the beginning of a line + to "From=20" in order to prevent other mail programs to replace + this with "> From" (to avoid MBox conflicts) and thus invalidate + the signature. + + :param text: text to canonicalize (already encoded as quoted-printable) + :rtype: str + """ + text = re.sub("\r?\n", "\r\n", text) + if not text.endswith("\r\n"): + text += "\r\n" + text = re.sub("^From ", "From=20", text, flags=re.MULTILINE) + return text + + +def email_as_string(mail): + """ + Converts the given message to a string, without mangling "From" lines + (like as_string() does). + + :param mail: email to convert to string + :rtype: str + """ + fp = StringIO() + g = Generator(fp, mangle_from_=False, maxheaderlen=78) + g.flatten(mail) + as_string = RFC3156_canonicalize(fp.getvalue()) + + if isinstance(mail, MIMEMultipart): + # Get the boundary for later + boundary = mail.get_boundary() + + # Workaround for http://bugs.python.org/issue14983: + # Insert a newline before the outer mail boundary so that other mail + # clients can verify the signature when sending an email which contains + # attachments. + as_string = re.sub(r'--(\r\n)--' + boundary, + '--\g<1>\g<1>--' + boundary, + as_string, flags=re.MULTILINE) + + return as_string |