Я пытаюсь получить все байтовые позиции частей MIME электронной почты от Python. Фактически мне нужны диапазоны между границами MIME.
Итак, это очень простое сообщение MIME, скопированное из https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html:
From: Nathaniel Borenstein <nsb@bellcore.com>
To: Ned Freed <ned@innosoft.com>
Subject: Sample message
MIME-Version: 1.0
Content-type: multipart/mixed; boundary="simple boundary"
This is the preamble. It is to be ignored, though it
is a handy place for mail composers to include an
explanatory note to non-MIME compliant readers.
--simple boundary
This is implicitly typed plain ASCII text.
It does NOT end with a linebreak.
--simple boundary
Content-type: text/plain; charset=us-ascii
This is explicitly typed plain ASCII text.
It DOES end with a linebreak.
--simple boundary--
This is the epilogue. It is also to be ignored.
Я хотел бы получить следующие цифры:
- 351-428 (первая часть с пустыми заголовками)
- 447-564 (вторая часть с заголовками)
Письма полон наземных мин, поэтому я хочу найти самое надежное решение. Я начал с модуля электронной почты Python и придумал что-то вроде этого:
import email
import email.policy
import mmap
def process_mail(f):
fp = open(f, 'rb')
msg = email.message_from_binary_file(fp, policy=email.policy.default)
boundaries = []
for part in msg.walk():
boundary = part.get_boundary()
if boundary is not None:
boundaries.append(boundary.encode('utf-8'))
return boundaries
file = '/tmp/test2'
f = open(file, 'r+b')
mm = mmap.mmap(f.fileno(), 0)
for boundary in process_mail(file):
pos = 0
while True:
idx = mm.find(b'--'+boundary, pos)
if idx < 0:
break
if pos:
print(pos, idx)
print("PART", mm[pos:idx])
pos = idx + len(b'--'+boundary)
, который еще не идеален из-за новых строк (что также может быть проблематичным c, например, \ n или \ r \ n или более странные вещи). Но я чувствую, что это довольно fr agile и хотел бы иметь решение, которое работает правильно во всех случаях (и, возможно, не требует повторного чтения файла один раз для анализа и один раз для нахождения границ).
Вопрос в том, что было бы наиболее эффективным / надежным решением для этого?