Here's a new version of the patch addressing Sean's comments.

>From f4d9e714b556a144644cb597a783e4469506ddd1 Mon Sep 17 00:00:00 2001
From: Jameson Graef Rollins <jroll...@finestructure.net>
Date: Tue, 12 Apr 2022 13:03:53 -0700
Subject: [PATCH] new script to reinject message via sendmail

---
 sendmail-reinject       | 73 +++++++++++++++++++++++++++++++++++++++++
 sendmail-reinject.1.pod | 45 +++++++++++++++++++++++++
 2 files changed, 118 insertions(+)
 create mode 100755 sendmail-reinject
 create mode 100644 sendmail-reinject.1.pod

diff --git a/sendmail-reinject b/sendmail-reinject
new file mode 100755
index 0000000..e50c484
--- /dev/null
+++ b/sendmail-reinject
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3
+
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright 2022 Jameson Graef Rollins
+
+import sys
+import argparse
+import subprocess
+
+import email
+from email.policy import default
+from email.utils import parseaddr, getaddresses
+
+
+def sendmail(recipients, message, sender):
+    """send message via sendmail"""
+    cmd = [
+        'sendmail',
+        '-f', sender,
+    ] + recipients
+    print(' '.join(cmd), file=sys.stderr)
+    subprocess.run(
+        cmd,
+        input=message.as_bytes(),
+        check=True,
+    )
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        description="Reinject an email message via sendmail.",
+    )
+    pgroup = parser.add_mutually_exclusive_group(required=True)
+    pgroup.add_argument(
+        'message', nargs='?', type=argparse.FileType('rb'),
+        help="email message path or '-' for stdin",
+    )
+    pgroup.add_argument(
+        '-i', '--notmuch-id',
+        help="message ID for notmuch extraction",
+    )
+
+    args = parser.parse_args()
+
+    if args.id:
+        import notmuch2 as notmuch
+        db = notmuch.Database()
+        query = f'id:{args.id}'
+        assert db.count_messages(query) == 1, "Message ID does not match exactly one message??"
+        for msg in db.messages(query):
+            path = msg.path
+            break
+        f = open(path, 'rb')
+    else:
+        f = args.message
+
+    # parse the email message
+    msg = email.message_from_binary_file(f, policy=default)
+
+    sender = parseaddr(msg['from'])[1]
+
+    # extract all recipients
+    tos = msg.get_all('to', [])
+    ccs = msg.get_all('cc', [])
+    resent_tos = msg.get_all('resent-to', [])
+    resent_ccs = msg.get_all('resent-cc', [])
+    recipients = [r[1] for r in getaddresses(tos + ccs + resent_tos + resent_ccs)]
+
+    sendmail(recipients, msg, sender)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/sendmail-reinject.1.pod b/sendmail-reinject.1.pod
new file mode 100644
index 0000000..f89d0f1
--- /dev/null
+++ b/sendmail-reinject.1.pod
@@ -0,0 +1,45 @@
+=encoding utf8
+
+=head1 NAME
+
+sendmail-reinject - reinject an e-mail via sendmail
+
+=head1 SYNOPSIS
+
+B<sendmail-reinject> B<message.eml>
+
+B<sendmail-reinject> B<-> <B<message.eml>
+
+B<sendmail-reinject> B<-i> B<messageID>
+
+
+=head1 DESCRIPTION
+
+B<sendmail-reinject> reinjects a message to your MTA via sendmail.
+The message is read in (via path, stdin, or from notmuch via message
+ID), the sender and recipients are extracted, and the appropriate
+senmdail command is contructed to resent the message.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--notmuch-id>,B<-i> B<messageID>
+
+Message ID of message to reinject as know to a local notmuch database.
+Assumes the python3-notmuch package is available.
+
+=item B<--help>, B<-h>
+
+Show usage instructions.
+
+=back
+
+=head1 SEE ALSO
+
+sendmail(1), notmuch(1)
+
+=head1 AUTHOR
+
+B<sendmail-reinject> and this manpage were written by Jameson Graef
+Rollins <jroll...@finestructure.net>.
-- 
2.35.1

Reply via email to