test_structure.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import socket
  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. import base64, re
  8. from convert import remove_email_extra
  9. def test_empty():
  10. sender = EmailSender(host=None, port=1234)
  11. msg = sender.get_message(
  12. sender="me@example.com",
  13. receivers="you@example.com",
  14. subject="An example",
  15. )
  16. structure = payloads_to_dict(msg)
  17. assert structure == {}
  18. def test_text():
  19. sender = EmailSender(host=None, port=1234)
  20. msg = sender.get_message(
  21. sender="me@example.com",
  22. receivers="you@example.com",
  23. subject="An example",
  24. text="Text content",
  25. )
  26. structure = payloads_to_dict(msg)
  27. assert structure == {
  28. 'text/plain': 'Text content\n'
  29. }
  30. def test_html():
  31. sender = EmailSender(host=None, port=1234)
  32. msg = sender.get_message(
  33. sender="me@example.com",
  34. receivers="you@example.com",
  35. subject="An example",
  36. html="<h1>HTML content</h1>",
  37. )
  38. structure = payloads_to_dict(msg)
  39. assert structure == {
  40. "multipart/mixed": {
  41. 'multipart/alternative': {
  42. 'text/html': '<h1>HTML content</h1>\n'
  43. }
  44. }
  45. }
  46. def test_text_and_html():
  47. sender = EmailSender(host=None, port=1234)
  48. msg = sender.get_message(
  49. sender="me@example.com",
  50. receivers="you@example.com",
  51. subject="An example",
  52. text="Text content",
  53. html="<h1>HTML content</h1>",
  54. )
  55. structure = payloads_to_dict(msg)
  56. assert structure == {
  57. "multipart/mixed": {
  58. 'multipart/alternative': {
  59. 'text/plain': 'Text content\n',
  60. 'text/html': '<h1>HTML content</h1>\n'
  61. }
  62. }
  63. }
  64. def test_attachment():
  65. sender = EmailSender(host=None, port=1234)
  66. msg = sender.get_message(
  67. sender="me@example.com",
  68. receivers="you@example.com",
  69. subject="An example",
  70. attachments={'data.txt': "Some content"}
  71. )
  72. structure = payloads_to_dict(msg)
  73. assert structure == {
  74. "multipart/mixed": {
  75. 'application/octet-stream': 'U29tZSBjb250ZW50\n'
  76. }
  77. }
  78. def test_html_inline():
  79. host = socket.getfqdn()
  80. img_data = '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooor8DP9oD/2Q=='
  81. img_bytes = base64.b64decode(img_data)
  82. sender = EmailSender(host=None, port=1234)
  83. msg = sender.get_message(
  84. sender="me@example.com",
  85. receivers="you@example.com",
  86. subject="An example",
  87. html='<p>HTML content</p> \n{{ my_image }}',
  88. body_images={
  89. "my_image": {
  90. "content": img_bytes,
  91. 'subtype': 'jpg'
  92. }
  93. },
  94. )
  95. structure = payloads_to_dict(msg)
  96. cid = re.search('(?<=cid:).+(?=@)', structure["multipart/mixed"]["multipart/alternative"]["multipart/related"]["text/html"]).group()
  97. assert structure == {
  98. "multipart/mixed": {
  99. "multipart/alternative": {
  100. "multipart/related": {
  101. 'text/html': f'<p>HTML content</p> \n<img src="cid:{cid}@{host}">\n',
  102. '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',
  103. }
  104. },
  105. }
  106. }
  107. def test_text_html_inline_attachment():
  108. host = socket.getfqdn()
  109. img_data = '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooor8DP9oD/2Q=='
  110. img_bytes = base64.b64decode(img_data)
  111. sender = EmailSender(host=None, port=1234)
  112. msg = sender.get_message(
  113. sender="me@example.com",
  114. receivers="you@example.com",
  115. subject="An example",
  116. text="Text content",
  117. html='<p>HTML content</p> \n{{ my_image }}',
  118. body_images={
  119. "my_image": {
  120. "content": img_bytes,
  121. 'subtype': 'jpg'
  122. }
  123. },
  124. attachments={'data.txt': "Some content"},
  125. )
  126. structure = payloads_to_dict(msg)
  127. cid = re.search('(?<=cid:).+(?=@)', structure["multipart/mixed"]["multipart/alternative"]["multipart/related"]["text/html"]).group()
  128. assert structure == {
  129. "multipart/mixed": {
  130. "multipart/alternative": {
  131. 'text/plain': 'Text content\n',
  132. "multipart/related": {
  133. 'text/html': f'<p>HTML content</p> \n<img src="cid:{cid}@{host}">\n',
  134. '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',
  135. }
  136. },
  137. # Attachments
  138. 'application/octet-stream': 'U29tZSBjb250ZW50\n'
  139. }
  140. }
  141. def test_text_html_inline_attachment_multiple():
  142. host = socket.getfqdn()
  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}@{host}">\n<img src="cid:{cid_2}@{host}">\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. }