summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJameson Graef Rollins <jrollins@finestructure.net>2022-04-12 13:03:53 -0700
committerSean Whitton <spwhitton@spwhitton.name>2022-05-16 16:45:24 -0700
commit932a5acda1c5e5fddcc4fba7d249b2d2b0168fa1 (patch)
treeffec91def4dc5a876c65237ffe1cd1e51f667dee
parent6224a07059b71d279c424641422461810d273a6d (diff)
downloadmailscripts-932a5acda1c5e5fddcc4fba7d249b2d2b0168fa1.tar.gz
new script to reinject message via sendmail(1)
This script simply takes an existing mail file, parses it for sender and all recipients, and constructs an appropriate sendmail(1) command to resend the message. It requires the sendmail(1) binary at runtime, and the notmuch python library in order to extract the message from an existing notmuch store. Signed-off-by: Jameson Graef Rollins <jrollins@finestructure.net>
-rwxr-xr-xsendmail-reinject73
-rw-r--r--sendmail-reinject.1.pod45
2 files changed, 118 insertions, 0 deletions
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 <jrollins@finestructure.net>.