Como Enviar Emails em Python: Explicação de Métodos SMTP e API

On junho 03, 2024
26min read
Aleksandr Varnin Full Stack Developer @ Railsware
Veljko Ristić Content Manager @ Mailtrap
How to Send an Email in Python

Enviar email com Python? Sem problemas. Este artigo cobre tudo o que você precisa saber sobre o envio de emails em Python, incluindo trechos de código, segurança e testes de email.

Setting up ‘smtplib’

O módulo smtplib do Python simplifica o processo de envio de emails diretamente de suas aplicações, oferecendo uma interface direta para interagir com servidores SMTP.

Esta seção orienta você na importação do smtplib, criação de um objeto SMTP para seu servidor e utilização de suas funções principais para enviar emails. Continue a ler para aprender como integrar funcionalidades de email em seus scripts Python.

O módulo smtplib incorporado pode ser importado usando a seguinte instrução:

import smtplib

Para enviar um email posteriormente, crie um objeto SMTP (Simple Mail Transfer Protocol):

smtpObj = smtplib.SMTP( [host [, port]] )

Detalhes dos parâmetros:

  • host − este é um argumento opcional e é o host que executa seu servidor SMTP. Pode ser especificado o endereço IP do host ou um nome de domínio.
  • port − se o argumento host for identificado, especifique uma porta onde o servidor SMTP está ouvindo.
  • local_hostname − se o servidor SMTP usado estiver em sua máquina local, especifique localhost

Um objeto SMTP tem um método de instância chamado sendmail que é usado para enviar uma mensagem e tem três parâmetros:

  • sender − string com o endereço do remetente.
  • receivers − lista de strings, uma para cada destinatário.
  • message − uma mensagem como string formatada conforme especificado nas RFCs.
smtpObj.sendmail(sender, receivers, message)

Para garantir que o módulo de email foi importado corretamente e obter a descrição completa de suas classes e argumentos, digite em uma sessão interativa do Python:

help(smtplib)

Consulte a documentação do Python para revisar o resto dos objetos SMTP (por exemplo, smtp.ehlo; smtp.send_message(msg) etc.) e como aplicá-los.

A seção seguinte mostra como enviar emails via Python usando o Mailtrap Email Sending, um recurso da plataforma Mailtrap Email Delivery. Primeiro, cobrirei o método SMTP e depois mostrarei como fazer isso com nosso SDK Python.

Enviar emails usando SMTP

O método é muito semelhante ao que foi abordado no smtplib acima, no entanto, você precisa configurar credenciais SMTP personalizadas. Aqui, assumo que você já se inscreveu no Mailtrap e verificou seu domínio.

Se não, confira nosso guia detalhado.

Além disso, confira nossas instruções em vídeo sobre como enviar emails em Python com Mailtrap usando smtplib.

Nota: O código abaixo contém credenciais fictícias do Mailtrap (exceto o endpoint do servidor). Certifique-se de substituí-las por suas credenciais reais.

Aqui está um script básico para enviar emails de plaintext com Python usando SMTP do Mailtrap.

import smtplib
from email.mime.text import MIMEText

# Configuração
port = 587
smtp_server = "live.smtp.mailtrap.io"
login = "api"  # Seu login gerado pelo Mailtrap
password = "1a2b3c4d5e6f7g"  # Sua senha gerada pelo Mailtrap

sender_email = "mailtrap@exemplo.com"
receiver_email = "novo@exemplo.com"

# Conteúdo de texto simples
text = """\
Oi,
Confira o novo artigo no blogue do Mailtrap:
Servidor SMTP para Testes: Cloud-based ou Local?
https://blog.mailtrap.io/2018/09/27/cloud-or-local-smtp-server/
Diga-nos que tipo de conteúdo você acha que seria útil e gostaria de ler!
"""

# Criar objeto MIMEText
message = MIMEText(text, "plain")
message["Subject"] = "Email em texto simples"
message["From"] = sender_email
message["To"] = receiver_email

# Enviar o email
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()  # Proteger a conexão
    server.login(login, password)
    server.sendmail(sender_email, receiver_email, message.as_string())

print('Enviado')

Resumo rápido:

  • Importações e configuração – Importei os módulos necessários da biblioteca padrão do Python para envio de email (smtplib e MIMEText).
  • Configuração do servidor de email – Os detalhes do servidor SMTP, incluindo o endereço do servidor, número da porta e credenciais de autenticação.
  • Conteúdo do email – Criei uma mensagem MIMEText que pode conter apenas texto simples. Mais tarde, mostrarei como incluir versões HTML e texto simples do email.
  • Envio do email – Usei um gerenciador de contexto (instrução with) para garantir que a conexão com o servidor SMTP seja devidamente fechada após o envio do email.

Bonus tip: Codificar dados sensíveis, como credenciais de login e informações do servidor, em seu script pode representar um risco de segurança. Por isso, recomendo usar variáveis de ambiente para armazenar informações sensíveis. Isso torna seu código mais seguro e flexível ao mover-se entre diferentes ambientes (desenvolvimento, teste, produção).

Enviar um email HTML

Se você quiser saber mais sobre como enviar emails HTML em Python, confira nosso tutorial dedicado.

Para modificar o script para enviar emails HTML (incluindo também vários destinatários), ajustarei como o corpo do email é criado e anexado. Aqui está o script revisado:

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

# Configuração
port = 587
smtp_server = "live.smtp.mailtrap.io"
login = "api"  # Seu login gerado pelo Mailtrap
password = "1a2b3c4d5e6f7g"  # Sua senha gerada pelo Mailtrap

sender_email = "mailtrap@exemplo.com"
receiver_email = "novo1@exemplo.com"

# Conteúdo de email
subject = "Email HTML Email sem Anexo"
html = """\
<html>
  <body>
    <p>Oi,<br>
    Este é um email de <b>teste</b> sem um anexo usando <a href="https://www.python.org">Python</a>.</p>
  </body>
</html>
"""

# Criar uma mensagem multipart e definir cabeçalhos
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject

# Anexar a parte em HTML
message.attach(MIMEText(html, "html"))

# Enviar o email
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()
    server.login(login, password)
    server.sendmail(sender_email, receiver_email, message.as_string())

print('Enviado')

Resumo rápido:

  • Anexando o conteúdo HTML – O conteúdo HTML é anexado à mensagem de email usando MIMEText(html, “html”) em vez de MIMEText (text, “plain”). Ao especificar html como o segundo argumento, informamos ao cliente de email que esta parte do email deve ser interpretada como HTML.

Enviar emails para vários destinatários

Aqui, reutilizarei o script acima e ajustarei como os endereços dos destinatários são tratados.

import smtplib
from email.mime.text import MIMEText

# Configuração
port = 587
smtp_server = "live.smtp.mailtrap.io"
login = "api"  # Seu login gerado pelo Mailtrap
password = "1a2b3c4d5e6f7g"  # Sua senha gerada pelo Mailtrap

sender_email = "mailtrap@exemplo.com"
# Lista de endereços de email dos destinatários
receiver_emails = ["novo1@exemplo.com", "novo2@exemplo.com", "novo3@exemplo.com"]

# Conteúdo em texto simples
text = """\
Oi,
Confira o novo artigo no blogue do Mailtrap:
Servidor SMTP para Testes: Cloud-based ou Local?
https://blog.mailtrap.io/2018/09/27/cloud-or-local-smtp-server/
Diga-nos que tipo de conteúdo você acha que seria útil e gostaria de ler!
"""

# Criar objeto MIMEText
message = MIMEText(text, "plain")
message["Subject"] = "Email em texto simples"
message["From"] = sender_email
# Juntar a lista de emails dos destinatários em uma string separada por vírgulas
message["To"] = ", ".join(receiver_emails)

# Enviar o email
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()  # Proteger a conexão
    server.login(login, password)
    # Loop através de cada destinatário e enviar o email individualmente
    for recipient in receiver_emails:
        server.sendmail(sender_email, recipient, message.as_string())

print('Enviado')

Resumo rápido do que é diferente do script original de plaintext:

  • Configuração de vários destinatários – Mudei a variável receiver_email para receiver_emails. Agora é uma lista de endereços de email em vez de uma única string.
  • Configurando o cabeçalho To – O cabeçalho To no objeto de mensagem MIMEText é definido juntando a lista de emails dos destinatários em uma única string separada por vírgulas. Isso é importante para o cabeçalho do email mostrar corretamente todos os destinatários quando eles receberem o email.
    • Nota: Alguns provedores de email (Outlook, Yahoo, Gmail, etc.) podem mostrar todos os destinatários no campo To para cada destinatário, o que não é desejável por motivos de privacidade. Você pode “corrigir” isso usando CC e/ou BCC.
  • Enviando emails em um loop – Em vez de enviar o email uma vez, o script agora faz um loop através de cada destinatário na lista receiver_emails e envia o email individualmente.

Pro Tip: ⬆️ Essa abordagem funciona bem para um pequeno número de destinatários. No entanto, para enviar emails para um grande número de destinatários, pode ser mais eficiente usar a capacidade do servidor SMTP para lidar com vários destinatários em uma única operação de envio, dependendo das limitações e políticas do servidor.

Enviar emails com anexos

Usarei MIMEMultipart já que anexos exigem um email multipart. Além disso, usarei a classe MIMEBase para anexar ficheiros. Aqui está o script atualizado:

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

# Configuração
port = 587
smtp_server = "live.smtp.mailtrap.io"
login = "api"  # Seu login gerado pelo Mailtrap
password = "1a2b3c4d5e6f7g"  # Sua senha gerada pelo Mailtrap

sender_email = "mailtrap@exemplo.com"
receiver_email = "novo@exemplo.com"  # Destinatário único

# Conteúdo do email
subject = "Email com Anexo"
body = "Oi,\nEste é um email de teste com anexo."

# Criar uma mensagem multipart e definir cabeçalhos
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject

# Adicionar corpo ao email
message.attach(MIMEText(body, "plain"))

# Especificar o caminho do arquivo de anexo
filename = "path/to/your/file.pdf"  # Altere para o caminho correto

# Abrir o ficheiro em modo binário
with open(filename, "rb") as attachment:
    part = MIMEBase("application", "octet-stream")
    part.set_payload(attachment.read())

# Codificar ficheiro em caracteres ASCII para enviar emails
encoders.encode_base64(part)

# Adicionar cabeçalho como par de chave/valor ao componente de anexo
part.add_header("Content-Disposition", f"attachment; filename= {filename}")

# Adicionar anexo à mensagem
message.attach(part)

# Enviar o email
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()
    server.login(login, password)
    server.sendmail(sender_email, receiver_email, message.as_string())

print('Enviado')

Resumo rápido:

  • Usando MIMEMultipart – Troquei de MIMEText para o corpo para MIMEMultipart para a estrutura geral da mensagem. Isso nos permite adicionar tanto a parte do texto quanto o anexo como partes separadas do email.
  • Adicionando o anexo:
    • Preparação do ficheiro – O ficheiro de anexo é aberto em modo binário rb, e seu conteúdo é lido.
    • Objeto MIMEBase – Um objeto MIMEBase é criado para o anexo, com o tipo definido como application/octet-stream. Este tipo é um fluxo binário genérico, o que significa que é adequado para qualquer tipo de ficheiro, e os provedores de email normalmente o tratam como um anexo.
    • Codificação – O conteúdo do ficheiro é codificado em base64 para garantir que ele possa ser transmitido com segurança por email. Isso é feito usando a função encoders.encode_base64(part).
    • Adicionando cabeçalhos – Um cabeçalho é adicionado à parte do anexo para indicar o nome do ficheiro e que ele deve ser tratado como um anexo (Content-Disposition header).
    • Anexando o ficheiro à mensagem – A parte do anexo é então anexada à mensagem usando message.attach(part).

Send an email with an embedded image

Para enviar emails com uma imagem incorporada (no conteúdo HTML), usarei a classe MIMEImage.

Incorporar uma imagem diretamente no email permite que ela seja exibida como parte do conteúdo do email em vez de um anexo separado. Veja como você pode fazer isso:

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.mime.base import MIMEBase
from email import encoders
import os

# Configuração
port = 587
smtp_server = "live.smtp.mailtrap.io"
login = "api"  # Seu login gerado pelo Mailtrap
password = "1a2b3c4d5e6f7g"  # Sua senha gerada pelo Mailtrap

sender_email = "mailtrap@exemplo.com"
receiver_email = "novo1@exemplo.com"

# Conteúdo HTML com uma imagem incorporada
html = """\
<html>
  <body>
    <p>Oi,<br>
    Este é um email de <b>teste</b> com uma imagem incorporada.<br>
    Aqui está uma imagem: <img src="cid:image1">.</p>
  </body>
</html>
"""

# Criar uma mensagem multipart e definir cabeçalhos
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = "Email HTML Email com Imagem Incorporada"

# Anexar a parte HTML
message.attach(MIMEText(html, "html"))

# Especificar o caminho para sua imagem
image_path = "path/to/your/image.jpg"  # Change this to the correct path

# Abrir o ficheiro de imagem em modo binário
with open(image_path, 'rb') as img:
    # Anexar o ficheiro de imagem
    msg_img = MIMEImage(img.read(), name=os.path.basename(image_path))
    # Definir o cabeçalho Content-ID para usar no corpo HTML
    msg_img.add_header('Content-ID', '<image1>')
    # Anexar a imagem à mensagem
    message.attach(msg_img)

# Enviar o email
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()
    server.login(login, password)
    server.sendmail(sender_email, receiver_email, message.as_string())

print('Enviado')

Resumo rápido:

  • Atualização do conteúdo HTML: O conteúdo HTML agora inclui uma tag <img> com um atributo src apontando para o Content-ID (cid) da imagem que você deseja embutir. Esse cid deve corresponder ao valor do cabeçalho Content-ID da imagem anexada.
  • Incorporando a imagem:
    • Usando MIMEImage – O script agora inclui a classe MIMEImage para lidar com o ficheiro de imagem. Esta classe é projetada especificamente para anexar imagens a emails.
    • Abrir ficheiro de imagem – A imagem que você deseja incorporar é aberta em modo binário.
    • Criar objeto MIMEImage – Os dados binários da imagem são usados para criar um objeto MIMEImage. Este objeto representa o anexo da imagem.
    • Cabeçalho Content-ID – O objeto MIMEImage recebe um cabeçalho Content-ID, que é referenciado pelo atributo src na tag <img> do conteúdo HTML. Essa ligação é o que permite ao provedor de email incorporar a imagem diretamente no corpo do email em vez de exibi-la como um anexo para download.
    • Anexando a imagem – O objeto MIMEImage é anexado à mensagem multipart, da mesma forma que outras partes são anexadas.

Envio assíncrono de emails

Para envio de email assíncrono, você precisa usar a biblioteca asyncio do Python junto com aiosmtplib, um cliente SMTP assíncrono.

Esta modificação permite que seu script envie emails sem bloquear a execução do seu programa, tornando-o mais eficiente, especialmente ao enviar vários emails ou realizar outras tarefas simultaneamente.

Para simplificar, enviarei um email text/plain para um único destinatário sem anexos e imagens incorporadas. Veja como funciona.

Primeiro, certifique-se de instalar o aiosmtplib.

pip install aiosmtplib

Agora, aqui está o script:

import asyncio
from email.mime.text import MIMEText
from aiosmtplib import SMTP

async def send_email_async(sender_email, receiver_email, smtp_server, port, login, password, subject, body):
    message = MIMEText(body)
    message["From"] = sender_email
    message["To"] = receiver_email
    message["Subject"] = subject
    
    async with SMTP(hostname=smtp_server, port=port) as smtp:
        await smtp.connect()
        await smtp.starttls()
        await smtp.login(login, password)
        await smtp.send_message(message)

async def main():
    # Configuração do email
    smtp_server = "live.smtp.mailtrap.io"
    port = 587
    sender_email = "mailtrap@exemplo.com"
    receiver_email = "novo@exemplo.com"  # Destinatário único
    login = "api"  # Seu login gerado pelo Mailtrap
    password = "1a2b3c4d5e6f7g"  # Sua senha gerada pelo Mailtrap
    subject = "Teste de Email Async"
    body = "Este é um email em texto simples enviado de forma assíncrona."
    
    await send_email_async(sender_email=sender_email, receiver_email=receiver_email, smtp_server=smtp_server, port=port, login=login, password=password, subject=subject, body=body)
    print("Email enviado de forma assíncrona.")

if __name__ == "__main__":
    asyncio.run(main())

Resumo rápido:

  • Definição da função assíncrona: O script agora define funções assíncronas usando async def.
  • Funcionalidade assíncrona: Utilizando asyncio e aiosmtplib, o script estabelece uma conexão SMTP assíncrona, faz login e envia o email. Esta abordagem permite o envio de emails sem bloqueio, o que é particularmente útil em aplicações que requerem manutenção de responsividade ao realizar operações de rede.
  • Executando o script: A função main assíncrona configura os detalhes do email e chama send_email_async para enviar o email. Ela demonstra como executar tarefas assíncronas em Python de forma eficaz, com asyncio.run(main()) iniciando a execução assíncrona.

Envio de emails em massa

O código acima usa live.smtp.mailtrap.io, que é o endpoint para emails transacionais. Mas o pacote de email da plataforma Mailtrap Email Delivery permite que você envie emails em massa via um stream separado bulk.smtp.mailtrap.io, sob o mesmo plano.

Configurações de Stream em Massa do Mailtrap

Agora, a única diferença é o Host (endpoint), e você precisará ajustar seu script para isso. Mas lembre-se de que emails transacionais e em massa têm infraestruturas separadas, embora suas credenciais sejam quase as mesmas. Isso ajuda a melhorar a entregabilidade e o gerenciamento de emails.

Para ilustrar as mudanças, criei um script simples usando o endpoint SMTP fornecido.

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

# Configuração para o servidor SMTP em Massa do Mailtrap
smtp_server = "bulk.smtp.mailtrap.io"
port = 587
login = "api"  # Seu login Mailtrap
password = "1a2b3c4d5e6f7g"  # Sua senha Mailtrap

sender_email = "mailtrap@exemplo.com"
receiver_email = "novo@exemplo.com"  # Destinatário único

# Criar uma mensagem MIMEText para texto simples
subject = "Email em Texto Simples via SMTP em Massa"
body = "Este é um email em texto simples enviado via o servidor do SMTP Bulk do Mailtrap."

# Criar uma mensagem MIMEMultipart e definir cabeçalhos
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject

# Anexar a parte de texto
message.attach(MIMEText(body, "plain"))

# Enviar o email
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()  # Proteger a conexão
    server.login(login, password)  # Fazer login no servidor SMTP
    server.sendmail(sender_email, receiver_email, message.as_string())  # Enviar o email

print('Email enviado com sucesso.')

Resumo rápido:

  • Uso do MIMEMultipart: Embora o email seja texto simples e enviado para um único destinatário, mantive o uso de MIMEMultipart. Essa abordagem oferece flexibilidade caso você decida adicionar anexos ou conteúdo HTML no futuro. No entanto, você poderia simplificar ainda mais usando apenas MIMEText.
  • Enviando o email: A chamada para server.sendmail é direta, especificando o remetente, o destinatário e convertendo o objeto da mensagem para um formato de string a ser enviado.

Pro Tip: Se você estiver usando variáveis de ambiente ou ficheiro de configuração externo para as credenciais SMTP, é melhor ter ficheiros separados para configuração Transacional e em Massa.

Enviar emails usando API

Para tornar sua integração mais direta, o Mailtrap possui um SDK Python oficial (◀️confira o link no GitHub). Vou usar isso para mostrar como enviar um email de texto simples, enviá-lo para vários destinatários, enviar emails em massa, etc.

Aqui, não cobrirei o método de envio de email assíncrono, pois o Mailtrap não o suporta, e não faz muito sentido em contextos de API.

Como lembrete, você precisará conectar e verificar seu domínio com o Mailtrap. Confira nosso guia detalhado e um vídeo bônus sobre como fazer isso.

Depois de feito isso, volte para o seu aplicativo Python e instale o SDK oficial do Mailtrap com o seguinte comando:

pip install mailtrap

Nota: certifique-se de que a versão do pacote seja 3.6+ ou superior.

Em seguida, você deve criar o objeto de email e preencher as variáveis (como email e nome) com suas credenciais do Mailtrap. Lembre-se de que você deve indicar o endereço com o domínio de envio verificado.

import mailtrap as mt

# criar objeto de email
mail = mt.Mail(
    sender=mt.Address(email="mailtrap@exemplo.com", name="Teste Mailtrap"),
    to=[mt.Address(email="seu@email.com")],
    subject="Você é incrível!!",
    text="Parabéns por ter enviado o teste de email com o Mailtrap!",
)

# criar cliente e enviar
client = mt.MailtrapClient(token="sua-chave-api")
client.send(mail)

Você também precisará criar o cliente com seu token de API. Vá para sua conta do Mailtrap, expandindo o menu Settings e escolhendo a guia API Tokens. Copie as credenciais clicando em Copy ao lado do seu token.

Depois, você pode usar o comando abaixo para enviar o email.

# criar cliente e enviar
client = mt.MailtrapClient(token="sua-chave-api")
client.send(mail)

Com isso fora do caminho, vou prosseguir para mostrar como aproveitar o SDK para diferentes casos de uso.

Aqui está um script básico para enviar email de texto simples:

from mailtrap import Mail, Address, MailtrapClient

# Criar um objeto Mail com detalhes básicos para um email de texto simples
mail = Mail(
    # Especificar o endereço de email do remetente e nome opcional
    sender=Address(email="mailtrap@exemplo.com", name="Teste Mailtrap"),
    # Especificar um ou mais destinatários; aqui usamos uma lista com um único destinatário
    to=[Address(email="seu@email.com", name="Seu Nome")],
    # Assunto do email
    subject="Email Básico em Texto Simples",
    # O conteúdo de texto simples do email
    text="Este é um email em texto simples enviado usando o SDK do Mailtrap. Rápido e sem complicações.",
    # Opcional: categorizar este email para facilitar a classificação ou gerenciamento no serviço Mailtrap
    category="Test",
    # Opcional: Cabeçalhos adicionais podem ser especificados, mas não são necessários para emails de texto simples
    headers={"X-Example-Header": "HeaderValue"}
)

# Inicializar o MailtrapClient com seu token de API
client = MailtrapClient(token="sua-chave-api")

# Enviar o email usando o método send do cliente
client.send(mail)

print("Email em texto simples enviado com sucesso.")

Resumo rápido:

  • Importação de classes: Apenas as classes Mail, Address e MailtrapClient da biblioteca Mailtrap são importadas, já que estamos focando em enviar um email de texto simples.
  • Criando o objeto Mail:
    • Mail – Um construtor usado para criar um objeto de email.
    • Sender – Usa a classe Address para definir o email e nome do remetente.
    • to – Uma lista de objetos Address para cada destinatário. Para email de texto simples, você geralmente tem um ou mais destinatários diretos listados aqui.
    • subject – A linha de assunto do email.
    • text – O conteúdo real do email, no formato de texto simples.
    • category e headers – Campos opcionais que permitem categorização adicional e cabeçalhos personalizados. Embora não sejam estritamente necessários para enviar um email de texto simples, podem ser úteis para fins organizacionais ou técnicos dentro do serviço Mailtrap ou para o manuseio do provedor de email.
  • Enviando o email:
    • Uma instância do MailtrapClient é criada e autenticada com um token de API.
    • O método send do MailtrapClient é então chamado, passando o objeto mail como argumento para enviar o email.
    • Finalmente, uma mensagem de confirmação é impressa para indicar que o email foi enviado.

Enviar um email HTML

Vou ajustar o script especificando o parâmetro html no objeto Mail com o conteúdo HTML.

from mailtrap import Mail, Address, MailtrapClient

# Criar um objeto Mail para enviar um email HTML
mail = Mail(
    sender=Address(email="mailtrap@exemplo.com", name="Teste Mailtrap"),
    to=[Address(email="destinatario@email.com", name="Nome do Destinatário")],
    subject="Assunto do Seu Email HTML Aqui",
    text="Este é o texto fallback que os destinatários verão para provedores de email que não suportam HTML",
    html="""
    <!DOCTYPE html>
    <html>
        <head>
            <title>Título do Email</title>
        </head>
        <body>
            <h1>Oi, Mundo!</h1>
            <p>Este é um <strong>email HTML</strong> enviado com o SDK Python do Mailtrap.</p>
            <p>Aqui está um link: <a href="https://exemplo.com">Visite Exemplo.com</a></p>
        </body>
    </html>
    """,
    # Você pode categorizar este email ou adicionar cabeçalhos personalizados conforme necessário
    category="HTML Email",
    headers={"X-Custom-Header": "Value"}
)

# Inicializar o MailtrapClient com seu token de API
client = MailtrapClient(token="sua-chave-api")

# Enviar o email
client.send(mail)

print("Email HTML enviado com sucesso.")

Resumo rápido:

  • Conteúdo HTML: O parâmetro html do objeto Mail é onde você coloca seu conteúdo HTML. Esta é a parte do email que será renderizada por provedores de email capazes de exibir HTML.
  • Conteúdo de texto de fallback: A versão em texto simples do conteúdo do email serve como fallback para provedores de email que não renderizam HTML ou para usuários que preferem emails em texto simples.
  • Enviando o email: Com o conteúdo HTML definido, o resto do processo para enviar o email permanece o mesmo.

Enviar emails para múltiplos destinatários

Vou modificar a parte dos destinatários da configuração do email para incluir múltiplos destinatários.

Há comentários ao longo do script para explicar como lidar com múltiplos destinatários tanto para o campo To quanto para adicionar destinatários Cc (Carbon Copy) e Bcc (Blind Carbon Copy). Portanto, não adicionarei a seção Resumo rápido neste caso, pois o método é simples e a lógica é óbvia no script.

from mailtrap import Mail, Address, MailtrapClient

# Criar um objeto Mail direcionado a múltiplos destinatários, incluindo endereços Cc e Bcc
mail = Mail(
    # Especificar o endereço de email do remetente e nome opcional
    sender=Address(email="mailtrap@exemplo.com", name="Mailtrap Test"),
    # Especificar múltiplos destinatários no campo "To"
    to=[
        Address(email="destinatario1@email.com", name="Destinatário Um"),
        Address(email="destinatario2@email.com", name="Destinatário Dois"),
    ],
    # Além disso, especificar destinatários no campo "Cc"
    cc=[
        Address(email="cc1@email.com", name="Cc Destinatário Um"),
        Address(email="cc2@email.com", name="Cc Destinatário Dois"),
    ],
    # E destinatários no campo "Bcc" para cópias ocultas
    bcc=[
        Address(email="bcc1@email.com", name="Bcc Destinatário Um"),
        Address(email="bcc2@email.com", name="Bcc Destinatário Dois"),
    ],
    # Assunto do email
    subject="Email para Múltiplos Destinatários",
    # O conteúdo de texto simples do email
    text="Este email é enviado para múltiplos destinatários, incluindo endereços Cc e Bcc.",
    # Opcional: categorizar este email ou adicionar cabeçalhos personalizados conforme necessário
    category="Mass Email",
    headers={"X-Custom-Header": "Value"}
)

# Inicializar o MailtrapClient com seu token de API
client = MailtrapClient(token="your-api-key")

# Enviar o email usando o método send do cliente
client.send(mail)

print("Email enviado para múltiplos destinatários com sucesso.")

Enviar um email com anexos

Aqui, precisarei me concentrar principalmente em como a classe Attachment é usada para incluir ficheiros no seu email. Este exemplo demonstrará a anexação de um ficheiro genérico, mas a abordagem é similar para qualquer tipo de ficheiro.

from mailtrap import Mail, Address, MailtrapClient, Attachment, Disposition
import base64
from pathlib import Path

# Preparar o ficheiro que você deseja anexar
file_path = Path("path/to/seu/ficheiro.pdf")  # Atualize para o caminho do seu ficheiro
file_content = file_path.read_bytes()  # Ler o conteúdo do ficheiro como bytes

# Codificar o conteúdo do ficheiro em base64
encoded_content = base64.b64encode(file_content)

# Criar um objeto Mail com um anexo
mail = Mail(
    sender=Address(email="mailtrap@exemplo.com", name="Teste Mailtrap"),
    to=[Address(email="destinatario@email.com", name="Nome do Destinatário")],
    subject="Email com Anexo",
    text="Este email contém um anexo. Confira-o!",
    # Definir o anexo
    attachments=[
        Attachment(
            content=encoded_content,  # O conteúdo codificado em base64 do ficheiro
            filename=file_path.name,  # O nome do ficheiro como deve aparecer no email
            disposition=Disposition.ATTACHMENT,  # Indica que o ficheiro é um anexo
            mimetype="application/pdf",  # O tipo MIME do ficheiro
            # `content_id` é opcional e geralmente usado para incorporar imagens diretamente no corpo HTML
        )
    ],
)

# Inicializar o MailtrapClient com seu token de API
client = MailtrapClient(token="sua-chave-api")

# Enviar o email
client.send(mail)

print("Email com anexo enviado com sucesso.")

Resumo rápido:

  • Preparando o ficheiro: O script começa especificando o caminho para o ficheiro que você deseja anexar e lendo seu conteúdo como bytes. É importante ler o ficheiro em modo binário (método read_bytes()) para garantir que o conteúdo seja codificado e transmitido corretamente.
  • Codificação base64: Como os protocolos de email não são seguros para binários, o conteúdo do ficheiro precisa ser codificado em base64. Essa codificação converte dados binários em um formato de texto que pode ser transmitido com segurança por email. O método base64.b64encode é usado para esse propósito.
  • Criando o anexo: A classe Attachment é instanciada com vários parâmetros:
    • content – O conteúdo codificado em base64 do ficheiro.
    • filename – O nome do ficheiro conforme você deseja que ele apareça no email.
    • disposition – Isto é definido como Disposition.ATTACHMENT para indicar que o ficheiro é um anexo (em vez de inline, que seria usado para imagens incorporadas).
    • mimetype – O tipo MIME do ficheiro, que ajuda os provedores de email a entender como lidar com o ficheiro. Para um PDF, isso é application/pdf.

Enviar um email com uma imagem incorporada

Aqui, anexarei a imagem para que ela possa ser exibida diretamente dentro do conteúdo HTML do email. Isso geralmente é alcançado anexando a imagem com um Content-ID (cid) que pode ser referenciado no HTML. Veja como fazer isso:

from mailtrap import Mail, Address, MailtrapClient, Attachment, Disposition
import base64
from pathlib import Path

# Especificar o caminho para sua imagem
image_path = Path("path/to/sua/imagem.jpg")
image_content = image_path.read_bytes()  # Ler o conteúdo da imagem como bytes

# Codificar o conteúdo da imagem em base64
encoded_image = base64.b64encode(image_content)

# Criar um objeto Mail com conteúdo HTML e uma imagem incorporada
mail = Mail(
    sender=Address(email="mailtrap@exemplo.com", name="Teste Mailtrap"),
    to=[Address(email="destinatario@email.com", name="Nome do Destinatário")],
    subject="Email com Imagem Incorporada",
    text="Este é o texto fallback que os destinatários verão para provedores de email que não suportam HTML",
    html="""
    <!DOCTYPE html>
    <html>
        <body>
            <h1>Oi, Mundo!</h1>
            <p>Este email contém uma imagem incorporada.</p>
            <!-- Use 'cid:image_cid' no atributo src para incorporar a imagem -->
            <img src="cid:image_cid">
        </body>
    </html>
    """,
    attachments=[
        Attachment(
            content=encoded_image,
            filename=image_path.name,
            disposition=Disposition.INLINE,  # Marcar o anexo como inline
            mimetype="image/jpeg",  # O tipo MIME da imagem
            content_id="image_cid",  # Content-ID usado para referenciar a imagem no atributo src do HTML
        )
    ],
)

# Inicializar o MailtrapClient com seu token de API
client = MailtrapClient(token="sua-chave-api")

# Enviar o email
client.send(mail)

print("Email com imagem incorporada enviado com sucesso.")

Resumo rápido:

  • Preparar a imagem: Antes de anexar a imagem, você lê seu conteúdo como bytes e depois a codifica em base64. Essa codificação é necessária porque o conteúdo do email (incluindo anexos) precisa ser transmitido em um formato de texto.
  • Conteúdo HTML: No parâmetro html do objeto Mail, você inclui uma tag <img> onde o atributo src usa um esquema cid: seguido pelo Content-ID do anexo da imagem (image_cid neste caso). Esse cid vincula a imagem incorporada no conteúdo HTML ao ficheiro de imagem anexado.
  • Anexando a imagem: A imagem é anexada usando a classe Attachment com vários parâmetros específicos:
    • content – O conteúdo codificado em base64 da imagem.
    • filename – O nome do ficheiro da imagem. Ele é usado como fallback em alguns provedores de email se a imagem não puder ser exibida.
    • disposition – Definido como Disposition.INLINE para indicar que o anexo deve ser exibido em linha com o conteúdo HTML, não como um anexo separado para download.
    • mimetype – Especifica o tipo MIME da imagem (por exemplo, “image/jpeg”). Isso ajuda o provedor de email a entender como lidar com o ficheiro.
    • content_id – Um identificador único para o anexo referenciado no atributo src do HTML para incorporar a imagem.
    • Enviando o email – O processo para enviar o email permanece inalterado.

Envio de emails em massa

Para relembrar, a plataforma Mailtrap Email Delivery permite que você envie emails em massa além de transacionais, sob o mesmo plano. Você precisa selecionar o stream, clicar no botão API e escolher a integração Python.

Configurações de Stream em Massa do Mailtrap

Com isso fora do caminho, aqui está o que mais você precisa fazer.

  1. Certifique-se de ter a biblioteca requests instalada. Se não, você pode instalá-la usando pip:
pip install requests
  1. Construa um payload JSON que especifica os detalhes do email e ajuste o campo to para incluir vários destinatários.
  1. Usando a biblioteca requests, faça uma solicitação POST para o endpoint Mailtrap Bulk API, fornecendo os cabeçalhos necessários (incluindo autorização) e o payload. Confira o script exemplificado abaixo.
import requests
import json

def send_mailtrap_email(payload):
    url = "https://bulk.api.mailtrap.io/api/send"
    headers = {
      "Authorization": "Bearer seu_token_api",  # Substitua pelo seu token de API Mailtrap
      "Content-Type": "application/json"
    }

    response = requests.post(url, headers=headers, data=json.dumps(payload))
    return response.text

payload = {
    "from": {"email": "mailtrap@mailtrapdemo.com", "name": "Teste Mailtrap"},
    "to": [{"email": "destinatario@exemplo.com"}],  # Adicione mais destinatários conforme necessário
    "subject": "Você é incrível!",
    "text": "Parabéns por enviar emails de teste com o Mailtrap!",
    "category": "Integration Test"
}

response_text = send_mailtrap_email(payload)
print(response_text)

Resumo rápido:

  • payload – É um dicionário que corresponde à estrutura JSON esperada pela API Mailtrap Bulk. Você pode modificar este dicionário para incluir os detalhes do seu email, como remetente, destinatário(s), assunto e corpo.
  • send_mailtrap_email – A função encapsula o processo de envio do email. Ela recebe o payload como entrada, converte-o para o formato JSON e faz uma solicitação POST para a API Bulk do Mailtrap.

Considerações de segurança ao enviar emails

Se você planeja automatizar o envio de emails e enviá-los para um grande número de destinatários consistentemente, é melhor tomar precauções extras. (Principalmente relacionadas ao método SMTP.)

Aqui, cobrirei alguns métodos testados e comprovados para evitar codificar credenciais em seus scripts e lidar com erros. Observe que as dicas abaixo se aplicam independentemente do provedor de email que você esteja usando (SendGrid, SES, conta do Gmail, etc.)

Usando variáveis de ambiente para informações sensíveis

Variáveis de ambiente são uma forma segura de gerenciar configurações e informações sensíveis fora do seu código de aplicação.

Em Python, você pode usar o módulo os para acessar variáveis de ambiente.

import os

smtp_server = os.getenv("SMTP_SERVER", "default.smtp.server")
login = os.getenv("SMTP_LOGIN")
password = os.getenv("SMTP_PASSWORD")

# Exemplo de uso em uma configuração de conexão SMTP
# smtp.login(login, password)

Antes de executar seu script, defina as variáveis de ambiente em seu sistema operacional. Por exemplo, em um terminal Linux ou macOS, você pode defini-las temporariamente assim:

export SMTP_SERVER=live.smtp.mailtrap.io
export SMTP_LOGIN=seu_login
export SMTP_PASSWORD=sua_senha

No Windows, você pode defini-las via linha de comando da seguinte forma:

set SMTP_SERVER=live.smtp.mailtrap.io
set SMTP_LOGIN=seu_login
set SMTP_PASSWORD=sua_senha

Tratamento de erros

Veja como gerenciar erros inesperados, como problemas de rede, problemas de autenticação ou outras exceções que podem ocorrer durante o processo de envio de email.

try:
    # Tentar enviar um email
    server.sendmail(sender_email, recipient_email, message.as_string())
except smtplib.SMTPException as e:
    print(f"Ocorreu um erro SMTP: {e}")
except Exception as e:
    print(f"Ocorreu um erro: {e}")

Usando SSL

Aqui está um esboço básico de como você pode usar smtplib.SMTP_SSL em um script para enviar um email:

import smtplib
from email.mime.text import MIMEText


# Configuração
port = 465
smtp_server = "live.smtp.mailtrap.io"
login = "username"
password = "password"


sender_email = "remetente@dominio_registado.com"
receiver_email = "destinatario@gmail.com"


text = """\
Oi,
Diga-nos que tipo de conteúdo você acha que seria útil e gostaria de ler!
"""


message = MIMEText(text, "plain")
message["Subject"] = "Email de texto simples"
message["From"] = sender_email
message["To"] = receiver_email




with smtplib.SMTP_SSL(smtp_server, port) as server:
    server.login(login, password)
    server.sendmail(sender_email, receiver_email, message.as_string())
    print("Email enviado com sucesso!")

Configuração externa

Armazenar dados de configuração (como detalhes do servidor SMTP e endereços de email) em ficheiros externos ou variáveis de ambiente aumenta a segurança e a flexibilidade do seu script. Para configurações mais complexas, você pode considerar usar um ficheiro JSON ou similar.

  • Exemplo de configuração JSON (config.json):
{
    "smtp_server": "live.smtp.mailtrap.io",
    "smtp_port": 587,
    "login": "seu_login",
    "password": "sua_senha"
}
  • Como carregar a configuração:
import json

with open('config.json', 'r') as config_file:
    config = json.load(config_file)

smtp_server = config.get('smtp_server')
smtp_port = config.get('smtp_port')
login = config.get('login')
password = config.get('password')

Dica: Se você quiser enviar emails da sua conta do Google e aproveitar o servidor SMTP do Gmail (smtp.gmail.com), nós já blogamos sobre isso. Confira o artigo aqui.

Teste e envio de emails em um ambiente de teste

Ao criar um novo aplicativo ou adicionar qualquer funcionalidade, especialmente ao fazer isso pela primeira vez, é essencial experimentar em um servidor de teste. Aqui está uma breve lista de razões:

  1. Você não atingirá as caixas de entrada de seus amigos e clientes. Isso é vital ao testar envio de emails em massa ou trabalhar com um banco de dados de emails.
  2. Você não inundará sua caixa de entrada com emails de teste.
  3. Seu domínio não será incluído na lista de bloqueio devido a spam.

Um ambiente de servidor SMTP de teste imita o trabalho de um servidor web de terceiros real. Nos exemplos a seguir, usarei o Mailtrap Email Testing, que permite aos desenvolvedores capturar o tráfego SMTP do estágio e inspecionar e depurar emails antes de enviá-los para destinatários reais.

Além disso, o Email Testing pode ajudar a validar seu HTML/CSS, analisar o conteúdo do email, visualizar txt e conteúdo, e dar uma pontuação de spam relevante. A ferramenta é fácil de configurar; tudo o que você precisa é copiar as credenciais geradas pelo aplicativo e colá-las no seu código.

Nota: Cobrirei os métodos SMTP e API separadamente. E se você quiser um tutorial detalhado sobre testes com Python, confira este artigo.

SMTP

Vá para o Mailtrap, selecione Email Testing, depois My Inbox. Na guia SMTP Settings, clique em Show credentials para revelar as credenciais de teste.

Configurações SMTP do Mailtrap Email Testing

Veja como funciona na prática:

import smtplib
port = 2525 
smtp_server = "sandbox.smtp.mailtrap.io"
login = "1b2c3d4e5d66f" # seu login gerado pelo Mailtrap
password = "1b2c3d4e5d66f" # sua senha gerada pelo Mailtrap

O Mailtrap torna as coisas ainda mais fáceis. Vá para a seção de integrações na guia de SMTP Settings e obtenha o template pronto para uso da mensagem de texto simples com suas credenciais do Mailtrap.

Nota importante: Os snippets usam credenciais fictícias por segurança, por favor, certifique-se de copiar e colar suas credenciais reais no código.

A opção mais básica para instruir seu código Python sobre quem envia o quê para quem é o método de instância sendmail(), que usarei aqui. Mas também temos integrações exemplares para Django e Flask.

Integração do Mailtrap Email Testing smtplib

Vamos dar uma olhada mais de perto no exemplo e adicionar algum tratamento de erros (veja as #explicações entre parênteses). Para capturar erros, usamos os blocos try e except. Consulte a documentação para a lista de exceções aqui.

# o primeiro passo é sempre o mesmo: importar todos os componentes necessários:
import smtplib
from socket import gaierror

# agora você pode brincar com seu código. Vamos definir o servidor SMTP separadamente aqui:
port = 2525 
smtp_server = "sandbox.smtp.mailtrap.io"
login = "1b2c3d4e5d66f" # cole seu login gerado pelo Mailtrap
password = "1b2c3d4e5d66f" # cole sua senha gerada pelo Mailtrap
# especifique os endereços de email do remetente e do destinatário
sender = "remetente@exemplo.com"
receiver = "mailtrap@exemplo.com"
# digite sua mensagem: use duas novas linhas (\n) para separar o assunto do corpo da mensagem, e use 'f' para inserir automaticamente variáveis no texto
message = f"""\
Subject: Oi Mailtrap
To: {receiver}
From: {sender}

Esta é a minha primeira mensagem em Python."""

try:
    #envie sua mensagem com as credenciais especificadas acima
    with smtplib.SMTP(smtp_server, port) as server:
        server.login(login, password)
        server.sendmail(sender, receiver, message)
    # diga ao script para relatar se sua mensagem foi enviada ou quais erros precisam ser corrigidos
    print('Enviado.')
except (gaierror, ConnectionRefusedError):
    print('Problema ao conectar ao servidor. Configurações de conexão incorretas?')
except smtplib.SMTPServerDisconnected:
    print('Problema ao conectar ao servidor. Usuário/senha incorretos?')
except smtplib.SMTPException as e:
    print('Ocorreu um erro SMTP: ' + str(e))

Assim que você obtiver o resultado Sent no Shell, deverá ver sua mensagem na sua caixa de entrada do Mailtrap:

Mensagem de teste do Mailtrap Python

Se você preferir trabalhar no ambiente local, o servidor de depuração SMTP local pode ser uma opção. Para esse propósito, o Python oferece um módulo smtpd. Ele possui um recurso DebuggingServer, que descartará as mensagens que você está enviando e as imprimirá no stdout. É compatível com todos os sistemas operacionais.

Defina seu servidor SMTP para localhost:1025

python -m smtpd -n -c DebuggingServer localhost:1025

Para executar o servidor de email SMTP na porta número 25, você precisará de permissões de root:

sudo python -m smtpd -n -c DebuggingServer localhost:25

Isso ajudará você a verificar se seu código está funcionando e apontar possíveis problemas, se houver. No entanto, isso não permitirá verificar como seu template de email HTML é renderizado.

API

Você pode conferir nossa documentação da API para detalhes completos sobre o teste da API. Usarei Python 3 para mostrar o método e guiar você passo a passo.

  1. Estabeleça uma conexão com o endpoint da API do Mailtrap Email Testing usando http.client.HTTPSConnection.
  2. Defina o conteúdo do seu email, incluindo destinatários (to, cc, bcc), remetente (from), assunto, conteúdo de texto e quaisquer anexos ou variáveis personalizadas como um payload JSON.
  3. Faça uma solicitação POST para a API Mailtrap Email Testing com seu payload e cabeçalhos necessários, incluindo seu token de API para autorização. Aqui está um exemplo:
import http.client
import json

def test_send_email():
    conn = http.client.HTTPSConnection("sandbox.api.mailtrap.io")
    
    payload = {
        "to": [{"email": "john_doe@exemplo.com", "name": "John Doe"}],
        "cc": [{"email": "jane_doe@exemplo.com", "name": "Jane Doe"}],
        "bcc": [{"email": "james_doe@exemplo.com", "name": "Jim Doe"}],
        "from": {"email": "vendas@exemplo.com", "name": "Exemplo de Equipa de Vendas"},
        "attachments": [
            {
                "content": "base64_encoded_content_here",
                "filename": "index.html",
                "type": "text/html",
                "disposition": "attachment"
            }
        ],
        "custom_variables": {"user_id": "45982", "batch_id": "PSJ-12"},
        "headers": {"X-Message-Source": "dev.mydomain.com"},
        "subject": "Sua Confirmação de Encomenda de Exemplo",
        "text": "Parabéns pela sua encomenda número 1234",
        "category": "API Test"
    }

    headers = {
        'Content-Type': "application/json",
        'Accept': "application/json",
        'Api-Token': "seu_token_api_aqui"  # Substitua pelo seu token de API real
    }

    # Converter o payload para uma string JSON
    json_payload = json.dumps(payload)

    # Fazer a solicitação POST
    conn.request("POST", "/api/send/inbox_id", json_payload, headers)  # Substitua 'inbox_id' pelo seu ID de caixa de entrada real

    # Obter a resposta
    response = conn.getresponse()
    data = response.read()

    print(data.decode("utf-8"))

if __name__ == "__main__":
    test_send_email()

Notas:

  • Payload: O dicionário contém todos os detalhes do email que você deseja testar. Certifique-se de substituir os valores de espaço reservado por dados reais relevantes para seu caso de teste. Para anexos, codifique o conteúdo do seu ficheiro em Base64 e inclua-o no campo content.
  • Headers: Inclua seus cabeçalhos Content-Type, Accept e Api-Token. O Api-Token deve ser seu token de API Mailtrap.
  • Solicitação e resposta: O script faz uma solicitação POST para o endpoint /api/send/inbox_id, substituindo inbox_id pelo seu ID de caixa de entrada real. Em seguida, lê e imprime a resposta para verificar o resultado.

Próximos passos com emails em Python

Demonstrei as opções de envio de emails com Python para descrever a lógica e uma gama de suas capacidades. Mas recomendo revisar a documentação do Python e experimentar seu próprio código para obter ótimos resultados!

Há uma variedade de frameworks e bibliotecas Python que tornam a criação de aplicativos mais elegante e dedicada. Em particular, alguns deles podem ajudar a melhorar sua experiência na construção de funcionalidades de envio de emails:

Os frameworks mais populares são:

  1. Flask, que oferece uma interface simples para envio de emails—Flask Mail. Sinta-se à vontade para saber mais no nosso guia sobre como enviar emails com Flask.
  2. Django pode ser uma ótima opção para construir templates HTML. Além disso, dê uma olhada no nosso tutorial de envio de emails com Django.
  3. Zope é útil para desenvolvimento de sites.
  4. Marrow Mailer é um framework de entrega de email dedicado que adiciona várias configurações úteis.
  5. Plotly e seu Dash podem ajudar no envio de gráficos e relatórios por email.

Boa sorte e não se esqueça de se manter seguro ao enviar seus emails!

Article by Aleksandr Varnin Full Stack Developer @ Railsware
Article by Veljko Ristić Content Manager @ Mailtrap

Linguist by trade, digital marketer at heart, I’m a Content Manager who’s been in the online space for 10+ years. From ads to e-books, I’ve covered it all as a writer, editor, project manager, and everything in between. Now, my passion is with email infrastructure with a strong focus on technical content and the cutting-edge in programming logic and flows. But I still like spreading my gospels while blogging purely about marketing.