通过 bash 从文件中检索电子邮件主题

问题描述 投票:0回答:1

我有一个 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

如您所见,我尝试使用 sedtail 命令从文件中获取第 9 行;问题是主题并不总是在第 9 行,并且文件名并没有说明其大部分内容。

我正在尝试使文件名采用易于理解的格式,因此我认为该主题可能会有所帮助。

电子邮件文件的第 n 行是以 主题:PD:主题

开头的行

我试图找到这条线,删除主题:PD:并将其余部分保留为ne文件名

bash email sed
1个回答
6
投票

以下是错误,但实现了您似乎要求的内容。

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版本,由
Xlea

提议的编辑中贡献,但是它违反了一般的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'])

© www.soinside.com 2019 - 2024. All rights reserved.