From 110ea885f226e63be4d38d3147d3a6fbacd9dc7f Mon Sep 17 00:00:00 2001 From: "Piotr F. Mieszkowski" Date: Sat, 2 Mar 2024 18:36:41 +0100 Subject: [PATCH] Deliver cleartext if Unicode encoding or message serialisation fail --- lacre/core.py | 7 +++++-- lacre/daemon.py | 4 ++-- lacre/mailop.py | 10 +++++++++- test/modules/test_stats.py | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/lacre/core.py b/lacre/core.py index f9e660c..7ae040a 100644 --- a/lacre/core.py +++ b/lacre/core.py @@ -40,7 +40,7 @@ import lacre.keyring as kcache import lacre.recipients as recpt import lacre.smime as smime from lacre.transport import send_msg, register_sender, SendFrom -from lacre.mailop import KeepIntact, InlineOpenPGPEncrypt, MimeOpenPGPEncrypt +from lacre.mailop import KeepIntact, InlineOpenPGPEncrypt, MimeOpenPGPEncrypt, MailSerialisationException LOG = logging.getLogger(__name__) @@ -127,7 +127,10 @@ def _gpg_encrypt_copy(message: EmailMessage, keys, recipients, encrypt_f): def _gpg_encrypt_to_bytes(message: EmailMessage, keys, recipients, encrypt_f) -> bytes: msg_copy = _gpg_encrypt_copy(message, keys, recipients, encrypt_f) - return msg_copy.as_bytes(policy=SMTPUTF8) + try: + return msg_copy.as_bytes(policy=SMTPUTF8) + except IndexError: + raise MailSerialisationException() def _gpg_encrypt_to_str(message: EmailMessage, keys, recipients, encrypt_f) -> str: diff --git a/lacre/daemon.py b/lacre/daemon.py index 8dda081..da2085c 100644 --- a/lacre/daemon.py +++ b/lacre/daemon.py @@ -22,7 +22,7 @@ from GnuPG import EncryptionException import lacre.core as gate import lacre.keyring as kcache import lacre.transport as xport -from lacre.mailop import KeepIntact +from lacre.mailop import KeepIntact, MailSerialisationException class MailEncryptionProxy: @@ -48,7 +48,7 @@ class MailEncryptionProxy: try: new_message = operation.perform(message) send(new_message, operation.recipients()) - except EncryptionException as e: + except (EncryptionException, MailSerialisationException, UnicodeEncodeError) as e: # If the message can't be encrypted, deliver cleartext. LOG.error('Unable to encrypt message, delivering in cleartext: %s', e) if not isinstance(operation, KeepIntact): diff --git a/lacre/mailop.py b/lacre/mailop.py index 7eff347..69d6d9b 100644 --- a/lacre/mailop.py +++ b/lacre/mailop.py @@ -22,6 +22,11 @@ from email.policy import SMTP, SMTPUTF8 LOG = logging.getLogger(__name__) +class MailSerialisationException(BaseException): + """We can't turn an EmailMessage into sequence of bytes.""" + pass + + class MailOperation: """Contract for an operation to be performed on a message.""" @@ -124,7 +129,10 @@ class KeepIntact(MailOperation): def perform(self, message: Message) -> bytes: """Return MESSAGE unmodified.""" - return message.as_bytes(policy=SMTPUTF8) + try: + return message.as_bytes(policy=SMTPUTF8) + except IndexError as e: + raise MailSerialisationException(e) def __repr__(self): """Return representation with just method and email.""" diff --git a/test/modules/test_stats.py b/test/modules/test_stats.py index f85b35e..a0e57e5 100644 --- a/test/modules/test_stats.py +++ b/test/modules/test_stats.py @@ -33,6 +33,6 @@ class ExecutionTimeLoggerTest(unittest.TestCase): self.assertEqual(handler.logged_records[1], 'Doing something') # Exception record should include the timing result and the traceback... - self.assertRegex(handler.logged_records[2], '^Just a test took 0 ms, raised exception\nTraceback.*') + self.assertRegex(handler.logged_records[2], '^Just a test took \\d ms, raised exception\nTraceback.*') # ...as well as the original exception self.assertRegex(handler.logged_records[2], 'Exception: this is a test$')