test_structure.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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. img_data = '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooor8DP9oD/2Q=='
  80. img_bytes = base64.b64decode(img_data)
  81. sender = EmailSender(host=None, port=1234)
  82. # CI may have long domain name thus we set it to such
  83. # that's shorter but looks realistic
  84. host = "REDMAIL-1234.mail.com"
  85. sender.domain = host
  86. msg = sender.get_message(
  87. sender="me@example.com",
  88. receivers="you@example.com",
  89. subject="An example",
  90. html='<p>HTML content</p> \n{{ my_image }}',
  91. body_images={
  92. "my_image": {
  93. "content": img_bytes,
  94. 'subtype': 'jpg'
  95. }
  96. },
  97. )
  98. structure = payloads_to_dict(msg)
  99. cid = re.search('(?<=cid:).+(?=@)', structure["multipart/mixed"]["multipart/alternative"]["multipart/related"]["text/html"]).group()
  100. assert structure == {
  101. "multipart/mixed": {
  102. "multipart/alternative": {
  103. "multipart/related": {
  104. 'text/html': f'<p>HTML content</p> \n<img src="cid:{cid}@{host}">\n',
  105. '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',
  106. }
  107. },
  108. }
  109. }
  110. def test_text_html_inline_attachment():
  111. img_data = '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooor8DP9oD/2Q=='
  112. img_bytes = base64.b64decode(img_data)
  113. sender = EmailSender(host=None, port=1234)
  114. # CI may have long domain name thus we set it to such
  115. # that's shorter but looks realistic
  116. host = "REDMAIL-1234.mail.com"
  117. sender.domain = host
  118. msg = sender.get_message(
  119. sender="me@example.com",
  120. receivers="you@example.com",
  121. subject="An example",
  122. text="Text content",
  123. html='<p>HTML content</p> \n{{ my_image }}',
  124. body_images={
  125. "my_image": {
  126. "content": img_bytes,
  127. 'subtype': 'jpg'
  128. }
  129. },
  130. attachments={'data.txt': "Some content"},
  131. )
  132. structure = payloads_to_dict(msg)
  133. cid = re.search('(?<=cid:).+(?=@)', structure["multipart/mixed"]["multipart/alternative"]["multipart/related"]["text/html"]).group()
  134. assert structure == {
  135. "multipart/mixed": {
  136. "multipart/alternative": {
  137. 'text/plain': 'Text content\n',
  138. "multipart/related": {
  139. 'text/html': f'<p>HTML content</p> \n<img src="cid:{cid}@{host}">\n',
  140. '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',
  141. }
  142. },
  143. # Attachments
  144. 'application/octet-stream': 'U29tZSBjb250ZW50\n'
  145. }
  146. }
  147. def test_text_html_inline_attachment_multiple():
  148. img_data = '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooor8DP9oD/2Q=='
  149. img_bytes = base64.b64decode(img_data)
  150. sender = EmailSender(host=None, port=1234)
  151. # CI may have long domain name thus we set it to such
  152. # that's shorter but looks realistic
  153. host = "REDMAIL-1234.mail.com"
  154. sender.domain = host
  155. msg = sender.get_message(
  156. sender="me@example.com",
  157. receivers="you@example.com",
  158. subject="An example",
  159. text="Text content",
  160. html='<p>HTML content</p> \n{{ my_image_1 }}\n{{ my_image_2 }}',
  161. body_images={
  162. "my_image_1": {
  163. "content": img_bytes,
  164. 'subtype': 'jpg'
  165. },
  166. "my_image_2": {
  167. "content": img_bytes,
  168. 'subtype': 'jpg'
  169. },
  170. },
  171. attachments={
  172. 'data_1.txt': "Some content 1",
  173. "data_2.txt": "Some content 2",
  174. },
  175. )
  176. structure = payloads_to_dict(msg)
  177. cid_1, cid_2 = re.findall('(?<=cid:).+(?=@)', structure["multipart/mixed"]["multipart/alternative"]["multipart/related"]["text/html"])
  178. assert structure == {
  179. "multipart/mixed": {
  180. "multipart/alternative": {
  181. 'text/plain': 'Text content\n',
  182. "multipart/related": {
  183. 'text/html': f'<p>HTML content</p> \n<img src="cid:{cid_1}@{host}">\n<img src="cid:{cid_2}@{host}">\n',
  184. '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',
  185. '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',
  186. }
  187. },
  188. # Attachments
  189. 'application/octet-stream': 'U29tZSBjb250ZW50IDE=\n',
  190. 'application/octet-stream_1': 'U29tZSBjb250ZW50IDI=\n'
  191. }
  192. }