Задача: собрать исходники писем с почтовых ящиков и сохранить сырые данные на сервере (локальном).
Средства реализации: php
& curl
Репозиторий с исходным кодом решения задачи здесь. Есть подробный readme, а код внутри прокомментирован.
Алгоритм довольно прост:
imap
протокол, Первая проблема заключалась в получении, разборе и использовании названий директорий на почтовом ящике. При авторизации на imap
сервере в ответе будет получен список директорий на ящике в UTF7-IMAP кодировке:
plaintext* LIST (\Unmarked \HasNoChildren \Drafts) "|" Drafts * LIST (\Unmarked \NoInferiors) "|" INBOX * LIST (\Unmarked \HasNoChildren) "|" Outbox * LIST (\Unmarked \HasNoChildren \Sent) "|" Sent * LIST (\Unmarked \HasNoChildren \Junk) "|" Spam * LIST (\Unmarked \HasNoChildren \Trash) "|" Trash
Нет проблем пока не появляются директории на кириллице с пробелами (название синтетическое для примера):
plaintext* LIST (\Trash) "/" "&BBoEPgRABDcEOAQ9BDA- &BBoEPgRABDcEOAQ9BDA-"
При попытке сканирования такой директории по адресу: imaps://imap.domain.zone/&BBoEPgRABDcEOAQ9BDA- &BBoEPgRABDcEOAQ9BDA-/
, imap
сервер выдал:
plaintextimap URL using bad/illegal format or missing URL
Декодировать строку можно так:
php$sDir = mb_convert_encoding($value, "UTF-8", "UTF7-IMAP");
Исходник письма может быть в любой кодировке.
Изначально требовалось чтобы скрипт отправлял исходник письма и некоторые другие данные на другой сервер, для этого данные паковал json_encode, пока не пошли письма в windows-1251
кодировке, на что json_encode
сказал:
plaintextMalformed UTF-8 characters, possibly incorrectly encoded
json_encode
, а принимающий сервер делал обратные операции и получал неизменные данные.Удалять письма надо по убыванию порядковых номеров (письмо с номером 1 удалять самым последним), иначе обратный порядок может привести к тому что порядковые номера при удалении будут изменены на imap сервере, а дальше неверная идентификация писем.
SEARCH ALL UNDELETED
) можно просто применить arsort к массиву с порядковыми номерами:php//получение порядковых номеров всех неудаленных писем в директории curl_setopt($hCurl, CURLOPT_URL, "$sImap/$value"); curl_setopt($hCurl, CURLOPT_CUSTOMREQUEST, "SEARCH ALL UNDELETED"); $sResponse = curl_exec($hCurl); $sResponse = str_replace("\r\n", "\n", $sResponse); $sResponse = mb_substr($sResponse, mb_strlen("* SEARCH ")); //парсим строку извлекая порядковые номера сообщений в директории $aStrs = explode(" ", $sResponse); //сортировка массива по убыванию, чтобы удалять не сбивая порядковые номера arsort($aStrs);