Rework encryption exception handling

Also: remove misleading comment about message.defects.
This commit is contained in:
Piotr F. Mieszkowski 2023-12-09 20:38:46 +01:00
parent fc08813bdc
commit 75c48282b0
3 changed files with 20 additions and 21 deletions

View File

@ -47,24 +47,22 @@ RX_CONFIRM = re.compile(br'key "([^"]+)" imported')
class EncryptionException(Exception):
"""Represents a failure to encrypt a payload."""
def __init__(self, issue: str, recipient: str, cause: str):
"""Initialise an exception."""
self._issue = issue
self._recipient = recipient
self._cause = cause
def __str__(self):
"""Return human-readable string representation."""
recipient, issue, cause, key = self.args
parts = []
if self._recipient:
parts.append('To: ' + self._recipient)
if recipient:
parts.append('To: ' + recipient)
if self._issue:
parts.append('Issue: ' + self._issue)
if issue:
parts.append('Issue: ' + issue)
if self._cause:
parts.append('Cause: ' + self._cause)
if key:
parts.append('Key: ' + key.decode())
if cause:
parts.append('Cause: ' + cause)
return '; '.join(parts)
@ -243,7 +241,7 @@ class GPGEncryptor:
if p.returncode != 0:
LOG.debug('Errors: %s', err)
details = parse_status(err)
raise EncryptionException(details['issue'], details['recipient'], details['cause'])
raise EncryptionException(details['issue'], details['recipient'], details['cause'], details['key'])
return (encdata, p.returncode)
def _popen(self):

View File

@ -42,10 +42,6 @@ class MailEncryptionProxy:
LOG.debug('Parsed into %s: %s', type(message), repr(message))
if message.defects:
# Sometimes a weird message cannot be encoded back and
# delivered, so before bouncing such messages we at least
# record information about the issues. Defects are identified
# by email.* package.
LOG.warning("Issues found: %d; %s", len(message.defects), repr(message.defects))
if conf.flag_enabled('daemon', 'log_headers'):
@ -63,7 +59,8 @@ class MailEncryptionProxy:
if not isinstance(operation, KeepIntact):
self._send_unencrypted(operation, message, envelope, send)
else:
LOG.error(f'Cannot perform {operation}')
LOG.error('Cannot perform: %s', operation)
raise e
except:
LOG.exception('Unexpected exception caught, bouncing message')

View File

@ -65,6 +65,10 @@ class GnuPGUtilitiesTest(unittest.TestCase):
uid = GnuPG._parse_uid_line(sample_in)
self.assertEqual(uid, 'alice@disposlab')
def test_exception_formatting(self):
e = GnuPG.EncryptionException('alice@disposlab', 'key expired', None, b'DEADBEEF')
self.assertEqual(str(e), 'To: alice@disposlab; Issue: key expired; Key: DEADBEEF')
def test_parse_statusfd_key_expired(self):
key_expired = b"""
[GNUPG:] KEYEXPIRED 1668272263
@ -74,9 +78,9 @@ class GnuPGUtilitiesTest(unittest.TestCase):
"""
result = GnuPG.parse_status(key_expired)
self.assertEqual(result['issue'], b'KEYEXPIRED')
self.assertEqual(result['issue'], 'key expired')
self.assertEqual(result['recipient'], b'name@domain')
self.assertEqual(result['cause'], 'No specific reason given')
self.assertEqual(result['cause'], 'Unknown')
self.assertEqual(result['key'], b'XXXXXXXXXXXXX')
def test_parse_statusfd_key_absent(self):
@ -88,7 +92,7 @@ class GnuPGUtilitiesTest(unittest.TestCase):
result = GnuPG.parse_status(non_specific_errors)
self.assertEqual(result['issue'], b'n/a')
self.assertEqual(result['recipient'], b'name@domain')
self.assertEqual(result['cause'], 'No specific reason given')
self.assertEqual(result['cause'], 'Unknown')
self.assertEqual(result['key'], b'n/a')