Python procmail处理后的邮件正文编码

Python procmail处理后的邮件正文编码,python,linux,bash,procmail,Python,Linux,Bash,Procmail,SMTP服务器上的.procmailrc中有以下行: BODY=`formail -I ""` 稍后,我将此正文回显到本地文件: echo "$BODY" >> $HOME/$FILENAME; \ 我也尝试过prinf(但我得到了同样的效果): 当我读这个文件时,我可以看到编码已经改变了。以下是我得到的: Administrator System=C3=B3w 虽然它应该是(波兰语): 如何直接在.procmailrc或更高版本(bash/python)中解码/编码正文以获得

SMTP服务器上的.procmailrc中有以下行:

BODY=`formail -I ""`
稍后,我将此正文回显到本地文件:

echo "$BODY" >> $HOME/$FILENAME; \
我也尝试过prinf(但我得到了同样的效果):

当我读这个文件时,我可以看到编码已经改变了。以下是我得到的:

Administrator System=C3=B3w
虽然它应该是(波兰语):

如何直接在.procmailrc或更高版本(bash/python)中解码/编码正文以获得正确的字符串

my
.procmailrc
中的另一行可以正常工作,但它需要额外的管道和perl编码器:

SUBJECT=`formail -xSubject: | tr -d '\n' | sed -e 's/^ //' | /usr/bin/perl -MEncode -ne 'print encode ("utf8",decode ("MIME-Header",$_ )) '`
主题包含UTF8字符,看起来一切正常。也许有一种方法可以在邮件正文中使用类似的解决方案

嗯。 我终于把一切都准备好了。以下是我所做的:

首先是.procmailrc文件:

现在转到python_script.py:

调试最困难的部分是.procmailrc配方,在那里我必须测试许多选项:0、:0f、:0fbW等等。。。终于找到了最合适的


下一个有问题的步骤是直接在.procmailrc中解码的$BODY部分。不过,我找到了解决方案,去掉了所有的东西,将所有的东西都转移到Python脚本中。正如tripleee建议的那样。

我认为可能是您的
echo
没有返回正确的unicode来写入文件,这里有两种解决方案可以帮助您:

要使用转义字符进行回显:

echo -e "$BODY" >> $HOME/$FILENAME; \
或者,使用
iconv
或类似方法将文件编码为utf-8,假设您在linux中有iconv

iconv -t UTF-8 original.txt > encoded_result.txt

它不会更改,但您正在缩放标题,以便正确的
内容类型:
标题不再存在(您还应保留
Mime版本:
和任何其他标准
内容-*
标题)

通过检查邮件客户端中的消息源,您应该看到Procmail或Bash实际上没有改变任何东西。您收到的文本实际上是字面上的
Administrator System=C3=B3w
,但MIME标题会通知您的电子邮件客户端,这是
内容传输编码:带引号的可打印
内容类型:text/plain;charset=“utf-8”
,因此它知道如何正确解码和显示这些信息

如果您只需要有效负载,则需要自己对其进行解码,但为了做到这一点,您需要MIME头中的这些信息,因此您不应该在处理消息之前杀死它们(如果有的话)。也许是这样的:

from email.parser import Parser
import sys

message = Parser().parse(sys.stdin)
if message['content-type'].lower().startswith('text/'):
    print(message.get_payload(decode=True))
else:
    raise DieScreamingInAnguish('aaaargh!')  # pseudo-pseudocode
这是非常简单的,因为它假设(像您当前的、甚至更坏的解决方案一样)消息包含单个文本部分。将其扩展到多部分消息在技术上并不困难,但具体如何实现这一点取决于您希望接收的多部分类型,以及您希望对有效负载执行的操作


比如在中,我建议您将更多或全部电子邮件操作迁移到Python中,如果您打算使用它的话。Procmail没有明确的MIME支持,因此您必须在Procmail中重新设计所有这些功能,这既不简单,也不是特别有成效。

我认为这更像是bash的东西,而不是python。您的bash是什么版本?GNU bash,版本4.2.37(1)没有
echo“$BODY”
返回正确的unicode?没有。“”引号只保留字符的正确位置,\n但看起来echo正在丢失邮件消息的原始utf-8编码。我相信您使用的是非utf-8终端,我已经发布了一个答案,希望能解决你的问题。我认为这与formail处理输入的方式有关。我更新了这方面的问题。好吧,也许文件转换为utf-8编码是一种解决方案。我不熟悉perl编码器,所以我必须将此留给其他人来帮助您。祝你好运谢谢你的建议!它们非常有用。你指出了正确的方向。我用我找到的解决方案更新了我的问题。
#!/usr/bin/python

from email.parser import Parser
import sys

temp_file = open("/home/(user)/file.txt","w")
temp_file.write("START\n")

if not message.is_multipart():
        temp_file.write(message.get_payload(decode=True))
else:
        for part in message.get_payload():
                if part.get_content_type() == 'text/plain':
                        temp_file.write(part.get_payload(decode=True))

temp_file.close()
echo -e "$BODY" >> $HOME/$FILENAME; \
iconv -t UTF-8 original.txt > encoded_result.txt
from email.parser import Parser
import sys

message = Parser().parse(sys.stdin)
if message['content-type'].lower().startswith('text/'):
    print(message.get_payload(decode=True))
else:
    raise DieScreamingInAnguish('aaaargh!')  # pseudo-pseudocode