我使用 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}"
就像不回显以 a 开头的行一样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
存在?两者都有各种有用的选项用于格式化文本和后记输出。
while read line...
当您可以仅使用cat ${1:--} > "$infile"
将标准输入保存到文件时,为什么循环很慢?使用变量时,请始终用双引号引起来。例如不要使用
$infile
,"$infile"
而是使用。使用 $(...) 而不是反引号。
该脚本不使用任何 bash 特定的功能,因此请使用
#!/bin/sh
(或者#!/bin/dash
如果您安装了它)。如果您使用的是
mkdir -p
,则无需测试该目录是否已存在。mkdir -p
已经为你做到了。gjots2lpr
来自乔茨2包似乎完成了脚本所做的大部分或全部工作。您的脚本可以替换为一个简单的包装器,
gjots2lpr
该包装器设置它用来覆盖默认值的环境变量(例如告诉它是否使用a2ps
orenscript
、使用什么 ps/pdf 查看器、使用什么打印命令等)。从
gjots2lpr -h
:
用法: gjots2lpr [-pt ] [ 文件名 ... ]
打印文本文件 - 如果可能的话,使用 postscript 或 PDF 以及可用的预览器和打印机对话框。它查找并使用它可以在系统上找到的任何实用程序。
如果未给出“文件名”,则打印 STDIN。