Статьи

Извлечение электронной почты из Android в .eml

Иногда экосистеме Android немного не хватает поддержки инструментов; например, мне нужно было извлечь набор отправленных элементов из почтового ящика POP3 — стандартный почтовый клиент позволяет выполнять только 3 действия: удалить, пометить как непрочитанное или избранное.

Вооружившись Android SDK, некоторыми SQL-запросами и скриптом Groovy, мы увидим, как можно восстановить электронную почту в файлы RFC822 .eml.

Хранение электронной почты

Стандартный клиент com.android.email хранит заголовки сообщений и их тела в двух базах данных sqlite, а AttachmentProvider хранит вложения на диске.

Исходный код доступен по адресу https://android.googlesource.com/platform/packages/apps/Email  — в данном случае это был телефон Samsung с версией 4.1.2, поэтому я проверил  ветку jb-mr0-release для проверки код, когда требуется.

Резервное копирование с помощью ADB

ADB — это  Android Debug Bridge , инструмент отладки, который является частью  инструментов платформы Android SDK . Выполнение ‘ adb usb ‘ (пере) запускает демон adbd, прослушивающий USB-соединения.

Следующим шагом является выбор параметров разработчика в разделе «Система» списка настроек (рисунок 1), а затем включение отладки по USB на устройстве (рисунок 2).

Рисунок 1 - Системные настройки

Рисунок 1 — Системные настройки

Рисунок 2 - Параметры разработчика

Рисунок 2 — Параметры разработчика

Затем подключитесь к устройству с помощью USB-кабеля и выполните команду « adb backup -f mybackup.ab -all » (вы также можете более избирательно подходить к нужному пакету, например, « adb backup -f mybackup.ab com.android.email » ). АБР предложит вам разблокировать телефон и разрешить выполнение резервного копирования.

Накачка бэкапа

Резервная копия Android — это tar-файл с дефлированным Zlib — спасибо http://nelenkov.blogspot.jp/2012/06/unpacking-android-backups.html  за подсказку, что его можно перекачать с помощью следующей команды:
dd if=mybackup.ab bs=24 skip=1|openssl zlib -d > mybackup.tar

Обратите внимание, что установка  openssl, которая была у  меня на OSX, не была скомпилирована с   поддержкой zlib , поэтому я запустил ее через виртуальную машину Ubuntu Vagrant, чтобы накачать файл tar.

ИЗУЧЕНИЕ РЕЗЕРВНОГО КОПИРОВАНИЯ

Распаковка файла tar даст вам структуру папок, как показано на рисунке 3; в этом случае базы данных sqlite находятся в  БД,  а вложения фотографий, снятые с телефона, находятся в  f .

Рисунок 3 - Расширенная смола

Рисунок 3 — Расширенная смола

Изучение баз данных

Sqlitebrowser  — хороший инструмент для просмотра базы данных sqlite и функций на следующих скриншотах.

Текущий скрипт ограничивает количество обрабатываемых сообщений одним почтовым ящиком для одной учетной записи. Для определения  mailboxKey  необходимо найти целевую учетную запись из   таблицы « Учетная запись» (рисунок 4), а затем изолировать нужный почтовый ящик для этой учетной записи в   таблице « Почтовый ящик» (рисунок 5).

Рисунок 4 - Структура таблицы счетов

Рисунок 4 — Структура таблицы счетов

Рисунок 5 - Структура таблицы почтовых ящиков

Рисунок 5 — Структура таблицы почтовых ящиков

Вы можете просмотреть данные или выполнить следующий запрос, чтобы получить список почтовых ящиков и их соответствующих учетных записей:

SELECT a.displayName as accountName, m._id as mailboxKey, m.displayName as mailboxName
FROM Account a, Mailbox m
WHERE m.accountKey = a._id

Если вы не хотите ограничивать извлечение одним почтовым ящиком или учетной записью, вы можете удалить  предложение WHERE  из первого   запроса SELECT .

Извлечение электронной почты

Удовлетворяя спецификации RFC822 и JavaMail (я создал расширение IMAP для Alfresco в 2006 году), я решил, что будет проще реконструировать  MimeMessage с использованием SQL & Groovy, чем пытаться адаптировать исходный код Android для запуска с устройства или создать Пользовательское приложение для запуска в эмуляторе.

НЕДОСТАТКИ

В качестве первого среза, который был достаточно хорош для моих целей, есть несколько недостатков:
1. Он установлен по умолчанию для поля Отправитель вместо преобразования значения Message.fromList  и использования   метода addFrom
2. Адреса используют только адрес, а не чем метка
3. При обработке тела используется только простой текст, а не альтернативные мультипликаторы.
4.  Body.textReply  отделен от  Body.textContent  разделительной линией из 25 штрихов; он не пытается восстановить информацию заголовка предыдущего сообщения в потоке
5. Скрипт не обрабатывает вложения — это было сознательное решение, так как фотографии с камеры были на  com.android.email/fдругие вложения «RAW» не были в  com.android.email/1.db_att/  согласно javadoc  класса AttachmentProvider

В качестве начальной подсказки, чтобы восстановить вложения, которые вам понадобятся, используйте MimeMultipart , создайте   объекты MimeBodyPart, начиная с запроса, такого как:

"""SELECT fileName, mimeType, size, contentId, contentUri, encoding
FROM Attachment
WHERE messageKey = ${msgKey}"""

АДРЕСА

Сценарий предоставляет один служебный метод для преобразования списка с указанием строки, в котором записи разделены  SOH символом (ASCII 1), а адреса электронной почты и соответствующие им отображаемые имена разделены  STX символом (ASCII 2).

Обработка состоит из итерации строк набора результатов таблицы сообщений, для каждой строки тело сообщения извлекается из отдельной базы данных sqlite, а затем создается JavaMail  MimeMessage  и выводится в файл.

ПОИСК ПРОБЛЕМЫ

Сценарий не может вызвать потерю данных на вашем устройстве, так как он работает с резервной копией. Если вы хотите сначала поэкспериментировать, вы можете установить ограничение (например  LIMIT 10) для первого  запроса SELECT, чтобы уменьшить количество получаемых им сообщений.
Кроме того, простой способ просмотра выходных данных, например, в Groovy Console, заключается в использовании msg.writeTo(System.out) вместо создания файла .eml.

ПОЛУЧИТЬ СЦЕНАРИЙ

Обычные заявления об отказе от ответственности распространяются на то, что скрипт не имеет гарантии, поддержки и т. Д. — получите его на GitHub:  https://gist.github.com/rbramley/65261127dfb857b03bb6