summaryrefslogtreecommitdiff
path: root/alot
diff options
context:
space:
mode:
Diffstat (limited to 'alot')
-rw-r--r--alot/db/message.py2
-rw-r--r--alot/db/utils.py26
-rw-r--r--alot/helper.py32
3 files changed, 42 insertions, 18 deletions
diff --git a/alot/db/message.py b/alot/db/message.py
index 10115072..b53ec6c0 100644
--- a/alot/db/message.py
+++ b/alot/db/message.py
@@ -101,7 +101,7 @@ class Message(object):
if not self._email:
try:
with open(path, 'rb') as f:
- self._email = utils.message_from_bytes(f.read())
+ self._email = utils.decrypted_message_from_bytes(f.read())
except IOError:
self._email = email.message_from_string(warning)
return self._email
diff --git a/alot/db/utils.py b/alot/db/utils.py
index d7c56310..37ef4c48 100644
--- a/alot/db/utils.py
+++ b/alot/db/utils.py
@@ -179,7 +179,7 @@ def _handle_encrypted(original, message):
# recovered plain text mail. maybe that's a feature.
malformed = str(e)
else:
- n = message_from_bytes(d)
+ n = decrypted_message_from_bytes(d)
# add the decrypted message to message. note that n contains all
# the attachments, no need to walk over n here.
@@ -214,7 +214,7 @@ def _handle_encrypted(original, message):
original.attach(content)
-def message_from_file(handle):
+def decrypted_message_from_file(handle):
'''Reads a mail from the given file-like object and returns an email
object, very much like email.message_from_file. In addition to
that OpenPGP encrypted data is detected and decrypted. If this
@@ -225,8 +225,18 @@ def message_from_file(handle):
:returns: :class:`email.message.Message` possibly augmented with
decrypted data
'''
- m = email.message_from_file(handle)
+ return decrypted_message_from_message(email.message_from_file(handle))
+
+def decrypted_message_from_message(m):
+ '''Detect and decrypt OpenPGP encrypted data in an email object. If this
+ succeeds, any mime messages found in the recovered plaintext
+ message are added to the returned message object.
+
+ :param m: an email object
+ :returns: :class:`email.message.Message` possibly augmented with
+ decrypted data
+ '''
# make sure no one smuggles a token in (data from m is untrusted)
del m[X_SIGNATURE_VALID_HEADER]
del m[X_SIGNATURE_MESSAGE_HEADER]
@@ -263,7 +273,7 @@ def message_from_file(handle):
return m
-def message_from_string(s):
+def decrypted_message_from_string(s):
'''Reads a mail from the given string. This is the equivalent of
:func:`email.message_from_string` which does nothing but to wrap
the given string in a StringIO object and to call
@@ -273,17 +283,15 @@ def message_from_string(s):
details.
'''
- return message_from_file(io.StringIO(s))
+ return decrypted_message_from_file(io.StringIO(s))
-def message_from_bytes(bytestring):
+def decrypted_message_from_bytes(bytestring):
"""Create a Message from bytes.
- Attempt to guess the encoding of the bytestring.
-
:param bytes bytestring: an email message as raw bytes
"""
- return message_from_file(io.StringIO(helper.try_decode(bytestring)))
+ return decrypted_message_from_message(email.message_from_bytes(bytestring))
def extract_headers(mail, headers=None):
diff --git a/alot/helper.py b/alot/helper.py
index 70d375c8..d0c21a49 100644
--- a/alot/helper.py
+++ b/alot/helper.py
@@ -22,7 +22,6 @@ from email.mime.image import MIMEImage
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
-import chardet
import urwid
import magic
from twisted.internet import reactor
@@ -384,17 +383,34 @@ def guess_mimetype(blob):
def guess_encoding(blob):
- """Use chardet to guess the encoding of a given data blob
+ """
+ uses file magic to determine the encoding of the given data blob.
- :param blob: A blob of bytes
- :type blob: bytes
+ :param blob: file content as read by file.read()
+ :type blob: data
:returns: encoding
:rtype: str
"""
- info = chardet.detect(blob)
- logging.debug('Encoding %s with confidence %f',
- info['encoding'], info['confidence'])
- return info['encoding']
+ # this is a bit of a hack to support different versions of python magic.
+ # Hopefully at some point this will no longer be necessary
+ #
+ # the version with open() is the bindings shipped with the file source from
+ # http://darwinsys.com/file/ - this is what is used by the python-magic
+ # package on Debian/Ubuntu. However it is not available on pypi/via pip.
+ #
+ # the version with from_buffer() is available at
+ # https://github.com/ahupp/python-magic and directly installable via pip.
+ #
+ # for more detail see https://github.com/pazz/alot/pull/588
+ if hasattr(magic, 'open'):
+ m = magic.open(magic.MAGIC_MIME_ENCODING)
+ m.load()
+ return m.buffer(blob)
+ elif hasattr(magic, 'from_buffer'):
+ m = magic.Magic(mime_encoding=True)
+ return m.from_buffer(blob)
+ else:
+ raise Exception('Unknown magic API')
def try_decode(blob):