testing.rst 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. .. _testing:
  2. How to Test
  3. ===========
  4. For testing purposes, it might be useful to prevent
  5. sending the actual email. This is especially preferable
  6. with unit tests. There are several ways to do this.
  7. .. note::
  8. Red Mail extends :stdlib:`email.message.EmailMessage <email.message.html#email.message.EmailMessage>`
  9. from standard library. You may use its attributes and
  10. methods for testing the contents of your messages.
  11. See :ref:`email_structure` for how Red Mail's
  12. emails are structured.
  13. Using get_message
  14. -----------------
  15. All of the arguments in method :py:meth:`.EmailSender.send`
  16. are passed to :py:meth:`.EmailSender.get_message` method
  17. which generates the message itself. Therefore, the simplest
  18. solution is to use this method instead of :py:meth:`.EmailSender.send`
  19. in tests:
  20. .. code-block:: python
  21. from redmail import EmailSender
  22. # Just put something as host and port
  23. email = EmailSender(host="localhost", port=0)
  24. msg = email.get_message(
  25. subject='email subject',
  26. sender="me@example.com",
  27. receivers=['you@example.com'],
  28. text="Hi, this is an email.",
  29. )
  30. assert str(msg) == """From: me@example.com
  31. Subject: Some news
  32. To: you@example.com
  33. Message-ID: <167294165062.31860.1664530310632362057@LAPTOP-1234GML0>
  34. Date: Sun, 31 Jan 2021 06:56:46 -0000
  35. Content-Type: text/plain; charset="utf-8"
  36. Content-Transfer-Encoding: 7bit
  37. MIME-Version: 1.0
  38. Hi, nice to meet you.
  39. """
  40. Mock Server
  41. -----------
  42. In case changing to method :py:meth:`.EmailSender.get_message`
  43. is inconvenient or it does not suit to your testing, you may
  44. also create a mock SMTP server that imitates an actual SMTP
  45. server instance:
  46. .. code-block:: python
  47. class MockSMTP:
  48. messages = []
  49. def __init__(self, host, port):
  50. self.host = host
  51. self.port = port
  52. def starttls(self):
  53. # Called only if use_startls is True
  54. return
  55. def login(self, username, password):
  56. # Log in to the server (if credentials passed)
  57. self.username = username
  58. self.password = password
  59. return
  60. def send_message(self, msg):
  61. # Instead of sending, we just store the message
  62. self.messages.append(msg)
  63. def quit(self):
  64. # Closing the connection
  65. return
  66. Then to use this mock:
  67. .. code-block:: python
  68. from redmail import EmailSender
  69. email = EmailSender(
  70. host="localhost",
  71. port=0,
  72. username="me@example.com",
  73. password="1234",
  74. cls_smtp=MockServer
  75. )
  76. email.send(
  77. subject='email subject',
  78. sender="me@example.com",
  79. receivers=['you@example.com'],
  80. text="Hi, this is an email.",
  81. )
  82. msgs = MockServer.messages
  83. assert msgs == ["""From: me@example.com
  84. Subject: Some news
  85. To: you@example.com
  86. Message-ID: <167294165062.31860.1664530310632362057@LAPTOP-1234GML0>
  87. Date: Sun, 31 Jan 2021 06:56:46 -0000
  88. Content-Type: text/plain; charset="utf-8"
  89. Content-Transfer-Encoding: 7bit
  90. MIME-Version: 1.0
  91. Hi, nice to meet you.
  92. """]
  93. Note that an instance of ``MockServer`` is created
  94. for each connection, often per sent email.
  95. Subclass Sender
  96. ---------------
  97. Another option is to just subclass the sender and
  98. change the email sending there:
  99. .. code-block:: python
  100. from redmail import EmailSender
  101. class MockSender(EmailSender):
  102. def __init__(self, *args, **kwargs):
  103. super().__init__(*args, **kwargs)
  104. self.messages = []
  105. def send_message(self, msg):
  106. self.messages.append(msg)
  107. Then to use this class:
  108. .. code-block:: python
  109. # Just put something as host and port
  110. email = MockSender(host="localhost", port=0)
  111. email.send(
  112. subject='email subject',
  113. sender="me@example.com",
  114. receivers=['you@example.com'],
  115. text="Hi, this is an email.",
  116. )
  117. msgs = email.messages
  118. assert msgs == ["""From: me@example.com
  119. Subject: Some news
  120. To: you@example.com
  121. Message-ID: <167294165062.31860.1664530310632362057@LAPTOP-1234GML0>
  122. Date: Sun, 31 Jan 2021 06:56:46 -0000
  123. Content-Type: text/plain; charset="utf-8"
  124. Content-Transfer-Encoding: 7bit
  125. MIME-Version: 1.0
  126. Hi, nice to meet you.
  127. """]