Boas Pessoal!

Nesta semana tive uma necessidade inusitada: precisava ler 1000 e-mails e pegar informações específicas em cada um. Como não estava afim de perder um dia inteiro nisso, resolvi usar o Python para me ajudar a resolver este problema.

O contexto

Precisava ler dentre 1000 e-mails do Gmail, quais tinham um determinado texto, até aqui, o próprio Gmail resolvia, mas, eu ainda precisava extrair 3 informações específicas do corpo de cada um destes e-mails e após isto, atribuir um label específico para facilitar futuras buscas.

Mão na massa

Utilizamos o módulo imaplib para conectar no Gmail via SSL e o módulo email para fazer o parser do e-mail.

import imaplib
import email

Primeiro configuramos as constantes com os dados de acesso a conta. Para leitura do Gmail, utilizamos o servidor imap.gmail.com. Caso você utilize autenticação em 2 etapas, configure uma “senha de app” no Gmail e utilize-a na constante FROM_PWD, caso contrário, terá falhas na autenticação.

FROM_EMAIL = "<seuemail>@gmail.com"  # substitua <seuemail> pelo seu email.
FROM_PWD = "<suasenha>"  # substitua <suasenha> pela sua senha
SMTP_SERVER = "imap.gmail.com"  # padrão
SMTP_PORT = 993  # padrão

Abrimos a conexão com o servidor e efetuamos o login.

mail = imaplib.IMAP4_SSL(SMTP_SERVER)
mail.login(FROM_EMAIL, FROM_PWD)

Neste ponto selecionamos a caixa de e-mail que queremos fazer a leitura, no meu caso, utilizei “inbox” para leitura dos e-mails. Como também vamos atribuir um label aos e-mails “processados”, passamos o parâmetro readonly=False.

mail.select('inbox', readonly=False)

Agora filtramos os e-mails pelo assunto específico, utilizando o critério SUBJECT. Veja a RFC 2060 para saber sobre outros critérios de busca, como recent, before, cc, etc.

type_mail, data = mail.search(None, 'SUBJECT ASSUNTO-ESPECÍFICO')
Desta forma, temos uma lista com os IDs dos e-mails.

Pegamos o primeiro e o último ID para iterarmos em cada um deles utilizando range().

mail_ids = data[0]

id_list = mail_ids.split()
first_email_id = int(id_list[0])
latest_email_id = int(id_list[-1])

for i in range(latest_email_id, first_email_id, -1):

Para obter os detalhes de cada e-mail, usamos mail.fetch com o protocolo RFC822.

typ, data = mail.fetch(str.encode(str(i)), '(RFC822)')

Onde i é o ID de cada e-mail que estamos iterando.

E obtemos os detalhes do e-mail como assunto e remetente.

msg = email.message_from_string(response_part[1].decode('utf-8'))
email_subject = msg['subject']
email_from = msg['from']

Para obter as informações específicas do corpo do e-mail, convertemos para string.

mail_str = str(msg)

Então pegamos as informações específicas, utilizando find e slice. Talvez usar o Beautiful Soup tornaria o parser menos verboso.

# INFORMAÇÃO DE DETALHE
detail_pos_ini = mail_str.find('class="luceeH0">Detail</td>')
detail_pos_inter = mail_str.find('<td class="luceeN1">', detail_pos_ini)
detail_pos_fim = mail_str.find('</td>', detail_pos_inter)
detail_str = mail_str[detail_pos_inter + 20:detail_pos_fim]

# SQL EVENTO
sql_pos_ini = mail_str.find('<td class="luceeH0">SQL</td>')
sql_pos_inter = mail_str.find('<td class="luceeN1">', sql_pos_ini)
sql_pos_fim = mail_str.find('</td>', sql_pos_inter)
sql_str = mail_str[sql_pos_inter + 20:sql_pos_fim]

# DATA/HORA EVENTO
datetime_error_pos_ini = mail_str.find('<h2>{ts ')
datetime_error_pos_fim = mail_str.find('</h2>', datetime_error_pos_ini)
datetime_error = mail_str[datetime_error_pos_ini + 4:datetime_error_pos_fim]

Para a necessidade, fizemos prints gerando um arquivo com a saída da execução do script Python.

print('DATA/HORA: ' + datetime_error + '\n')
print('EVENTO: ' + detail_str.replace('\n', ' ') + '\n')
print('SQL: \n' + sql_str + '\n')

E por fim, adicionamos um label ao e-mail que acabamos de iterar usando mail.store.

labeled = mail.store(str.encode(str(i)), '+X-GM-LABELS', 'seu_label')

Caso queira remover o label, substitua o sinal ‘+’ por ‘-‘.`

Após iterar a lista de e-mails, efetuamos o logout no servidor.

mail.logout()

É isto.

O arquivo completo deste post você encontra no meu Github.

E você, já precisou conectar no servidor de e-mail com Python? Gostaria de acrescentar, corrigir ou sugerir algo? Comente a vontade!

Este post foi baseado neste How to Read Email From Gmail Using Python.

Gde. abraço!

Ed