mailbox no Python: caixas de e-mail

Publicado em: 12/08/2026
Tempo de leitura: 6 minutos
Documento e caixa de entrada representando caixas de e-mail com mailbox no Python

O módulo mailbox da biblioteca padrão manipula caixas de e-mail armazenadas em disco. Ele suporta formatos como Maildir, mbox, MH, Babyl e MMDF e fornece uma interface semelhante a um dicionário, na qual chaves identificam mensagens. O módulo é útil em migrações, backups, indexadores, filtros locais, ferramentas forenses e integrações com clientes de correio.

Ele não baixa mensagens de servidores IMAP nem envia e-mails por SMTP. Sua responsabilidade é ler e modificar estruturas locais de mailbox. Para interpretar cabeçalhos, MIME, anexos e conteúdo, combine-o com o pacote email.

Escolher o formato correto

Maildir guarda cada mensagem em um arquivo separado dentro de diretórios tmp, new e cur. Esse desenho tolera melhor acesso por processos diferentes e normalmente não requer locking global. Já mbox e MMDF armazenam várias mensagens em um único arquivo e exigem cuidado especial com concorrência.

Para novos sistemas que precisam de escrita concorrente, Maildir costuma ser a opção mais segura. Para interoperar com um arquivo existente, mantenha o formato original e respeite sua política de locking.

Abrir um Maildir

import mailbox

caixa = mailbox.Maildir("correio", create=True)
print(len(caixa))

for mensagem in caixa:
    print(mensagem.get("Subject"))

A iteração padrão devolve representações de mensagens, não chaves. Cada acesso produz um novo objeto baseado no estado atual da caixa. Alterar esse objeto em memória não atualiza a mailbox até que você o atribua novamente à chave.

Iterar por chaves

for chave in caixa.iterkeys():
    mensagem = caixa.get_message(chave)
    print(chave, mensagem.get("From"))

As chaves só têm significado para aquela instância e formato. Operações como MH.pack() podem invalidar chaves existentes. Não trate uma chave como identificador global permanente.

Adicionar uma mensagem

from email.message import EmailMessage

mensagem = EmailMessage()
mensagem["From"] = "alice@example.com"
mensagem["To"] = "bob@example.com"
mensagem["Subject"] = "Relatório"
mensagem.set_content("Conteúdo do relatório")

chave = caixa.add(mensagem)
print(chave)

add() aceita objetos Message, mensagens do pacote email, strings, bytes e arquivos binários. O conteúdo é copiado; a mailbox não mantém uma referência viva ao objeto fornecido.

Substituir uma mensagem

mensagem = caixa.get_message(chave)
mensagem.replace_header("Subject", "Relatório revisado")
caixa[chave] = mensagem

Em formatos específicos, alguns metadados como flags e estado podem ser preservados ao substituir. Leia as regras da subclasse usada.

Remover com remove, del ou discard

caixa.remove(chave)
# del caixa[chave]
# caixa.discard(chave)

remove() e del geram KeyError se a chave não existe. discard() ignora o caso, o que pode ser melhor quando outro processo modifica a caixa.

Locking em formatos de arquivo único

Ao modificar mbox, MMDF ou outros formatos com locking, adquira o lock antes de ler e alterar e libere no final.

import mailbox

caixa = mailbox.mbox("arquivo.mbox")
caixa.lock()
try:
    for chave, mensagem in caixa.iteritems():
        if mensagem.get("Subject") == "Remover":
            caixa.discard(chave)
    caixa.flush()
finally:
    caixa.unlock()
    caixa.close()

Sem locking, duas aplicações podem sobrescrever mudanças, perder mensagens ou corromper o arquivo inteiro. ExternalClashError indica conflito ao adquirir o lock.

Maildir e concorrência

Maildir não usa locking global porque cada mensagem é um arquivo. Mesmo assim, a documentação alerta que métodos de escrita podem gerar colisões em múltiplas threads se elas manipularem a mesma mailbox sem coordenação.

Use um lock da aplicação para writers dentro do mesmo processo e teste o comportamento no sistema de arquivos real, especialmente em volumes de rede.

Flags do Maildir

Python 3.13 adicionou métodos rápidos para consultar e modificar flags sem abrir a mensagem inteira.

flags = caixa.get_flags(chave)
caixa.add_flag(chave, "S")
caixa.remove_flag(chave, "F")
caixa.set_flags(chave, "RS")

Uma instância MaildirMessage já carregada não é atualizada automaticamente quando as flags são alteradas pela mailbox. Evite misturar os dois caminhos sem recarregar.

Informações do Maildir

get_info() e set_info(), também disponíveis desde Python 3.13, acessam a seção de informações no nome do arquivo. Prefira os métodos de flags quando a intenção for estados padronizados como lida, respondida ou marcada.

Pastas Maildir

print(caixa.list_folders())
arquivados = caixa.add_folder("Arquivados.2026")
subcaixa = caixa.get_folder("Arquivados.2026")

O estilo Courier usa nomes iniciados por ponto no disco e níveis separados por ponto. Pastas não devem conter outras fisicamente; o aninhamento é lógico.

Limpar arquivos temporários

Maildir.clean() remove arquivos em tmp sem acesso recente, conforme a convenção do formato. Execute com cuidado e mantenha backup quando o diretório estiver em armazenamento instável.

Ler como bytes, string ou arquivo

dados = caixa.get_bytes(chave)
texto = caixa.get_string(chave)

with caixa.get_file(chave) as arquivo:
    cabecalho = arquivo.readline()

get_bytes() preserva uma representação binária. get_string() passa pelo pacote email e produz uma representação limpa de 7 bits. Para processamento fiel, prefira bytes e um parser com política explícita.

Factory personalizada

O parâmetro factory recebe um arquivo binário e pode devolver uma representação própria.

from email import policy
from email.parser import BytesParser

def fabrica(arquivo):
    return BytesParser(policy=policy.default).parse(arquivo)

caixa = mailbox.Maildir("correio", factory=fabrica)

Uma factory evita construir objetos específicos da mailbox quando você quer apenas mensagens modernas do pacote email. Ela também pode extrair somente metadados para reduzir memória.

mbox e a linha From

O formato mbox separa mensagens por linhas que começam com From . Corpos que contêm essa sequência no início de linha são escapados na gravação. Variações de mbox não são totalmente compatíveis.

Os métodos get_bytes(), get_file() e get_string() de mbox aceitam o parâmetro from_ para incluir ou remover a linha Unix From.

MH e sequências

MH armazena cada mensagem em arquivo e permite sequências nomeadas.

caixa = mailbox.MH("mh")
sequencias = caixa.get_sequences()
sequencias["importantes"] = ["1", "3"]
caixa.set_sequences(sequencias)

pack() renumera mensagens para eliminar lacunas e invalida chaves já emitidas. Nunca continue usando chaves antigas depois dessa operação.

Migrar entre formatos

origem = mailbox.mbox("origem.mbox")
destino = mailbox.Maildir("destino", create=True)

origem.lock()
try:
    for mensagem in origem:
        destino.add(mensagem)
finally:
    origem.unlock()
    origem.close()
    destino.close()

Antes da migração, conte mensagens, registre hashes, preserve flags quando possível e valide anexos. Faça uma cópia do arquivo de origem e teste a leitura pelo cliente de destino.

Modificar durante a iteração

A iteração da mailbox tem semântica definida: mensagens adicionadas depois da criação do iterador não aparecem, e mensagens removidas antes de serem alcançadas são ignoradas. Ainda assim, concorrência entre processos pode invalidar uma chave.

Segurança de conteúdo

Mensagens podem conter cabeçalhos malformados, MIME profundo, anexos enormes, nomes perigosos e conteúdo HTML ativo. Não execute anexos nem renderize HTML sem sanitização. Defina limites de tamanho, profundidade e quantidade de partes.

Backups e atomicidade

Antes de operações destrutivas em mbox, faça backup e verifique espaço livre. flush() grava alterações pendentes, mas não substitui backup nem transação de alto nível.

Em Maildir, operações individuais são mais isoladas, mas uma migração de milhares de mensagens ainda precisa de checkpoint e capacidade de retomada.

Exemplo de exportação de metadados

import json
import mailbox

caixa = mailbox.Maildir("correio")
registros = []
for chave in caixa.iterkeys():
    msg = caixa.get_message(chave)
    registros.append({
        "key": str(chave),
        "from": msg.get("From"),
        "to": msg.get("To"),
        "subject": msg.get("Subject"),
        "date": msg.get("Date"),
        "flags": msg.get_flags(),
    })

with open("indice.json", "w", encoding="utf-8") as f:
    json.dump(registros, f, ensure_ascii=False, indent=2)

Não trate cabeçalhos como confiáveis. Datas podem ser inválidas e campos podem repetir.

Erros frequentes

  • Modificar mbox sem lock.
  • Esperar que alterar um objeto Message atualize a caixa.
  • Usar chaves como IDs permanentes.
  • Fechar a mailbox enquanto um arquivo retornado ainda está em uso.
  • Confundir mailbox local com IMAP.
  • Ignorar variantes de mbox.
  • Processar anexos sem limites.

Boas práticas

  • Prefira Maildir para escrita concorrente.
  • Use locking nos formatos que exigem.
  • Chame flush() e close().
  • Preserve backups antes de mudanças em lote.
  • Use parsing binário com política explícita.
  • Valide contagem, flags e hashes após migração.
  • Imponha limites ao conteúdo não confiável.

Conteúdos relacionados

Veja quopri, mimetypes, fileinput, filecmp e ExitStack.

Consulte a documentação oficial do mailbox e a documentação do pacote email.

Conclusão

mailbox oferece uma API uniforme para formatos de correio locais muito diferentes. O uso confiável depende de entender locking, cópia de mensagens, semântica das chaves, diferenças de formato e riscos de conteúdo. Para novas caixas concorrentes, Maildir costuma ser a base mais segura.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Editor de texto representando formatação com textwrap no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    textwrap no Python: formate textos

    Aprenda textwrap no Python para quebrar, preencher, encurtar, indentar e remover recuos de textos com controle de largura e espaços.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Pasta e lupa representando filtros de nomes com fnmatch no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    fnmatch no Python: filtre nomes de arquivos

    Aprenda fnmatch no Python para filtrar nomes de arquivos com curingas, controlar maiúsculas, excluir padrões e evitar confundir glob com

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Monitor com dados binários representando arrays numéricos compactos no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    array no Python: números compactos

    Aprenda array no Python para armazenar números compactos, manipular bytes, arquivos binários e buffers com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    10/08/2026
    Círculo cromático representando conversões RGB, HSV e HLS com colorsys no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    colorsys no Python: RGB, HSV e HLS

    Aprenda colorsys no Python para converter cores entre RGB, HSV, HLS e YIQ, gerar paletas e evitar erros com escalas

    Ler mais

    Tempo de leitura: 6 minutos
    09/08/2026
    Ícone de configuração representando arquivos plist com plistlib no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    plistlib no Python: arquivos plist

    Aprenda plistlib no Python para ler e gravar arquivos plist XML e binários, validar dados e integrar configurações Apple com

    Ler mais

    Tempo de leitura: 7 minutos
    08/08/2026
    Cadeado digital representando credenciais por host com netrc no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    netrc no Python: credenciais por host

    Aprenda netrc no Python para ler credenciais por host, validar permissões, tratar erros e integrar clientes de rede com segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    08/08/2026