Статьи

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

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

Работа с флагами электронной почты

С каждым сообщением обычно связан список флагов: непрочитанный, отвеченный, помеченный, черновик и т. Д. Мы можем проверить свойство сообщения « Unseen Если сообщение было просмотрено, мы получим значение «U». Итак, возвращаясь к коду из первой части, давайте изменим его, чтобы показать состояние чтения / непрочитанного.

 <?php
$numMessages = imap_num_msg($imap);
for ($i = $numMessages; $i > ($numMessages - 20); $i--) {
    $header = imap_header($imap, $i);

    ...

    $uid = imap_uid($imap, $i);
    $class = ($header->Unseen == "U") ? "unreadMsg" : "readMsg";

    echo "<ul class="' . $class . '">';
    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>";
}

Мы можем проверить состояние свойства Unseen

 .unreadMsg {
    color: #000;
    font-weight: bold;
}

.readMsg {
    color: #999;
}

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

 <?php
if ($header->Flagged == "F") {
    $class .= " flaggedMsg";
}

Чтобы установить флаги для сообщения, мы используем impa_setflag_full()

 <?php
$status = imap_setflag_full($imap, $uid, "\Seen \Flagged", ST_UID);

Приведенный выше код помечает сообщение как «Read (\ Seen)» и устанавливает помеченный статус на «F». Я всегда предпочитаю использовать UID вместо порядкового номера электронной почты в качестве второго параметра, поэтому я должен установить необязательный четвертый параметр с константой ST_UID С помощью этой функции вы также можете указать другие флаги, такие как Черновик, Удаленный и Ответ.

Хотя я установил флаги только для одного сообщения, вы можете указать диапазон, например «1,10», в качестве второго параметра для установки флагов для нескольких сообщений, если хотите.

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

Функция imap_delete() Он помечает их для удаления, но фактически не удаляет их из вашей учетной записи. Функция imap_expunge()

 <?php
imap_delete($imap, $uid, FT_UID);
imap_expunge($imap);

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

Просмотр вложений электронной почты

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

Существуют различные методы для чтения структуры сообщения и идентификации вложений. Библиотека, упомянутая в первой части, класс Receive Mail, разработанный Mitul Koradia, также имеет функции для их загрузки. Но здесь я буду использовать функции, включенные в раздел комментариев для функции imap_fetchstructure()

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

  stdClass Object
 (
   [тип] => 1
   [кодировка] => 0
   [ifsubtype] => 1
   [subtype] => MIXED
   [ifdescription] => 0
   [ifid] => 0
   [ifdisposition] => 0
   [ifdparameters] => 0
   [ifparameters] => 1
   [параметры] => массив
     (
       [0] => stdClass Object
         (
             [attribute] => ГРАНИЦА
             [значение] => bcaec54b516462cef304c7e9d5c3
         )
     )
   [parts] => Массив
     (
       [0] => stdClass Object
         (
           [тип] => 1
           [кодировка] => 0
           [ifsubtype] => 1
           [subtype] => АЛЬТЕРНАТИВА
           [ifdescription] => 0
           [ifid] => 0
           [ifdisposition] => 0
           [ifdparameters] => 0
           [ifparameters] => 1
           [параметры] => массив
             (
               [0] => stdClass Object
                 (
                   [attribute] => ГРАНИЦА
                   [значение] => bcaec54b516462ceeb04c7e9d5c1
                 )
             )
           [parts] => Массив
             (
               [0] => stdClass Object
                 (
                   [тип] => 0
                   [кодировка] => 0
                   [ifsubtype] => 1
                   [subtype] => PLAIN
                   [ifdescription] => 0
                   [ifid] => 0
                   [линии] => 1
                   [bytes] => 2
                   [ifdisposition] => 0
                   [ifdparameters] => 0
                   [ifparameters] => 1
                   [параметры] => массив
                     (
                       [0] => stdClass Object
                         (
                           [attribute] => CHARSET
                           [значение] => ISO-8859-1
                         )
                     )
                 )
               [1] => stdClass Object
                 (
                   [тип] => 0
                   [кодировка] => 0
                   [ifsubtype] => 1
                   [subtype] => HTML
                   [ifdescription] => 0
                   [ifid] => 0
                   [линии] => 1
                   [байтов] => 6
                   [ifdisposition] => 0
                   [ifdparameters] => 0
                   [ifparameters] => 1
                   [параметры] => массив
                     (
                       [0] => stdClass Object
                         (
                           [attribute] => CHARSET
                           [значение] => ISO-8859-1
                         )
                     )
                 )
             )
         )
       [1] => stdClass Object
         (
           [тип] => 3
           [кодировка] => 3
           [ifsubtype] => 1
           [subtype] => ZIP
           [ifdescription] => 0
           [ifid] => 0
           [bytes] => 115464
           [ifdisposition] => 1
           [disposition] => ПРИЛОЖЕНИЕ
           [ifdparameters] => 1
           [dparameters] => Массив
             (
               [0] => stdClass Object
                 (
                   [attribute] => FILENAME
                   [value] => weekly-reports.zip
                 )
             )
           [ifparameters] => 1
           [параметры] => массив
             (
               [0] => stdClass Object
                 (
                   [attribute] => NAME
                   [value] => weekly-reports.zip
                 )
             )
         )
     )
 ) 

Если вы внимательно посмотрите на конструкцию, вы увидите вложение как часть с disposition Это письмо имеет 1 вложение, но вполне возможно иметь несколько вложений и, следовательно, несколько частей с «ATTACHMENT». Мы можем легко идентифицировать вложения, проверив этот параметр.

 <?php
$mailStruct = imap_fetchstructure($imap, $i);
$attachments = getAttachments($imap, $i, $mailStruct, "");

Внутри функции viewMailbox() Сначала мы получаем структуру каждого письма с помощью функции imap_fetchstructure (). Он вернет объект, подобный показанному ранее. Затем мы вызываем getAttachments()

 <?php
function getAttachments($imap, $mailNum, $part, $partNum) {
    $attachments = array();

    if (isset($part->parts)) {
        foreach ($part->parts as $key => $subpart) {
            if($partNum != "") {
                $newPartNum = $partNum . "." . ($key + 1);
            }
            else {
                $newPartNum = ($key+1);
            }
            $result = getAttachments($imap, $mailNum, $subpart,
                $newPartNum);
            if (count($result) != 0) {
                 array_push($attachments, $result);
             }
        }
    }
    else if (isset($part->disposition)) {
        if ($part->disposition == "ATTACHMENT") {
            $partStruct = imap_bodystruct($imap, $mailNum,
                $partNum);
            $attachmentDetails = array(
                "name"    => $part->dparameters[0]->value,
                "partNum" => $partNum,
                "enc"     => $partStruct->encoding
            );
            return $attachmentDetails;
        }
    }

    return $attachments;
}

Сначала мы проверяем, установлены ли части для текущего электронного письма, а затем мы должны рекурсивно пройти через каждую часть. Мы должны изменить номер детали и передать его на рекурсивный вызов. Как видите, номера подразделов разбиты на точечные сегменты. Если у вас есть 3 уровня номера детали, это будет что-то вроде 1.0.1.

Когда другие детали недоступны, мы проверяем, доступен ли параметр утилизации и имеет ли он значение «ATTACHMENT». В таких ситуациях мы получаем структуру данной части, используя imap_bodystruct() И imap_bodystruct()imap_fetchstructure() Единственное различие между ними состоит в том, что мы можем использовать imap_bodystruct()

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

 <?php
echo "Attachments: ";
foreach ($attachments as $attachment) {

echo '<a href="mail.php?func=' . $func . '&folder=' . $folder . '&uid=' . $uid .
    '&part=' . $attachment["partNum"] . '&enc=' . $attachment["enc"] . '">' .
    $attachment["name"] . "</a>";
}

Загрузка приложений

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

 <?php
function downloadAttachment($imap, $uid, $partNum, $encoding, $path) {
    $partStruct = imap_bodystruct($imap, imap_msgno($imap, $uid), $partNum);

    $filename = $partStruct->dparameters[0]->value;
    $message = imap_fetchbody($imap, $uid, $partNum, FT_UID);

    switch ($encoding) {
        case 0:
        case 1:
            $message = imap_8bit($message);
            break;
        case 2:
            $message = imap_binary($message);
            break;
        case 3:
            $message = imap_base64($message);
            break;
        case 4:
            $message = quoted_printable_decode($message);
            break;
    }

    header("Content-Description: File Transfer");
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=" . $filename);
    header("Content-Transfer-Encoding: binary");
    header("Expires: 0");
    header("Cache-Control: must-revalidate");
    header("Pragma: public");
    echo $message;
}

Сначала нам нужно получить структуру данной части, чтобы идентифицировать имя вложения, что делается с помощью imap_bodystruct() Вы можете видеть, что я использовал imap_msgno( это потому, что imap_bodystruct () не принимает UID, поэтому мы должны преобразовать UID в порядковый номер.

Затем мы получаем содержимое вложения с помощью imap_fetchbody() Он будет получать только содержимое данного номера детали. Затем мы используем соответствующую функцию декодирования контента в соответствии с типом кодирования данного вложения для его декодирования.

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

Резюме

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

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