Belle II Software development
mail_utils.py
1
8import os
9import sys
10import re
11import subprocess
12import random
13import markdown
14import smtplib
15from string import Template
16from email.mime.multipart import MIMEMultipart
17from email.mime.text import MIMEText
18from email.charset import add_charset, QP
19
20import validationpath
21
22
23def get_greeting(name):
24 """
25 Get a random greeting and closing statement using name
26 """
27 greetings = [
28 "Dear",
29 "Dearest",
30 "Hi",
31 "Salutations",
32 "Hello",
33 "Exalted",
34 "Yo",
35 "Honorable",
36 "To the esteemed",
37 "Magnificent",
38 "Glorious",
39 "Howdy",
40 ]
41 closing = [
42 "Bye",
43 "Cheers",
44 "Best Regards",
45 "Best Wishes",
46 "Yours sincerely",
47 "Yours truly",
48 "Thank you",
49 "Seeya",
50 "Toodle-loo",
51 "Ciao",
52 "Hochachtungsvoll",
53 ]
54 return {
55 "greeting": f"{random.choice(greetings)} {name}",
56 "closing": random.choice(closing),
57 }
58
59
60def markdown_to_plaintext(text):
61 """
62 removes markdown specific formatting elements from text
63 """
64 # replace all links of the form [text](url) by just the url.
65 replace_links = re.compile(r"\[.*?]\‍(([^)]*)\‍)")
66 text = replace_links.sub(r"\1", text)
67 # also replace all {: ... } braces which contain attribute lists
68 replace_attrs = re.compile(r"\{:([^\}\n]*?)\}")
69 text = replace_attrs.sub(r"", text)
70 # replace <http://link>, <https://link> and <me@mail.com> by removing <>
71 replace_autolink = re.compile(r"<(https?://[^>]*|[^> ]+@[^> ]+)>")
72 text = replace_autolink.sub(r"\1", text)
73 return text
74
75
76def send_mail(
77 name, recipient, subject, text, link=None, link_title=None, mood="normal"
78):
79 """
80 Send an email to `name` at mail address `recipient` with the given subject and text.
81
82 This function will add a greeting at the top and a closing statement at the
83 bottom and convert the mail text to html using markdown.
84
85 The optional link/link_title argument can be used to easily add a link to
86 the mail for users to click.
87 """
88 all_moods = ["happy", "normal", "meh", "angry", "livid", "dead"]
89 if mood not in all_moods:
90 raise KeyError(
91 f"Unknown mood please use one of {', '.join(all_moods)}"
92 )
93
94 add_charset("utf-8", QP, QP, "utf-8")
95 msg = MIMEMultipart("alternative")
96 msg["Subject"] = subject
97 msg["From"] = "B2Bot <b2soft@mail.desy.de>"
98 if (
99 "bamboo_email_override" in os.environ
100 and os.environ["bamboo_email_override"].find("@") > 0
101 ):
102 msg["To"] = os.environ["bamboo_email_override"]
103 else:
104 msg["To"] = recipient
105
106 if (
107 "bamboo_email_bcc" in os.environ
108 and os.environ["bamboo_email_bcc"].find("@") > 0
109 ):
110 msg["Bcc"] = os.environ["bamboo_email_bcc"]
111
112 data = get_greeting(name)
113 data["mood"] = mood
114 data["title"] = subject
115 data["text"] = markdown_to_plaintext(text)
116 data["plain_link"] = ""
117 # Format the final goto link correctly if it is given
118 if link is not None:
119 if link_title is not None:
120 text += f"\n\n[{link_title}]({link}){{:.goto}}"
121 data["plain_link"] = f"\n\n{link_title}: {link}"
122 else:
123 text += f"\n\n<{link}>{{:.goto}}"
124 data["plain_link"] = f"\n\n{link}"
125
126 # parse plain text to html
127 data["body"] = markdown.markdown(
128 text,
129 output_format="xhtml1",
130 extensions=["markdown.extensions.attr_list"],
131 )
132 # create multipart mime mail
133 msg.attach(
134 MIMEText(
135 f'{data["greeting"]},\n\n{data["text"]}{data["plain_link"]}\n\n{data["closing"]}\n\tThe Belle II Software Bot (B2Bot)',
136 "plain",
137 )
138 )
139 template = Template(
140 open(
141 os.path.join(
143 "validation/html_static/templates/template_mail.html",
144 )
145 ).read()
146 )
147 msg.attach(MIMEText(template.substitute(**data), "html"))
148
149 if os.environ.get("bamboo_DRYRUN", False):
150 # print("Send Mail: ", msg.as_bytes().decode(), file=sys.stderr)
151 open(msg["To"] + ".html", "w").write(template.substitute(**data))
152 else:
153 # check for a local mail_config.py and use it to send the mail if it
154 # exists, otherwise use /usr/sbin/sendmail
155 try:
156 from mail_config import sendmail
157
158 try:
159 sendmail(msg)
160 except smtplib.SMTPAuthenticationError as e:
161 print(
162 "!!!!!!!!!!!!!!!!!!!!!\n"
163 "AN ERROR OCCURED DURING SENDING OF MAILS:",
164 file=sys.stderr,
165 )
166 print(e, file=sys.stderr)
167 print("!!!!!!!!!!!!!!!!!!!!!", file=sys.stderr)
168 except ImportError:
169 subprocess.run(
170 ["/usr/sbin/sendmail", "-t", "-oi"], input=msg.as_bytes()
171 )