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] = mensagemEm 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()eclose(). - 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.







