test_structure.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. from redmail import EmailSender
  2. import pytest
  3. from convert import remove_extra_lines, payloads_to_dict
  4. from getpass import getpass, getuser
  5. from platform import node
  6. import base64, re
  7. from convert import remove_email_extra
  8. def test_empty():
  9. sender = EmailSender(host=None, port=1234)
  10. msg = sender.get_message(
  11. sender="me@example.com",
  12. receivers="you@example.com",
  13. subject="An example",
  14. )
  15. structure = payloads_to_dict(msg)
  16. assert structure == {
  17. "multipart/mixed": {}
  18. }
  19. def test_text():
  20. sender = EmailSender(host=None, port=1234)
  21. msg = sender.get_message(
  22. sender="me@example.com",
  23. receivers="you@example.com",
  24. subject="An example",
  25. text="Text content",
  26. )
  27. structure = payloads_to_dict(msg)
  28. assert structure == {
  29. "multipart/mixed": {
  30. 'text/plain': 'Text content\n'
  31. }
  32. }
  33. def test_html():
  34. sender = EmailSender(host=None, port=1234)
  35. msg = sender.get_message(
  36. sender="me@example.com",
  37. receivers="you@example.com",
  38. subject="An example",
  39. html="<h1>HTML content</h1>",
  40. )
  41. structure = payloads_to_dict(msg)
  42. assert structure == {
  43. "multipart/mixed": {
  44. 'multipart/alternative': {
  45. 'text/html': '<h1>HTML content</h1>\n'
  46. }
  47. }
  48. }
  49. def test_text_and_html():
  50. sender = EmailSender(host=None, port=1234)
  51. msg = sender.get_message(
  52. sender="me@example.com",
  53. receivers="you@example.com",
  54. subject="An example",
  55. text="Text content",
  56. html="<h1>HTML content</h1>",
  57. )
  58. structure = payloads_to_dict(msg)
  59. assert structure == {
  60. "multipart/mixed": {
  61. 'multipart/alternative': {
  62. 'text/plain': 'Text content\n',
  63. 'text/html': '<h1>HTML content</h1>\n'
  64. }
  65. }
  66. }
  67. def test_attachment():
  68. sender = EmailSender(host=None, port=1234)
  69. msg = sender.get_message(
  70. sender="me@example.com",
  71. receivers="you@example.com",
  72. subject="An example",
  73. attachments={'data.txt': "Some content"}
  74. )
  75. structure = payloads_to_dict(msg)
  76. assert structure == {
  77. "multipart/mixed": {
  78. 'application/octet-stream': 'U29tZSBjb250ZW50\n'
  79. }
  80. }
  81. def test_html_inline():
  82. img_data = '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooor8DP9oD/2Q=='
  83. img_bytes = base64.b64decode(img_data)
  84. sender = EmailSender(host=None, port=1234)
  85. msg = sender.get_message(
  86. sender="me@example.com",
  87. receivers="you@example.com",
  88. subject="An example",
  89. html='<p>HTML content</p> \n{{ my_image }}',
  90. body_images={
  91. "my_image": {
  92. "content": img_bytes,
  93. 'subtype': 'jpg'
  94. }
  95. },
  96. )
  97. structure = payloads_to_dict(msg)
  98. cid = re.search('(?<=cid:).+(?=@)', structure["multipart/mixed"]["multipart/alternative"]["multipart/related"]["text/html"]).group()
  99. assert structure == {
  100. "multipart/mixed": {
  101. "multipart/alternative": {
  102. "multipart/related": {
  103. 'text/html': f'<p>HTML content</p> \n<img src="cid:{cid}@example.com">\n',
  104. 'image/jpg': '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcG\nBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwM\nDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooo\nr8DP9oD/2Q==\n',
  105. }
  106. },
  107. }
  108. }
  109. def test_text_html_inline_attachment():
  110. img_data = '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooor8DP9oD/2Q=='
  111. img_bytes = base64.b64decode(img_data)
  112. sender = EmailSender(host=None, port=1234)
  113. msg = sender.get_message(
  114. sender="me@example.com",
  115. receivers="you@example.com",
  116. subject="An example",
  117. text="Text content",
  118. html='<p>HTML content</p> \n{{ my_image }}',
  119. body_images={
  120. "my_image": {
  121. "content": img_bytes,
  122. 'subtype': 'jpg'
  123. }
  124. },
  125. attachments={'data.txt': "Some content"},
  126. )
  127. structure = payloads_to_dict(msg)
  128. cid = re.search('(?<=cid:).+(?=@)', structure["multipart/mixed"]["multipart/alternative"]["multipart/related"]["text/html"]).group()
  129. assert structure == {
  130. "multipart/mixed": {
  131. "multipart/alternative": {
  132. 'text/plain': 'Text content\n',
  133. "multipart/related": {
  134. 'text/html': f'<p>HTML content</p> \n<img src="cid:{cid}@example.com">\n',
  135. 'image/jpg': '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcG\nBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwM\nDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooo\nr8DP9oD/2Q==\n',
  136. }
  137. },
  138. # Attachments
  139. 'application/octet-stream': 'U29tZSBjb250ZW50\n'
  140. }
  141. }
  142. def test_text_html_inline_attachment_multiple():
  143. img_data = '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooor8DP9oD/2Q=='
  144. img_bytes = base64.b64decode(img_data)
  145. sender = EmailSender(host=None, port=1234)
  146. msg = sender.get_message(
  147. sender="me@example.com",
  148. receivers="you@example.com",
  149. subject="An example",
  150. text="Text content",
  151. html='<p>HTML content</p> \n{{ my_image_1 }}\n{{ my_image_2 }}',
  152. body_images={
  153. "my_image_1": {
  154. "content": img_bytes,
  155. 'subtype': 'jpg'
  156. },
  157. "my_image_2": {
  158. "content": img_bytes,
  159. 'subtype': 'jpg'
  160. },
  161. },
  162. attachments={
  163. 'data_1.txt': "Some content 1",
  164. "data_2.txt": "Some content 2",
  165. },
  166. )
  167. structure = payloads_to_dict(msg)
  168. cid_1, cid_2 = re.findall('(?<=cid:).+(?=@)', structure["multipart/mixed"]["multipart/alternative"]["multipart/related"]["text/html"])
  169. assert structure == {
  170. "multipart/mixed": {
  171. "multipart/alternative": {
  172. 'text/plain': 'Text content\n',
  173. "multipart/related": {
  174. 'text/html': f'<p>HTML content</p> \n<img src="cid:{cid_1}@example.com">\n<img src="cid:{cid_2}@example.com">\n',
  175. 'image/jpg': '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcG\nBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwM\nDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooo\nr8DP9oD/2Q==\n',
  176. 'image/jpg_1': '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcG\nBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwM\nDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooo\nr8DP9oD/2Q==\n',
  177. }
  178. },
  179. # Attachments
  180. 'application/octet-stream': 'U29tZSBjb250ZW50IDE=\n',
  181. 'application/octet-stream_1': 'U29tZSBjb250ZW50IDI=\n'
  182. }
  183. }