我为fetchmail编写了一个脚本,用于从帐户接收邮件,并将消息传输到procmail,以便应用过滤器和保存附件。我对消息的主题使用了过滤器,但是源主题中有cyrillics,所以当fetchmail将消息传递到procmail时,最后的主题以UTF-8加密开始,然后只是胡言乱语。
Procmail脚本如下所示:
:0fHw
*^Content-Type:*text/plain; *charset="?(iso-8859-1|US-ASCII|UNKNOWN-8BIT)"?
| formail -i "Content-Type: text/plain; charset=windows-1251"
:0
*^content-Type:
{
:0c
$HOME/fetchmail/backup
:0f
*^Subject:.*ASVA
| uudeview -i +a +o -p $HOME/fetchmail/attachments -
}这些脚本在拉丁主题上工作得很好,但是由于西里尔主题,我的过滤器没有看到我所放的关键字。如何将主题转换成正确的cyrillics和latinics?我安装了语言包,局部变量设置为ru_RU:UTF-8,当我用cyrillics编写时,它会被正确地显示出来。
发布于 2019-08-27 13:05:51
看来你说的是RFC 2047:电子邮件头的MIME编码。此后,RFCs对RFC进行了扩展,以允许更多的字符集,并可选择地包括语言规范。
由于最初的电子邮件和MIME规范包含了这样的假设,即头将只包含严格的US-ASCII,因此头编码与消息体的MIME编码完全不同。
格式如下:
=? [*language] ? ? ?=要么是Q表示引用-打印,要么是B表示base64编码.如果这条信息看起来完全是胡言乱语,我想你是在看base64。字符集名称和编码字母都不区分大小写.
所以你可能会看到:
Subject: =?utf-8?b?SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSB1bmRlcnN0b29kIHRoZSBleGFtcGxlLgo=?=或者添加一个语言ID:
Subject: =?utf-8*en?b?SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSB1bmRlcnN0b29kIHRoZSBleGFtcGxlLgo=?=手动解码示例:
$ echo "SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSB1bmRlcnN0b29kIHRoZSBleGFtcGxlLgo=" | base64 -d
If you can read this, you understood the example.现有的Procmail脚本包括强制将字符集编码标记为iso-8859-1、US-ASCII和UNKNOWN-8BIT为windows-1251,这表明您的实际问题可能是字符编码的标签错误。换言之:
windows-1251 cyrillics,而不会将它们标记为cyrillics,可能还会出现在标头中。在这种情况下,MTA需要对8位字符进行编码和标记,才能传递邮件。但是,如果8位字符没有标签,则只有原始邮件客户端确切地知道字符集实际上是什么。
事实之后标注字符集的问题是,识别字符集可能需要人类级别的理解,以了解内容是否具有解释为特定字符集的意义。因此,您将最终使用启发式,这有时是错误的。
例如,如果您收到的电子邮件实际上是正确编码的iso-8859-1,您的脚本将错误标签为windows-1251,导致任何北欧/西欧重音字符显示为随机的,无意义的Cyrillics。但是,如果这比接收被错误标记为windows-1251的iso-8859-1编码的消息更少见,那么您可能会选择接受这种风险,这是很好的。
我认为您必须调查您的有问题的消息,以了解它们的Subject:头实际上是如何编码的。他们是否:
windows-1251?base64-encoded UTF-8?base64-encoded误标为UTF-8的-encoded?不幸的是,procmail及其配套的formail可能不足以以未编码的形式获取Subject:头。他们是自2001年以来未得到维护和就连他们的作者现在也建议继续做其他的事情。但是,如果您现在想继续使用procmail,那么您需要这样的脚本:
https://github.com/akkana/scripts/blob/master/decodemail.py
我已经大约10年没有做过重要的procmail脚本了,所以下面的例子可能是错误的,或者有更好的方法来做到这一点。但也许这对解释如何解决这个问题是有用的.
您必须首先解码Subject:头的内容,并将其存储到一个变量中:
:0 h
SUBJDECODED=| decodemail.py Subject:
:0 h
SUBJWASRAW=| formail -xSubject: | recode windows-1251..UTF-8为了纠正标记错误的编码,您可能需要将字符集从实际的任何内容重新编码到系统使用的UTF-8:
SUBJWASWIN1251=`echo "$SUBJDECODED" | recode windows-1251..UTF-8`如果有多个可能的编码,您可能需要创建这样的多个变量。
然后,您可以根据主题的任意版本进行匹配:
:0
* SUBJWASRAW ?? your-subject-regexp-here
{
# Here the subject was raw windows-1251 without any encoding at all.
# The variable has it converted to valid UTF-8 used by this system,
# so now the header can be rewritten in an useful form.
# (This example leaves the subject as raw unlabelled UTF-8 which
# may or may not be acceptable to whatever you use to view your email with.
# But on modern RFC 6532 compliant mail clients
# in a system that uses UTF-8 throughout it may actually be OK.)
:0 f
| formail -i "Subject: $SUBJWASRAW"
}
:0
* SUBJWASWIN1251 ?? your-subject-regexp-here
{
# regexp matched, so we know the subject was windows-1251
# mislabeled as UTF-8. Fix it.
:0 f
| formail -i "Subject: $SUBJWASWIN1251"
}
:0
* SUBJDECODED ?? your-subject-regexp-here
{
# regexp matched to subject decoded according to existing label
# so we know that it was validly labelled. But it still needs to
# be rewritten as it may have been something other than UTF-8.
:0 f
| formail -i "Subject: $SUBJDECODED"
}
# Any further rules should be able to match on the subject as usual.注意:your-subject-regexp-here正则表达式不应该包含^Subject:.*前缀,因为变量将只包含Subject:头的值。
https://unix.stackexchange.com/questions/537606
复制相似问题