From 67a847605769d5e255168a65d780594383569b75 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 2 Nov 2019 01:28:24 -0400 Subject: email-print-mime-structure: add decryption capability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- debian/control | 1 + 1 file changed, 1 insertion(+) (limited to 'debian/control') 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 -- cgit v1.2.3 From e910230a9fb8a5151bede6d043679ec50570290f Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 9 Nov 2019 16:48:14 -0500 Subject: email-print-mime-structure: Add --use-gpg-agent for decryption In some cases, the user may want to try to use their own GnuPG secret keys to decrypt encrypted parts of the message. By default it is disabled so that we aren't accidentally triggering the use of user secret key material. Note that gpg(1) says: It is highly recommended to use [--batch] along with the options --status-fd and --with-colons for any unattended use of gpg. I am deliberately choosing to not use either --status-fd or --with-colons for email-print-mime-structure. I'm not using --with-colons because there is no output from GnuPG that we expect to be machine-readable -- we're just looking for the cleartext of whatever ciphertext is in the message part. I'm not using --status-fd because there is nothing actionable we can do with GnuPG status messages, and asking for them would require switching from subprocess.run to subprocess.Popen to take advantage of the pass_fds argument, which in turn would make the script only work in a POSIX environment (I believe, but have not tested, that the script can currently be used on Windows). Signed-off-by: Daniel Kahn Gillmor --- debian/control | 2 ++ email-print-mime-structure | 22 +++++++++++++++++++++- email-print-mime-structure.1.pod | 24 +++++++++++++++++++----- 3 files changed, 42 insertions(+), 6 deletions(-) (limited to 'debian/control') 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 are used ephemerally, and +do not interact with any local GnuPG keyring. + +=item B<--use-gpg-agent=>I|I + +If I, and B 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) + +If both B<--pgpkey=>I and B<--use-gpg-agent=true> are +supplied, I arguments will be tried before falling back to +GnuPG. + +If B has been asked to decrypt parts with +either B<--pgpkey=>I 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 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's output is not stable, and is not intended to be interpreted by machines, so please do not depend on it in scripts! -- cgit v1.2.3 From 92eaaca02a0945e2ede9b54975ed218ece9632c3 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sun, 10 Nov 2019 01:00:47 -0700 Subject: demote gpg, gpg-agent Recommends->Suggests See discussion in #944340. Signed-off-by: Sean Whitton --- debian/changelog | 1 + debian/control | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'debian/control') diff --git a/debian/changelog b/debian/changelog index 85e3e47..af4030a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,7 @@ mailscripts (0.13-1) UNRELEASED; urgency=medium notmuch-extract-patch. * email-print-mime-structure: add --use-gpg-agent option (Closes: #944340). Thanks to Daniel Kahn Gillmor for the patch series. + - Suggest gpg & gpg-agent. -- Sean Whitton Sat, 09 Nov 2019 15:01:23 -0700 diff --git a/debian/control b/debian/control index 4c3b956..f92f7a1 100644 --- a/debian/control +++ b/debian/control @@ -38,10 +38,11 @@ Depends: Recommends: devscripts, git, - gpg, - gpg-agent, notmuch, python3-pgpy, +Suggests: + gpg, + gpg-agent, Architecture: all Description: collection of scripts for manipulating e-mail on Debian This package provides a collection of scripts for manipulating e-mail -- cgit v1.2.3 From 818dba1efe67f7b01f6d601c6462a40567c9ed7f Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 10 Nov 2019 09:31:58 -0500 Subject: email-print-mime-structure: add tab completion This is modeled after the use of argcomplete in diffoscope, and it should be possible to use it for any other pythonic mailscript that uses argparse. Signed-off-by: Daniel Kahn Gillmor --- Makefile | 9 ++++++++- debian/control | 3 +++ debian/mailscripts.bash-completion | 1 + debian/rules | 2 +- email-print-mime-structure | 15 +++++++++++++++ 5 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 debian/mailscripts.bash-completion (limited to 'debian/control') diff --git a/Makefile b/Makefile index 352f6f0..0cd06b7 100644 --- a/Makefile +++ b/Makefile @@ -3,14 +3,21 @@ MANPAGES=mdmv.1 mbox2maildir.1 \ email-extract-openpgp-certs.1 \ email-print-mime-structure.1 \ notmuch-import-patch.1 +COMPLETIONS=completions/bash/email-print-mime-structure -all: $(MANPAGES) +all: $(MANPAGES) $(COMPLETIONS) clean: rm -f $(MANPAGES) + rm -rf completions %.1: %.1.pod pod2man --section=1 --date="Debian Project" --center="User Commands" \ --utf8 \ --name=$(subst .1,,$@) \ $^ $@ + +completions/bash/%: + mkdir -p completions/bash + register-python-argcomplete3 $(notdir $@) > $@.tmp + mv $@.tmp $@ diff --git a/debian/control b/debian/control index f92f7a1..782636f 100644 --- a/debian/control +++ b/debian/control @@ -4,9 +4,11 @@ Priority: optional Maintainer: Sean Whitton Standards-Version: 4.1.5 Build-Depends: + bash-completion, debhelper (>= 10), dh-elpa, perl, + python3-argcomplete, Vcs-Git: https://git.spwhitton.name/mailscripts Vcs-Browser: https://git.spwhitton.name/mailscripts @@ -39,6 +41,7 @@ Recommends: devscripts, git, notmuch, + python3-argcomplete, python3-pgpy, Suggests: gpg, diff --git a/debian/mailscripts.bash-completion b/debian/mailscripts.bash-completion new file mode 100644 index 0000000..435576f --- /dev/null +++ b/debian/mailscripts.bash-completion @@ -0,0 +1 @@ +completions/bash/email-print-mime-structure diff --git a/debian/rules b/debian/rules index e8e22ba..6d50bf4 100755 --- a/debian/rules +++ b/debian/rules @@ -1,4 +1,4 @@ #!/usr/bin/make -f %: - dh $@ --with elpa + dh $@ --with elpa --with bash-completion diff --git a/email-print-mime-structure b/email-print-mime-structure index 5497597..aac8194 100755 --- a/email-print-mime-structure +++ b/email-print-mime-structure @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +# PYTHON_ARGCOMPLETE_OK # -*- coding: utf-8 -*- # Copyright (C) 2019 Daniel Kahn Gillmor @@ -45,6 +46,11 @@ try: except ImportError: pgpy = None +try: + import argcomplete #type: ignore +except ImportError: + argcomplete = None + class MimePrinter(object): def __init__(self, args:Namespace): self.args = args @@ -152,6 +158,15 @@ def main() -> None: parser.add_argument('--use-gpg-agent', metavar='true|false', type=bool, default=False, help='Ask local GnuPG installation for decryption') + + if argcomplete: + argcomplete.autocomplete(parser) + elif '_ARGCOMPLETE' in os.environ: + logging.error('Argument completion requested but the "argcomplete" ' + 'module is not installed. ' + 'Maybe you want to "apt install python3-argcomplete"') + sys.exit(1) + args:Namespace = parser.parse_args() msg:Union[Message, str, int, Any] = email.message_from_file(sys.stdin) -- cgit v1.2.3 From 8ef023c49c264bb77f2d1a64a0ba3c0630407de7 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sun, 10 Nov 2019 09:06:44 -0700 Subject: Declare compliance with Debian Policy 4.4.1 Thanks to Daniel Kahn Gillmor for taking the time to verify that no changes are required. Signed-off-by: Sean Whitton --- debian/changelog | 3 +++ debian/control | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'debian/control') diff --git a/debian/changelog b/debian/changelog index 09441a6..caf14cc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,9 @@ mailscripts (0.14-1) UNRELEASED; urgency=medium * email-print-mime-structure: add bash completion (Closes: #944434). Thanks to Daniel Kahn Gillmor for the patch. + * Declare compliance with Debian Policy 4.4.1. + Thanks to Daniel Kahn Gillmor for taking the time to verify that no + changes are required. -- Sean Whitton Sun, 10 Nov 2019 09:01:58 -0700 diff --git a/debian/control b/debian/control index 782636f..72b57c3 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: mailscripts Section: mail Priority: optional Maintainer: Sean Whitton -Standards-Version: 4.1.5 +Standards-Version: 4.4.1 Build-Depends: bash-completion, debhelper (>= 10), -- cgit v1.2.3