Imprimindo mensagens de e-mail do mutt – como evitar quebra de linha?

Imprimindo mensagens de e-mail do mutt – como evitar quebra de linha?

Eu uso o mutt como cliente de e-mail e recentemente decidi consertar minha configuração de impressão de e-mail.

Eu conheço o Muttprint, mas decidi não usá-lo. Eu descobri o seguinte.

Em .muttrc, eu tenho:

set print_command="grep -v X-Spam-Status | $HOME/bin/mutt_print.sh"

O ~/bin/mutt_print.shscript, que adaptei de coisas que encontrei na net, é este:

#!/bin/bash

PDIR="$HOME/tmp/mutt_print" 
OPEN_PDF=zathura

# create temp dir if it does not exist
if [ ! -d "$PDIR" ]; then
    mkdir -p "$PDIR" 2>/dev/null
    if [ $? -ne 0 ]; then
        echo "Unable to make directory '$PDIR'" 1>&2
        exit 2
    fi
fi

infile="`mktemp $PDIR/mutt_XXXXXXXX.txt`"
tmpfile="`mktemp $PDIR/mutt_XXXXXXXX.ps`"
outfile="`mktemp $PDIR/mutt_XXXXXXXX.pdf`"

echo "infile = $infile"
echo "tmpfile = $tmpfile"
echo "outfile = $outfile"

while read line
do
  echo "$line" >> $infile
done < "${1:-/dev/stdin}"

echo "running vim $infile -c \"hardcopy > $outfile | q\""
vim $infile -c "hardcopy > $tmpfile | q"
echo "running ps2pdf $tmpfile $outfile"
ps2pdf $tmpfile $outfile

read
$OPEN_PDF $outfile >/dev/null 2>&1 &
sleep 1
rm $infile $tmpfile $outfile

Então, quando decido imprimir uma mensagem, Mutt a abre com o Zathura e posso imprimi-la ou salvar o PDF - esta é a configuração que desejo.

Porém, percebi que embora eu grepremovesse a X-Spam-Statuslinha, nem sempre funciona: às vezes o like parece quebrado antes de ser enviado para o comando de impressão, e parte dele é exibido no PDF:

Date: Wed, 11 May 2016 21:17:14 −0300
From: John Doe <[email protected]>
To: my-email@here
Subject: Re: blah
tests=FREEMAIL_FROM,HTML_MESSAGE,RDNS_NONE,T_DKIM_INVALID

A X-Spam-Statuslinha da mensagem original era

X-Spam-Status: No, hits=2.4 required=8.0 tests=FREEMAIL_FROM,HTML_MESSAGE,RDNS_NONE,T_DKIM_INVALID

que está quebrado entre required=8.0e tests....

Então - como posso evitar a quebra dessa linha?

(Também aceito sugestões de melhorias no roteiro)

Responder1

Parece que essa X-Spam-Statuslinha é um cabeçalho RFC822 'continuado' que abrange várias linhas.

Um cabeçalho começa com espaços não em branco no primeiro caractere de uma linha. Uma linha não em branco com espaço em branco no início é uma continuação da linha anterior e uma linha em branco termina os cabeçalhos.

Se você deseja filtrar um cabeçalho específico, precisará de algo mais compatível com RFC822 do que grep. Talvez uma coisa perlou awkoutra.

Você pode até fazer algo sobre isso

while read line
do
  echo "$line" >> $infile
done < "${1:-/dev/stdin}"

como não fazer eco de uma linha que começa com a X-Spam-Status(e definir um sinalizador) e, em seguida, pular as linhas 'continuadas' até atingir um novo cabeçalho (e limpar o sinalizador).

De qualquer forma, é necessário que o programa conheça como os cabeçalhos RFC822 são formatados.

Talvez você precise se perguntar se você realmente se importa tanto com aquele cabeçalho em sua impressão

Ainda assim, um filtro não é tão difícil

#!/user/bin/perl

my $skip=0;

# First do the headers
while(<STDIN>)
{
        #Test for end of headers
        if(/^\s*$/)
        {
                #copy the header ending blank
                printf $_;

                #exit the while loop
                last;
        }

        #Starts with non whitespace, new header
        $skip = 0 if /^\S/;

        #skip stuff if its the header we don't want
        $skip = 1 if /^X-Spam-Status/i;

        #copy lines if we're not skipping
        print $_ if !$skip;
}

# now the rest of the file
while(<STDIN>)
{
        #copy lines
        print $_;
}

Responder2

Como diz @infixed, o cabeçalho X-Spam-Status continua em várias linhas.

Se você tiver procmailinstalado, poderá usar seu formailutilitário para concatenar cabeçalhos continuados.

De man formail:

-c Concatena campos continuados no cabeçalho. Pode ser conveniente ao pós-processar mensagens com utilitários de texto padrão (orientados a linhas).

Por exemplo:

set print_command="formail -c | grep -v X-Spam-Status: | $HOME/bin/mutt_print.sh"

Melhor ainda, você pode usar formail -Ipara remover um cabeçalho, sem a necessidade de grep -v:

set print_command="formail -I X-Spam-Status | $HOME/bin/mutt_print.sh"

-I campo de cabeçalho

O mesmo que -i, exceto que quaisquer campos semelhantes existentes são simplesmente removidos. Se headerfield consistir apenas em um nome de campo, ele efetivamente excluirá o campo.


RE: melhorias no script:

  1. Por que usar o vim (ecópia impressa) quando as ferramentas gostam a2pse enscriptexistem?

    Ambos têm todos os tipos de opções úteis para formatar texto e saída postscript.

  2. Por que o loop lento while read line...quando você poderia usar apenas cat ${1:--} > "$infile"para salvar o stdin em um arquivo?

  3. Sempre coloque aspas duplas em suas variáveis ​​ao usá-las. por exemplo, não use $infile, use "$infile"em vez disso.

  4. Use $(...) em vez de crases.

  5. O script não usa nenhum recurso específico do bash, então use #!/bin/sh(ou talvez #!/bin/dashse você o tiver instalado).

  6. Se estiver usando mkdir -p, não será necessário testar se o diretório já existe. mkdir -pjá faz isso por você.

  7. gjots2lprdegjots2package parece fazer a maior parte ou tudo o que o seu script faz.

    Seu script pode ser substituído por um wrapper simples gjots2lprque define as variáveis ​​de ambiente usadas para substituir os padrões (por exemplo, para informar se deve usar a2psor enscript, qual visualizador ps/pdf usar, qual comando de impressão usar, etc.).

    De gjots2lpr -h:

Uso: gjots2lpr [-pt ] [ nome do arquivo ... ]

Imprime um arquivo de texto - se possível usando postscript ou PDF e pré-visualizadores e caixas de diálogo da impressora disponíveis. Ele procura e usa todos os utilitários que encontrar no sistema.

Se 'nome do arquivo' não for fornecido, STDIN será impresso.

informação relacionada