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 | |
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
-rw-r--r-- | alot/commands/envelope.py | 5 | ||||
-rw-r--r-- | alot/commands/thread.py | 4 | ||||
-rw-r--r-- | alot/crypto.py | 51 | ||||
-rw-r--r-- | alot/db/envelope.py | 4 | ||||
-rw-r--r-- | alot/helper.py | 59 |
5 files changed, 63 insertions, 60 deletions
diff --git a/alot/commands/envelope.py b/alot/commands/envelope.py index b67231b7..b90816d2 100644 --- a/alot/commands/envelope.py +++ b/alot/commands/envelope.py @@ -19,6 +19,7 @@ from alot import crypto from alot.commands import Command, registerCommand from alot.commands import globals from alot.helper import string_decode +from alot.helper import email_as_string from alot.settings import settings from alot.utils.booleanaction import BooleanAction from alot.db.errors import DatabaseError @@ -130,7 +131,7 @@ class SaveCommand(Command): # store mail locally # add Date header mail['Date'] = email.Utils.formatdate(localtime=True) - path = account.store_draft_mail(crypto.email_as_string(mail)) + path = account.store_draft_mail(email_as_string(mail)) msg = 'draft saved successfully' @@ -201,7 +202,7 @@ class SendCommand(Command): try: self.mail = self.envelope.construct_mail() self.mail['Date'] = email.Utils.formatdate(localtime=True) - self.mail = crypto.email_as_string(self.mail) + self.mail = email_as_string(self.mail) except GPGProblem, e: ui.clear_notify([clearme]) ui.notify(e.message, priority='error') diff --git a/alot/commands/thread.py b/alot/commands/thread.py index 04fadeeb..ca73c75f 100644 --- a/alot/commands/thread.py +++ b/alot/commands/thread.py @@ -21,7 +21,6 @@ from alot.commands.globals import MoveCommand from alot.commands.globals import CommandCanceled from alot.commands.envelope import SendCommand from alot import completion -from alot import crypto from alot.db.utils import decode_header from alot.db.utils import encode_header from alot.db.utils import extract_headers @@ -32,6 +31,7 @@ from alot.db.errors import DatabaseROError from alot.settings import settings from alot.helper import parse_mailcap_nametemplate from alot.helper import split_commandstring +from alot.helper import email_as_string from alot.utils.booleanaction import BooleanAction from alot.completion import ContactsCompleter @@ -315,7 +315,7 @@ class ForwardCommand(Command): original_mail = Message() original_mail.set_type('message/rfc822') original_mail['Content-Disposition'] = 'attachment' - original_mail.set_payload(crypto.email_as_string(mail)) + original_mail.set_payload(email_as_string(mail)) envelope.attach(Attachment(original_mail)) # copy subject diff --git a/alot/crypto.py b/alot/crypto.py index 1270485d..4c74f1bf 100644 --- a/alot/crypto.py +++ b/alot/crypto.py @@ -4,41 +4,11 @@ import re import os -from email.generator import Generator from cStringIO import StringIO from alot.errors import GPGProblem, GPGCode -from email.mime.multipart import MIMEMultipart import gpgme -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 - - def _hash_algo_name(hash_algo): """ Re-implements GPGME's hash_algo_name as long as pygpgme doesn't wrap that @@ -85,27 +55,6 @@ def RFC3156_micalg_from_algo(hash_algo): return 'pgp-' + hash_algo.lower() -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 get_key(keyid, validate=False, encrypt=False, sign=False): diff --git a/alot/db/envelope.py b/alot/db/envelope.py index a9c4fc7c..6550baeb 100644 --- a/alot/db/envelope.py +++ b/alot/db/envelope.py @@ -184,7 +184,7 @@ class Envelope(object): inner_msg = textpart if self.sign: - plaintext = crypto.email_as_string(inner_msg) + plaintext = helper.email_as_string(inner_msg) logging.debug('signing plaintext: ' + plaintext) try: @@ -229,7 +229,7 @@ class Envelope(object): unencrypted_msg = inner_msg if self.encrypt: - plaintext = crypto.email_as_string(unencrypted_msg) + plaintext = helper.email_as_string(unencrypted_msg) logging.debug('encrypting plaintext: ' + plaintext) try: 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 |