test_inline_media.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. from redmail import EmailSender
  2. import re
  3. from pathlib import Path
  4. from io import BytesIO
  5. import pytest
  6. import pandas as pd
  7. import numpy as np
  8. from resources import get_mpl_fig, get_pil_image
  9. from convert import remove_extra_lines
  10. def compare_image_mime(mime_part, mime_part_html, orig_image:bytes):
  11. assert 'image/png' == mime_part.get_content_type()
  12. image_bytes = mime_part.get_content()
  13. assert orig_image == image_bytes
  14. # Check the HTML mime has the image
  15. image_info = dict(mime_part.items())
  16. cid_parts = image_info['Content-ID'][1:-1].split(".")
  17. cid = "{}.{}.=\n{}.{domain}".format(*cid_parts[:3], domain='.'.join(cid_parts[3:]))
  18. cid = image_info['Content-ID'][1:-1]
  19. mime_part_html_cleaned = mime_part_html.get_payload().replace("=\n", "")
  20. assert f'<img src=3D"cid:{cid}">' in mime_part_html_cleaned or f'<img src="cid:{cid}">' in mime_part_html_cleaned
  21. @pytest.mark.parametrize(
  22. "get_image_obj", [
  23. pytest.param(lambda x: str(x), id="Path (str)"),
  24. pytest.param(lambda x: Path(str(x)), id="Path (pathlib)"),
  25. pytest.param(lambda x: open(str(x), 'rb').read(), id="Bytes (bytes)"),
  26. pytest.param(lambda x: BytesIO(open(str(x), 'rb').read()), id="Bytes (BytesIO)"),
  27. pytest.param(lambda x: {"maintype": "image", "subtype": "png", "content": open(str(x), 'rb').read()}, id="Dict specs"),
  28. ]
  29. )
  30. def test_with_image_file(get_image_obj, dummy_png):
  31. with open(str(dummy_png), "rb") as f:
  32. dummy_bytes = f.read()
  33. image_obj = get_image_obj(dummy_png)
  34. sender = EmailSender(server=None, port=1234)
  35. msg = sender.get_message(
  36. sender="me@gmail.com",
  37. receiver="you@gmail.com",
  38. subject="Some news",
  39. html_body='<h1>Hi,</h1> Nice to meet you. Look at this shit: <img src="{{ my_image }}">',
  40. body_images={"my_image": image_obj}
  41. )
  42. assert "multipart/alternative" == msg.get_content_type()
  43. #mime_text = msg.get_payload()[0]
  44. mime_html = msg.get_payload()[0].get_payload()[0]
  45. mime_image = msg.get_payload()[0].get_payload()[1]
  46. compare_image_mime(mime_image, mime_html, orig_image=dummy_bytes)
  47. # Test receivers etc.
  48. headers = dict(msg.items())
  49. assert {
  50. 'from': 'me@gmail.com',
  51. 'subject': 'Some news',
  52. 'to': 'you@gmail.com',
  53. #'MIME-Version': '1.0',
  54. 'Content-Type': 'multipart/alternative'
  55. } == headers
  56. @pytest.mark.parametrize(
  57. "get_image_obj", [
  58. pytest.param(get_mpl_fig, id="Matplotlib figure"),
  59. pytest.param(get_pil_image, id="PIL image"),
  60. ]
  61. )
  62. def test_with_image_obj(get_image_obj):
  63. image_obj, image_bytes = get_image_obj()
  64. sender = EmailSender(server=None, port=1234)
  65. msg = sender.get_message(
  66. sender="me@gmail.com",
  67. receiver="you@gmail.com",
  68. subject="Some news",
  69. html_body='<h1>Hi,</h1> Nice to meet you. Look at this shit: <img src="{{ my_image }}">',
  70. body_images={"my_image": image_obj}
  71. )
  72. assert "multipart/alternative" == msg.get_content_type()
  73. #mime_text = msg.get_payload()[0]
  74. mime_html = msg.get_payload()[0].get_payload()[0]
  75. mime_image = msg.get_payload()[0].get_payload()[1]
  76. compare_image_mime(mime_image, mime_html, orig_image=image_bytes)
  77. # Test receivers etc.
  78. headers = dict(msg.items())
  79. assert {
  80. 'from': 'me@gmail.com',
  81. 'subject': 'Some news',
  82. 'to': 'you@gmail.com',
  83. #'MIME-Version': '1.0',
  84. 'Content-Type': 'multipart/alternative'
  85. } == headers
  86. @pytest.mark.parametrize(
  87. "df,", [
  88. pytest.param(
  89. pd.DataFrame(
  90. [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
  91. columns=pd.Index(["first", "second", "third"]),
  92. ),
  93. id="Simple dataframe"
  94. ),
  95. pytest.param(
  96. pd.DataFrame(
  97. [[1], [2], [3]],
  98. columns=pd.Index(["first"]),
  99. ),
  100. id="Single column datafram"
  101. ),
  102. pytest.param(
  103. pd.DataFrame(
  104. [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
  105. columns=pd.Index(["first", "second", "third"]),
  106. index=pd.Index(["a", "b", "c"], name="category")
  107. ),
  108. id="Simple dataframe with index"
  109. ),
  110. pytest.param(
  111. pd.DataFrame(
  112. [[1, 2, 3, "a"], [4, 5, 6, "b"], [7, 8, 9, "c"], [10, 11, 12, "d"]],
  113. columns=pd.MultiIndex.from_tuples([("parent a", "child a"), ("parent a", "child b"), ("parent b", "child a"), ("parent c", "child a")], names=["lvl 1", "lvl 2"]),
  114. index=pd.MultiIndex.from_tuples([("row a", "sub a"), ("row a", "sub b"), ("row b", "sub a"), ("row c", "sub a")], names=["cat 1", "cat 2"]),
  115. ),
  116. id="Complex dataframe"
  117. ),
  118. pytest.param(
  119. pd.DataFrame(
  120. [[1, 2], [4, 5]],
  121. columns=pd.MultiIndex.from_tuples([("col a", "child b", "subchild a"), ("col a", "child b", "subchild a")]),
  122. index=pd.MultiIndex.from_tuples([("row a", "child b", "subchild a"), ("row a", "child b", "subchild a")]),
  123. ),
  124. id="Multiindex end with spanned"
  125. ),
  126. pytest.param(
  127. pd.DataFrame(
  128. [],
  129. columns=pd.Index(["first", "second", "third"]),
  130. ),
  131. id="Empty datafram"
  132. ),
  133. ]
  134. )
  135. def test_with_html_table_no_error(df, tmpdir):
  136. sender = EmailSender(server=None, port=1234)
  137. msg = sender.get_message(
  138. sender="me@gmail.com",
  139. receiver="you@gmail.com",
  140. subject="Some news",
  141. html_body='The table {{my_table}}',
  142. body_tables={"my_table": df}
  143. )
  144. assert "multipart/alternative" == msg.get_content_type()
  145. #mime_text = msg.get_payload()[0]
  146. html = remove_extra_lines(msg.get_payload()[0].get_payload()).replace("=20", "").replace('"3D', "")
  147. #tmpdir.join("email.html").write(html)
  148. # TODO: Test the HTML is as required
  149. assert html