Dependências
Este script em Python tem as seguintes dependências:
imapclient
: biblioteca para acesso à caixa de entrada do Outlook via IMAPemail
: biblioteca padrão do Python para trabalhar com e-mailsos
: biblioteca padrão do Python para interagir com o sistema operacionaldotenv
: biblioteca para carregar variáveis de ambiente a partir de um arquivo.env
bs4
(BeautifulSoup): biblioteca para extrair informações de páginas HTMLurllib
: biblioteca padrão do Python para manipulação de URLs
Variáveis de Ambiente
Este script usa as seguintes variáveis de ambiente:
EMAIL_ADDRESS
: endereço de e-mail da conta do Outlook a ser usadaEMAIL_PASSWORD
: senha da conta do Outlook a ser usadaIMAP_SERVER
: endereço do servidor IMAP do OutlookIMAP_SSL
: indica se deve ser usada uma conexão SSL/TLS para se conectar ao servidor IMAP (True
) ou não (False
).UNSEEN
(opcional): indica se devem ser buscados apenas e-mails não lidos (True
) ou todos os e-mails (False
). Se esta variável não for definida ou se seu valor não for"True"
, serão buscados todos os e-mails.FOLDERS_EMAIL
: lista separada por vírgulas das pastas a serem verificadas em busca de e-mails contendo os links para descadastramento.KEYWORDS_FILE
: caminho para o arquivo de texto contendo as palavras-chave a serem procuradas nos links dos e-mails. Cada palavra-chave deve estar em uma linha separada.
As variáveis de ambiente são carregadas a partir de um arquivo .env
na raiz do projeto.
Funcionamento
Busca de e-mails
O script conecta-se à conta do Outlook e percorre as pastas indicadas em FOLDERS_EMAIL
, buscando e-mails não lidos (se UNSEEN
for "True"
) ou todos os e-mails (caso contrário).
Para cada e-mail encontrado, o script verifica se o conteúdo do e-mail é HTML. Se for, extrai os links contidos no HTML usando a biblioteca BeautifulSoup. Em seguida, verifica se algum desses links contém alguma das palavras-chave presentes no arquivo indicado em KEYWORDS_FILE
.
Caso algum link contenha uma das palavras-chave, o script armazena as informações do e-mail (remetente e assunto) e o link em um dicionário e adiciona esse dicionário a uma lista.
Geração do arquivo HTML
Com a lista de informações dos links de descadastramento em mãos, o script gera um arquivo HTML a partir de um modelo localizado em templates/template.html
.
O modelo HTML contém uma tabela com as informações do remetente, assunto e link de descadastramento. O script preenche as linhas dessa tabela com as informações armazenadas na lista de dicionários.
O arquivo HTML gerado é salvo em unsubscribe_links.html
.
Uso
Antes de executar o script, é necessário definir as variáveis de ambiente no arquivo .env
e criar um arquivo keywords.txt
com as palavras-chave que devem ser procuradas nos links dos e-mails.
O arquivo unsubscribe_links.html
será gerado na mesma pasta do script, contendo a tabela com os links de descadastramento encontrados nos e-mails.
To-do para execução do script:
- Renomear o arquivo
.env.sample
para.env
;
mv .env.sample .env
- Preencher as informações do arquivo
.env
com as credenciais do Outlook e as variáveis de ambiente necessárias;
Exemplo de arquivo .env
:
EMAIL_ADDRESS=johndoe@outlook.com
EMAIL_PASSWORD=mypassword
IMAP_SERVER=outlook.office365.com
IMAP_SSL=True
UNSEEN=True
FOLDERS_EMAIL=Inbox,Sent Items
KEYWORDS_FILE=keywords.txt
- Criar um arquivo
keywords.txt
na raiz do projeto com as palavras-chave a serem procuradas nos links dos e-mails;
Exemplo de arquivo keywords.txt
:
unsubscribe
descadastre-se
cancelar inscrição
descadastrar
descadastrar-se
Update Profile
unsubscribe here
-
Instalar as dependências do projeto usando o comando pip install -r requirements.txt no terminal;
-
Salve o o conteudo abaixo em um arquivo chamado
script.py
import imapclient
import email
import os
from dotenv import load_dotenv
from bs4 import BeautifulSoup
from urllib.parse import urljoin
from email.header import decode_header
# carrega as variáveis de ambiente do arquivo .env
load_dotenv()
# Insira suas credenciais do Outlook aqui
email_address = os.getenv('EMAIL_ADDRESS')
email_password = os.getenv('EMAIL_PASSWORD')
# Leia as palavras-chave de um arquivo de texto
with open('keywords.txt', 'r', encoding='utf-8') as file:
keywords = [line.strip().lower() for line in file]
unseen_only = os.getenv('UNSEEN')
if unseen_only is None or unseen_only.lower() == 'true':
search_criteria = ['UNSEEN']
else:
search_criteria = ['ALL']
# Conectar à caixa de entrada do Outlook
imap_server = os.getenv('IMAP_SERVER')
imap_ssl = os.getenv('IMAP_SSL')
client = imapclient.IMAPClient(imap_server, ssl=imap_ssl)
client.login(email_address, email_password)
folders = os.getenv('FOLDERS_EMAIL').split(',')
links_info = []
for folder in folders:
# Conectar à pasta atual
client.select_folder(folder, readonly=True)
# Buscar e-mails não lidos
messages = client.search(search_criteria)
# Iterar pelos e-mails
for msg_id in messages:
msg_data = client.fetch(msg_id, ['RFC822'])
msg = email.message_from_bytes(msg_data[msg_id][b'RFC822'])
# Verificar se o e-mail é HTML
if msg.is_multipart():
for part in msg.walk():
if part.get_content_type() == 'text/html':
html_content = part.get_payload(decode=True)
break
else:
if msg.get_content_type() == 'text/html':
html_content = msg.get_payload(decode=True)
else:
continue
# Extrair links usando BeautifulSoup
soup = BeautifulSoup(html_content, 'html.parser')
for link in soup.find_all('a', href=True):
href = link['href']
text = link.text.lower()
# Verificar se alguma das palavras-chave está presente no texto do link
if any(keyword in text for keyword in keywords):
# Evitar links repetidos
if href not in [info['link'] for info in links_info]:
# Decodificar o campo "From"
decoded_from = decode_header(msg['From'])
from_email = ''.join([str(part, encoding or 'utf-8') if isinstance(part, bytes) else part for part, encoding in decoded_from])
# Decodificar o campo "Subject"
decoded_subject = decode_header(msg['Subject'])
#subject = ''.join([str(part, encoding or 'utf-8') if isinstance(part, bytes) else part for part, encoding in decoded_subject])
subject = ''.join([str(part, encoding or 'utf-8') if isinstance(part, bytes) else part for part, encoding in decoded_subject if encoding != 'unknown-8bit'])
# Armazenar informações em um dicionário
link_info = {'from': from_email, 'subject': subject, 'link': href}
links_info.append(link_info)
# print(f'Link encontrado: {href}')
# Encerrar a conexão com o servidor de e-mail
client.logout()
# Gerar conteúdo HTML
template_path = os.path.join(os.path.dirname(__file__), 'templates', 'template.html')
with open(template_path, 'r') as f:
html_template = f.read()
# Gerar linhas da tabela
table_rows = ''
for info in links_info:
row = f'<tr><td>{info["from"]}</td><td>{info["subject"]}</td><td><a href="{info["link"]}">Clique aqui para descadastrar</a></td></tr>'
table_rows += row
# Combinar modelo HTML e linhas da tabela
html_content = html_template.format(table_rows=table_rows)
# Salvar conteúdo HTML em um arquivo
with open('unsubscribe_links.html', 'w', encoding='utf-8') as file:
file.write(html_content)
print('Arquivo HTML gerado: unsubscribe_links.html')
-
Executar o script usando o comando python unsubscribe_links.py no terminal;
-
Verificar se o arquivo unsubscribe_links.html foi gerado com sucesso na raiz do projeto.