test_body.py 9.5 KB

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