(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como validar e limpar emails em Python para dados: passo a passo

João Barros 22 de August de 2026 4 min de leitura

Aprender a validar e limpar emails em Python para dados é útil para melhorar a qualidade de bases de dados, reduzir falhas no envio de notificações e garantir melhor correspondência entre registos. Este tutorial mostra como detetar formatos inválidos, normalizar domínios comuns e eliminar duplicados de forma prática.

Pré-requisitos

  • Python 3.8+ instalado.
  • Bibliotecas: pandas, email-validator (instalação via pip).
  • Editor de texto ou Jupyter Notebook.

Passo 1: Instalar dependências

Instale as bibliotecas necessárias. A biblioteca email-validator faz a validação sintáctica e algumas correcções básicas; pandas facilita a manipulação de dados.

pip install pandas email-validator

Passo 2: Carregar dados de exemplo

Crie um DataFrame simples com emails que contenham erros comuns: espaços, maiúsculas, pontos duplicados, domínios com typos e entradas vazias.

import pandas as pd

df = pd.DataFrame({
    'id': [1,2,3,4,5,6],
    'email': [
        'Joao.Silva@Exemplo.COM ',
        'maria..souza@@gmail.com',
        'ana@gnail.con',
        '  ',
        'pedro@exemplo.com',
        'PEDRO@Exemplo.com'
    ]
})
print(df)

Passo 3: Normalizar strings básicas

Remova espaços em branco à volta, converta para minúsculas e reduza pontos duplicados na parte local do email. Isto reduz diferenças triviais entre endereços.

def normalize_basic(email):
    if not isinstance(email, str):
        return ''
    e = email.strip().lower()
    # reduzir pontos duplicados na parte antes do @
    if '@' in e:
        local, domain = e.split('@', 1)
        while '..' in local:
            local = local.replace('..', '.')
        e = f"{local}@{domain}"
    return e

df['email_norm'] = df['email'].apply(normalize_basic)
print(df[['email','email_norm']])

Passo 4: Validar sintaxe com email-validator

Use email-validator para verificar se o formato é válido e receber recomendações. A função abaixo retorna um estado e a versão normalizada pelo validador quando possível.

from email_validator import validate_email, EmailNotValidError

def validate_email_safe(email):
    if not email:
        return {'valid': False, 'reason': 'empty', 'email': ''}
    try:
        v = validate_email(email, check_deliverability=False)
        return {'valid': True, 'reason': '', 'email': v.email}
    except EmailNotValidError as e:
        return {'valid': False, 'reason': str(e), 'email': ''}

res = df['email_norm'].apply(validate_email_safe)
res_df = pd.json_normalize(res)
df = pd.concat([df, res_df.add_prefix('val_')], axis=1)
print(df[['email_norm','val_valid','val_reason','val_email']])

Passo 5: Corrigir domínios comuns com typos

Muitos erros vêm de domínios escritos incorretamente (ex.: gnail -> gmail). Crie um dicionário de correcções para aplicar após a validação sintáctica.

COMMON_DOMAINS = {
    'gnail.com': 'gmail.com',
    'gnail.con': 'gmail.com',
    'exemplo.com': 'exemplo.com',  # exemplo pretendido
}

def fix_common_domain(email):
    if not email or '@' not in email:
        return email
    local, domain = email.split('@', 1)
    domain_fix = COMMON_DOMAINS.get(domain, domain)
    return f"{local}@{domain_fix}"

# aplicar apenas onde há um email validado em val_email ou tentar usar email_norm
df['email_fixed'] = df['val_email'].where(df['val_email'] != '', df['email_norm']).apply(fix_common_domain)
print(df[['email_norm','val_email','email_fixed']])

Passo 6: Revalidar e marcar inválidos

Revalide os emails corrigidos para separar os que continuam inválidos. Mantenha uma coluna com o estado final: valid/invalid/unknown.

final_res = df['email_fixed'].apply(validate_email_safe)
final_df = pd.json_normalize(final_res)
df = pd.concat([df, final_df.add_prefix('final_')], axis=1)

def status(row):
    if row['final_valid']:
        return 'valid'
    if not row['email_fixed']:
        return 'invalid'
    return 'invalid'

df['status'] = df.apply(status, axis=1)
print(df[['email','email_fixed','final_valid','status']])

Passo 7: Remover duplicados e consolidar

Ao normalizar e corrigir, é comum surgir duplicados (ex.: pedro@exemplo.com e PEDRO@Exemplo.com). Use pandas para deduplicar mantendo o primeiro registo ou agregando IDs.

# criar chave para deduplicar
clean = df[df['status']=='valid'].copy()
clean['email_canonical'] = clean['email_fixed']
# manter o primeiro id por email
clean_dedup = clean.drop_duplicates(subset=['email_canonical'], keep='first')
print(clean_dedup[['id','email','email_canonical']])

Verificar o resultado

Confirme que os emails válidos estão normalizados, inválidos identificados e duplicados removidos. Verifique números: total original, válidos finais, inválidos e duplicados removidos.

total = len(df)
validos = df['status'].eq('valid').sum()
invalidos = df['status'].eq('invalid').sum()
deduped = len(clean_dedup)
print(f"Total: {total}, Válidos: {validos}, Inválidos: {invalidos}, Após deduplicação: {deduped}")

Conclusão

Agora tem um processo simples para normalizar, validar e limpar emails em Python para dados, incluindo correcções de domínios e deduplicação. Próximos passos: integrar este pipeline num ETL, usar check_deliverability=True com cuidado ou enriquecer com validação SMTP. Dica: mantenha um registo das correcções para auditar alterações nos emails.