O parâmetro strict de email.utils.getaddresses ajuda a analisar listas de endereços de e-mail com regras mais rigorosas. Ele é útil quando uma aplicação recebe cabeçalhos como To, Cc ou Reply-To e precisa rejeitar entradas malformadas em vez de tentar corrigi-las silenciosamente. Neste guia, você vai entender quando usar o modo estrito, como validar resultados, quais erros ainda precisam de tratamento adicional e como integrar essa função a sistemas reais.
O que faz getaddresses
getaddresses recebe uma sequência de strings e devolve pares no formato (nome, endereço). A função interpreta nomes de exibição, vírgulas, aspas e outros elementos da sintaxe de cabeçalhos. O uso básico é direto:
from email.utils import getaddresses
cabecalhos = [
'Ana <ana@example.com>, Bruno <bruno@example.com>'
]
for nome, endereco in getaddresses(cabecalhos, strict=True):
print(nome, endereco)
Com strict=True, o parser evita aceitar diversas construções inválidas que versões antigas toleravam. Isso melhora a previsibilidade, principalmente quando os dados vêm de formulários, integrações ou mensagens externas.
Por que o modo estrito importa
Um parser permissivo pode transformar uma entrada ruim em um resultado aparentemente válido. Isso é perigoso porque a aplicação pode enviar mensagens para um destinatário diferente do esperado, registrar dados inconsistentes ou aceitar conteúdo criado para confundir filtros. O modo estrito reduz esse risco ao exigir uma estrutura mais próxima da especificação.
Mesmo assim, getaddresses não substitui uma política completa de validação. Ele analisa a sintaxe do cabeçalho, mas não confirma se o domínio existe, se a caixa postal recebe mensagens ou se o endereço pertence ao usuário. Por isso, combine parsing, validação de domínio, confirmação por e-mail e limites de negócio.
Validando o resultado
Depois do parsing, trate campos vazios e resultados inesperados:
from email.utils import getaddresses
def extrair_destinatarios(valores: list[str]) -> list[str]:
resultado = []
for nome, endereco in getaddresses(valores, strict=True):
endereco = endereco.strip()
if not endereco or '@' not in endereco:
raise ValueError('Endereço inválido')
resultado.append(endereco)
if not resultado:
raise ValueError('Nenhum destinatário válido')
return resultado
Essa verificação é simples, mas deixa clara uma regra importante: nunca confie somente na quantidade de pares devolvidos. Confirme que o endereço não está vazio, aplique seus limites e normalize apenas o necessário.
Não normalize demais
Transformar tudo para minúsculas pode parecer conveniente, mas a parte local de um endereço é tecnicamente sensível a maiúsculas em alguns servidores. Na prática, muitos provedores ignoram essa diferença, porém uma aplicação genérica deve preservar o valor original e usar uma versão normalizada apenas para comparação interna.
Também evite remover caracteres válidos, como sinais de mais, pontos ou sublinhados. Um filtro agressivo pode alterar um endereço correto. Para aprender mais sobre tratamento seguro de strings, veja o conteúdo sobre Python e os guias de Python avançado.
Separando parsing de autorização
Uma boa arquitetura separa três etapas: interpretar o cabeçalho, validar o endereço e decidir se ele pode ser usado. Por exemplo, um sistema corporativo pode aceitar apenas domínios autorizados. Essa regra não pertence ao parser.
DOMINIOS_PERMITIDOS = {'example.com', 'empresa.com.br'}
def dominio_permitido(endereco: str) -> bool:
_, dominio = endereco.rsplit('@', 1)
return dominio.lower() in DOMINIOS_PERMITIDOS
Essa separação facilita testes e reduz erros. O parser cuida da sintaxe; sua aplicação cuida das regras de segurança e negócio.
Tratando entradas vindas da web
Em formulários, limite o tamanho total do campo e a quantidade de endereços antes de processar. Uma lista enorme pode consumir tempo e memória desnecessários. Também registre falhas de parsing sem gravar dados sensíveis completos nos logs.
Quando o sistema envia mensagens, mantenha os destinatários em estruturas separadas para To, Cc e Bcc. Não concatene tudo em uma única string depois da validação. Isso reduz confusões e facilita auditoria.
Exemplo com dataclass
from dataclasses import dataclass
from email.utils import getaddresses
@dataclass(frozen=True)
class Destinatario:
nome: str
endereco: str
def parse_destinatarios(valores: list[str]) -> list[Destinatario]:
itens = []
for nome, endereco in getaddresses(valores, strict=True):
if not endereco or '@' not in endereco:
raise ValueError(f'Entrada inválida: {nome!r}')
itens.append(Destinatario(nome.strip(), endereco.strip()))
return itens
Uma estrutura imutável ajuda a evitar alterações acidentais depois da validação. Esse padrão combina bem com APIs, filas e serviços de envio.
Testes importantes
Crie testes para endereços simples, nomes com espaços, nomes entre aspas, múltiplos destinatários, entradas vazias, vírgulas extras e strings malformadas. Teste também limites de tamanho e duplicatas.
def test_destinatario_valido():
itens = parse_destinatarios(['Ana <ana@example.com>'])
assert itens[0].endereco == 'ana@example.com'
def test_destinatario_invalido():
try:
parse_destinatarios(['entrada sem endereco'])
except ValueError:
pass
else:
raise AssertionError('Era esperado ValueError')
Para aprofundar seus testes, consulte também os artigos de testes e o material sobre automação.
Compatibilidade de versões
Antes de usar o argumento strict, confirme a versão mínima do Python adotada pelo projeto. Bibliotecas distribuídas para ambientes antigos podem precisar de um caminho alternativo. Uma abordagem segura é declarar explicitamente a versão mínima no pyproject.toml e cobrir o comportamento no CI.
Evite capturar TypeError silenciosamente para tentar novamente sem strict, porque isso pode esconder erros reais. Se a compatibilidade for obrigatória, isole a decisão em uma função pequena e documentada.
Segurança e limites
O modo estrito reduz ambiguidades, mas não elimina riscos como injeção de cabeçalhos. Nunca aceite quebras de linha arbitrárias em campos controlados pelo usuário. Remova ou rejeite \r e \n antes de construir cabeçalhos e prefira as classes do pacote email, que aplicam regras próprias.
Também não use endereços analisados como comandos, caminhos ou identificadores sem validação adicional. Trate cada camada conforme seu contexto.
Referências oficiais
A documentação do módulo email.utils descreve o comportamento das funções auxiliares. Para compreender a sintaxe de mensagens, consulte também a RFC 5322.
Conclusão
email.utils.getaddresses(..., strict=True) é uma melhoria importante para aplicações que processam cabeçalhos de e-mail. Use-o para reduzir tolerância a entradas malformadas, mas mantenha validações adicionais, limites, testes e regras de autorização. A combinação de parsing estrito, modelos imutáveis e políticas claras produz sistemas mais seguros e previsíveis.







