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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#!/usr/bin/python
import os
import re
import sys
import email
import boto3
import socket
import argparse
from botocore.exceptions import NoRegionError
# These are all the sendmail options we don't support but have to accept so we
# can ignore them without messing up the command line.
#
# Format is (argument, takes parameters)
IGNORED = (
("-4", False), ("-6", False), ("-au", True), ("-ap", True),
("-am", True), ("-ba", False), ("-bd", False), ("-bi", False),
("-bm", False), ("-bp", False), ("-bs", False), ("-bt", False),
("-bv", False), ("-bz", False), ("-C", True), ("-d", True),
("-E", False), ("-h", True), ("-m", False), ("-M", True),
("-N", True), ("-n", False), ("-oA", True), ("-oc", False),
("-od", True), ("-oD", False), ("-oe", False), ("-oF", True),
("-of", False), ("-og", True), ("-oH", True), ("-oi", False),
("-oL", True), ("-om", False), ("-oo", False), ("-oQ", True),
("-or", True), ("-oS", True), ("-os", False), ("-oT", True),
("-ot", False), ("-ou", True), ("-q", True), ("-R", True),
("-v", False), ("-F", True), ("-t", True),
)
# A rough approximation of an email address but should be good enough to pick
# emails out of a command line
SORTA_EMAIL = re.compile("\S+@\S+\.\S+")
if os.path.exists("/etc/mailname"):
with open("/etc/mailname", "r") as fp:
MAIL_DOMAIN = fp.read().strip()
else:
MAIL_DOMAIN = socket.getfqdn()
# Configuration comes from the environment or metadata service
try:
client = boto3.client("ses")
except NoRegionError:
boto3.setup_default_session(region_name="us-west-2")
client = boto3.client("ses")
def parse_args():
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("-V", action="store_true", dest="display_version")
parser.add_argument("-f", nargs=1, dest="sender_addr")
parser.add_argument("-r", nargs=1, dest="sender_addr")
for arg, nargs in IGNORED:
parser.add_argument(arg, nargs="?" if nargs else None)
opts, args = parser.parse_known_args()
addresses = [a for a in args if SORTA_EMAIL.match(a)]
return opts, addresses
def main():
opts, addresses = parse_args()
if opts.display_version:
print("SES raw mail sender (definitely not sendmail)")
sys.exit(0)
try:
sender = opts.sender_addr[0]
except (IndexError, TypeError):
sender = None
msg = email.message_from_string(sys.stdin.read().encode("us-ascii"))
# Fix up cron emails
if 'Cron Daemon' in msg.get("From"):
msg.replace_header("From", "cron-no-reply@{}".format(MAIL_DOMAIN))
ses_args = {"RawMessage": {"Data": msg.as_string()}}
if sender and not SORTA_EMAIL.match(sender):
raise Exception("Sender email does not look like an email")
if sender:
ses_args["Source"] = sender
if addresses:
ses_args["Destinations"] = addresses
client.send_raw_email(**ses_args)
if __name__ == "__main__":
try:
main()
sys.exit(0)
except Exception as e:
print("Error during sending:")
print(e)
sys.exit(1)
|