Как получить почту в PHP через IMAP, POP3

Как получить почту в PHP через IMAP, POP3

Как получить почту в PHP через IMAP, POP3

Как получить почту в PHP через IMAP, POP3

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

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

Собственно для начала, чтобы все заработало успешно вам нужно установить imap модуль php. Инструкций в интернете много, рассказывать об этом тут я не буду. Идем далее, секрет работы с разными протоколами кроется в методе подключения к почтовому серверу.

$inbox = imap_open('{'.$account->pop3_server.':995/novalidate-cert/pop3/ssl}INBOX', $account->pop3_login, $account->pop3_password);

Где свойства модели $account->pop3_server, $account->pop3_login и $account->pop3_password — это адрес сервера, логин и пароль от него соответственно. Например : pop.yandex.ru, maxim, maxim4569.

:995/novalidate-cert/pop3/ssl}INBOX

Здесь, как вы уже поняли 995, это порт. Флаг novalidate-cert отвечает за проверку сертификата ssl; pop3 — протокол подключения pop3; ssl — использовать ssl защиту. Здесь, также можно указать папку, с которой работаем. Так как в pop3 они не поддерживаются, указываем по умолчанию — INBOX.

Все просто. Дальше начинаются сложности и тысячи полуработающих инструкций в интернете, как получить почту.

Первым делом, нам нужно получить номера писем на сервере. Здесь есть много разных подходов, я выбрал поиск, выглядит это так:

$emails = imap_search($inbox,'ALL');

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

Так как в $emails у нас содержится массив номеров сообщений электронной почты, мы запускаем цикл по нему:

foreach($emails as $mail)

Теперь  $mail содержит номер конкретного письма в ящике, с ним мы и будем работать. Для получения заголовка письма, достаточно использовать функцию imap_headerinfo, параметрами которой являются наше подключение к серверу и номер сообщения.

$headers = imap_headerinfo($inbox, $mail);

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

imap_utf8

Дальше начинается самое интересное. Есть множество примеров, библиотек для получения текста письма и вложений. Я перечитал очень много статей на тему «Как получить почту в PHP через IMAP, POP3» и собрал все самое лучше и оптимальное на мой взгляд.

Как же получить текст сообщения? Тут все не так просто. Дело в том, что сообщения могут быть как обычными текстовыми, так и html. Из-за этого они получаются разными способами. Собрав все, получается примерно такой код:

$message = imap_fetchbody($inbox, $mail, 1.2);

if (imap_base64($message))
    $message = imap_base64($message);
else {
    $message = imap_fetchbody($inbox, $mail, 1);
    if (imap_base64($message))
        $message = imap_base64($message);
}

Что это все значит? Так как email сообщение состоит из нескольких частей, с помощью метода imap_fetchbody мы получаем нужную часть email сообщения, манипулируя третьим параметром в вызове метода. $inbox и $mail — наше подключение и номер сообщения, полученные ранее.

В случае с первым вызовом, мы получаем html часть сообщения, она обычно закодирована в base64 формате. Если она присутствует и PHP может ее раскодировать, мы используем эти данные. В случае неудачи, мы получаем текстовую часть сообщения. Здесь мы опять же пытаемся раскодировать сообщение, если оно закодировано. Почтовые сервера кодируют кириллицу так, например.

Таким образом, в результате выполнения этого участка кода, у нас, в переменной $message содержится текст сообщения, будь это html или обычный текст.

Идем дальше…вложения..

Здесь было очень сложно. Потому как люди пишут инструкции с кучей ненужных циклов, сторонних методов и т.д. и т.п. Я постарался максимально упростить все, получилось следующее:

$structure = imap_fetchstructure($inbox, $mail);

if (is_array($structure->parts))
{
    foreach ($structure->parts as $key => $part)
    {
        if ($part->ifdisposition && $part->disposition == "ATTACHMENT")
        {
            $uploadDir = 'assets/attachments/' . md5($headers->message_id) . '/';
            if (!file_exists($uploadDir))
                mkdir($uploadDir, 0777, true);
            elseif (!is_writable($uploadDir))
                chdir($uploadDir, 0777);
            $content = imap_fetchbody($inbox, $mail, $key+1);
            if($part->encoding == 3)
                $content = base64_decode($content);
            elseif($part->encoding == 4)
                $content = quoted_printable_decode($content);
            if(!empty($content) && $part->ifdparameters && is_array($part->dparameters))
            {
                foreach($part->dparameters as $object)
                    if(strtolower($object->attribute) == 'filename')
                    {
                        $file_name = $object->value;
                        file_put_contents($uploadDir.$file_name, $content);
                        break;
                    }
            }
        }
    }
}

Для начала, мы получаем структуру email сообщения с помощью метода imap_fetchstructure. Здесь можно получить много полезной информации, при необходимости, но нам потребуются части сообщения, которые находятся в свойстве parts в виде массива.

Дальше в цикле просматриваем все эти части:

foreach ($structure->parts as $key => $part)

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

if ($part->ifdisposition && $part->disposition == "ATTACHMENT")

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

$content = imap_fetchbody($inbox, $mail, $key+1);
if($part->encoding == 3)
    $content = base64_decode($content);
elseif($part->encoding == 4)
    $content = quoted_printable_decode($content);

Таким образом, в переменной $content у вас будет хранится раскодированное содержимое одного из вложенных файлов. Это содержимое вы можете сохранить на диск, как это я делаю.

Собственно это была небольшая инструкция на тему «Как получить почту в PHP через IMAP, POP3». Все методы универсальны для разных протоколов. Единственное, в IMAP вы можете еще работать с папками. В этой статье я рассмотрел самые сложные и неоднозначные моменты на мой взгляд.

Похожие записи
  • Как запустить веб приложение через NP... Как запустить веб приложение через NPM с помощью serve. Есть множество способов запустить свои web html проекты. Для этого потребуется веб-сервер. Есть несколько простых веб-серверов для nodejs, которые можно использовать для запуска приложений. Это очень удобно для разработки и отладки. В данной статье не берем Express, так как он довольно сложен для настройки и использования. [...]
  • Как отследить все Javascript события ... Привет, сегодня я хочу рассказать тебе о простом но очень полезном методе, который позволяет отследить все Javascript события в Chrome. Он тебе поможет отследить все события, все вызовы всех функций на твоем сайте. Очень полезная команда для отладки фронт-энда. [...]
  • Как пользоваться популярными трекерам... Как пользоваться популярными трекерами без стороннего софта, прокси серверов или расширений Все просто. Недавно я писал про один из способ улучшить работу вашего интернета, который вы можете найти здесь и здесь. Днс сервера гугла помогут вам с этим, но могут и не помочь, как было у меня, потому как провайдер блокировал весь трафик, поступающий с данного [...]
  • Встраивание Foundation в Laravel с по... Что такое Elixir? Elixir — это компонент Laravel, позволяющий без проблем встраивать scss, sass, less компоненты в ваш проект. С помощью данного компонента очень легко можно подключить любые фронт-энд пакеты из npm, скомпилировать их, вести версии. Инструкция Для начала, чтобы скомпилировать исходный код фронтэнд библиотек, как известно, вам необходимо установить node с менеджером пакетов npm. [...]
  • ORM для CodeIgniter Недавно я писал про свой небольшой проект — доработку для CodeIgniter. Прочитать предыдущие статьи вы можете здесь. Здесь пойдет речь о упрощенной версии этого проекта, которую вы можете найти здесь. Собственно второй проект является упрощенной версией первого, так как не содержит моих методов для получения данных. Если вы искали именно это, то прошу. Генераторы моделей [...]

2 комментариев

  1. 21.12.2016    

    Скиньте этот скрипт на на почту пож. Что то у меня не получается получить контент.

    • 14.02.2017    

      К сожалению целых исходников не осталось, не могу скинуть.

Добавить комментарий