Работа с входящей почтой через протокол IMAP средствами PHP

Работа с входящей почтой через протокол IMAP средствами PHP

На днях мне пришло задание написать небольшой модуль на PHP, который бы позволил работать с входящей почтой. Немного по гуглив я увидел что для данного задания мне подходит один из протоколов POP3 и IMAP.
Но выбор был очевиден что использовать я буду IMAP так как он более функциональный и современней, протокола POP3.

Теперь мне надо было быстренько разобраться как работать с протоколам IMAP, как получить письма из почтового сервера Yandex/Google.

Для более удобной работы я выбрал библиотеку PhpImap, так как она может быстро и легко реализует все нужные для меня задачи.

Подключение к почтовому серверу.

Теперь когда мы определились с выбором протокола и выбором библиотеки, будем пробовать подключатся к почтовому серверу.

Для полноценной работы PHP с протоколом IMAP, необходимо подключить расширение php_imap.dll/imap.so в файле php.ini.

Для начало попробуем подключится к Yandex почте так как у меня меньше всего возникло с ней проблем.

//Подключаем библиотеки 
include('/phpImap/Mailbox.php');
include('/phpImap/IncomingMail.php');
//Для удобства создам константы для подключения к почтовому серверу.
define('MAIL_IMAP_SERVER', 'imap.yandex.ru');
define('MAIL_IMAP_SERVER_PORT', 993);
define('MAIL_IMAP_LOGIN', '[email protected]'); 
define('MAIL_IMAP_PASS', 'example_pass');
define('MAIL_IMAP_PATH', '{'.MAIL_IMAP_SERVER.':'.MAIL_IMAP_SERVER_PORT.'/imap/ssl}INBOX');
$mailbox = new PhpImap\Mailbox(MAIL_IMAP_PATH, MAIL_IMAP_LOGIN, MAIL_IMAP_PASS, __DIR__);
try {
    $mailbox->getImapStream();
} catch (Exception $e) {
    die($e->getMessage());
}

Как мы видим конструктор класса Mailbox принимает следующие аргументы:

  • MAIL_IMAP_PATH - Cодержит в себе адрес сервера (MAIL_IMAP_SERVER), порт подключения (MAIL_IMAP_SERVER_PORT), тип соединения (imap) и показываем что соединение будет зашифровано (ssl). После фигурных скобок указываем папку к которой будем подключаться, в данном случае к входящим сообщениям (INBOX).
  • MAIL_IMAP_LOGIN - Почтовый ящик которому будем подключатся.
  • MAIL_IMAP_PASS - Пароль (чаще всего это пароль от почтового ящика).
  • __DIR__ - Это путь к папке в которой будут сохраняться вложенные файлы и почтовые сообщения.

После этого мы проверим, создалось ли наше подключение через метод getImapStream() если по какой-то причине подключения не создастся то приложение выбрасывает исключения с причиной не удачного подключения.

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

Теперь давайте сравним подключение к почте Gmail.

define('MAIL_IMAP_SERVER', 'imap.gmail.com');
define('MAIL_IMAP_SERVER_PORT', 993);
define('MAIL_IMAP_LOGIN', '[email protected]'); 
define('MAIL_IMAP_PASS', 'example_pass'); 
define('MAIL_IMAP_PATH', '{'.MAIL_IMAP_SERVER.':'.MAIL_IMAP_SERVER_PORT.'/imap/ssl}INBOX');

Как мы видим оно практически не отличается от предыдущего подключения, но скорей всего у Вас сработает исключение при подключении к серверу.
Это проблема связана с тем что в Gmail работа протокола IMAP отключена по умолчанию. Включить её можно в настройках во вкладке Пересылка и POP/IMAP в опции Доступ по протоколу IMAP ⇒ Включить IMAP.

После того когда мы включили работу по протоколу IMAP нам надо создать пароль приложение. Для того чтобы его можно было создать нам необходимо сделать двух факторную авторизацию для данного профиля. После чего можно приступить к его созданию. Когда мы создадим новый пароль для приложения нам необходимо его будет вписать в константу MAIL_IMAP_PASS для подключения к серверу.

Учтите что при создании пароля приложений у Вас может быть так и не получится подключиться к серверу это связно с тем что данный пароль еще не применялся окончательно к сервису Gmail обычно это занимает 5-60 минут.

Выборка данных

После успешного подключения, мы можем выполнить запрос для получения потовых сообщений из сервера. Для этого мы будем использовать метод searchMailBox(string $criteria) который по сути является оберткой метода imap_search. Тут важно понять что аргумент $criteria является неким критерием поиска нужных нам сообщений, сам метод возвращает идентификаторы элементов которые в последствии нам пригодятся для получения детальной информации почтового сообщения.

$mailsIds = $mailbox->searchMailBox('ALL');

Как Вы уже догадались тут мы получаем все сообщения.
А теперь давайте попробуем разобраться и с другими не менее важными критериями поиска:

//Все сообщения за 3 дня.
$mailsIds = $mailbox->searchMailBox('SINCE "'.date('d-M-Y',strtotime("-3 day")).'"'); 
//Непрочитанные сообщения за 3 дня.
$mailsIds = $mailbox->searchMailBox('UNSEEN SINCE "'.date('d-M-Y',strtotime("-3 day")).'"');
//Поиск сообщений с таким соответствием в заголовке TEXT.
$mailsIds = $mailbox->searchMailBox('TEXT "Новостная рассылка"');
//Поиск сообщений с таким соответствием в заголовке BODY.
$mailsIds = $mailbox->searchMailBox('BODY "Информационное сообщение"');
//Поиск по емейлу отправителя.
$mailsIds = $mailbox->searchMailBox('FROM "[email protected]"');
//Получить сообщения  по заголовку SUBJECT
$mailsIds = $mailbox->searchMailBox('SUBJECT "Выпущены обновления для вашего телефона"');

Данный пример хорошо отражает основы использование критериев поиска.

Получение информации

Теперь когда у нас есть массив идентификаторов сообщений мы готовы его обработать:

//Получаем идентификатор последнего сообщения из массива.
$id = end($mailsIds);
//Получаем экземпляр объекта класса IncomingMail который содержит информацию о сообщении.
$mail = $mailbox->getMail($id);
//Получаем файлы вложенные к данному сообщению если он есть.
$mail->getAttachments();
//Выводим сообщения.
echo $mail->textHtml;

Вот мы и получили сообщения из нашего письма и его вложения без всяких заморочек.

Дополнительные возможности.

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

Сохраняем сообщения по его ид.

$mailbox->saveMail($id,$id.'.eml');

Устанавливаем сообщения как непрочитанное по его id.

$mailbox->markMailAsUnread($id);

Устанавливаем сообщения как прочитанное по его id.

$mailbox->markMailAsRead($id);

Устанавливаем на сообщение пометку по его id.

$mailbox->markMailAsImportant($id);

Удаляем сообщения по его id.

$mailbox->deleteMail($id);

Естественно мы здесь рассмотрели только незначительную часть но очень важную при работе с входящими почтовыми сообщениями. Также вы можете скачать рассмотренное нами приложение.