1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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()
|