test_attachments.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. from redmail import EmailSender
  2. import base64
  3. from pathlib import Path
  4. import pytest
  5. from resources import get_mpl_fig, get_pil_image
  6. from convert import remove_extra_lines
  7. def to_encoded(s:str):
  8. return str(base64.b64encode(s.encode()), 'ascii')
  9. def test_with_text():
  10. sender = EmailSender(host=None, port=1234)
  11. msg = sender.get_message(
  12. sender="me@gmail.com",
  13. receivers="you@gmail.com",
  14. subject="Some news",
  15. text="Hi, this is an email",
  16. attachments={'data.txt': "Some content"}
  17. )
  18. assert msg.get_content_type() == "multipart/mixed"
  19. text, attachment = msg.get_payload()
  20. assert text.get_content_type() == 'text/plain'
  21. assert attachment.get_content_type() == 'application/octet-stream'
  22. assert text.get_payload() == "Hi, this is an email\n"
  23. filename = attachment.get_filename()
  24. data = attachment.get_payload()
  25. assert filename == 'data.txt'
  26. assert to_encoded("Some content") == data.replace('\n', '')
  27. def test_with_html():
  28. sender = EmailSender(host=None, port=1234)
  29. msg = sender.get_message(
  30. sender="me@gmail.com",
  31. receivers="you@gmail.com",
  32. subject="Some news",
  33. html="<h1>Hi, this is an email.</h1>",
  34. attachments={'data.txt': "Some content"}
  35. )
  36. assert msg.get_content_type() == "multipart/alternative"
  37. html, attachment = msg.get_payload()
  38. assert html.get_content_type() == 'text/html'
  39. assert attachment.get_content_type() == 'application/octet-stream'
  40. assert html.get_payload() == "<h1>Hi, this is an email.</h1>\n"
  41. filename = attachment.get_filename()
  42. data = attachment.get_payload()
  43. assert attachment.get_content_type() == 'application/octet-stream'
  44. assert filename == 'data.txt'
  45. assert to_encoded("Some content") == data.replace('\n', '')
  46. def test_with_text_and_html():
  47. sender = EmailSender(host=None, port=1234)
  48. msg = sender.get_message(
  49. sender="me@gmail.com",
  50. receivers="you@gmail.com",
  51. subject="Some news",
  52. text="Hi, this is an email.",
  53. html="<h1>Hi, this is an email.</h1>",
  54. attachments={'data.txt': "Some content"}
  55. )
  56. assert msg.get_content_type() == "multipart/alternative"
  57. text, html, attachment = msg.get_payload()
  58. assert text.get_content_type() == "text/plain"
  59. assert html.get_content_type() == "text/html"
  60. assert attachment.get_content_type() == 'application/octet-stream'
  61. assert text.get_payload() == 'Hi, this is an email.\n'
  62. assert html.get_payload() == '<h1>Hi, this is an email.</h1>\n'
  63. filename = attachment.get_filename()
  64. data = attachment.get_payload()
  65. assert filename == 'data.txt'
  66. assert to_encoded("Some content") == data.replace('\n', '')
  67. def test_no_body():
  68. sender = EmailSender(host=None, port=1234)
  69. msg = sender.get_message(
  70. sender="me@gmail.com",
  71. receivers="you@gmail.com",
  72. subject="Some news",
  73. attachments={'data.txt': 'Some content'}
  74. )
  75. assert msg.get_content_type() == "multipart/mixed"
  76. assert len(msg.get_payload()) == 1
  77. attachment = msg.get_payload(0)
  78. assert attachment.get_content_type() == 'application/octet-stream'
  79. filename = attachment.get_filename()
  80. data = attachment.get_payload()
  81. assert filename == 'data.txt'
  82. assert to_encoded("Some content") == data.replace('\n', '')
  83. def test_dict_string():
  84. sender = EmailSender(host=None, port=1234)
  85. msg = sender.get_message(
  86. sender="me@gmail.com",
  87. receivers="you@gmail.com",
  88. subject="Some news",
  89. attachments={'data.txt': 'Some content'}
  90. )
  91. assert msg.get_content_type() == "multipart/mixed"
  92. attachment = msg.get_payload(0)
  93. filename = attachment.get_filename()
  94. data = attachment.get_payload()
  95. assert filename == 'data.txt'
  96. assert to_encoded("Some content") == data.replace('\n', '')
  97. def test_dict_bytes():
  98. sender = EmailSender(host=None, port=1234)
  99. msg = sender.get_message(
  100. sender="me@gmail.com",
  101. receivers="you@gmail.com",
  102. subject="Some news",
  103. attachments={'data.bin': bytes(10)}
  104. )
  105. assert msg.get_content_type() == "multipart/mixed"
  106. payload = msg.get_payload(0)
  107. filename = payload.get_filename()
  108. data = payload.get_payload()
  109. assert filename == 'data.bin'
  110. assert base64.b64encode(bytes(10)).decode() == data.replace('\n', '')
  111. def test_dict_path(tmpdir):
  112. file = tmpdir.join("data.txt")
  113. file.write("Some content")
  114. sender = EmailSender(host=None, port=1234)
  115. msg = sender.get_message(
  116. sender="me@gmail.com",
  117. receivers="you@gmail.com",
  118. subject="Some news",
  119. attachments={'myfile.txt': Path(str(file))}
  120. )
  121. assert msg.get_content_type() == "multipart/mixed"
  122. payload = msg.get_payload(0)
  123. filename = payload.get_filename()
  124. data = payload.get_payload()
  125. assert filename == 'myfile.txt'
  126. assert to_encoded("Some content") == data.replace('\n', '')
  127. def test_dict_dataframe_txt():
  128. pytest.importorskip("pandas")
  129. import pandas as pd
  130. sender = EmailSender(host=None, port=1234)
  131. msg = sender.get_message(
  132. sender="me@gmail.com",
  133. receivers="you@gmail.com",
  134. subject="Some news",
  135. attachments={'myfile.txt': pd.DataFrame({'a': [1,2,3], 'b': ['1', '2', '3']})}
  136. )
  137. expected = str(pd.DataFrame({'a': [1,2,3], 'b': ['1', '2', '3']}))
  138. assert msg.get_content_type() == "multipart/mixed"
  139. payload = msg.get_payload(0)
  140. filename = payload.get_filename()
  141. data = payload.get_payload()
  142. assert filename == 'myfile.txt'
  143. assert to_encoded(expected) == data.replace('\n', '')
  144. def test_dict_dataframe_csv():
  145. pytest.importorskip("pandas")
  146. import pandas as pd
  147. df = pd.DataFrame({'a': [1,2,3], 'b': ['1', '2', '3']})
  148. sender = EmailSender(host=None, port=1234)
  149. msg = sender.get_message(
  150. sender="me@gmail.com",
  151. receivers="you@gmail.com",
  152. subject="Some news",
  153. attachments={'myfile.csv': df}
  154. )
  155. assert msg.get_content_type() == "multipart/mixed"
  156. payload = msg.get_payload(0)
  157. filename = payload.get_filename()
  158. data = payload.get_payload()
  159. assert filename == 'myfile.csv'
  160. assert to_encoded(df.to_csv()) == data.replace('\n', '')
  161. def test_dict_dataframe_html():
  162. pytest.importorskip("pandas")
  163. import pandas as pd
  164. sender = EmailSender(host=None, port=1234)
  165. msg = sender.get_message(
  166. sender="me@gmail.com",
  167. receivers="you@gmail.com",
  168. subject="Some news",
  169. attachments={'myfile.html': pd.DataFrame({'a': [1,2,3], 'b': ['1', '2', '3']})}
  170. )
  171. expected = '<table border="1" class="dataframe">\n <thead>\n <tr style="text-align: right;">\n <th></th>\n <th>a</th>\n <th>b</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>1</td>\n <td>1</td>\n </tr>\n <tr>\n <th>1</th>\n <td>2</td>\n <td>2</td>\n </tr>\n <tr>\n <th>2</th>\n <td>3</td>\n <td>3</td>\n </tr>\n </tbody>\n</table>'
  172. assert msg.get_content_type() == "multipart/mixed"
  173. payload = msg.get_payload(0)
  174. filename = payload.get_filename()
  175. data = payload.get_payload().replace('\n', '')
  176. assert filename == 'myfile.html'
  177. assert to_encoded(expected) == data
  178. def test_dict_dataframe_invalid():
  179. pytest.importorskip("pandas")
  180. import pandas as pd
  181. sender = EmailSender(host=None, port=1234)
  182. with pytest.raises(ValueError):
  183. msg = sender.get_message(
  184. sender="me@gmail.com",
  185. receivers="you@gmail.com",
  186. subject="Some news",
  187. attachments={'myfile.something': pd.DataFrame({'a': [1,2,3], 'b': ['1', '2', '3']})}
  188. )
  189. def test_dict_dataframe_excel_no_error():
  190. pytest.importorskip("pandas")
  191. pytest.importorskip("openpyxl")
  192. import pandas as pd
  193. sender = EmailSender(host=None, port=1234)
  194. msg = sender.get_message(
  195. sender="me@gmail.com",
  196. receivers="you@gmail.com",
  197. subject="Some news",
  198. attachments={'myfile.xlsx': pd.DataFrame({'a': [1,2,3], 'b': ['1', '2', '3']})}
  199. )
  200. assert msg.get_content_type() == "multipart/mixed"
  201. payload = msg.get_payload(0)
  202. filename = payload.get_filename()
  203. data = payload.get_payload()
  204. assert filename == 'myfile.xlsx'
  205. # Excels are harder to verify
  206. def test_dict_pil_no_error():
  207. pil, bytes_img = get_pil_image()
  208. sender = EmailSender(host=None, port=1234)
  209. msg = sender.get_message(
  210. sender="me@gmail.com",
  211. receivers="you@gmail.com",
  212. subject="Some news",
  213. attachments={'myimg.png': pil}
  214. )
  215. assert msg.get_content_type() == "multipart/mixed"
  216. payload = msg.get_payload(0)
  217. filename = payload.get_filename()
  218. data = payload.get_payload()
  219. assert filename == 'myimg.png'
  220. assert str(base64.b64encode(bytes_img), 'ascii') == data.replace('\n', '')
  221. def test_dict_matplotlib_no_error():
  222. fig, bytes_fig = get_mpl_fig()
  223. sender = EmailSender(host=None, port=1234)
  224. msg = sender.get_message(
  225. sender="me@gmail.com",
  226. receivers="you@gmail.com",
  227. subject="Some news",
  228. attachments={'myimg.png': fig}
  229. )
  230. assert msg.get_content_type() == "multipart/mixed"
  231. payload = msg.get_payload(0)
  232. filename = payload.get_filename()
  233. data = payload.get_payload()
  234. assert filename == 'myimg.png'
  235. assert str(base64.b64encode(bytes_fig), 'ascii') == data.replace('\n', '')
  236. def test_dict_invalid():
  237. sender = EmailSender(host=None, port=1234)
  238. with pytest.raises(TypeError):
  239. msg = sender.get_message(
  240. sender="me@gmail.com",
  241. receivers="you@gmail.com",
  242. subject="Some news",
  243. attachments={'myimg.png': sender}
  244. )
  245. def test_dict_invalid_key():
  246. fig, bytes_fig = get_mpl_fig()
  247. sender = EmailSender(host=None, port=1234)
  248. with pytest.raises(TypeError):
  249. msg = sender.get_message(
  250. sender="me@gmail.com",
  251. receivers="you@gmail.com",
  252. subject="Some news",
  253. attachments={sender: 'something'}
  254. )
  255. def test_dict_multiple(tmpdir):
  256. file1 = tmpdir.join("file_1.txt")
  257. file1.write("Some content 1")
  258. file2 = tmpdir.join("file_2.txt")
  259. file2.write("Some content 2")
  260. sender = EmailSender(host=None, port=1234)
  261. msg = sender.get_message(
  262. sender="me@gmail.com",
  263. receivers="you@gmail.com",
  264. subject="Some news",
  265. attachments={'data_1.txt': Path(file1), 'data_2.txt': Path(file2)}
  266. )
  267. assert msg.get_content_type() == "multipart/mixed"
  268. expected = [('data_1.txt', 'Some content 1'), ('data_2.txt', 'Some content 2')]
  269. for payload, expected in zip(msg.iter_attachments(), expected):
  270. filename = payload.get_filename()
  271. data = payload.get_payload()
  272. assert filename == expected[0]
  273. assert to_encoded(expected[1]) == data.replace('\n', '')
  274. # List attachments
  275. # ----------------
  276. def test_list_path(tmpdir):
  277. file = tmpdir.join("data.txt")
  278. file.write("Some content")
  279. sender = EmailSender(host=None, port=1234)
  280. msg = sender.get_message(
  281. sender="me@gmail.com",
  282. receivers="you@gmail.com",
  283. subject="Some news",
  284. attachments=[Path(str(file))]
  285. )
  286. assert msg.get_content_type() == "multipart/mixed"
  287. payload = msg.get_payload(0)
  288. filename = payload.get_filename()
  289. data = payload.get_payload()
  290. assert filename == 'data.txt'
  291. assert to_encoded("Some content") == data.replace('\n', '')
  292. def test_list_string_path(tmpdir):
  293. file = tmpdir.join("data.txt")
  294. file.write("Some content")
  295. sender = EmailSender(host=None, port=1234)
  296. msg = sender.get_message(
  297. sender="me@gmail.com",
  298. receivers="you@gmail.com",
  299. subject="Some news",
  300. attachments=[str(file)]
  301. )
  302. assert msg.get_content_type() == "multipart/mixed"
  303. payload = msg.get_payload(0)
  304. filename = payload.get_filename()
  305. data = payload.get_payload()
  306. assert filename == 'data.txt'
  307. assert to_encoded("Some content") == data.replace('\n', '')
  308. def test_list_string_error():
  309. sender = EmailSender(host=None, port=1234)
  310. with pytest.raises(ValueError):
  311. msg = sender.get_message(
  312. sender="me@gmail.com",
  313. receivers="you@gmail.com",
  314. subject="Some news",
  315. attachments=['just something']
  316. )
  317. def test_list_multiple(tmpdir):
  318. file1 = tmpdir.join("data_1.txt")
  319. file1.write("Some content 1")
  320. file2 = tmpdir.join("data_2.txt")
  321. file2.write("Some content 2")
  322. sender = EmailSender(host=None, port=1234)
  323. msg = sender.get_message(
  324. sender="me@gmail.com",
  325. receivers="you@gmail.com",
  326. subject="Some news",
  327. attachments=[Path(str(file1)), Path(str(file2))]
  328. )
  329. assert msg.get_content_type() == "multipart/mixed"
  330. expected = [('data_1.txt', 'Some content 1'), ('data_2.txt', 'Some content 2')]
  331. for payload, expected in zip(msg.iter_attachments(), expected):
  332. filename = payload.get_filename()
  333. data = payload.get_payload()
  334. assert filename == expected[0]
  335. assert to_encoded(expected[1]) == data.replace('\n', '')
  336. def test_list_invalid():
  337. sender = EmailSender(host=None, port=1234)
  338. with pytest.raises(TypeError):
  339. msg = sender.get_message(
  340. sender="me@gmail.com",
  341. receivers="you@gmail.com",
  342. subject="Some news",
  343. attachments=[sender]
  344. )
  345. def test_string_path(tmpdir):
  346. file = tmpdir.join("data.txt")
  347. file.write("Some content")
  348. sender = EmailSender(host=None, port=1234)
  349. msg = sender.get_message(
  350. sender="me@gmail.com",
  351. receivers="you@gmail.com",
  352. subject="Some news",
  353. attachments=str(file)
  354. )
  355. assert msg.get_content_type() == "multipart/mixed"
  356. payload = msg.get_payload(0)
  357. filename = payload.get_filename()
  358. data = payload.get_payload()
  359. assert filename == 'data.txt'
  360. assert to_encoded("Some content") == data.replace('\n', '')
  361. def test_string_error():
  362. sender = EmailSender(host=None, port=1234)
  363. with pytest.raises(ValueError):
  364. msg = sender.get_message(
  365. sender="me@gmail.com",
  366. receivers="you@gmail.com",
  367. subject="Some news",
  368. attachments="just something"
  369. )
  370. def test_path(tmpdir):
  371. file = tmpdir.join("data.txt")
  372. file.write("Some content")
  373. sender = EmailSender(host=None, port=1234)
  374. msg = sender.get_message(
  375. sender="me@gmail.com",
  376. receivers="you@gmail.com",
  377. subject="Some news",
  378. attachments=Path(file)
  379. )
  380. assert msg.get_content_type() == "multipart/mixed"
  381. payload = msg.get_payload(0)
  382. filename = payload.get_filename()
  383. data = payload.get_payload()
  384. assert filename == 'data.txt'
  385. assert to_encoded("Some content") == data.replace('\n', '')