diff options
-rw-r--r-- | debian/control | 2 | ||||
-rwxr-xr-x | email-print-mime-structure | 22 | ||||
-rw-r--r-- | email-print-mime-structure.1.pod | 24 |
3 files changed, 42 insertions, 6 deletions
diff --git a/debian/control b/debian/control index fc2bccc..4c3b956 100644 --- a/debian/control +++ b/debian/control @@ -38,6 +38,8 @@ Depends: Recommends: devscripts, git, + gpg, + gpg-agent, notmuch, python3-pgpy, Architecture: all diff --git a/email-print-mime-structure b/email-print-mime-structure index c22d556..5497597 100755 --- a/email-print-mime-structure +++ b/email-print-mime-structure @@ -29,9 +29,11 @@ Example: If you want to number the parts, i suggest piping the output through something like "cat -n" ''' +import os import sys import email import logging +import subprocess from argparse import ArgumentParser, Namespace from typing import Optional, Union, List, Tuple, Any @@ -70,7 +72,7 @@ class MimePrinter(object): nbytes = len(payload) print(f'{prefix}{z.get_content_type()}{cset}{disposition}{fname} {nbytes:d} bytes') - try_decrypt:bool = True if self.args.pgpkey else False + try_decrypt:bool = self.args.pgpkey or self.args.use_gpg_agent if try_decrypt and \ (parent is not None) and \ @@ -84,6 +86,8 @@ class MimePrinter(object): return if self.args.pgpkey: cryptopayload = self.pgpy_decrypt(self.args.pgpkey, ciphertext) + if cryptopayload is None and self.args.use_gpg_agent: + cryptopayload = self.gpg_decrypt(ciphertext) if cryptopayload is None: logging.warning(f'Unable to decrypt') return @@ -108,6 +112,19 @@ class MimePrinter(object): pass return None + def gpg_decrypt(self, ciphertext:str) -> Optional[Message]: + inp:int + outp:int + inp, outp = os.pipe() + with open(outp, 'w') as outf: + outf.write(ciphertext) + out:subprocess.CompletedProcess[bytes] = subprocess.run(['gpg', '--batch', '--decrypt'], + stdin=inp, + capture_output=True) + if out.returncode == 0: + return email.message_from_bytes(out.stdout) + return None + 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) @@ -132,6 +149,9 @@ def main() -> None: epilog="Example: email-print-mime-structure <message.eml") parser.add_argument('--pgpkey', metavar='KEYFILE', action='append', help='OpenPGP Transferable Secret Key for decrypting') + parser.add_argument('--use-gpg-agent', metavar='true|false', type=bool, + default=False, + help='Ask local GnuPG installation for decryption') 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 b846d87..69b1cdc 100644 --- a/email-print-mime-structure.1.pod +++ b/email-print-mime-structure.1.pod @@ -29,6 +29,25 @@ 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. +OpenPGP secret keys listed in B<--pgpkey=> are used ephemerally, and +do not interact with any local GnuPG keyring. + +=item B<--use-gpg-agent=>I<true>|I<false> + +If I<true>, and B<email-print-mime-structure> encounters a +PGP/MIME-encrypted part, it will try to decrypt the part using the +secret keys found in the local installation of GnuPG. (default: +I<false>) + +If both B<--pgpkey=>I<KEYFILE> and B<--use-gpg-agent=true> are +supplied, I<KEYFILE> arguments will be tried before falling back to +GnuPG. + +If B<email-print-mime-structure> has been asked to decrypt parts with +either B<--pgpkey=>I<KEYFILE> or with B<--use-gpg-agent=true>, and it +is unable to decrypt an encrypted part, it will emit a warning to +stderr. + =item B<--help>, B<-h> Show usage instructions. @@ -49,11 +68,6 @@ Show usage instructions. =head1 LIMITATIONS -B<email-print-mime-structure> only decrypts encrypted e-mails using -raw, non-password-protected OpenPGP secret keys (see B<--pgpkey>, -above). If it is unable to decrypt an encrypted part with the -supplied keys, it will warn on stderr. - B<email-print-mime-structure>'s output is not stable, and is not intended to be interpreted by machines, so please do not depend on it in scripts! |