Как бы я разумно различал два файла mbox?

У меня есть два mbox-файла, каждый из которых содержит около 6 тысяч электронных писем. Они должны быть более или менее идентичными, хотя #1 содержит около 100 электронных писем, которые #2 не содержат. Я хотел бы создать третий файл mbox, содержащий мои 100 сообщений - так сказать, diff.

Я использовал автоматическую пересылку сообщений из одной папки "Входящие" в другую (на стороне сервера), которая случайным образом не пересылала несколько сообщений по какой-то странной неопределенной причине. #2 - это входящие сообщения, в которые пересылались электронные письма - множество прочитанных и отвеченных сообщений с дополнительными заголовками, содержащими информацию о том, как они были переадресованы. #1 - это недавний дамп с использованием imap непрочитанных сообщений размером 6 тыс.


Я работаю с Thunderbird под Linux.

3 ответа

Решение

Следующий скрипт Python решает проблему:

import mailbox

inbox_2 = mailbox.mbox('inbox_2_file')
inbox_1 = mailbox.mbox('inbox_1_file')

inbox_diff = mailbox.mbox('inbox_diff_file', create=True)

inbox_2_ids = []
for message in inbox_2:
    inbox_2_ids.append(message.get('Message-ID'))

for message in inbox_1:
    if message.get('Message-ID') not in inbox_2_ids:
        inbox_diff.add(message)

inbox_diff.flush()

Большое спасибо за размещение вашего вопроса и ответа, @sme. Сценарий Python прекрасно работает, если каждое из сообщений электронной почты содержит идентификатор сообщения. К сожалению, это не всегда так, поскольку на самом деле Message-ID не является обязательным полем.

С небольшим изменением ваш сценарий может быть использован для создания нового файла mbox, содержащего все сообщения электронной почты, в которых отсутствует поле Message-ID:

import mailbox

inbox_1 = mailbox.mbox('inbox_1_file')

inbox_missing_message_id = mailbox.mbox('inbox_missing_message_id_file', create=True)

for message in inbox_1:
    if message.get('Message-ID') is None:
        inbox_missing_message_id.add(message)

inbox_missing_message_id.flush()

Где-то 5 лет спустя. Мне пришлось сравнить почтовые ящики с резервной копией Thunderbird объемом 306 МБ и 338 МБ. Поэтому я поместил все отличные советы в автономный вспомогательный скрипт, который меняет mbox2 на mbox1. При этом также создаются соответствующие почтовые ящики с электронными письмами, в которых отсутствует поле Message-ID. У меня это работает на Mac «из коробки», создавая два дополнительных почтовых ящика с электронными письмами без идентификатора сообщения размером 52 КБ и 10 КБ. Более чем управляемо!

Надеюсь, это может пригодиться. Спасибо за ваше понимание.

      #!/usr/bin/env python3

import mailbox
import sys
import os

if len(sys.argv) <= 2:
    print("USAGE: {} <mbox2> <mbox1>".format(os.path.basename(sys.argv[0])))
    print("       <diff> = <mbox2> - <mbox1> is based on 'Message-ID' field")
    print("       E-mails with no 'Message-ID' are copied <mbox[1|2]_no_Message-ID>.")
    print("       Original mailboxes are left unaltered.")
    sys.exit(1)
    
if not os.path.isfile(sys.argv[1]):
    print(" * mbox_file {} does not exist.".format(sys.argv[1]))
    sys.exit(2)
if not os.path.isfile(sys.argv[2]):
    print(" * mbox_file {} does not exist.".format(sys.argv[2]))
    sys.exit(2)

mbox1_file = sys.argv[1]
mbox2_file = sys.argv[2]

outfile = os.path.join(
    os.path.dirname(mbox1_file)
    , '{}2_diff_{}1'.format(os.path.basename(mbox2_file), os.path.basename(mbox1_file))
)
if os.path.isfile(outfile):
    print(" * OUTPUT mbox_file {} already exists.".format(outfile))
    sys.exit(2)

nomsgid1_file = os.path.join(
    os.path.dirname(mbox1_file)
    , '{}_no_Message-ID'.format(os.path.basename(mbox1_file))
)
if os.path.isfile(nomsgid1_file):
    print(" * OUTPUT mbox_file {} already exists.".format(nomsgid1_file))
    sys.exit(2)


nomsgid2_file = os.path.join(
    os.path.dirname(mbox2_file)
    , '{}_no_Message-ID'.format(os.path.basename(mbox2_file))
)
if os.path.isfile(nomsgid2_file):
    print(" * OUTPUT mbox_file {} already exists.".format(nomsgid2_file))
    sys.exit(2)


inbox_1 = mailbox.mbox(mbox1_file)
inbox_2 = mailbox.mbox(mbox2_file)
inbox_diff = mailbox.mbox(outfile, create=True)
inbox1_missing_message_id = mailbox.mbox(nomsgid1_file, create=True)
inbox2_missing_message_id = mailbox.mbox(nomsgid2_file, create=True)


inbox_2_ids = []
for message in inbox_2:
    msgid = message.get('Message-ID')
    if msgid is None:
        inbox2_missing_message_id.add(message)
    else:
        inbox_2_ids.append(msgid)

for message in inbox_1:
    msgid = message.get('Message-ID')
    if msgid is None:
        inbox1_missing_message_id.add(message)
    elif msgid not in inbox_2_ids:
        inbox_diff.add(message)

inbox_diff.flush()
inbox2_missing_message_id.flush()
inbox1_missing_message_id.flush()

PS Я также столкнулся с несколькими проблемами с кодировкой. Как вы знаете, электронные письма очень сложно автоматически проверить на правильную кодировку, а utf-8 не всегда работает. Жестоким, но работающим решением было изменить каждое явлениеasciiкодировка вmailbox.pyбиблиотека дляlatin-1иutf8, следующее:

get_messageфункция:

      try:
  msg.set_from(from_line[5:].decode('latin-1'))
except Exception as e:
  msg.set_from(from_line[5:].decode('utf8'))
return msg

_install_message()функция:

      author = message.get_from().encode('utf8')
[...]
from_line = from_line.encode('utf8')
Другие вопросы по тегам