Статьи

Изучение библиотеки PHP IMAP, часть 1

Некоторые веб-приложения могут требовать, чтобы функции почтового клиента были доступны пользователям. В этих ситуациях мы можем либо написать свои собственные, либо настроить клиенты с открытым исходным кодом, такие как SquirrelMail или Roundcube. Независимо от того, что вы выберете, знание работы с почтовым расширением PHP IMAP будет полезно.

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

Чтобы продемонстрировать функциональность, я буду использовать примеры кода, которые можно использовать для запуска сценариев вашего собственного почтового клиента. Я предполагаю один веб-скрипт, который использует эти параметры URL для вызова необходимых функций:

  • func — тип требуемой функциональности (например: чтение электронной почты, просмотр входящих сообщений, удаление сообщений)
  • folder — имя папки почтового ящика для подключения (например: входящие, отправленные, спам)
  • uid — уникальный идентификатор таргетинга электронной почты

Параметры можно получить с помощью $_GET а оператор switch можно использовать для вызова соответствующих действий.

 <?php $func = (!empty($_GET["func"])) ? $_GET["func"] : "view"; $folder = (!empty($_GET["folder"])) ? $_GET["folder"] : "INBOX"; $uid = (!empty($_GET["uid"])) ? $_GET["uid"] : 0; // connect to IMAP // ... switch ($func) { case "delete": deleteMail($imap, $folder, $uid); break; case "read": deleteMail($imap, $folder, $uid); break; case "view": default: viewMail($imap, $folder); break; } 

Подключение к IMAP

Чтобы установить соединение с сервером IMAP, мы используем imap_connect() как показано здесь:

 <?php $imap = imap_open($mailboxPath, $username, $password); 

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

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

  • Gmail {imap.gmail.com:993/imap/ssl}INBOX
  • Yahoo {imap.mail.yahoo.com:993/imap/ssl}INBOX
  • AOL {imap.aol.com:993/imap/ssl}INBOX

На некоторых серверах SSL не включен, и в этом случае вы не указали бы «SSL» в строке. Другие серверы могут использовать самозаверяющие сертификаты, в которые вы можете включить «novalidate-cert».

 <?php $imap = imap_open("{localhost:993/imap/ssl/novalidate-cert}", "username", "password"); 

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

  • Отображение списка папок почтовых ящиков в вашей учетной записи электронной почты
  • Отображение списка почтовых сообщений в папке
  • Просмотр содержимого письма

Перечисление папок

Папки «Входящие», «Отправленные», «Корзина» и «Спам» присутствуют практически во всех учетных записях электронной почты, и пользователи часто могут создавать собственные папки. Чтобы просмотреть сообщения в этих папках, нам нужно изменить строку подключения. Например, я использовал «INBOX» в строке пути ранее. Если бы я хотел подключиться к папке со спамом, я мог бы вместо этого использовать что-то вроде «Спам». Но даже если он будет указан как спам в вашей учетной записи электронной почты при просмотре через почтовый клиент, реальное имя папки может не совпадать. Мы можем перечислить все доступные папки в учетной записи, используя imap_list() .

 <?php $folders = imap_list($imap, "{imap.gmail.com:993/imap/ssl}", "*"); echo "<ul>"; foreach ($folders as $folder) { $folder = str_replace("{imap.gmail.com:993/imap/ssl}", "", imap_utf7_decode($folder)); echo '<li><a href="mail.php?folder=' . $folder . '&func=view">' . $folder . '</a></li>'; } echo "</ul>"; 

Мы должны передать дескриптор соединения, полученный с помощью imap_open() в качестве исходного параметра, в imap_list() . Нам также нужно пропустить пустую строку пути (без папки, например, «INBOX»). Звезда в качестве третьего параметра запрашивает все доступные папки.

Список сообщений электронной почты

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

Сначала нам нужно получить количество доступных сообщений, используя imap_num_msg() . Затем мы можем использовать функцию imap_header() чтобы получить информацию заголовка для каждого сообщения.

Скажем, если мы хотим, чтобы последние 20 писем:

 <?php $numMessages = imap_num_msg($imap); for ($i = $numMessages; $i > ($numMessages - 20); $i--) { $header = imap_header($imap, $i); $fromInfo = $header->from[0]; $replyInfo = $header->reply_to[0]; $details = array( "fromAddr" => (isset($fromInfo->mailbox) && isset($fromInfo->host)) ? $fromInfo->mailbox . "@" . $fromInfo->host : "", "fromName" => (isset($fromInfo->personal)) ? $fromInfo->personal : "", "replyAddr" => (isset($replyInfo->mailbox) && isset($replyInfo->host)) ? $replyInfo->mailbox . "@" . $replyInfo->host : "", "replyName" => (isset($replyTo->personal)) ? $replyto->personal : "", "subject" => (isset($header->subject)) ? $header->subject : "", "udate" => (isset($header->udate)) ? $header->udate : "" ); $uid = imap_uid($imap, $i); echo "<ul>"; echo "<li><strong>From:</strong>" . $details["fromName"]; echo " " . $details["fromAddr"] . "</li>"; echo "<li><strong>Subject:</strong> " . $details["subject"] . "</li>"; echo '<li><a href="mail.php?folder=' . $folder . '&uid=' . $uid . '&func=read">Read</a>'; echo " | "; echo '<a href="mail.php?folder=' . $folder . '&uid=' . $uid . '&func=delete">Delete</a></li>'; echo "</ul>"; } 

Соединение $imap должно быть открыто для нужной папки. Затем мы можем просмотреть последние 20 электронных писем, используя количество сообщений, полученных imap_num_msg() . Соединение и номер электронной почты присваиваются imap_header() для получения информации заголовка, которую затем можно проанализировать на предмет интересных деталей, таких как адрес электронной почты и имя отправителя, тема и т. Д.

Обратите внимание, что номер электронной почты, который мы получаем при использовании общего количества сообщений, не является уникальным идентификатором сообщения. Если в вашем почтовом ящике 100 писем, то последним будет 100, предыдущим будет 99 и т. Д. Но это не уникально. Если вы удалите сообщение с номером 100, а затем получите новое сообщение, его номер также будет равен 100.

Мы должны получить уникальный идентификатор для электронной почты, чтобы продолжить другие действия. Каждое письмо имеет уникальный идентификатор, называемый UID, который мы можем получить, imap_uid() номер электронной почты для функции imap_uid() . UID уникален и не изменится со временем.

Просмотр содержимого сообщения

Чтение электронной почты на самом деле не так просто, как предыдущие задачи, поэтому я собираюсь использовать класс Receive Mail, разработанный Mitul Koradia, в качестве отправной точки, чтобы упростить задачу. Из класса я извлек и адаптировал следующие три функции для нашего примера здесь:

 <?php function getBody($uid, $imap) { $body = get_part($imap, $uid, "TEXT/HTML"); // if HTML body is empty, try getting text body if ($body == "") { $body = get_part($imap, $uid, "TEXT/PLAIN"); } return $body; } function get_part($imap, $uid, $mimetype, $structure = false, $partNumber = false) { if (!$structure) { $structure = imap_fetchstructure($imap, $uid, FT_UID); } if ($structure) { if ($mimetype == get_mime_type($structure)) { if (!$partNumber) { $partNumber = 1; } $text = imap_fetchbody($imap, $uid, $partNumber, FT_UID); switch ($structure->encoding) { case 3: return imap_base64($text); case 4: return imap_qprint($text); default: return $text; } } // multipart if ($structure->type == 1) { foreach ($structure->parts as $index => $subStruct) { $prefix = ""; if ($partNumber) { $prefix = $partNumber . "."; } $data = get_part($imap, $uid, $mimetype, $subStruct, $prefix . ($index + 1)); if ($data) { return $data; } } } } return false; } function get_mime_type($structure) { $primaryMimetype = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER"); if ($structure->subtype) { return $primaryMimetype[(int)$structure->type] . "/" . $structure->subtype; } return "TEXT/PLAIN"; } 

Функция getBody() получает содержимое письма, передавая его UID и соединение IMAP. Внутри функции мы вызываем get_part() с типом содержимого TEXT / HTML. Простые текстовые электронные письма намного легче читать. Поэтому сначала мы пытаемся найти содержимое HTML внутри электронного письма.

Затем мы читаем структуру письма, используя imap_fetchstructure() . Эта функция взяла бы номер электронной почты по умолчанию, но мы изменили библиотечную функцию, чтобы использовать вместо FT_UID UID, передав константу FT_UID .

Затем мы получаем mime-тип сообщения электронной почты, используя get_mime_type() . Есть восемь типов MIME, возвращаемых этой функцией в виде целых чисел:

  • 0 — ТЕКСТ
  • 1 — МУЛЬТИПАРТ
  • 2 — СООБЩЕНИЕ
  • 3 — ПРИМЕНЕНИЕ
  • 4 — АУДИО
  • 5 — ИЗОБРАЖЕНИЕ
  • 6 — ВИДЕО
  • 7 — ДРУГОЕ

Мы преобразуем возвращаемое целое число в фактическую строку типа mime, используя массив типов mime.

Составные сообщения могут иметь большое количество подтипов, поэтому мы рекурсивно просматриваем все подтипы, используя номера imap_fetchBody() и извлекаем содержимое электронной почты, используя imap_fetchBody() когда правильная часть найдена с использованием типа mime.

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

  • 0 — 7 бит
  • 1 — 8 бит
  • 2 — Двоичный
  • 3 — BASE64
  • 4 — цитируемая печать
  • 5 — ДРУГОЙ

Резюме

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

Изображение через Fotolia