summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Totzke <patricktotzke@gmail.com>2014-08-02 17:31:44 +0200
committerPatrick Totzke <patricktotzke@gmail.com>2014-08-02 17:31:44 +0200
commit880cd37cf5104d386d82bc86b5279ba4e753baa7 (patch)
treed80fc9c459d25ddfc57735a49d80cb0951908c4a
parentde18f2e4eb6d1c7af81634f1d5c27dfa4db6ec0a (diff)
parent1912b7cdedc3ffb88ba953e4e8877fdec6c38893 (diff)
Merge branch '0.3.5-fix-forwards-682'
-rw-r--r--alot/commands/envelope.py5
-rw-r--r--alot/commands/thread.py13
-rw-r--r--alot/crypto.py51
-rw-r--r--alot/db/envelope.py4
-rw-r--r--alot/helper.py59
5 files changed, 71 insertions, 61 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 f2e034f2..ca73c75f 100644
--- a/alot/commands/thread.py
+++ b/alot/commands/thread.py
@@ -9,6 +9,7 @@ import argparse
from twisted.internet.defer import inlineCallbacks
import subprocess
from email.Utils import getaddresses, parseaddr
+from email.message import Message
import mailcap
from cStringIO import StringIO
@@ -30,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
@@ -305,11 +307,16 @@ class ForwardCommand(Command):
envelope.body = mailcontent
+ for a in self.message.get_attachments():
+ envelope.attach(a)
+
else: # attach original mode
# attach original msg
- mail.set_type('message/rfc822')
- mail['Content-Disposition'] = 'attachment'
- envelope.attach(Attachment(mail))
+ original_mail = Message()
+ original_mail.set_type('message/rfc822')
+ original_mail['Content-Disposition'] = 'attachment'
+ original_mail.set_payload(email_as_string(mail))
+ envelope.attach(Attachment(original_mail))
# copy subject
subject = decode_header(mail.get('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