testing.rst 3.9 KB

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