summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/control1
-rwxr-xr-xemail-print-mime-structure34
-rw-r--r--email-print-mime-structure.1.pod8
3 files changed, 43 insertions, 0 deletions
diff --git a/debian/control b/debian/control
index 6d3a54f..fc2bccc 100644
--- a/debian/control
+++ b/debian/control
@@ -39,6 +39,7 @@ Recommends:
devscripts,
git,
notmuch,
+ python3-pgpy,
Architecture: all
Description: collection of scripts for manipulating e-mail on Debian
This package provides a collection of scripts for manipulating e-mail
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)
diff --git a/email-print-mime-structure.1.pod b/email-print-mime-structure.1.pod
index 03a8e29..209c725 100644
--- a/email-print-mime-structure.1.pod
+++ b/email-print-mime-structure.1.pod
@@ -21,6 +21,14 @@ something like "cat -n".
=over 4
+=item B<--pgpkey=>I<KEYFILE>
+
+I<KEYFILE> should name an OpenPGP transferable secret key that is not
+password-protected. If a PGP/MIME-encrypted message is found on
+standard input, this key will be tried for decryption. May be used
+multiple times if you want to try decrypting with more than one secret
+key.
+
=item B<--help>, B<-h>
Show usage instructions.