0
# Email Testing
1
2
Email testing fixtures for capturing and testing Django email functionality. These fixtures provide access to Django's email outbox and DNS configuration for comprehensive email testing.
3
4
## Capabilities
5
6
### Email Outbox
7
8
Fixture providing access to Django's email outbox for testing sent emails.
9
10
```python { .api }
11
def mailoutbox() -> List[django.core.mail.EmailMessage]:
12
"""
13
Access Django's email outbox for testing sent emails.
14
15
Returns a list of EmailMessage objects that have been sent during
16
the test. The outbox is automatically cleared between tests.
17
Requires Django's locmem email backend or test email backend.
18
19
Returns:
20
List[EmailMessage]: List of email messages sent during test
21
"""
22
```
23
24
Usage example:
25
```python
26
from django.core import mail
27
28
def test_email_sending(mailoutbox):
29
from django.core.mail import send_mail
30
31
# Send an email
32
send_mail(
33
subject="Test Subject",
34
message="Test message body",
35
from_email="from@example.com",
36
recipient_list=["to@example.com"],
37
)
38
39
# Check that email was sent
40
assert len(mailoutbox) == 1
41
email = mailoutbox[0]
42
assert email.subject == "Test Subject"
43
assert email.body == "Test message body"
44
assert email.from_email == "from@example.com"
45
assert email.to == ["to@example.com"]
46
47
def test_multiple_emails(mailoutbox):
48
from django.core.mail import send_mail
49
50
# Send multiple emails
51
send_mail("Subject 1", "Body 1", "from@example.com", ["to1@example.com"])
52
send_mail("Subject 2", "Body 2", "from@example.com", ["to2@example.com"])
53
54
# Check all emails
55
assert len(mailoutbox) == 2
56
assert mailoutbox[0].subject == "Subject 1"
57
assert mailoutbox[1].subject == "Subject 2"
58
59
def test_email_with_attachments(mailoutbox):
60
from django.core.mail import EmailMessage
61
62
email = EmailMessage(
63
subject="Test with attachment",
64
body="Message with attachment",
65
from_email="from@example.com",
66
to=["to@example.com"],
67
)
68
email.attach("test.txt", "File content", "text/plain")
69
email.send()
70
71
assert len(mailoutbox) == 1
72
sent_email = mailoutbox[0]
73
assert len(sent_email.attachments) == 1
74
assert sent_email.attachments[0] == ("test.txt", "File content", "text/plain")
75
```
76
77
### Email DNS Patching
78
79
Fixture that patches DNS name used in email message headers.
80
81
```python { .api }
82
def django_mail_patch_dns() -> None:
83
"""
84
Patch DNS name used in Django email message headers.
85
86
Patches the DNS_NAME used by Django's email system to use
87
a test-friendly DNS name instead of the system's actual DNS name.
88
Automatically uses the value from django_mail_dnsname fixture.
89
"""
90
```
91
92
### Email DNS Name
93
94
Fixture providing the DNS name used for email testing.
95
96
```python { .api }
97
def django_mail_dnsname() -> str:
98
"""
99
Provide DNS name for email testing.
100
101
Returns the DNS name used in email message headers during testing.
102
Default value is "fake-tests.example.com" but can be overridden
103
by parametrizing this fixture.
104
105
Returns:
106
str: DNS name for email testing (default: "fake-tests.example.com")
107
"""
108
```
109
110
Usage example:
111
```python
112
def test_email_dns_name(mailoutbox, django_mail_dnsname):
113
from django.core.mail import send_mail
114
115
send_mail(
116
subject="Test DNS",
117
message="Test message",
118
from_email="from@example.com",
119
recipient_list=["to@example.com"],
120
)
121
122
# Check that custom DNS name is used
123
assert django_mail_dnsname == "fake-tests.example.com"
124
# Email will use this DNS name in headers
125
126
# Override DNS name for specific test
127
@pytest.fixture
128
def django_mail_dnsname():
129
return "custom-test.example.com"
130
131
def test_custom_dns_name(mailoutbox, django_mail_dnsname):
132
# This test will use "custom-test.example.com" as DNS name
133
pass
134
```
135
136
## Email Configuration
137
138
For email testing to work properly, configure Django settings:
139
140
```python
141
# In Django settings for testing
142
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
143
144
# Or in test
145
def test_with_locmem_backend(settings, mailoutbox):
146
settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
147
# Now mailoutbox will capture emails
148
```
149
150
## Email Testing Types
151
152
```python { .api }
153
from django.core.mail import EmailMessage, EmailMultiAlternatives
154
from typing import List, Tuple, Optional, Any
155
156
# Email message types
157
EmailMessageType = EmailMessage
158
EmailList = List[EmailMessage]
159
160
# Email content types
161
EmailSubject = str
162
EmailBody = str
163
EmailAddress = str
164
EmailAddressList = List[str]
165
166
# Attachment types
167
AttachmentTuple = Tuple[str, str, str] # (filename, content, mimetype)
168
AttachmentList = List[AttachmentTuple]
169
170
# DNS configuration
171
DnsName = str
172
173
# Email message structure
174
class EmailMessage:
175
subject: str
176
body: str
177
from_email: str
178
to: List[str]
179
cc: List[str]
180
bcc: List[str]
181
reply_to: List[str]
182
attachments: List[AttachmentTuple]
183
extra_headers: dict[str, str]
184
185
def send(self, fail_silently: bool = False) -> bool: ...
186
def attach(self, filename: str, content: str, mimetype: str) -> None: ...
187
def attach_file(self, path: str, mimetype: Optional[str] = None) -> None: ...
188
189
class EmailMultiAlternatives(EmailMessage):
190
alternatives: List[Tuple[str, str]] # (content, mimetype)
191
192
def attach_alternative(self, content: str, mimetype: str) -> None: ...
193
194
# Mail outbox access
195
from django.core import mail
196
MailOutbox = mail.outbox
197
```