
Я использую 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: улучшения в скрипте:
Зачем использовать vim (итвердая копия) когда существуют такие инструменты, как
a2ps
и ?enscript
Оба они имеют множество полезных опций для форматирования текста и вывода PostScript.
Зачем нужен медленный
while read line...
цикл, если можно простоcat ${1:--} > "$infile"
сохранить stdin в файл?Всегда заключайте переменные в двойные кавычки, когда используете их. Например, не используйте
$infile
, вместо этого используйте"$infile"
.Используйте $(...) вместо обратных кавычек.
Скрипт не использует никаких специфичных для bash функций, поэтому используйте
#!/bin/sh
(или, возможно#!/bin/dash
, если он у вас установлен).Если вы используете
mkdir -p
, вам не нужно проверять, существует ли уже каталог. ,mkdir -p
он уже сделает это за вас.gjots2lpr
изgjots2пакет, похоже, делает большую часть или все то, что делает ваш скрипт.Ваш скрипт можно заменить простой оболочкой,
gjots2lpr
которая устанавливает переменные среды, которые он использует для переопределения значений по умолчанию (например, чтобы указать, использовать лиa2ps
илиenscript
, какой просмотрщик ps/pdf использовать, какую команду печати использовать и т. д.).От
gjots2lpr -h
:
Использование: gjots2lpr [-pt ] [ имя_файла ... ]
Печатает текстовый файл - если возможно, используя postscript или PDF и доступные предпросмотрщики и диалог принтера. Он ищет и использует любые утилиты, которые может найти в системе.
Если «имя файла» не указано, то печатается STDIN.