summaryrefslogtreecommitdiff
path: root/email-print-mime-structure
diff options
context:
space:
mode:
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>2019-11-02 01:28:24 -0400
committerSean Whitton <spwhitton@spwhitton.name>2019-11-02 08:44:19 -0700
commit67a847605769d5e255168a65d780594383569b75 (patch)
treeffdc4362c00917605de5baf23f033be46eda3ef2 /email-print-mime-structure
parenta858e19c0eb6c2a12d832b3dd256ef64c72f0fc1 (diff)
downloadmailscripts-67a847605769d5e255168a65d780594383569b75.tar.gz
email-print-mime-structure: add decryption capability
Add simple decryption capability for email-print-mime-structure, so that it can do stuff like this: $ email-print-mime-structure --pgpkey alice@openpgp.example.sec.asc < msg.eml └┬╴multipart/encrypted 2190 bytes ├─╴application/pgp-encrypted 11 bytes └─╴application/octet-stream 1613 bytes ↧ (decrypts to) └─╴text/plain 425 bytes $ At the moment, it only works with keys that can be found in the filesystem, and when the pgpy module is installed. Possible future work: - try using gpg to do the decryption from whatever gpg's system capabilities are I've added python3-pgpy to the list of Recommends, since it is not a hard dependency. Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
Diffstat (limited to 'email-print-mime-structure')
-rwxr-xr-xemail-print-mime-structure34
1 files changed, 34 insertions, 0 deletions
diff --git a/email-print-mime-structure b/email-print-mime-structure
index 33579a7..eb513b3 100755
--- a/email-print-mime-structure
+++ b/email-print-mime-structure
@@ -38,6 +38,11 @@ from typing import Optional, Union, List, Tuple, Any
from email.charset import Charset
from email.message import Message
+try:
+ import pgpy #type: ignore
+except ImportError:
+ pgpy = None
+
class MimePrinter(object):
def __init__(self, args:Namespace):
self.args = args
@@ -66,6 +71,33 @@ class MimePrinter(object):
print(f'{prefix}{z.get_content_type()}{cset}{disposition}{fname} {nbytes:d} bytes')
+ if self.args.pgpkey and \
+ (parent is not None) and \
+ (parent.get_content_type().lower() == 'multipart/encrypted') and \
+ (str(parent.get_param('protocol')).lower() == 'application/pgp-encrypted') and \
+ (num == 2):
+ if pgpy is None:
+ logging.warning(f'Python module pgpy is not available, not decrypting (try "apt install python3-pgpy")')
+ else:
+ cryptopayload:Optional[Message] = None
+ keyname:str
+ for keyname in self.args.pgpkey:
+ try:
+ key:pgpy.PGPKey
+ key, _ = pgpy.PGPKey.from_file(keyname)
+ msg:pgpy.PGPMessage = pgpy.PGPMessage.from_blob(z.get_payload())
+ msg = key.decrypt(msg)
+ cryptopayload = email.message_from_bytes(msg.message)
+ break
+ except:
+ pass
+ if cryptopayload is None:
+ logging.warning(f'Unable to decrypt')
+ else:
+ newprefix = prefix[:-3] + ' '
+ print(f'{newprefix}↧ (decrypts to)')
+ self.print_tree(cryptopayload, newprefix + '└', z, 0)
+
def print_tree(self, z:Message, prefix:str, parent:Optional[Message], num:int) -> None:
if (z.is_multipart()):
self.print_part(z, prefix+'┬╴', parent, num)
@@ -88,6 +120,8 @@ class MimePrinter(object):
def main() -> None:
parser:ArgumentParser = ArgumentParser(description='Read RFC2822 MIME message from stdin and emit a tree diagram to stdout.',
epilog="Example: email-print-mime-structure < message.eml")
+ parser.add_argument('--pgpkey', metavar='KEYFILE', action='append',
+ help='OpenPGP Transferable Secret Key for decrypting')
args:Namespace = parser.parse_args()
msg:Union[Message, str, int, Any] = email.message_from_file(sys.stdin)