test_body.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. from textwrap import dedent
  2. import sys
  3. from redmail import EmailSender
  4. import pytest
  5. from convert import remove_extra_lines, payloads_to_dict
  6. from getpass import getpass, getuser
  7. from platform import node
  8. from convert import remove_email_extra, remove_email_content_id, prune_generated_headers
  9. import platform
  10. PYTHON_VERSION = platform.sys.version_info
  11. IS_PY37 = sys.version_info < (3, 8)
  12. def test_text_message():
  13. sender = EmailSender(host=None, port=1234)
  14. msg = sender.get_message(
  15. sender="me@example.com",
  16. receivers="you@example.com",
  17. subject="Some news",
  18. text="Hi, nice to meet you.",
  19. )
  20. msg = prune_generated_headers(str(msg))
  21. assert str(msg) == dedent("""
  22. From: me@example.com
  23. Subject: Some news
  24. To: you@example.com
  25. Message-ID: <<message_id>>
  26. Date: <date>
  27. Content-Type: text/plain; charset="utf-8"
  28. Content-Transfer-Encoding: 7bit
  29. MIME-Version: 1.0
  30. Hi, nice to meet you.
  31. """)[1:]
  32. def test_html_message():
  33. sender = EmailSender(host=None, port=1234)
  34. msg = sender.get_message(
  35. sender="me@example.com",
  36. receivers="you@example.com",
  37. subject="Some news",
  38. html="<h3>Hi,</h3><p>Nice to meet you</p>",
  39. )
  40. msg = prune_generated_headers(str(msg))
  41. assert remove_email_content_id(str(msg)) == dedent("""
  42. From: me@example.com
  43. Subject: Some news
  44. To: you@example.com
  45. Message-ID: <<message_id>>
  46. Date: <date>
  47. Content-Type: multipart/mixed; boundary="===============<ID>=="
  48. --===============<ID>==
  49. Content-Type: multipart/alternative;
  50. boundary="===============<ID>=="
  51. --===============<ID>==
  52. Content-Type: text/html; charset="utf-8"
  53. Content-Transfer-Encoding: 7bit
  54. MIME-Version: 1.0
  55. <h3>Hi,</h3><p>Nice to meet you</p>
  56. --===============<ID>==--
  57. --===============<ID>==--
  58. """)[1:]
  59. def test_text_and_html_message():
  60. sender = EmailSender(host=None, port=1234)
  61. msg = sender.get_message(
  62. sender="me@example.com",
  63. receivers="you@example.com",
  64. subject="Some news",
  65. html="<h3>Hi,</h3><p>nice to meet you.</p>",
  66. text="Hi, nice to meet you.",
  67. )
  68. msg = prune_generated_headers(str(msg))
  69. assert remove_email_content_id(str(msg)) == dedent("""
  70. From: me@example.com
  71. Subject: Some news
  72. To: you@example.com
  73. Message-ID: <<message_id>>
  74. Date: <date>
  75. MIME-Version: 1.0
  76. Content-Type: multipart/mixed; boundary="===============<ID>=="
  77. --===============<ID>==
  78. Content-Type: multipart/alternative;
  79. boundary="===============<ID>=="
  80. --===============<ID>==
  81. Content-Type: text/plain; charset="utf-8"
  82. Content-Transfer-Encoding: 7bit
  83. Hi, nice to meet you.
  84. --===============<ID>==
  85. Content-Type: text/html; charset="utf-8"
  86. Content-Transfer-Encoding: 7bit
  87. MIME-Version: 1.0
  88. <h3>Hi,</h3><p>nice to meet you.</p>
  89. --===============<ID>==--
  90. --===============<ID>==--
  91. """)[1:]
  92. @pytest.mark.parametrize(
  93. "html,expected_html,text,expected_text,extra", [
  94. pytest.param(
  95. "<h3>Hi,</h3> <p>This is {{ user }} from {{ node }}. I'm really {{ sender.full_name }}.</p>",
  96. f"<h3>Hi,</h3> <p>This is {getuser()} from {node()}. I'm really Me.</p>\n",
  97. "Hi, \nThis is {{ user }} from {{ node }}. I'm really {{ sender.full_name }}.",
  98. f"Hi, \nThis is {getuser()} from {node()}. I'm really Me.\n",
  99. None,
  100. id="With default extras"
  101. ),
  102. pytest.param(
  103. "<h3>Hi {{ receiver }},</h3> <p>This is {{ user }} from {{ node }}. I'm really {{ sender.full_name }}.</p>",
  104. f"<h3>Hi you,</h3> <p>This is overridden from {node()}. I'm really Me.</p>\n",
  105. "Hi {{ receiver }}, This is {{ user }} from {{ node }}. I'm really {{ sender.full_name }}.",
  106. f"Hi you, This is overridden from {node()}. I'm really Me.\n",
  107. {"user": "overridden", "receiver": "you"},
  108. id="Custom extra"
  109. ),
  110. ]
  111. )
  112. def test_with_jinja_params(html, text, extra, expected_html, expected_text):
  113. sender = EmailSender(host=None, port=1234)
  114. msg = sender.get_message(
  115. sender="me@gmail.com",
  116. receivers="you@gmail.com",
  117. subject="Some news",
  118. text=text,
  119. html=html,
  120. body_params=extra
  121. )
  122. # Validate structure
  123. structure = payloads_to_dict(msg)
  124. assert structure == {
  125. 'multipart/mixed': {
  126. 'multipart/alternative': {
  127. 'text/plain': structure["multipart/mixed"]["multipart/alternative"]["text/plain"],
  128. 'text/html': structure["multipart/mixed"]["multipart/alternative"]["text/html"],
  129. }
  130. }
  131. }
  132. assert "multipart/mixed" == msg.get_content_type()
  133. alternative = msg.get_payload()[0]
  134. text_part, html_part = alternative.get_payload()
  135. text = remove_email_extra(text_part.get_payload())
  136. html = remove_email_extra(html_part.get_payload())
  137. assert expected_html == html
  138. assert expected_text == text
  139. @pytest.mark.parametrize("use_jinja_obj,use_jinja", [
  140. pytest.param(None, False, id="Use arg"),
  141. pytest.param(False, None, id="Use attr"),
  142. pytest.param(True, False, id="Override"),
  143. ])
  144. def test_without_jinja(use_jinja_obj, use_jinja):
  145. html = "<h3>Hi,</h3> <p>This is {{ user }} from { node }. I'm really {{ sender.full_name }}.</p>"
  146. text = "Hi, \nThis is {{ user }} from { node }. I'm really {{ sender.full_name }}."
  147. sender = EmailSender(host=None, port=1234)
  148. sender.use_jinja = use_jinja_obj
  149. msg = sender.get_message(
  150. sender="me@example.com",
  151. receivers="you@example.com",
  152. subject="Some news",
  153. text=text,
  154. html=html,
  155. use_jinja=use_jinja,
  156. )
  157. encoding = '7bit' if IS_PY37 else 'quoted-printable'
  158. expected = dedent("""
  159. From: me@example.com
  160. Subject: Some news
  161. To: you@example.com
  162. Message-ID: <<message_id>>
  163. Date: <date>
  164. MIME-Version: 1.0
  165. Content-Type: multipart/mixed; boundary="===============<ID>=="
  166. --===============<ID>==
  167. Content-Type: multipart/alternative;
  168. boundary="===============<ID>=="
  169. --===============<ID>==
  170. Content-Type: text/plain; charset="utf-8"
  171. Content-Transfer-Encoding: 7bit
  172. Hi,
  173. This is {{ user }} from { node }. I'm really {{ sender.full_name }}.
  174. --===============<ID>==
  175. Content-Type: text/html; charset="utf-8"
  176. Content-Transfer-Encoding: """ + encoding + """
  177. MIME-Version: 1.0
  178. <h3>Hi,</h3> <p>This is {{ user }} from { node }. I'm really {{ sender.full_n=
  179. ame }}.</p>
  180. --===============<ID>==--
  181. --===============<ID>==--
  182. """)[1:]
  183. if IS_PY37:
  184. expected = expected.replace('sender.full_n=\n', 'sender.full_n')
  185. msg = prune_generated_headers(str(msg))
  186. assert remove_email_content_id(msg) == expected
  187. def test_with_error():
  188. sender = EmailSender(host=None, port=1234)
  189. try:
  190. raise RuntimeError("Deliberate failure")
  191. except:
  192. msg = sender.get_message(
  193. sender="me@gmail.com",
  194. receivers="you@gmail.com",
  195. subject="Some news",
  196. text="Error occurred \n{{ error }}",
  197. html="<h1>Error occurred: </h1>{{ error }}",
  198. )
  199. alternative = msg.get_payload()[0]
  200. text_part, html_part = alternative.get_payload()
  201. text = remove_email_extra(text_part.get_payload())
  202. html = remove_email_extra(html_part.get_payload())
  203. if IS_PY37:
  204. text = text.replace('Error occurred \n', 'Error occurred\n')
  205. html = html.replace('<span style="color:', '<span style=3D"color:')
  206. assert text.startswith('Error occurred\nTraceback (most recent call last):\n File "')
  207. assert text.endswith(', in test_with_error\n raise RuntimeError("Deliberate failure")\nRuntimeError: Deliberate failure\n')
  208. assert html.startswith('<h1>Error occurred: </h1>\n <div>\n <h4>Traceback (most recent call last):</h4>\n <pre><code> File &quot;')
  209. assert html.endswith(', in test_with_error\nraise RuntimeError(&quot;Deliberate failure&quot;)</code></pre>\n <span style=3D"color: red; font-weight: bold">Deliberate failure</span>: <span>RuntimeError</span>\n </div>\n')
  210. def test_set_defaults():
  211. email = EmailSender(host=None, port=1234)
  212. email.sender = 'me@gmail.com'
  213. email.receivers = ['you@gmail.com', 'they@gmail.com']
  214. email.subject = "Some email"
  215. msg = email.get_message(text="Hi, an email")
  216. headers = {
  217. key: val if key not in ('Message-ID', 'Date') else '<ID>'
  218. for key, val in msg.items()
  219. }
  220. assert {
  221. 'From': 'me@gmail.com',
  222. 'To': 'you@gmail.com, they@gmail.com',
  223. 'Subject': 'Some email',
  224. 'Content-Type': 'text/plain; charset="utf-8"',
  225. 'Content-Transfer-Encoding': '7bit',
  226. 'MIME-Version': '1.0',
  227. 'Message-ID': '<ID>',
  228. 'Date': '<ID>',
  229. } == headers
  230. def test_missing_subject():
  231. email = EmailSender(host=None, port=1234)
  232. with pytest.raises(ValueError):
  233. email.get_message(sender="me@example.com", receivers=['you@example.com'])
  234. def test_no_table_templates():
  235. email = EmailSender(host="localhost", port=0)
  236. assert email.default_html_theme == "modest.html"
  237. assert email.default_text_theme == "pandas.txt"
  238. email.default_html_theme = None
  239. email.default_text_theme = None
  240. msg = email.get_message(
  241. sender="me@gmail.com",
  242. receivers="you@gmail.com",
  243. subject="Some news",
  244. text="An example",
  245. html="<h1>An example</h1>"
  246. )
  247. headers = {
  248. key: val
  249. for key, val in msg.items()
  250. if key not in ('Message-ID', 'Date')
  251. }
  252. assert headers == {
  253. 'From': 'me@gmail.com',
  254. 'Subject': 'Some news',
  255. 'To': 'you@gmail.com',
  256. 'MIME-Version': '1.0',
  257. 'Content-Type': 'multipart/mixed',
  258. }