似乎您正在处理的至少一些电子邮件已被编码为quoted-printable。
此编码用于使 8 位字符数据可在 7 位(仅限 ASCII)系统上传输,但它也强制执行 76 个字符的固定行长度。这是通过插入一个软换行符来实现的,该换行符由“=”和行尾标记组成。
Python 提供了quopri模块来处理来自quoted-printable 的编码和解码。从quoted-printable 解码您的数据将删除这些软换行符。
例如,让我们使用您问题的第一段。
>>> import quopri
>>> s = """I'm writing a small script to run through large folders of copyright notice emails and finding relevant information (IP and timestamp). I've already found ways around a few little formatting hurdles (sometimes IP and TS are on different lines, sometimes on same, sometimes in different places, timestamps come in 4 different formats, etc.)."""
>>> # Encode to latin-1 as quopri deals with bytes, not strings.
>>> bs = s.encode('latin-1')
>>> # Encode
>>> encoded = quopri.encodestring(bs)
>>> # Observe the "=\n" inserted into the text.
>>> encoded
b"I'm writing a small script to run through large folders of copyright notice=\n emails and finding relevant information (IP and timestamp). I've already f=\nound ways around a few little formatting hurdles (sometimes IP and TS are o=\nn different lines, sometimes on same, sometimes in different places, timest=\namps come in 4 different formats, etc.)."
>>> # Printing without decoding from quoted-printable shows the "=".
>>> print(encoded.decode('latin-1'))
I'm writing a small script to run through large folders of copyright notice=
emails and finding relevant information (IP and timestamp). I've already f=
ound ways around a few little formatting hurdles (sometimes IP and TS are o=
n different lines, sometimes on same, sometimes in different places, timest=
amps come in 4 different formats, etc.).
>>> # Decode from quoted-printable to remove soft line breaks.
>>> print(quopri.decodestring(encoded).decode('latin-1'))
I'm writing a small script to run through large folders of copyright notice emails and finding relevant information (IP and timestamp). I've already found ways around a few little formatting hurdles (sometimes IP and TS are on different lines, sometimes on same, sometimes in different places, timestamps come in 4 different formats, etc.).
要正确解码,需要处理整个消息正文,这与您使用readline
. 解决此问题的一种方法是将解码的字符串加载到缓冲区中:
import io
def getIP(em):
with open(em, 'rb') as f:
bs = f.read()
decoded = quopri.decodestring(bs).decode('latin-1')
ce = io.StringIO(decoded)
iplabel = ""
while not ("Torrent Hash Value: " in iplabel):
iplabel = ce.readline()
...
如果您的文件包含完整的电子邮件(包括标题),那么使用电子邮件模块中的工具将自动处理此解码。
import email
from email import policy
with open('message.eml') as f:
s = f.read()
msg = email.message_from_string(s, policy=policy.default)
body = msg.get_content()