send_email.py 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #!/usr/bin/python3
  2. #
  3. # Licensed to the Apache Software Foundation (ASF) under one or more
  4. # contributor license agreements. See the NOTICE file distributed with
  5. # this work for additional information regarding copyright ownership.
  6. # The ASF licenses this file to You under the Apache License, Version 2.0
  7. # (the "License"); you may not use this file except in compliance with
  8. # the License. You may obtain a copy of the License at
  9. #
  10. # http://www.apache.org/licenses/LICENSE-2.0
  11. #
  12. # Unless required by applicable law or agreed to in writing, software
  13. # distributed under the License is distributed on an "AS IS" BASIS,
  14. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. # See the License for the specific language governing permissions and
  16. # limitations under the License.
  17. #
  18. import smtplib
  19. import ssl
  20. from typing import List
  21. try:
  22. import jinja2
  23. except ModuleNotFoundError:
  24. exit("Jinja2 is a required dependency for this script")
  25. try:
  26. import click
  27. except ModuleNotFoundError:
  28. exit("Click is a required dependency for this script")
  29. SMTP_PORT = 587
  30. SMTP_SERVER = "mail-relay.apache.org"
  31. PROJECT_NAME = "Superset"
  32. PROJECT_MODULE = "superset"
  33. PROJECT_DESCRIPTION = "Apache Superset (incubating) is a modern, enterprise-ready business intelligence web application"
  34. def string_comma_to_list(message: str) -> List[str]:
  35. if not message:
  36. return []
  37. return [element.strip() for element in message.split(",")]
  38. def send_email(
  39. smtp_server: str,
  40. smpt_port: int,
  41. username: str,
  42. password: str,
  43. sender_email: str,
  44. receiver_email: str,
  45. message: str,
  46. ):
  47. """
  48. Send a simple text email (SMTP)
  49. """
  50. context = ssl.create_default_context()
  51. with smtplib.SMTP(smtp_server, smpt_port) as server:
  52. server.starttls(context=context)
  53. server.login(username, password)
  54. server.sendmail(sender_email, receiver_email, message)
  55. def render_template(template_file: str, **kwargs) -> str:
  56. """
  57. Simple render template based on named parameters
  58. :param template_file: The template file location
  59. :kwargs: Named parameters to use when rendering the template
  60. :return: Rendered template
  61. """
  62. template = jinja2.Template(open(template_file).read())
  63. return template.render(kwargs)
  64. def inter_send_email(username, password, sender_email, receiver_email, message):
  65. print("--------------------------")
  66. print("SMTP Message")
  67. print("--------------------------")
  68. print(message)
  69. print("--------------------------")
  70. confirm = input("Is the Email message ok? (yes/no): ")
  71. if confirm not in ("Yes", "yes", "y"):
  72. exit("Exit by user request")
  73. try:
  74. send_email(
  75. SMTP_SERVER,
  76. SMTP_PORT,
  77. username,
  78. password,
  79. sender_email,
  80. receiver_email,
  81. message,
  82. )
  83. print("Email sent successfully")
  84. except smtplib.SMTPAuthenticationError:
  85. exit("SMTP User authentication error, Email not sent!")
  86. except Exception as e:
  87. exit(f"SMTP exception {e}")
  88. class BaseParameters(object):
  89. def __init__(
  90. self, email=None, username=None, password=None, version=None, version_rc=None
  91. ):
  92. self.email = email
  93. self.username = username
  94. self.password = password
  95. self.version = version
  96. self.version_rc = version_rc
  97. self.template_arguments = dict()
  98. def __repr__(self):
  99. return f"Apache Credentials: {self.email}/{self.username}/{self.version}/{self.version_rc}"
  100. @click.group()
  101. @click.pass_context
  102. @click.option(
  103. "--apache_email",
  104. prompt="Apache Email",
  105. help="Your Apache email this will be used for SMTP From",
  106. )
  107. @click.option(
  108. "--apache_username", prompt="Apache username", help="Your LDAP Apache username"
  109. )
  110. @click.option(
  111. "--apache_password",
  112. prompt="Apache password",
  113. hide_input=True,
  114. help="Your LDAP Apache password",
  115. )
  116. @click.option("--version", envvar="SUPERSET_VERSION")
  117. @click.option("--version_rc", envvar="SUPERSET_VERSION_RC")
  118. def cli(ctx, apache_email, apache_username, apache_password, version, version_rc):
  119. """ Welcome to releasing send email CLI interface! """
  120. base_parameters = BaseParameters(
  121. apache_email, apache_username, apache_password, version, version_rc
  122. )
  123. base_parameters.template_arguments["project_name"] = PROJECT_NAME
  124. base_parameters.template_arguments["project_module"] = PROJECT_MODULE
  125. base_parameters.template_arguments["project_description"] = PROJECT_DESCRIPTION
  126. base_parameters.template_arguments["version"] = base_parameters.version
  127. base_parameters.template_arguments["version_rc"] = base_parameters.version_rc
  128. base_parameters.template_arguments["sender_email"] = base_parameters.email
  129. ctx.obj = base_parameters
  130. @cli.command("vote_pmc")
  131. @click.option(
  132. "--receiver_email",
  133. default="dev@superset.apache.org",
  134. type=str,
  135. prompt="The receiver email (To:)",
  136. )
  137. @click.pass_obj
  138. def vote_pmc(base_parameters, receiver_email):
  139. template_file = "email_templates/vote_pmc.j2"
  140. base_parameters.template_arguments["receiver_email"] = receiver_email
  141. message = render_template(template_file, **base_parameters.template_arguments)
  142. inter_send_email(
  143. base_parameters.username,
  144. base_parameters.password,
  145. base_parameters.template_arguments["sender_email"],
  146. base_parameters.template_arguments["receiver_email"],
  147. message,
  148. )
  149. @cli.command("result_pmc")
  150. @click.option(
  151. "--receiver_email",
  152. default="dev@superset.apache.org",
  153. type=str,
  154. prompt="The receiver email (To:)",
  155. )
  156. @click.option(
  157. "--vote_bindings",
  158. default="",
  159. type=str,
  160. prompt="A List of people with +1 binding vote (ex: Max,Grace,Krist)",
  161. )
  162. @click.option(
  163. "--vote_nonbindings",
  164. default="",
  165. type=str,
  166. prompt="A List of people with +1 non binding vote (ex: Ville)",
  167. )
  168. @click.option(
  169. "--vote_negatives",
  170. default="",
  171. type=str,
  172. prompt="A List of people with -1 vote (ex: John)",
  173. )
  174. @click.pass_obj
  175. def result_pmc(
  176. base_parameters, receiver_email, vote_bindings, vote_nonbindings, vote_negatives
  177. ):
  178. template_file = "email_templates/result_pmc.j2"
  179. base_parameters.template_arguments["receiver_email"] = receiver_email
  180. base_parameters.template_arguments["vote_bindings"] = string_comma_to_list(
  181. vote_bindings
  182. )
  183. base_parameters.template_arguments["vote_nonbindings"] = string_comma_to_list(
  184. vote_nonbindings
  185. )
  186. base_parameters.template_arguments["vote_negatives"] = string_comma_to_list(
  187. vote_negatives
  188. )
  189. message = render_template(template_file, **base_parameters.template_arguments)
  190. inter_send_email(
  191. base_parameters.username,
  192. base_parameters.password,
  193. base_parameters.template_arguments["sender_email"],
  194. base_parameters.template_arguments["receiver_email"],
  195. message,
  196. )
  197. @cli.command("vote_ipmc")
  198. @click.option(
  199. "--receiver_email",
  200. default="general@incubator.apache.org",
  201. type=str,
  202. prompt="The receiver email (To:)",
  203. )
  204. @click.option("--voting_thread", prompt="The URL for the PMC voting thread")
  205. @click.option(
  206. "--vote_mentors",
  207. default="",
  208. type=str,
  209. prompt="A list of mentors that have already voted (ex: Alan,Justin)",
  210. )
  211. @click.pass_obj
  212. def vote_ipmc(base_parameters, receiver_email, voting_thread, vote_mentors):
  213. template_file = "email_templates/vote_ipmc.j2"
  214. base_parameters.template_arguments["receiver_email"] = receiver_email
  215. base_parameters.template_arguments["voting_thread"] = voting_thread
  216. base_parameters.template_arguments["vote_mentors"] = string_comma_to_list(
  217. vote_mentors
  218. )
  219. message = render_template(template_file, **base_parameters.template_arguments)
  220. inter_send_email(
  221. base_parameters.username,
  222. base_parameters.password,
  223. base_parameters.template_arguments["sender_email"],
  224. base_parameters.template_arguments["receiver_email"],
  225. message,
  226. )
  227. @cli.command("result_ipmc")
  228. @click.option(
  229. "--receiver_email",
  230. default="general@incubator.apache.org",
  231. type=str,
  232. prompt="The receiver email (To:)",
  233. )
  234. @click.option(
  235. "--vote_bindings",
  236. default="",
  237. type=str,
  238. prompt="A List of people with +1 binding vote (ex: Alan,Justin)",
  239. )
  240. @click.option(
  241. "--vote_nonbindings",
  242. default="",
  243. type=str,
  244. prompt="A List of people with +1 non binding vote (ex: Ville)",
  245. )
  246. @click.option(
  247. "--vote_negatives",
  248. default="",
  249. type=str,
  250. prompt="A List of people with -1 vote (ex: John)",
  251. )
  252. @click.pass_obj
  253. def result_ipmc(
  254. base_parameters, receiver_email, vote_bindings, vote_nonbindings, vote_negatives
  255. ):
  256. template_file = "email_templates/result_ipmc.j2"
  257. base_parameters.template_arguments["receiver_email"] = receiver_email
  258. base_parameters.template_arguments["vote_bindings"] = string_comma_to_list(
  259. vote_bindings
  260. )
  261. base_parameters.template_arguments["vote_nonbindings"] = string_comma_to_list(
  262. vote_nonbindings
  263. )
  264. base_parameters.template_arguments["vote_negatives"] = string_comma_to_list(
  265. vote_negatives
  266. )
  267. message = render_template(template_file, **base_parameters.template_arguments)
  268. inter_send_email(
  269. base_parameters.username,
  270. base_parameters.password,
  271. base_parameters.template_arguments["sender_email"],
  272. base_parameters.template_arguments["receiver_email"],
  273. message,
  274. )
  275. @cli.command("announce")
  276. @click.option(
  277. "--receiver_email",
  278. default="dev@superset.apache.org",
  279. type=str,
  280. prompt="The receiver email (To:)",
  281. )
  282. @click.pass_obj
  283. def announce(base_parameters, receiver_email):
  284. template_file = "email_templates/announce.j2"
  285. base_parameters.template_arguments["receiver_email"] = receiver_email
  286. message = render_template(template_file, **base_parameters.template_arguments)
  287. inter_send_email(
  288. base_parameters.username,
  289. base_parameters.password,
  290. base_parameters.template_arguments["sender_email"],
  291. base_parameters.template_arguments["receiver_email"],
  292. message,
  293. )
  294. cli()