我有一个 shell 脚本,可将文件从服务器邮件文件夹下载到 NAS 设备,以便客户端在本地创建备份副本。
文件保存为 11469448248.H15587P19346.smtp.x14.eu_2,S 文件。 我已将扩展名更改为标准 .eml 格式,以便电子邮件客户端可以从光盘读取它们。
for f in *.smtp.x14.eu_2,S; do
#sed "9q;d" $f
#tail -n+9 $f | head -n1
mv -- "$f" "${f%.smtp.x14.eu_2,S}.eml";
done
如您所见,我尝试使用 sed 和 tail 命令从文件中获取第 9 行;问题是主题并不总是在第 9 行,并且文件名并没有说明其大部分内容。
我正在尝试使文件名采用易于理解的格式,因此我认为该主题可能会有所帮助。
电子邮件文件的第 n 行是以 主题:PD:主题
开头的行我试图找到这条线,删除主题:PD:并将其余部分保留为ne文件名
以下是错误,但实现了您似乎要求的内容。
subj=$(sed -n '/^Subject: PD *//!d;p;q;/^$/q' "$f")
这样做的问题是,它在普通情况下会成功,但当您有 MIME RFC2047 编码的
Subject:
标头时,以及(更简单地)当 Subject:
标头跨越多于一行时,它会失败。
我会用一种稍微现代的编程语言来解决这个问题。这不完全是一句简单的话,但用 Python 就足够简单了。
subj=$(./emailsubj.py "$f")
其中
emailsubj.py
包含或多或少类似的东西
#!/usr/bin/env python
from email.parser import Parser
from email.header import Header, decode_header
from sys import argv
for filename in argv[1:]:
with open(filename, 'rb') as handle: # handle file not found etc?
message = Parser().parse(handle)
try:
subj = ''.join([frag.decode(enc) if enc else frag
for frag, enc in decode_header(message['subject'])])
except HeaderParseError, UnicodeDecodeError:
subj = message['subject'] # maybe warn about error?
print(subj)
(显然,请记住
chmod +x emailsubj.py
。)
这会检索整个
Subject:
标头,对于模块化工具来说似乎是一个很好的设计。如果您想在提取标头后删除前缀,shell 有简单的“参数扩展”功能,可以做到这一点。例如,
echo "${subj#PD: )"
显示
$subj
的值,并删除该值前面的任何前缀
PD:
。
这是一个Python 3版本,由在提议的编辑中贡献,但是它违反了一般的Stack Overflow准则,因此在我将其合并到这个答案之前被拒绝了。
#!/usr/bin/env python3
from email.parser import BytesParser
from email.header import Header, decode_header
from email.errors import HeaderParseError
from sys import argv
for filename in argv[1:]:
with open(filename, 'rb') as handle: # handle file not found etc?
message = BytesParser().parse(handle)
try:
subj = ''.join([
frag.decode(enc if enc else "utf-8")
if isinstance(frag, bytes) else frag
for frag, enc in decode_header(message['subject'])])
except (HeaderParseError, UnicodeDecodeError): # maybe warn about error?
subj = message['subject']
subj = subj.decode("utf-8") if isinstance(subj, bytes) else subj
print(subj)
不过,您可能只需要一个简单得多的版本。以下练习了 Python 3.6+ 改进的
email
库(暂时要求您命名一个显式
policy
,但是),它更加简单且更通用。from email import message_from_binary_file
from email.policy import default
from sys import argv
for filename in argv[1:]:
with open(filename, 'rb') as handle: # handle file not found etc?
message = message_from_binary_file(handle, policy=default)
print(message['subject'])