Skip to main content

Библиотека для парсинга email переписки

Project description

Simple Email Parse

Библиотека для парсинга email-переписок из HTML-файлов. Извлекает структурированную информацию о сообщениях, включая заголовки (From, Sent, To, Subject) и текст сообщений.

Установка

pip install simple-email-parse

Быстрый старт

from email_parser import EmailParser

parser = EmailParser("email.htm", remove_img=True)

messages = parser.get_dict()
print(f"Найдено сообщений: {len(messages)}")

for msg in messages:
    if msg['header']:
        print(f"От: {msg['header']['From']['email']}")
        print(f"Дата: {msg['header']['Sent']}")
    print(f"Текст: {msg['text'][:100]}...")
    print("---")

parser.save_json("output.json")

Архитектура

Библиотека состоит из трех основных компонентов:

1. EmailParser

Главный класс для парсинга email. Последовательно применяет HtmlProcessor и JsonProcessor для извлечения структурированных данных.

Параметры:

  • filepath - путь к HTML-файлу
  • html - HTML-строка (альтернатива filepath)
  • soup - готовый BeautifulSoup объект (альтернатива filepath/html)
  • encoding - кодировка файла (автоопределение: utf-8, windows-1251)
  • remove_img - удалять изображения из текста
  • main_contact - основной контакт для сообщений без заголовка

Методы:

  • get_dict() - возвращает список словарей с сообщениями
  • get_json() - возвращает JSON-строку
  • save_json(filepath) - сохраняет результат в JSON-файл
  • save_html(filepath) - сохраняет обработанный HTML

2. HtmlProcessor

Обрабатывает HTML-код email, нормализуя структуру и выделяя заголовки сообщений.

Алгоритм работы

Этап 1: Инициализация и предобработка

  • Чтение HTML из файла/строки/soup
  • Удаление BOM (\ufeff) и DOCTYPE
  • Обработка изображений: замена <img> на текстовые маркеры
  • Упрощение ссылок: преобразование <a> в span/p с форматом [текст](url)

Этап 2: Очистка HTML

  • Удаление системных тегов (html, body, head, style, script, meta)
  • Удаление пустых тегов (рекурсивно)
  • Сохранение специальных атрибутов (simple-email-parse-attr)
  • Удаление всех остальных атрибутов (class, style, id)

Этап 3: Упрощение структуры

  • Преобразование всех тегов в div/span/br/blockquote/table
  • Блочные теги (p, h1-h6, ul, ol, li) → div
  • Инлайн теги (b, i, strong, em) → span

Этап 4: Обработка сиротных узлов

  • Поиск последовательностей текст + span
  • Оборачивание в div только если содержимое является заголовком
  • Проверка через адаптеры заголовков

Этап 5: Распаковка span

  • Специальные span с quote_header → div
  • Если span содержит div → unwrap
  • Текстовые span → склеиваются с пробелами

Этап 6: Обнаружение заголовков Используются адаптеры для поиска заголовков:

  1. Контекстный поиск:
    • После <hr> (с игнорированием <br>)
    • Перед/внутри <blockquote>
  2. Глобальный поиск: все div, p, span
  3. Сортировка кандидатов по глубине (от вложенных к корневым)
  4. Применение адаптеров: DividerHeader → MultipleDivHeader → KeyValueHeader → OnelineHeader

Этап 7: Обработка пересылаемых сообщений (Fwd)

  • Поиск разделителей "---Пересылаемое сообщение---"
  • Поиск заголовка после разделителя (с игнорированием <br>)
  • Оборачивание в <blockquote> до маркера конца

Этап 8: Улучшение структуры цитат

  1. Превращение div[simple-email-parse-attr="quote"]<blockquote>
  2. Распаковка заголовков из лишних оберток
  3. Распаковка цитат из лишних div (unwrap родителя, если единственный значимый контент)
  4. Перенос заголовков внутрь следующей цитаты
  5. Финальная распаковка пустых оберток

Этап 9: Упрощение div-блоков Выполняется циклически (while changed):

  1. Wrap Orphans: оборачивание сирот (текст, таблицы) в div
  2. Flattening: если div содержит структурные блоки как прямых детей → unwrap
  3. Backward Merge: слияние с предыдущим div или затягивание контента
  4. Forward Suck: затягивание следующего контента

Этап 10: Обеспечение blockquote

  • Оборачивание блоков после quote_header в <blockquote>
  • Жадный захват всех элементов до следующего заголовка

Этап 11: Вложение соседних цитат

  • Обработка снизу вверх
  • Если перед цитатой стоит другая цитата → перемещение внутрь

Этап 12: Перенос остатков

  • Обработка сверху вниз (рекурсивно)
  • Перенос "хвостов" после цитаты в div перед цитатой
  • Объединение с существующим контентом через <br>

Этап 13: Преобразование переносов строк

  • <br>\n
  • SHY (\xad) → удаление
  •   → пробел
  • Схлопывание пробелов
  • Удаление пробелов вокруг \n
  • Ограничение: 2+ \n → \n\n

3. JsonProcessor

Извлекает сообщения из обработанного HTML и парсит заголовки.

Алгоритм работы

Этап 1: Рекурсивное извлечение сообщений

  • Обход дерева blockquote
  • Поиск заголовков (simple-email-parse-attr="quote_header_*")
  • Извлечение текста между заголовком и вложенными цитатами
  • Сохранение HTML-содержимого (включая таблицы)

Этап 2: Парсинг контактов Поддерживаемые форматы:

  • Name <email@example.com>
  • Name [mailto:email@example.com]
  • "Name" <email@example.com>
  • email@example.com

Этап 3: Парсинг даты/времени Поддерживаемые форматы:

  • 14.05.2024, 17:35
  • Вторник, 14 мая 2024, 17:35 +03:00
  • Wednesday, May 08, 2024 1:34 PM
  • пт, 15 апр. 2022 г. в 20:47
  • 8 мая 2024 г., 13:55:58 +03:00

Этап 4: Парсинг заголовков

Блочный формат (KeyValue):

From: Sender <sender@example.com>
Sent: Tuesday, May 14, 2024 5:35 PM
To: Receiver <receiver@example.com>
Subject: Test Subject

Однострочный формат:

21.09.2023, 16:13, 'Name' <email@example.com>:

Этап 5: Разворот порядка сообщений

  • Самое глубокое (старое) сообщение → первое
  • Реверсирование списка

Этап 6: Обработка временных меток Вычисление времени для сообщений без явного указания:

  • Первое сообщение: время следующего минус 1 час
  • Последнее сообщение: время предыдущего плюс 1 час
  • Среднее сообщение: среднее между предыдущим и следующим
  • Поиск ближайших сообщений с реальным временем (не 00:00:00)
  • Согласование timezone (добавление МСК если нужно)

Этап 7: Конвертация в МСК

  • Все временные метки конвертируются в московское время (UTC+3)
  • Если timezone не указан → считается МСК

Этап 8: Формирование результата

[
  {
    "header": {
      "From": {"name": "Sender", "email": "sender@example.com"},
      "Sent": "2024-05-14T17:35:00+03:00",
      "To": {"name": "Receiver", "email": "receiver@example.com"},
      "Subject": "Test"
    },
    "text": "Message text..."
  }
]

Адаптеры заголовков

DividerHeaderAdapter

Обнаруживает разделители пересылаемых сообщений:

---Пересылаемое сообщение---
---Forwarded message---

MultipleDivHeaderAdapter

Обнаруживает многострочные заголовки, разбитые на несколько div:

<div>Кому: email@example.com;</div>
<div>Тема: Test Subject;</div>
<div>29.10.2025, 09:16, "Sender" <email@example.com>:</div>

Правила:

  • Минимум 2 элемента с ключевыми словами
  • Первый div должен начинаться с ключевого слова
  • Не более 5 элементов в группе
  • Общая длина не более 600 символов

KeyValueHeaderAdapter

Обнаруживает блочные заголовки с ключами:

From: sender@example.com
Sent: Tuesday, May 14, 2024
To: receiver@example.com
Subject: Test

Правила:

  • Минимум 2 ключа (From, Sent, To, Subject, Cc)
  • Первый ключ в начале текста (не далее 50 символов)
  • Отсутствие разбиения между соседними элементами

OnelineHeaderAdapter

Обнаруживает однострочные заголовки:

21.09.2023, 16:13, 'Name' <email@example.com>:
Вы писали 8 мая 2024 г., 13:55:58:

Правила:

  • Длина 10-350 символов
  • Не более 3 переносов строк
  • Наличие даты + времени + email/ключевых слов
  • Заканчивается на двоеточие

Особенности и узкие места

Обработка пробелов и переносов

  • При распаковке span всегда добавляются пробелы для предотвращения слипания слов
  • Важно игнорировать <br> при поиске заголовков, так как они часто окружают заголовки
  • Разделители <br> правильно обрабатываются при слиянии div

Обработка заголовков

  • Проверка вложенности: родительские контейнеры отступают, если внутри уже найден заголовок
  • Look Behind: проверка предыдущего соседа для избежания ложных срабатываний на фрагментах заголовков
  • Сортировка кандидатов по глубине позволяет обрабатывать сначала вложенные элементы

Обработка цитат

  • Распаковка цитат выполняется дважды: до и после переноса заголовков
  • Проверка "мусорных" узлов (_is_removable_node) включает пустые текстовые узлы, <br> и пустые div
  • При переносе заголовков используется _is_removable_node для пропуска <br>

Обработка div-блоков

  • Защита от бесконечного цикла: проверка только прямых потомков (children), не всех (descendants)
  • Важно различать: для unwrap_div нужен <br> как контент (ignore_br=False), для process_headers - нет (ignore_br=True)

Обработка временных меток

  • Особый случай: время 00:00:00 без timezone → признак отсутствия времени (только дата)
  • Время 00:00:00 С timezone → реальное время полуночи
  • Сохранение даты при вычислении времени для корректности

Примеры использования

Базовое использование

from email_parser import EmailParser

parser = EmailParser("email.htm")
messages = parser.get_dict()

for msg in messages:
    print(f"Header: {msg['header']}")
    print(f"Text: {msg['text']}")

Использование с HTML-строкой

html = "<div>Email content...</div>"
parser = EmailParser(html=html, remove_img=True)
json_output = parser.get_json()

Использование с основным контактом

from json_processor import Contact

main_contact = Contact(email="me@example.com", name="My Name")
parser = EmailParser("email.htm", main_contact=main_contact)

messages = parser.get_dict()

Раздельное использование процессоров

from html_processor import HtmlProcessor
from json_processor import JsonProcessor

html_proc = HtmlProcessor("email.htm", remove_img=True)
html_proc.process()

json_proc = JsonProcessor(html=html_proc.soup)
messages = json_proc.process()

Лицензия

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

simple_email_parse-0.1.tar.gz (28.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

simple_email_parse-0.1-py3-none-any.whl (26.3 kB view details)

Uploaded Python 3

File details

Details for the file simple_email_parse-0.1.tar.gz.

File metadata

  • Download URL: simple_email_parse-0.1.tar.gz
  • Upload date:
  • Size: 28.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.0

File hashes

Hashes for simple_email_parse-0.1.tar.gz
Algorithm Hash digest
SHA256 154144d554bbfa018a5c18a3e5fbd3fba10559e7c48b71b174fcd02b1221cf02
MD5 b965abfe5be924612bd83126e7161bb3
BLAKE2b-256 8c1cbfd5e71b92f107af2aae476bfe534c5ce578848bbaa12f6a0c93b8cd72bd

See more details on using hashes here.

File details

Details for the file simple_email_parse-0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for simple_email_parse-0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 371f6a594ca33dc3887d0e632e000e3c8b88e8f7e878ea2ce844b1854693bde1
MD5 a8840d4c72f43058565866943522319b
BLAKE2b-256 73c1cbc0725630afb20f0e7f84df333b0fdcd0d88e48cb021a0e75282b2b3f63

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page