test_inline_media.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. from redmail import EmailSender
  2. import re
  3. from pathlib import Path
  4. from io import BytesIO
  5. import pytest
  6. # Importing Pandas from utils (is None if missing package)
  7. from redmail.email.utils import pd
  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(host=None, port=1234)
  35. msg = sender.get_message(
  36. sender="me@gmail.com",
  37. receivers="you@gmail.com",
  38. subject="Some news",
  39. html='<h1>Hi,</h1> Nice to meet you. Look at this: {{ 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(host=None, port=1234)
  65. msg = sender.get_message(
  66. sender="me@gmail.com",
  67. receivers="you@gmail.com",
  68. subject="Some news",
  69. html='<h1>Hi,</h1> Nice to meet you. Look at this: <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. "get_df,", [
  88. pytest.param(
  89. lambda: 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. lambda: pd.DataFrame(
  97. [[1], [2], [3]],
  98. columns=pd.Index(["first"]),
  99. ),
  100. id="Single column datafram"
  101. ),
  102. pytest.param(
  103. lambda: 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. lambda: 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. lambda: 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. lambda: 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(get_df, tmpdir):
  136. pytest.importorskip("pandas")
  137. df = get_df()
  138. sender = EmailSender(host=None, port=1234)
  139. msg = sender.get_message(
  140. sender="me@gmail.com",
  141. receivers="you@gmail.com",
  142. subject="Some news",
  143. html='The table {{my_table}}',
  144. body_tables={"my_table": df}
  145. )
  146. assert "multipart/alternative" == msg.get_content_type()
  147. #mime_text = msg.get_payload()[0]
  148. html = remove_extra_lines(msg.get_payload()[0].get_payload()).replace("=20", "").replace('"3D', "")
  149. #tmpdir.join("email.html").write(html)
  150. # TODO: Test the HTML is as required
  151. assert html