1
0

testing.rst 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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@example.com>
  34. Content-Type: text/plain; charset="utf-8"
  35. Content-Transfer-Encoding: 7bit
  36. MIME-Version: 1.0
  37. Hi, nice to meet you.
  38. """
  39. Mock Server
  40. -----------
  41. In case changing to method :py:meth:`.EmailSender.get_message`
  42. is inconvenient or it does not suit to your testing, you may
  43. also create a mock SMTP server that imitates an actual SMTP
  44. server instance:
  45. .. code-block:: python
  46. class MockSMTP:
  47. messages = []
  48. def __init__(self, host, port):
  49. self.host = host
  50. self.port = port
  51. def starttls(self):
  52. # Called only if use_startls is True
  53. return
  54. def login(self, username, password):
  55. # Log in to the server (if credentials passed)
  56. self.username = username
  57. self.password = password
  58. return
  59. def send_message(self, msg):
  60. # Instead of sending, we just store the message
  61. self.messages.append(msg)
  62. def quit(self):
  63. # Closing the connection
  64. return
  65. Then to use this mock:
  66. .. code-block:: python
  67. from redmail import EmailSender
  68. email = EmailSender(
  69. host="localhost",
  70. port=0,
  71. username="me@example.com",
  72. password="1234",
  73. cls_smtp=MockServer
  74. )
  75. email.send(
  76. subject='email subject',
  77. sender="me@example.com",
  78. receivers=['you@example.com'],
  79. text="Hi, this is an email.",
  80. )
  81. msgs = MockServer.messages
  82. assert msgs == ["""from: me@example.com
  83. subject: Some news
  84. to: you@example.com
  85. Message-ID: <167294165062.31860.1664530310632362057@example.com>
  86. Content-Type: text/plain; charset="utf-8"
  87. Content-Transfer-Encoding: 7bit
  88. MIME-Version: 1.0
  89. Hi, nice to meet you.
  90. """]
  91. Note that an instance of ``MockServer`` is created
  92. for each connection, often per sent email.
  93. Subclass Sender
  94. ---------------
  95. Another option is to just subclass the sender and
  96. change the email sending there:
  97. .. code-block:: python
  98. from redmail import EmailSender
  99. class MockSender(EmailSender):
  100. def __init__(self, *args, **kwargs):
  101. super().__init__(*args, **kwargs)
  102. self.messages = []
  103. def send_message(self, msg):
  104. self.messages.append(msg)
  105. Then to use this class:
  106. .. code-block:: python
  107. # Just put something as host and port
  108. email = MockSender(host="localhost", port=0)
  109. email.send(
  110. subject='email subject',
  111. sender="me@example.com",
  112. receivers=['you@example.com'],
  113. text="Hi, this is an email.",
  114. )
  115. msgs = email.messages
  116. assert msgs == ["""from: me@example.com
  117. subject: Some news
  118. to: you@example.com
  119. Message-ID: <167294165062.31860.1664530310632362057@example.com>
  120. Content-Type: text/plain; charset="utf-8"
  121. Content-Transfer-Encoding: 7bit
  122. MIME-Version: 1.0
  123. Hi, nice to meet you.
  124. """]