Como enviar emails com Python

Fala Pythonistas! Tudo certo!?

Hoje, vamos aprender a utilizar a biblioteca smtplib do Python para utilização de um servidor SMTP e envio de emails com arquivos, anexos e até emails mais elaborados com HTML.

Bom, você sabe como funciona o SMTP? Caso não, o SMTP é um protocolo de rede que faz transferência de emails, esse protocolo também define as informações que vão ser inseridas na mensagem como arquivos, imagens, links e entre outras informações.

No protocolo, também pode ser definido o "caminho" que o email deve percorrer para chegar ao destinatário como o host de emails do google por exemplo.

No dia a dia, SSL e outros métodos são utilizados para garantir a integridade e segurança do envio.


E aí? Vamos pro código?

Primeiramente, vamos "Setar" o ambiente para criar o server SMTP.

No início do seu arquivo Python, importe essas bibliotecas para começar usar as ferramentas do servidor:

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

Após importar todas as bibliotecas, crie as variáveis com as configurações de host, porta, usuário e senha:

host = 'smtp.gmail.com'
port = 25
user = '<Usuário (Email)>'
password = '<Senha (Email)>'

Neste caso, vamos estar usando o host do google (Gmail) como o provedor de envios, coloque o seu email no user e sua senha no password para terminarmos a configuração inicial do SMTP.

A porta que estamos usando é a 25, a padrão do SMTP, caso queira utilizar uma porta com protocolos de segurança, pesquise sobre as portas 587, 465 e entre outras...


Com a configuração feita, podemos inicializar a classe SMTP e realizar o login na conta adicionada:

server = smtplib.SMTP(host, port)
server.login(user, password)

Agora vamos usar o MIMEMultipart, MIMEText e MIMEBase para definir as informações do corpo do email, usando o mesmo user do login, fazemos o seguinte código:

email_body = MIMEMultipart()
email_body['From'] = user
email_body['To'] = '<EMAIL_DE_DESTINO>'
email_body['Subject'] = '<ASSUNTO_DA_MENSAGEM>'

Caso queira colocar mais de um email, basta colocar os emails em forma de uma lista de strings e utilizar o método join() para converter os elementos da lista em uma string separada por vírgula:

emails = ['1234@gmail.com', 'abc123@gmail.com']
email_body['To'] = ','.join(emails)

Para adicionar texto no email você pode utilizar o MIMEText com o texto a ser inserido, o subtype e o charset desejado:

message = 'Fala pessoal do post!\nEsse é um teste de email.'
email_body.attach(MIMEText(_text=message, _subtype='plain', _charset='UTF-8'))

Para adicionar HTML no corpo do email basta adicionar a mensagem em html e colocar o subtype como 'html'.

html = '''
<html>
  <head></head>
  <body>
    <h3>Fala Pythonista! Tudo Certo?</h3>    
    <p>
        Já viu o meu post sobre dados aleatórios? 
        <a href="https://gustavomenezes.hashnode.dev/gerando-dados-aleatorios-com-python">
            Post sobre dados aleatórios
        </a> 
    </p>
  </body>
</html>
'''
email_body.attach(MIMEText(_text=html, _subtype='html'))

Para adicionar arquivos em anexo no corpo no email, primeiramente, defina o caminho e o nome do arquivo:

filename = '<NOME_DO_ARQUIVO_COM_EXTENSÃO>'
filepath = '<CAMINHO_ATÉ_O_ARQUIVO>'

Voce pode usar o modulo "os" do Python para pegar o diretório absoluto do arquivo, mais especificamente o método abspath()

Leia o arquivo em formato binário, crie o objeto MIMEBase para a leitura do arquivo, faça leitura dos binários, adicione o content-type, header e feche o arquivo:

attachment = open(filepath, 'rb')
file = MIMEBase(_maintype='application', _subtype='octet-stream')
file.set_payload(attachment.read())
encoders.encode_base64(file)
file.add_header('Content-Disposition', f'attachment; filename= {filename}')
attachment.close()

Fazer o encode para base64 garante parcialmente a integridade e a segurança do arquivo a ser enviado.


E finalmente, para enviar o email, basta adicionar o remetente, destinatário e o corpo da mensagem em formato de string e feche o servidor para não ficar usando processamento de desnecessário:

server.sendmail(email_body['From'], email_body['To'], email_body.as_string())
server.quit()

O resultado final irá se parecer com isso:

teste_email.PNG


Obs: Caso tenha problemas em configurar o seu email para testes, utilize este link para ajuda com a conta do google.

Script Completo:

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


host = 'smtp.gmail.com'
port = 25
user = '<EMAIL>'
password = '<SENHA_DO_EMAIL>'

server = smtplib.SMTP(host, port)
server.ehlo()
server.starttls()
server.login(user, password)

message = 'Fala pessoal do post!\nEsse é um teste de email.'

html = '''
<html>
  <head></head>
  <body>
    <h3>Fala Pythonista! Tudo Certo?</h3>    
    <p>
        Já viu o meu post sobre dados aleatórios? 
        <a href="https://gustavomenezes.hashnode.dev/gerando-dados-aleatorios-com-python">
            Post sobre dados aleatórios
        </a> 
    </p>
  </body>
</html>
'''

email_body = MIMEMultipart()
email_body['From'] = user
email_body['To'] = '<DESTINATÁRIO>'
email_body['Subject'] = '<ASSUNTO_DO_EMAIL>'

filename = '<NOME_DO_ARQUIVO>'
filepath = os.path.abspath(filename)

attachment = open(filepath, 'rb')
file = MIMEBase(_maintype='application', _subtype='octet-stream')
file.set_payload(attachment.read())
encoders.encode_base64(file)
file.add_header('Content-Disposition', f'attachment; filename= {filename}')
attachment.close()

email_body.attach(file)
email_body.attach(MIMEText(_text=message, _subtype='plain', _charset='UTF-8'))
email_body.attach(MIMEText(_text=html, _subtype='html'))

server.sendmail(
    email_body['From'],
    email_body['To'],
    email_body.as_string()
)

server.quit()

Até a próxima :)