IT & Engineering

Enviar e-mail usando Python3 e a API do Mailgun

Quer otimizar seu processo de envio de e-mails usando Python3? Reunimos nossos profissionais de Python para trazer um guia para você. Neste tutorial, vamos analisar como enviar e-mails de forma programática usando Python3 e a API de e-mail do Sinch Mailgun.
Imagem para Enviar e-mail usando Python3 e a API do Mailgun

Se você quer otimizar sua abordagem para o envio programático de e-mails, está em boas mãos. Nossa equipe de desenvolvimento tem a experiência necessária para você começar. Continue lendo enquanto detalhamos a integração do Python3 com a robusta API de e-mail do Mailgun, com insights, orientações e otimizações ao longo do caminho.

Por onde começar: o que você precisa para este tutorial

Ao enviar e-mails, você tem duas opções: manual ou programática. Quando estamos falando sobre e-mails transacionais especificamente, a opção programática é a melhor escolha. Em vez de enviar notificações ou atualizações importantes de e-mail manualmente, você pode usar scripts de e-mail automatizados para economizar tempo e reduzir erros.

Scripts (pequenos programas que automatizam tarefas) oferecem uma forma mais eficiente de enviar e-mails em massa, agendar mensagens ou serem chamados diretamente pela sua aplicação. Alguns casos de uso para o envio de e-mails por scripts automatizados incluem:

  • Envio de e-mails de boas-vindas para cadastro de usuários
  • Envio de alertas e notificações de aplicações, como informar a base de usuários sobre o uso do serviço ou notificar admins quando os recursos do servidor estiverem baixos
  • Envio de relatórios, como um relatório semanal de novos clientes
  • Envio de campanhas de marketing (por exemplo, para promover novos produtos ou serviços)

Neste tutorial, você vai aprender a enviar e-mails usando scripts em Python3 e a API do Mailgun.

Pré-requisitos

Para acompanhar este tutorial de Python3 e API de e-mail, você precisará do seguinte:

  • Python 3.9 ou superior. O Python costuma ser descrito como o canivete suíço das linguagens de programação e oferece uma ampla gama de recursos. Além de seus muitos outros usos, o Python é excelente para escrever vários scripts.
  • Uma conta do Mailgun. O Mailgun é uma plataforma de envio de e-mail que permite enviar e rastrear e-mails. Se você ainda não usa o Mailgun, pode acompanhar este tutorial com nossa avaliação gratuita.

Configurando um novo projeto Python

Vamos nos aprofundar.

Comece criando um diretório adequado para o seu projeto Python e adicione um arquivo .env vazio dentro dele. Antes de prosseguir, considere criar e ativar um novo ambiente virtual antes de instalar as bibliotecas Python necessárias para este tutorial. Isso isola o seu projeto, o que evita conflitos de dependências.

Para instalar as bibliotecas necessárias (requests e python-dotenv) usando o pip no seu ambiente virtual, execute o seguinte comando:

pip install requests python-dotenv

A biblioteca requests permite fazer chamadas de API, enquanto a biblioteca python-dotenv permite armazenar a chave de API fora do seu código.

Como obter uma chave de API com o Mailgun

Em seguida, você vai obter uma chave de API na sua conta do Mailgun, que será usada para fazer chamadas de API para o Mailgun.

Faça o login na sua conta do Mailgun e crie uma chave de API na página Segurança da API, que pode ser acessada por um menu suspenso abaixo do seu nome, no canto superior direito.

New API key location in Mailgun

Copie e cole essa chave de API no arquivo .env do seu projeto.

MAILGUN_API_KEY=”Your API Key Here”

Enquanto estiver no Mailgun, anote os seus domínios de envio no painel do Mailgun.

Se você estiver em um plano gratuito, verá um domínio de sandbox, que será usado no endpoint da API e no endereço de e-mail do remetente ao enviar e-mails pela API do Mailgun. O domínio de sandbox segue o formato .mailgun.org, conforme mostrado abaixo.

Sandbox domain in Mailgun

Você precisará fazer upgrade para um plano pago se quiser usar um domínio de e-mail personalizado para enviar e-mails pelo Mailgun. O plano gratuito permite apenas o domínio de sandbox, e você pode enviar e-mails para no máximo cinco endereços verificados. No entanto, esse plano gratuito é útil durante a fase de desenvolvimento, ao integrar a API do Mailgun ao seu sistema.

Importações e inicialização

Em seguida, crie o arquivo main.py no diretório do seu projeto e copie e cole este código:

                                

                                    ```python import jsonrnimport requestsrnimport loggingrnrnimport osrnfrom dotenv import load_dotenvrnrnlogging.basicConfig(level=logging.INFO) # set log levelrnload_dotenv() # for reading API key from `.env` file.rnrn# Sandbox API URL format: https://api.mailgun.net/v3/sandbox<ID>.mailgun.org/messagesrnMAILGUN_API_URL = "https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages"rnFROM_EMAIL_ADDRESS = "Sender Name <SENDER_EMAIL_ID>"
                                
                            

Ele usa o registro padrão do Python e o configura para o nível INFO com este código:

                                

                                    ```pythonrnlogging.basicConfig(level=logging.INFO)rn```
                                
                            

A função load_dotenv() vem da biblioteca python-dotenv e é usada para carregar variáveis de ambiente do arquivo .env no seu código Python. É uma das práticas recomendadas armazenar e ler informações confidenciais, como credenciais e chaves de API, do arquivo .env.

MAILGUN_API_URL define o URL da API para o seu script em Python e indica o ID de e-mail do remetente. Ambos devem usar o seu domínio de envio de e-mail ou o domínio de sandbox mencionado antes.

Envio de e-mails individuais usando a API do Mailgun

Vamos primeiro analisar a maneira mais simples de usar a API do Mailgun: enviando um único e-mail. Você pode usar isso em casos pontuais, como o envio de um lembrete ou de um e-mail de acompanhamento para um cliente de alto valor. Isso também permitirá que você rastreie a entrega do e-mail.

Copie e cole o código abaixo no seu arquivo main.py após as importações e inicialização:

                                

                                    ```pythonrndef send_single_email(to_address: str, subject: str, message: str):rn    try:rn        api_key = os.getenv("MAILGUN_API_KEY")  # get API-Key from the `.env` filernrn        resp = requests.post(MAILGUN_API_URL, auth=("api", api_key),rn                             data={"from": FROM_EMAIL_ADDRESS,rn                                   "to": to_address, "subject": subject, "text": message})rn        if resp.status_code == 200:  # successrn            logging.info(f"Successfully sent an email to '{to_address}' via Mailgun API.")rn        else:  # errorrn            logging.error(f"Could not send the email, reason: {resp.text}")rnrn    except Exception as ex:rn        logging.exception(f"Mailgun error: {ex}")rnrnif __name__ == "__main__":rn    send_single_email("Manish <manish@exanple.com>", "Single email test", "Testing Mailgun API for a single email")rn```
                                
                            

Esta função send_single_email(…) recebe três argumentos: to_address, subject e message. to_address é para um único endereço de e-mail, e os outros dois são para o assunto e o conteúdo do e-mail.

O código lê a chave de API do Mailgun do arquivo .env e a usa para fazer uma chamada de API, estabelecendo uma conexão segura com a API_URL especificada. Essa chave de API atua como um identificador exclusivo, permitindo que o Mailgun autentique a chamada de API e verifique quem está usando seus serviços.

Você deve usar a sua chave de API exclusiva para garantir a autenticação adequada. O endereço de e-mail do remetente usado nesta chamada de API também deve estar associado ao seu domínio válido ou ao domínio de sandbox do Mailgun. Caso contrário, a chamada falhará com uma mensagem de erro.

Os parâmetros de dados são enviados pelo método POST do HTTP para o endpoint da API com a chamada requests.post(…).

Quando a chamada de API for bem-sucedida, seu e-mail entrará na fila para entrega, e a API retornará o status HTTP 200 (OK). Em caso de erro, a API retornará uma mensagem de erro com um código de status HTTP apropriado. Ambos os casos são devidamente registrados por este snippet de código.

if __name__ == “__main__” mostra como essa função pode ser chamada no seu script.

Ao executar este script no seu terminal, será mostrado o seguinte:

Python script running in terminal

Envio de e-mail em massa com a API do Mailgun

Embora você possa usar a função send_single_email(…) em um loop para enviar e-mails a múltiplos destinatários, não é o método mais eficiente devido a atrasos de E/S de rede. Essa abordagem também pode esbarrar nos limites de taxa da API.

Em vez disso, use Envio em lote para o envio de e-mails para múltiplos destinatários. O snippet de código abaixo demonstra como usá-lo no seu script em Python.

Copie e cole a função send_batch_emails(…) no seu arquivo main.py depois da função send_single_email(…) e modifique a parte __main__ conforme mostrado abaixo:

                                

                                    ```pythonrndef send_batch_emails(recipients: dict, subject: str, message: str):rn    try:rn        api_key = os.getenv("MAILGUN_API_KEY")  # get API-Key from the `.env` filernrn        to_address = list(recipients.keys())  # get only email addressesrn        recipients_json = json.dumps(recipients)    # for API callrnrn        logging.info(f"Sending email to {len(to_address)} IDs...")rn        resp = requests.post(MAILGUN_API_URL, auth=("api", api_key),rn                             data={"from": FROM_EMAIL_ADDRESS,rn                                   "to": to_address, "subject": subject, "text": message,rn                                   "recipient-variables": recipients_json})rn        if resp.status_code == 200:  # successrn            logging.info(f"Successfully sent email to {len(recipients)} recipients via Mailgun API.")rn        else:   # errorrn            logging.error(f"Could not send emails, reason: {resp.text}")rn    except Exception as ex:rn        logging.exception(f"Mailgun error: {ex}")rnrnif __name__ == "__main__":rn    # send_single_email("Manish <manish@exanple.com>", "Single email test", "Testing Mailgun API for a single email")rn    _recipients = {"manish@example.com": {"name": "Manish", "id": 1},rn                   "jakkie@example.com": {"name": "Jakkie", "id": 2},rn                   "elzet@example.com": {"name": "Elzet", "id": 3}}rnrn    send_batch_emails(_recipients, "Hi, %recipient.name%!", "Testing Mailgun API. This email is sent via Mailgun API.")rn```
                                
                            

Como faço para enviar vários e-mails personalizados? 

O Batch Sending usa um parâmetro especial chamado Variáveis de destinatário, que permite enviar e-mails personalizados a vários destinatários em uma única chamada de API. O uso das Variáveis de destinatário com o envio em lote garante que o Mailgun envie e-mails individuais a cada destinatário no campo “to”. Sem elas, cada destinatário verá os endereços de e-mail de todos os destinatários no campo “to”.

Aqui está um exemplo de variável de destinatário, com endereços de e-mail como chaves e os atributos “name” e “id” correspondentes como valores:

{“manish@example.com”: {“name”: “Manish”, “id”: 1},

“jakkie@example.com”: {“name”: “Jakkie”, “id”: 2},

“elzet@example.com”: {“name”: “Elzet”, “id”: 3}}

A função send_batch_emails(…) tem três parâmetros: recipients, subject e message. Note que recipients é um objeto de dicionário que representa a variável de destinatário discutida acima.

O código extrai primeiro os endereços de e-mail desse dicionário usando to_address = list(recipients.keys()) e, em seguida, converte o dicionário para JSON para uso na API com a chamada recipients_json = json.dumps(recipients).

A variável recipients_json é passada na chamada de API para o campo recipient-variables, que é usado para personalizar o assunto e o conteúdo do e-mail. O assunto é especificado da seguinte forma:

“Olá, %recipient.name%!”

A API do Mailgun substitui de forma correta o nome de cada destinatário a partir do JSON ao enviar e-mails com %recipient.name%. Assim, no exemplo acima, Manish, Jakkie e Elzet receberão linhas de assunto personalizadas: “Olá, Manish!” “Olá, Jakkie!” e “Olá, Elzet!”. Da mesma forma, você pode personalizar o conteúdo do e-mail usando qualquer valor %recipient.KEY-NAME%.

O restante do código send_batch_emails(…) é semelhante ao da função send_single_email(…), com a diferença de que ele envia vários destinatários de e-mail em uma única chamada de API.

Ao executar este script, você verá o seguinte:

Python script running in terminal
Lembre-se: o número máximo de destinatários permitidos em uma única chamada de API para envio em lote do Mailgun é mil. Você pode descobrir mais sobre a API do Batch Sending aqui.

Aqui está um exemplo de como esse e-mail vai aparecer na caixa de entrada do destinatário:

Email sent using Mailgun API

Recursos adicionais da API de e-mail do Mailgun

A API do Mailgun oferece vários recursos adicionais para facilitar a sua vida.

Envio de e-mails em HTML com anexos

A API do Mailgun permite enviar e-mails com anexos, independentemente de ser com conteúdo em texto ou HTML. Você pode usar o mesmo endpoint da API (https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages) com um ‘attachment’ adicional passado ao parâmetro files, conforme mostrado abaixo:

                                

                                    ```pythonrnfiles = {'attachment': open('weekly-report.csv', 'rb')}     # file you want to attachrnresp = requests.post(MAILGUN_API_URL, auth=("api", api_key), files=files,rn                     data={"from": FROM_EMAIL_ADDRESS,rn                           "to": to_address, "subject": subject, "text": message})rn```
                                
                            

Entrega e rastreamento de e-mails

O Mailgun fornece rastreamento detalhado de e-mails, incluindo quando os e-mails são entregues ou abertos, links são clicados, e-mails sofrem devolução, ocorre o cancelamento de inscrição ou os e-mails são marcados como spam. Esses dados são disponibilizados pelo painel de controle no painel e por meio da API.

O Mailgun também salva os e-mails permanentemente se eles não puderem ser entregues (devolução definitiva) ou se algum destinatário cancelar a inscrição ou marcar o e-mail como spam. Nesses casos, o Mailgun não tentará enviar e-mails para esses destinatários novamente.

Modelos de e-mail

A API do Mailgun permite criar modelos em HTML para padronizar o layout do e-mail e torná-lo mais atraente com layouts predefinidos e conteúdo padrão.

Você pode encontrar os modelos na barra lateral esquerda, no menu de envio.

Teste de e-mail 

O Mailgun também fornece ferramentas de teste de e-mail para ajudar a garantir que as suas mensagens fiquem com a aparência e tenham o desempenho esperados. Com Inspecionar, você pode verificar automaticamente problemas como links corrompidos, imagens ausentes ou gatilhos de spam. A Pré-visualização de e-mail permite ver como o e-mail será renderizado em diferentes clientes e dispositivos, ao passo que Acessibilidade de e-mail o teste ajuda a confirmar que o seu conteúdo está em conformidade com as normas de acessibilidade. Você pode saber mais sobre o software de teste de e-mail do Mailgun e integrar essas verificações ao seu fluxo de trabalho na criação de e-mails com a API. 

Bibliotecas alternativas de e-mail em Python 

Antes de procurar uma API de e-mail dedicada, vale a pena entender as ferramentas nativas que o Python oferece para enviar e-mails, junto com algumas opções mais leves de terceiros. 

O Python inclui dois módulos principais para e-mail com base em SMTP: smtplib e email.  

smtplib 

O módulo smtplib gerencia as sessões de SMTP e permite conectar a um servidor SMTP usando SMTP_SSL() para TLS implícito (geralmente porta 465) ou SMTP() com starttls() para TLS oportunista (normalmente porta 587). A autenticação é processada com um nome de usuário e senha padrão. 

O pacote email é responsável pela construção da mensagem. EmailMessage oferece uma API moderna de alto nível, enquanto MIMEText e MIMEMultipart têm suporte a texto sem formatação, HTML e payloads de várias partes. 

Este código compila um e-mail simples e o envia com segurança por um servidor SMTP usando Python:

                                

                                    from email.message import EmailMessage 
import smtplib 
 
msg = EmailMessage() 
msg["From"] = "you@example.com" 
msg["To"] = "friend@example.com" 
msg["Subject"] = "Hello" 
msg.set_content("Sent with Python!") 
 
with smtplib.SMTP("smtp.example.com", 587) as smtp: 
    smtp.starttls() 
    smtp.login("username", "password") 
    smtp.send_message(msg) 
                                
                            

Yagmail 

Várias bibliotecas de terceiros reduzem ainda mais o código boilerplate. O Yagmail oferece uma abstração voltada ao Gmail para o envio de mensagens e anexos com o mínimo de configuração. O python-emails adiciona recursos de alto nível, como renderização de modelos, composição estruturada de mensagens e assinatura DKIM. 

Como regra geral, evite inserir credenciais no código. Use o módulo getpass() do Python para a inserção segura de senhas, armazene as chaves de API em variáveis de ambiente e sempre transmita e-mails por conexões criptografadas por TLS. 

Autenticação e segurança 

É importante ter algumas práticas recomendadas e dicas em mente ao enviar e-mails de forma programática. 

Tratamento de erros 

Quando o seu script usa uma API de terceiros, como o Mailgun, para enviar e-mails, é preciso tratar erros que possam ocorrer relacionados a falhas de rede ou de API e respostas da API que indiquem erros. Isso garante que o script funcione perfeitamente, seja capaz de detectar problemas como chaves de API ou URLs inválidos e saiba quando os e-mails não foram enviados pela API do Mailgun. Sem o tratamento de erros, seu script pode falhar silenciosamente e resultar em e-mails não entregues. 

Os snippets de código acima preveem o tratamento de erros que possam ocorrer. Em primeiro lugar, eles verificam o código de status da resposta (resp.status_code). Se ele não for bem-sucedido (HTTP 200), o sistema registra a mensagem de erro para que você possa depurar o problema. 

Ambas as funções send_single_email(…) e send_batch_emails(…) também usam um bloco try-except para garantir que as exceções sejam identificadas e registradas de forma correta. 

Entregabilidade de e-mail 

A entregabilidade de e-mail significa garantir que os e-mails cheguem à caixa de entrada do destinatário, e não à pasta de spam. É necessária uma boa reputação do remetente para se alcançar uma alta entregabilidade. Quando falamos sobre a construção de um envio programático, há algumas coisas específicas que podemos analisar para melhorar a sua entregabilidade de e-mail, como a autenticação e a otimização dos e-mails para serem responsivos.  

Autenticar o seu e-mail 

Use SPF, DKIM e DMARC para validar sua identidade como remetente. Envie e-mails apenas a assinantes verificados que optaram por recebê-los, além de remover regularmente assinantes inativos e quem marcar os seus e-mails como spam. 

O DMARC está se tornando um requisito da indústria. Saiba mais sobre por que e como funciona esse padrão de autenticação no nosso artigo sobre a perspectiva do DMARC.

Comece a enviar com o Python3 e a API de e-mail do Mailgun

Neste artigo, você aprendeu a enviar e-mails usando um script em Python e a API do Mailgun. Você também aprendeu sobre recursos do Mailgun como o rastreamento de e-mails e modelos, bem como a importância do tratamento de erros, otimização da entregabilidade e envio de e-mails responsivos.

Geeks de e-mail ajudam outros geeks de e-mail. Você pode encontrar o código discutido neste tutorial no este repositório do GitHub.

Isso foi útil? Se sim, não deixe de assinar a nossa newsletter para receber mais tutoriais, anúncios e insights do setor.

Perguntas frequentes

Use o TLS (STARTTLS) na porta 587 quando quiser fazer upgrade de uma conexão simples para criptografada e o SSL (TLS implícito) na porta 465 quando a conexão já iniciar criptografada. 

  • TLS (STARTTLS): smtplib.SMTP(host, 587) → starttls() → login() → send_message() 
  • SSL (TLS implícito): smtplib.SMTP_SSL(host, 465) → login() → send_message() 

Em ambos os casos, construa a mensagem (por exemplo, com a classe EmailMessage) e a envie com smtp.send_message(msg). Faça a autenticação sempre usando as credenciais de SMTP (nome de usuário/senha) do seu provedor. 

  • EmailMessage: API moderna de alto nível. Melhor opção padrão para a maioria dos casos de uso. Facilita a definição de cabeçalhos, adição de texto sem formatação, inclusão de alternativas em HTML (add_alternative()) e anexos de arquivos com menos repetição de código. 
  • MIMEText: componente de nível inferior para uma única parte de texto (texto sem formatação ou HTML). Útil quando você quer controle explícito sobre apenas uma parte do corpo. 
  • MIMEMultipart: contêiner para a combinação de várias partes de MIME (texto + HTML + anexos). Comum em exemplos antigos; você anexa manualmente arquivos e partes de MIMEText. 

Se estiver começando do zero, prefira EmailMessage, a menos que precise de compatibilidade com padrões de construção MIME antigos. 

Use variáveis de ambiente para as credenciais nos aplicativos implantados (CI/CD, contêineres, servidores) e getpass() para scripts locais interativos. 

As variáveis de ambiente mantêm as informações secretas fora do controle de versão e dos logs. Armazene os valores como senhas e nomes de usuários ou chaves de API na forma SMTP_USER, SMTP_PASS, MAILGUN_API_KEY, etc., e os leia no tempo de execução. 

A função getpass.getpass() solicita de forma segura uma senha sem exibi-la no terminal, sendo muito útil para os scripts rápidos ou testes locais. 

Um padrão comum é: leia as informações do ambiente primeiro e recorra à função getpass() apenas se for necessário. 

O Yagmail é projetado de forma específica para os fluxos de trabalho do Gmail. Portanto, ele reduz o boilerplate SMTP e simplifica as tarefas comuns do Gmail. 

Principais vantagens para quem usa o Gmail: 

  • Menos código: configuração mínima para o envio de mensagens, HTML e anexos. 
  • Ergonomia voltada ao Gmail: API mais amigável para a redação de mensagens e tratamento de anexos. 
  • Iteração mais rápida: ideal para scripts e ferramentas internas onde você quer que o envio de e-mails seja simples sem gerenciar manualmente as partes de MIME. 

Se você estiver enviando apenas pelo Gmail e quiser menos peças móveis que uma construção base de smtplib e MIME, o Yagmail é muitas vezes o caminho mais rápido. 

Com o python-emails, você geralmente: 

  • Renderiza um modelo (frequentemente HTML + texto) usando os auxiliares de modelo da biblioteca (ou passa conteúdos pré-renderizados da sua própria engine de modelo). 
  • Anexa as configurações de DKIM usando a chave privada e o seletor DKIM do seu domínio antes do envio. 

Na prática, você vai: 

  • Criar um objeto de e-mail (subject/from/to) 
  • Fornecer corpos HTML/texto renderizados (e, opcionalmente, variáveis para os modelos) 
  • Configurar a assinatura DKIM usando: 
    • um seletor (por exemplo, mailgun ou padrão) 
    • seu domínio de assinatura 
    • a chave privada DKIM (carregada com segurança de variáveis de ambiente ou de um gerenciador de chaves) 

Para a produção, mantenha a chave privada DKIM fora do código-fonte (variáveis de ambiente ou arquivos secretos montados) e valide a assinatura por meio de verificações dos cabeçalhos das mensagens em uma caixa de correio que mostra os resultados de autenticação e de DKIM-Signature. 

Mantenha-me informado! Receba ótimos recursos em sua caixa de entrada toda semana.
Envie-me a newsletter da Mailjet. Eu concordo expressamente em receber a newsletter e sei que posso cancelar a inscrição facilmente a qualquer momento.

Verifique sua caixa de entrada mensalmente para receber sua newsletter da Mailjet!