Печать сообщений электронной почты из Mutt — как избежать переноса строки?

Печать сообщений электронной почты из Mutt — как избежать переноса строки?

Я использую Mutt в качестве почтового клиента и недавно решил исправить настройки печати электронной почты.

Я знаю о Muttprint, но я решил им не пользоваться. Я придумал следующее.

На .muttrc, у меня есть:

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

Сценарий ~/bin/mutt_print.sh, который я адаптировал из материалов, найденных в сети, выглядит следующим образом:

#!/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

Итак, когда я решаю распечатать сообщение, Mutt открывает его с помощью Zathura, и я могу либо распечатать его, либо сохранить в формате PDF — именно такая настройка мне и нужна.

Однако я заметил, что хотя я и grepудалял X-Spam-Statusстроку, это не всегда срабатывало: иногда строка оказывается разорванной до отправки в команду печати, и часть ее отображается в 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

Строка X-Spam-Statusв исходном сообщении была

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

который разрывается между required=8.0и tests....

Итак, как мне избежать разрыва этой линии?

(Я также приветствую любые предложения по улучшению сценария)

решение1

Похоже, что эта X-Spam-Statusстрока — «продолженный» заголовок RFC822, охватывающий несколько строк.

Заголовок начинается с непробельного символа в первом символе строки. Непустая строка с пробелом в начале является продолжением предыдущей строки, а пустая строка завершает заголовки.

Если вы хотите отфильтровать определенный заголовок, вам понадобится что-то более соответствующее RFC822, чем grep. Возможно, что-то вроде perlили awk.

Вы даже можете что-то с этим сделать.

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

например, не выводить строку, начинающуюся с X-Spam-Status(и устанавливать флаг), а затем пропускать «продолжающиеся» строки, пока не встретится новый заголовок (и не сбросить флаг).

В любом случае требуется, чтобы программа знала, как форматируются заголовки RFC822.

Может быть, вам стоит спросить себя, действительно ли вас так волнует заголовок в вашей распечатке?

Но фильтр не так уж и сложен.

#!/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 $_;
}

решение2

Как говорит @infixed, заголовок X-Spam-Status продолжается на нескольких строках.

Если вы procmailустановили эту утилиту, вы можете использовать ее formailдля объединения продолжающихся заголовков.

От man formail:

-c Объединить непрерывные поля в заголовке. Может быть удобно при постобработке почты стандартными (строчно-ориентированными) текстовыми утилитами.

Например:

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

Еще лучше, вы можете использовать formail -Iдля удаления заголовка без необходимости grep -v:

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

-I поле заголовка

То же, что и -i, за исключением того, что любые существующие похожие поля просто удаляются. Если headerfield состоит только из имени поля, он фактически удаляет поле.


RE: улучшения в скрипте:

  1. Зачем использовать vim (итвердая копия) когда существуют такие инструменты, как a2psи ?enscript

    Оба они имеют множество полезных опций для форматирования текста и вывода PostScript.

  2. Зачем нужен медленный while read line...цикл, если можно просто cat ${1:--} > "$infile"сохранить stdin в файл?

  3. Всегда заключайте переменные в двойные кавычки, когда используете их. Например, не используйте $infile, вместо этого используйте "$infile".

  4. Используйте $(...) вместо обратных кавычек.

  5. Скрипт не использует никаких специфичных для bash функций, поэтому используйте #!/bin/sh(или, возможно #!/bin/dash, если он у вас установлен).

  6. Если вы используете mkdir -p, вам не нужно проверять, существует ли уже каталог. , mkdir -pон уже сделает это за вас.

  7. gjots2lprизgjots2пакет, похоже, делает большую часть или все то, что делает ваш скрипт.

    Ваш скрипт можно заменить простой оболочкой, gjots2lprкоторая устанавливает переменные среды, которые он использует для переопределения значений по умолчанию (например, чтобы указать, использовать ли a2psили enscript, какой просмотрщик ps/pdf использовать, какую команду печати использовать и т. д.).

    От gjots2lpr -h:

Использование: gjots2lpr [-pt ] [ имя_файла ... ]

Печатает текстовый файл - если возможно, используя postscript или PDF и доступные предпросмотрщики и диалог принтера. Он ищет и использует любые утилиты, которые может найти в системе.

Если «имя файла» не указано, то печатается STDIN.

Связанный контент