Como dividir caixas de correio existentes com base na data com o procmail

2

Tenho enormes caixas de correio que gostaria de gerenciar com base na idade do conteúdo: backup, arquivamento ou remoção. Eu gostaria de dividir essas caixas de correio ao longo da data de suas mensagens contidas.

Para uma caixa de correio:

${MAILDIR}/${TOPIC}

Aqui está o esquema de uma nova estrutura de diretórios na qual eu gostaria de falar:

${MAILDIR}/${YEAR}/${MONTH}/${TOPIC}

Existe uma maneira de conseguir essa divisão sem muitos comandos bifurcados?

    
por daniel Azuelos 18.03.2015 / 20:04

2 respostas

1

Primeiramente, alguns esclarecimentos. O cabeçalho Date: não é muito confiável, já que o remetente pode configurá-lo para praticamente qualquer coisa. No entanto, as alternativas também não são muito atraentes; alguns clientes de email realmente tentam analisar os cabeçalhos Received: , mas como o conteúdo do cabeçalho não é padronizado corretamente, isso pode falhar. Se você tiver suas mensagens no formato mk de Berkeley, o pseudo-cabeçalho From_ geralmente contém o registro de data e hora da entrega local, mas imagino que existam programas de entrega que também omitam isso (e parece que você não está usando o mbox). / p>

Então, vamos analisar a análise do cabeçalho RFC822 Date: sem bifurcar.

Um enigma adicional é que nem todos os remetentes usam uma data RFC822 válida neste cabeçalho. Supondo que você não esteja classificando o spam, provavelmente é possível identificar um padrão alternativo para o (s) correspondente (s) que fazem isso; Vou simplesmente ignorar essa lata de vermes aqui. (Eu só esbarrei nisso quando lidava com spam, mas parecia ser bastante prevalente nos e-mails do Japão, o IIRC.)

Eu vejo que você não se importa com o dia do mês, mas estou incluindo aqui também, apenas no caso de alguém achar isso útil.

# Poor man's associative array...  Remove leading zeros if desired
# (but then also change the MONTH regex below, as per comment there)
MONTHS='Jan 01
Feb 02
Mar 03
Apr 04
May 05
Jun 06
Jul 07
Aug 08
Sep 09
Oct 10
Nov 11
Dec 12'

:0
* ^Date:[   ]*[A-Z][a-z][a-z], \/[ 0-3][0-9] [A-Z][a-z][a-z] [12][0-9][0-9][0-9]
{
    RDATE=$MATCH
    :0
    * RDATE ?? ^ *\/[1-9][0-9]?
    { DAY=$MATCH }
    :0
    * RDATE ?? () \/[12][0-9][0-9][0-9]
    { YEAR=$MATCH }
    :0
    * RDATE ?? () \/[A-Z][a-z][a-z]
    { MON=$MATCH }
    :0  # Adjust if you don't want leading zeros -- $MON \/[1-9][0-9]?
    * $ MONTHS ?? $MON \/[01][0-9]
    { MONTH=$MATCH }

    :0  # Assume TOPIC is set by caller, or somehow determined above
    $YEAR/$MONTH/$TOPIC
}

Apenas para recapitular as construções usadas acima, o token \/ especial faz com que as correspondências após serem capturadas em MATCH (o Procmail não possui referências anteriores apropriadas) e VAR ?? como o prefixo de uma condição causa a condição a ser aplicada em relação ao valor da variável VAR em vez de contra os cabeçalhos da mensagem. Finalmente, $ é necessário se você quiser que a condição contenha o valor expandido de uma variável (normalmente, $ significa apenas uma nova linha). Ah, e como sempre, o espaço em branco em [ ]* deveria ser uma aba e um espaço.

A receita acima é útil principalmente para analisar mensagens individuais. Se você quiser dividir uma caixa de correio por data, eu realmente não vejo como você poderia evitar a análise de cada mensagem separadamente e, em seguida, arquivar cada uma delas onde ela pertence.

Se você quiser realmente otimizar e ter mensagens de um período de tempo restrito, suponho que você poderia enumerar expressões regulares para cada um dos meses que deseja cobrir, algo como

for month in 2014/11 2014/12 2015/01 2015/02 2015/03; do
    printf ':0\n* ^Date:[ \t]*[A-Z][a-z][a-z], [ 0-3][0-9] %s\n%s/$TOPIC\n' \
        "$(date -d "${month%/*}-${month#*/}-01" +'%b %Y')" "$month"
done >months.rc

mas eu não estou totalmente convencido de que ele realmente irá poupá-lo de qualquer ciclo (meça se você precisar!: -)

    
por 26.03.2015 / 14:34
0

Para conseguir essa tarefa, usei um shell script e um arquivo procmailrc.

O núcleo do script de shell é apenas uma maneira de dividir uma caixa de correio enorme e alimentá-la para o procmail com um arquivo procmailrc ajustado:

$ cat <<eof >splitter.sh
#!/bin/sh

orig_mailbox=$1

formail -s <${orig_mailbox} procmail ${HOME}/src/splitter_procmailrc
eof

E o arquivo procmailrc é baseado em uma única regra que usará date para extrair os campos corretos do cabeçalho Date: (que, esperamos, foi um sistema gerado em um sistema operacional limpo). date também exibirá os campos obrigatórios YYYY/MM com o formato "+%Y/%m" .

cat <<eof >${HOME}/src/splitter_procmailrc

MAILDIR=${HOME}/Mail/tmp
LOGFILE=${HOME}/Mail/tmp/procmail.log

:0 w
* ^Subject: TOPIC
* ^Date: \/.*$
|    (    ;\
          ORIG_MONTH_DIR='date -j -f "%a, %d %b %Y" "${MATCH}" "+%Y/%m"' ;\
          [ -d ${ORIG_MONTH_DIR} ] || mkdir -p ${ORIG_MONTH_DIR} ;\
          cat >>${ORIG_MONTH_DIR}/TOPIC ;\
     )
:0 E
Error
eof

A segunda regra está aqui apenas no caso de eu pegar qualquer erro no primeiro para poder classificar o problema e ajustar o arquivo procmailrc.

    
por 08.05.2015 / 18:49