1"""
2Tools for sending email.
3"""
4
5from django.conf import settings
6
7# Imported for backwards compatibility and for the sake
8# of a cleaner namespace. These symbols used to be in
9# django/core/mail.py before the introduction of email
10# backends and the subsequent reorganization (See #10355)
11from django.core.mail.message import (
12 DEFAULT_ATTACHMENT_MIME_TYPE,
13 BadHeaderError,
14 EmailAlternative,
15 EmailAttachment,
16 EmailMessage,
17 EmailMultiAlternatives,
18 SafeMIMEMultipart,
19 SafeMIMEText,
20 forbid_multi_line_headers,
21 make_msgid,
22)
23from django.core.mail.utils import DNS_NAME, CachedDnsName
24from django.utils.module_loading import import_string
25
26__all__ = [
27 "CachedDnsName",
28 "DNS_NAME",
29 "EmailMessage",
30 "EmailMultiAlternatives",
31 "SafeMIMEText",
32 "SafeMIMEMultipart",
33 "DEFAULT_ATTACHMENT_MIME_TYPE",
34 "make_msgid",
35 "BadHeaderError",
36 "forbid_multi_line_headers",
37 "get_connection",
38 "send_mail",
39 "send_mass_mail",
40 "mail_admins",
41 "mail_managers",
42 "EmailAlternative",
43 "EmailAttachment",
44]
45
46
47def get_connection(backend=None, fail_silently=False, **kwds):
48 """Load an email backend and return an instance of it.
49
50 If backend is None (default), use settings.EMAIL_BACKEND.
51
52 Both fail_silently and other keyword arguments are used in the
53 constructor of the backend.
54 """
55 klass = import_string(backend or settings.EMAIL_BACKEND)
56 return klass(fail_silently=fail_silently, **kwds)
57
58
59def send_mail(
60 subject,
61 message,
62 from_email,
63 recipient_list,
64 fail_silently=False,
65 auth_user=None,
66 auth_password=None,
67 connection=None,
68 html_message=None,
69):
70 """
71 Easy wrapper for sending a single message to a recipient list. All members
72 of the recipient list will see the other recipients in the 'To' field.
73
74 If from_email is None, use the DEFAULT_FROM_EMAIL setting.
75 If auth_user is None, use the EMAIL_HOST_USER setting.
76 If auth_password is None, use the EMAIL_HOST_PASSWORD setting.
77
78 Note: The API for this method is frozen. New code wanting to extend the
79 functionality should use the EmailMessage class directly.
80 """
81 connection = connection or get_connection(
82 username=auth_user,
83 password=auth_password,
84 fail_silently=fail_silently,
85 )
86 mail = EmailMultiAlternatives(
87 subject, message, from_email, recipient_list, connection=connection
88 )
89 if html_message:
90 mail.attach_alternative(html_message, "text/html")
91
92 return mail.send()
93
94
95def send_mass_mail(
96 datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None
97):
98 """
99 Given a datatuple of (subject, message, from_email, recipient_list), send
100 each message to each recipient list. Return the number of emails sent.
101
102 If from_email is None, use the DEFAULT_FROM_EMAIL setting.
103 If auth_user and auth_password are set, use them to log in.
104 If auth_user is None, use the EMAIL_HOST_USER setting.
105 If auth_password is None, use the EMAIL_HOST_PASSWORD setting.
106
107 Note: The API for this method is frozen. New code wanting to extend the
108 functionality should use the EmailMessage class directly.
109 """
110 connection = connection or get_connection(
111 username=auth_user,
112 password=auth_password,
113 fail_silently=fail_silently,
114 )
115 messages = [
116 EmailMessage(subject, message, sender, recipient, connection=connection)
117 for subject, message, sender, recipient in datatuple
118 ]
119 return connection.send_messages(messages)
120
121
122def mail_admins(
123 subject, message, fail_silently=False, connection=None, html_message=None
124):
125 """Send a message to the admins, as defined by the ADMINS setting."""
126 if not settings.ADMINS:
127 return
128 if not all(isinstance(a, (list, tuple)) and len(a) == 2 for a in settings.ADMINS):
129 raise ValueError("The ADMINS setting must be a list of 2-tuples.")
130 mail = EmailMultiAlternatives(
131 "%s%s" % (settings.EMAIL_SUBJECT_PREFIX, subject),
132 message,
133 settings.SERVER_EMAIL,
134 [a[1] for a in settings.ADMINS],
135 connection=connection,
136 )
137 if html_message:
138 mail.attach_alternative(html_message, "text/html")
139 mail.send(fail_silently=fail_silently)
140
141
142def mail_managers(
143 subject, message, fail_silently=False, connection=None, html_message=None
144):
145 """Send a message to the managers, as defined by the MANAGERS setting."""
146 if not settings.MANAGERS:
147 return
148 if not all(isinstance(a, (list, tuple)) and len(a) == 2 for a in settings.MANAGERS):
149 raise ValueError("The MANAGERS setting must be a list of 2-tuples.")
150 mail = EmailMultiAlternatives(
151 "%s%s" % (settings.EMAIL_SUBJECT_PREFIX, subject),
152 message,
153 settings.SERVER_EMAIL,
154 [a[1] for a in settings.MANAGERS],
155 connection=connection,
156 )
157 if html_message:
158 mail.attach_alternative(html_message, "text/html")
159 mail.send(fail_silently=fail_silently)