Enviando e-mail¶
Although Python provides a mail sending interface via the smtplib
module, Django provides a couple of light wrappers over it. These wrappers are
provided to make sending email extra quick, to help test email sending during
development, and to provide support for platforms that can’t use SMTP.
O código pode ser encontrado no módulo django.core.mail
.
Exemplo rápido¶
Em duas linhas:
from django.core.mail import send_mail
send_mail(
"Subject here",
"Here is the message.",
"[email protected]",
["[email protected]"],
fail_silently=False,
)
O email é enviado usando o host e porta SMTP especificados em EMAIL_HOST
e EMAIL_PORT
. As configurações EMAIL_HOST_USER
e EMAIL_HOST_PASSWORD
, se definidas, são usadas para autenticar no servidor SMTP, e as configurações EMAIL_USE_TLS
e EMAIL_USE_SSL
controlam se uma conexão segura deve ou não ser usada.
Nota
O conjunto de caracteres do email enviado com django.core.mail
será definido como sendo o valor da configuração DEFAULT_CHARSET
.
send_mail()
¶
-
send_mail
(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None, html_message=None)¶
In most cases, you can send email using django.core.mail.send_mail()
.
Os parâmetros subject
, message
, from_email
e recipient_list
devem ser informados.
subject
: uma string.message
: uma string.from_email
: A string. IfNone
, Django will use the value of theDEFAULT_FROM_EMAIL
setting.recipient_list
: uma lista de strings, onde cada item representa um endereço de email. Cada membro derecipient_list
verá os outros recipientes no campo “To:” da mensagem de email.fail_silently
: A boolean. When it’sFalse
,send_mail()
will raise ansmtplib.SMTPException
if an error occurs. See thesmtplib
docs for a list of possible exceptions, all of which are subclasses ofSMTPException
.auth_user
: O username opcional para ser usado na autenticação do servidor SMTP. Se isso não for fornecido, o Django irá usar o valor da configuraçãoEMAIL_HOST_USER
.auth_password
: A senha opcional para ser usada na autenticação no servidor SMTP. Se isso não for fornecido, o Django irá usar o valor da configuraçãoEMAIL_HOST_PASSWORD
.connection
: O backend opcional a ser usado para o de email. Se indefinido, uma instância do backend default será usada. Veja a documentação em Email backends para mais detalhes.html_message
: Sehtml_message
for fornecido, o email resultante será um multipart/alternative email commessage
sendo do tipo text/plain ehtml_message
sendo do tipo text/html.
O valor retornado será o número de mensagens entregues com sucesso (o que pode ser 0
ou 1
já que ele só pode enviar uma mensagem).
send_mass_mail()
¶
-
send_mass_mail
(datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None)¶
django.core.mail.send_mass_mail()
foi pensado para manipular envios massivos de email.
datatuple
é uma tupla na qual cada elemento possui o seguinte formato:
(subject, message, from_email, recipient_list)
fail_silently
, auth_user
e auth_password
possuem as mesmas funções do método send_mail()
.
Cada elemento separadamente da datatuple
resulta em uma mensagem em separado. Como no método send_mail()
, destinatários na mesma lista recipient_list
serão capazes de visualizar os outros endereços no campo “To:” das mensagens de email.
Por exemplo, o código abaixo enviaria duas mensagens diferentes para dois conjuntos diferentes de destinatários; porém, somente uma conexão para o servidor de email seria aberta:
message1 = (
"Subject here",
"Here is the message",
"[email protected]",
["[email protected]", "[email protected]"],
)
message2 = (
"Another Subject",
"Here is another message",
"[email protected]",
["[email protected]"],
)
send_mass_mail((message1, message2), fail_silently=False)
O valor de retorno será o número de mensagens entregues com sucesso.
send_mass_mail()
vs. send_mail()
¶
A principal diferença entre os métodos send_mass_mail()
e send_mail()
é que o método send_mail()
abre uma nova conexão para o servidor de email toda vez que é executado, enquanto que o método send_mass_mail()
utiliza uma única conexão para todas as suas mensagens. Isso faz com que o método send_mass_mail()
seja um pouco mais eficiente.
mail_admins()
¶
-
mail_admins
(subject, message, fail_silently=False, connection=None, html_message=None)¶
django.core.mail.mail_admins()
é um atalho para o envio de email para os admins do site, conforme definido na configuração ADMINS
setting.
mail_admins()
prefixa o conteúdo com o valor da configuração EMAIL_SUBJECT_PREFIX
, que é "[Django] "
por padrão.
O cabeçalho “From:” do email será o valor da configuração SERVER_EMAIL
.
Esse método existe por conveniência e legibilidade.
Se html_message
é fornecido, o email resultante será um email do tipo multipart/alternative com message
sendo do tipo text/plain e html_message
sendo do tipo text/html.
mail_managers()
¶
-
mail_managers
(subject, message, fail_silently=False, connection=None, html_message=None)¶
django.core.mail.mail_managers()
é parecido com mail_admins()
, exceto pelo fato de que ele envia um email para os mantenedores do site, conforme definido na configuração MANAGERS
.
Exemplos¶
Isso envia um único email para john@example.com e jane@example.com, com ambos aparecendo no campo “To:”:
send_mail(
"Subject",
"Message.",
"[email protected]",
["[email protected]", "[email protected]"],
)
Isso envia uma mensagem para john@example.com e jane@example.com, com ambos recebendo um email em separado:
datatuple = (
("Subject", "Message.", "[email protected]", ["[email protected]"]),
("Subject", "Message.", "[email protected]", ["[email protected]"]),
)
send_mass_mail(datatuple)
Prevenindo injeção de cabeçalhos¶
injeção de cabeçalhos é uma vulnerabilidade de segurança onde um atacante insere cabeçalhos extras no email para controlar os campos “To:” e “From:” em mensagens de email geradas pelos seus scripts.
As funções de email do Django descritas acima protegem contra injeção de cabeçalhos proibindo novas linhas nos valores do cabeçalho. Se qualquer campo subject
, from_email
ou recipient_list
contém uma nova linha (seja no estilo Unix, Windows ou Mac), a função de email (por exemplo, o método BadHeaderError`()
(uma subclasse de ValueError
) e, por tanto, não envia o email. É sua responsabilidade validar todos os dados do email antes de passá-los para as funções de email.
If a message
contains headers at the start of the string, the headers will
be printed as the first bit of the email message.
Segue uma view de exemplo que recebe subject
, message
e from_email
de uma requisição POST, envia esses dados para admin@example.com e redireciona para “/contact/thanks/” no final:
from django.core.mail import BadHeaderError, send_mail
from django.http import HttpResponse, HttpResponseRedirect
def send_email(request):
subject = request.POST.get("subject", "")
message = request.POST.get("message", "")
from_email = request.POST.get("from_email", "")
if subject and message and from_email:
try:
send_mail(subject, message, from_email, ["[email protected]"])
except BadHeaderError:
return HttpResponse("Invalid header found.")
return HttpResponseRedirect("/contact/thanks/")
else:
# In reality we'd use a form class
# to get proper validation errors.
return HttpResponse("Make sure all fields are entered and valid.")
A classe EmailMessage
¶
As funções do Django send_mail()
e send_mass_mail()
são na verdade pequenos wrappers que fazem uso da classe EmailMessage
.
Nem todas as funcionalidades da classe EmailMessage
estão disponíveis através das funções send_mail()
e funções wrapper relacionadas. Se você quiser usar recursos avançados, tais como destinatários BCC’ed, anexar de arquivos, ou email de múltiplas partes, você terá que criar instâncias da classe EmailMessage
diretamente.
Nota
Esse é um recurso de design. A função send_mail()
e funções relacionadas foram originalmente a única interface que o Django fornecia. Porém, a lista de parâmetros que elas aceitavam foi aos poucos crescendo com o passar do tempo. Fez sentido mudar para um design mais orientado a objetos para mensagens de email e manter as funções originais apenas para manter compatibilidade com versões anteriores.
A classe EmailMessage
é responsável por criar a mensagem de email em si. O email backend é depois responsável pelo envio da mensagem.
For convenience, EmailMessage
provides a send()
method for sending a single email. If you need to send multiple messages, the
email backend API provides an alternative.
Objetos EmailMessage
¶
-
class
EmailMessage
¶
A classe EmailMessage
é inicializada com os seguintes parâmetros (na seguinte ordem, se argumentos posicionais são usados). Todos os parâmetros são opcionais e podem ser informados a qualquer momento anterior a chamada do método send()
.
subject
: A linha de assunto do email.body
: O corpo do texto. Deve ser uma mensagem em texto simples.from_email
: The sender’s address. Bothfred@example.com
and"Fred" <fred@example.com>
forms are legal. If omitted, theDEFAULT_FROM_EMAIL
setting is used.to
: Uma lista de tuplas de endereços dos destinatários.bcc
: uma lista de tuplas de endereços usados no cabeçalho “Bcc” ao enviar o email.connection
: uma instância do email backend. Utilize esse parâmetro se você quiser usar a mesma conexão para múltiplas mensagens. Se omitido, uma nova conexão é criada quando a funçãosend()
é chamada.attachments
: A list of attachments to put on the message. These can be eitherMIMEBase
instances, or(filename, content, mimetype)
triples.headers
: um dicionário de cabeçalhos extras para colocar na mensagem. As chaves são os nomes dos cabeçalhos, valores são os valores do cabeçalho. É responsabilidade de quem chama garantir que os nomes e valores dos cabeçalhos estão no formato correto para uma mensagem de email. O atributo correspondente éextra_headers
.cc
: uma lista ou tupla de endereços de destinatários usados no cabeçalho “Cc” no envio do email.reply_to
: uma lista ou tupla de endereços de destinatários usados no cabeçalho “Reply-To” no envio do email.
Por exemplo:
from django.core.mail import EmailMessage
email = EmailMessage(
"Hello",
"Body goes here",
"[email protected]",
["[email protected]", "[email protected]"],
["[email protected]"],
reply_to=["[email protected]"],
headers={"Message-ID": "foo"},
)
A classe possui os seguintes métodos:
send(fail_silently=False)
sends the message. If a connection was specified when the email was constructed, that connection will be used. Otherwise, an instance of the default backend will be instantiated and used. If the keyword argumentfail_silently
isTrue
, exceptions raised while sending the message will be quashed. An empty list of recipients will not raise an exception. It will return1
if the message was sent successfully, otherwise0
.message()
constructs adjango.core.mail.SafeMIMEText
object (a subclass of Python’sMIMEText
class) or adjango.core.mail.SafeMIMEMultipart
object holding the message to be sent. If you ever need to extend theEmailMessage
class, you’ll probably want to override this method to put the content you want into the MIME object.recipients()
retorna uma lista de todos os destinatários da mensagem, independentemente de eles serem gravados nos atributosto
,cc
oubcc
. Esse é outro método que você pode precisar sobrescrever ao fazer uma subclasse, porque o servidor SMTP precisa saber toda a lista de destinatários quando a mensagem é enviada. Se você adicionar outra forma de especificar os destinatários em sua classe, eles precisam ser retornados desse método também.attach()
cria um novo anexo de arquivo e adiciona ele a mensagem. Existem duas maneiras de chamarattach()
:You can pass it a single argument that is a
MIMEBase
instance. This will be inserted directly into the resulting message.Alternativamente, você pode passar ao
attach()
três argumentos:filename
,content
emimetype
.filename
é o nome do anexo de arquivo que será exibido no email,content
é a data que estará contida dentro do anexo emimetype
é o tipo MIME opcional para o anexo. Se você omitirmimetype
, o tipo MIME será inferido do nome do anexo de arquivo.Por exemplo:
message.attach("design.png", img_data, "image/png")
If you specify a
mimetype
of message/rfc822, it will also acceptdjango.core.mail.EmailMessage
andemail.message.Message
.For a
mimetype
starting with text/, content is expected to be a string. Binary data will be decoded using UTF-8, and if that fails, the MIME type will be changed to application/octet-stream and the data will be attached unchanged.In addition, message/rfc822 attachments will no longer be base64-encoded in violation of RFC 2046#section-5.2.1, which can cause issues with displaying the attachments in Evolution and Thunderbird.
attach_file()
creates a new attachment using a file from your filesystem. Call it with the path of the file to attach and, optionally, the MIME type to use for the attachment. If the MIME type is omitted, it will be guessed from the filename. You can use it like this:message.attach_file("/images/weather_map.png")
For MIME types starting with text/, binary data is handled as in
attach()
.
Enviando tipos de conteúdo alternativos¶
Pode ser útil incluir múltiplas versões de conteúdo em um email; o exemplo clássico é enviar tanto a versão em texto simples quanto a versão em HTML de uma mensagem. Com a biblioteca de email do Django, você pode fazer isso usando a classe EmailMultiAlternatives
. Essa subclasse de EmailMessage
possui um método attach_alternative()
para inclusão de versões extras de corpos de mensagens no email. Todos os outros métodos (incluindo a inicialização da classe) são herdados diretamente da classe EmailMessage
.
Para enviar uma combinação de texto simples e HTML, você pode escrever:
from django.core.mail import EmailMultiAlternatives
subject, from_email, to = "hello", "[email protected]", "[email protected]"
text_content = "This is an important message."
html_content = "<p>This is an <strong>important</strong> message.</p>"
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()
Por padrão, o tipo MIME de um parâmetro body
em uma classe EmailMessage
é "text/plain"
. É uma boa prática deixar assim, porque isso garante que qualquer destinatário esteja apto a ler o email, independentemente do cliente de email. Porém, se você estiver confiante que seus destinatários podem manipular um tipo alternativo de conteúdi, você pode usar o atributo content_subtype
da classe EmailMessage
para mudar o principal tipo de conteúdo. O principal tipo sempre será “text”``, mas você pode mudar o subtipo. Por exemplo:
msg = EmailMessage(subject, html_content, from_email, [to])
msg.content_subtype = "html" # Main content is now text/html
msg.send()
Backends de email¶
O envio de email em si é manipulado pelo email backend.
A classe do email backend tem os métodos a seguir:
open()
instancia uma conexão de longa duração para envio de email.close()
fecha a conexão atual de envio de email.send_messages(email_messages)
sends a list ofEmailMessage
objects. If the connection is not open, this call will implicitly open the connection, and close the connection afterward. If the connection is already open, it will be left open after mail has been sent.
Ela também pode ser usada como em um gerenciador de contexto, que irá automaticamente chamar open()
e close()
conforme necessário:
from django.core import mail
with mail.get_connection() as connection:
mail.EmailMessage(
subject1,
body1,
from1,
[to1],
connection=connection,
).send()
mail.EmailMessage(
subject2,
body2,
from2,
[to2],
connection=connection,
).send()
Obtendo uma instância de um email backend¶
A funçção get_connection()
em django.core.mail
retorna uma instância do email backend que você pode utilizar.
-
get_connection
(backend=None, fail_silently=False, *args, **kwargs)¶
Por padrão, uma chamada para get_connection()
irá retornar uma instância do email backend definido em EMAIL_BACKEND
. Se você especificar o argumento backend
, uma instância desse backend será criada.
O argumento fail_silently
controla como o backend deve manipular erros. Se fail_silently
é True, exceções durante o processo de envio de email serão ignoradas silenciosamente.
Todos os outros argumentos são passados diretamente para o construtor do email backend.
O Django é fornecido com vários backends de envio de email. Com exceção do backend SMTP (que é o padrão), esses backends só são úteis durante testes e desenvolvimento. Se você tiver requisitos especiais de envio de email, você pode escrever o seu próprio email backend.
SMTP backend¶
-
class
backends.smtp.
EmailBackend
(host=None, port=None, username=None, password=None, use_tls=None, fail_silently=False, use_ssl=None, timeout=None, ssl_keyfile=None, ssl_certfile=None, **kwargs)¶ Este é o backend padrão. Email será enviado através de um servidor SMTP.
O valor de cada argumento é obtido da respectiva configuração se o argumento for
None
:host
:EMAIL_HOST
port
:EMAIL_PORT
username
:EMAIL_HOST_USER
password
:EMAIL_HOST_PASSWORD
use_tls
:EMAIL_USE_TLS
use_ssl
:EMAIL_USE_SSL
timeout
:EMAIL_TIMEOUT
ssl_keyfile
:EMAIL_SSL_KEYFILE
ssl_certfile
:EMAIL_SSL_CERTFILE
O backend SMTP é a configuração padrão herdada do Django. Se você quiser especificá-la explicitamente, adicione o seguinte as suas configurações:
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
Se não definido, o
timeout
padrão será o fornecido pela funçãosocket.getdefaulttimeout()
, que por padrão éNone
(sem limite de tempo).
Console backend¶
Ao invés de enviar emails reais o console backend escreve esses emails que poderiam ser enviados na saída padrão. Por padrão, o console backend direciona para stdout
. Você pode usar diferentes objetos fornecendo o argumento nomeado stream
ao construir a conexão.
Para especificar esse backend, coloque o seguinte nas suas configurações:
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
Esse backend não é intencionado para uso em produção – ele é fornecido como uma conveniência que pode ser usado durante o desenvolvimento.
File backend¶
O file backend escreve emails em um arquivo. Um novo arquivo é criado para cada nova sessão que é aberto no backend. O diretório para o qual os arquivos são escritos ou é obitdo da configuração EMAIL_FILE_PATH
ou do argumento nomeado file_path
ao criar uma conexão com o método get_connection()
.
Para especificar esse backend, coloque o seguinte nas suas configurações:
EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend"
EMAIL_FILE_PATH = "/tmp/app-messages" # change this to a proper location
Esse backend não é intencionado para uso em produção – ele é fornecido como uma conveniência que pode ser usado durante o desenvolvimento.
In-memory backend¶
O 'locmem'
backend armazena mensagens em um atributo especial do módulo django.core.mail
. O atributo outbox
é criado quando a primeira mensagem é enviada. É uma lista com uma instância da classe EmailMessage
para cada mensagem que possa ser enviada.
Para especificar esse backend, coloque o seguinte nas suas configurações:
EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
Esse backend não é intencionado para uso em produção – ele é fornecido como uma conveniência que pode ser usado durante o desenvolvimento e teste.
Django’s test runner automatically uses this backend for testing.
Dummy backend¶
Como o nome sugere o dummy backend não faz nada com suas mensagens. Para definir esse backend, coloque o seguinte em suas configurações:
EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend"
Esse backend não é intencionado para uso em produção – ele é fornecido como uma conveniência que pode ser usado durante o desenvolvimento.
Definindo um email backend customizado¶
Se você precisa mudar como os emails são enviados você pode escrever o seu próprio email backend. A configuração EMAIL_BACKEND
em seu arquivo de configurações é então o caminho Python do import para a sua classe backend.
Bckends de email customizados devem ser subclasses de BaseEmailBackend
que está localizada no módulo django.core.mail.backends.base
. Um backend de email customizado deve implementar o método send_messages(email_messages)
. Esse método recebe uma lista de instâncias da classe EmailMessage
e retorna o número de mensagens entregues com sucesso. Se o seu backend possui qualquer conceito de sessão persistente ou conexão, você também deve implementar os métodos open()
e close()
. Consulte smtp.EmailBackend
para uma implementação de referência.
Enviando mútiplos emails¶
Estabelecer e fechar uma conexão SMTP (ou qualquer outra conexão de rede, nesse caso) é um processo custoso. Se você tem muitos emails para enviar, faz sentido reutilizar uma conexão SMTP, ao invés de criar e destruir uma conexão toda vez que você desejar enviar um email.
Existem duas maneiras de dizer a um email backend para reutilizar uma conexão.
Primeiramente, você pode usar o método send_messages()
. send_messages()
recebe uma lista de instâncias da classe EmailMessage
(ou de subclasses), e envia todas elas usando uma única conexão.
Por exemplo, se você tiver uma função chamada get_notification_email()
que retorna uma lista de objetos da classe EmailMessage
representando algum email periódico que você gostaria de enviar, voê pode enviá-los usando uma única chamada para send_messages:
from django.core import mail
connection = mail.get_connection() # Use default email connection
messages = get_notification_email()
connection.send_messages(messages)
Neste exemplo, a chamada send_messages()
abre uma conexão no backend, envia a lista de mensagens, e então fecha a conexão novamente.
A segunda abordagem é usar os métodos open()
e close()
no backend de email para manualmente controlar a conexão. send_messages()
não irá abrir ou fechar manualmente a conexão se ela já estiver aberta, se você manualmente abrir a conexão, você pode controlar quando ela será fechada. Por exemplo:
from django.core import mail
connection = mail.get_connection()
# Manually open the connection
connection.open()
# Construct an email message that uses the connection
email1 = mail.EmailMessage(
"Hello",
"Body goes here",
"[email protected]",
["[email protected]"],
connection=connection,
)
email1.send() # Send the email
# Construct two more messages
email2 = mail.EmailMessage(
"Hello",
"Body goes here",
"[email protected]",
["[email protected]"],
)
email3 = mail.EmailMessage(
"Hello",
"Body goes here",
"[email protected]",
["[email protected]"],
)
# Send the two emails in a single call -
connection.send_messages([email2, email3])
# The connection was already open so send_messages() doesn't close it.
# We need to manually close the connection.
connection.close()
Configurando o email para o desenvolvimento¶
Existem momentos em que você não quer que o Django envie quaisquer emails. Por exemplo, enquanto estiver desenvolvendo um website, você provavelmente não quer enviar milhares de emails – mas você pode querer validar que esses email serão enviados para as pessoas certas nas condições certas, e que esses emails irão conter o conteúdo correto.
The easiest way to configure email for local development is to use the
console email backend. This backend
redirects all email to stdout
, allowing you to inspect the content of mail.
O file email backend também pode ser útil durante o desenvolvimento – esse backend despeja o conteúdo de todoas as conexões SMTP para um arquivo que pode ser inspecionado quando você desejar.
Another approach is to use a “dumb” SMTP server that receives the emails locally and displays them to the terminal, but does not actually send anything. The aiosmtpd package provides a way to accomplish this:
python -m pip install aiosmtpd
python -m aiosmtpd -n -l localhost:8025
This command will start a minimal SMTP server listening on port 8025 of
localhost. This server prints to standard output all email headers and the
email body. You then only need to set the EMAIL_HOST
and
EMAIL_PORT
accordingly. For a more detailed discussion of SMTP
server options, see the documentation of the aiosmtpd module.
Para mais informações sobre testes unitários no envio de emails em suas aplicações, veja a seção Serviços de E-mail sobre testes da documentação.