imap库_探索PHP IMAP库,第2部分

imap库

In the first part of this series I discussed how to connect to IMAP servers using the PHP IMAP extension. In this part we’ll complete the series by discussing working with folders and reading email content. Let’s get started!

本系列第一部分中,我讨论了如何使用PHP IMAP扩展连接到IMAP服务器。 在这一部分中,我们将通过讨论使用文件夹和阅读电子邮件内容来完成本系列。 让我们开始吧!

使用电子邮件标志 (Working with Email Flags)

A list of flags are usually associated with each message: unread, replied, flagged, draft, etc. We can check the message’s Unseen property to identify whether it has been read or not. If the message has been viewed then we’ll get the value “U”. So going back to the code from part one, let’s modify it to show the read/unread status.

通常,每条消息都带有标志列表:未读,已答复,已标记,草稿等。我们可以检查消息的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>";
}

We can check the status of the Unseen property assign different CSS classes to the markup which can show the read/unread email information differently.

我们可以检查Unseen属性的状态,为标记分配不同CSS类,从而可以不同地显示已读/未读电子邮件信息。

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

.readMsg {
    color: #999;
}

We can also create special flags on emails. For example, let’s say we wanted to mark a message as starred. For this we use the Flagged property which will have the value “F” if the message is flagged.

我们还可以在电子邮件上创建特殊标记。 例如,假设我们要将邮件标记为已加星标。 为此,我们使用Flagged属性,如果标记了消息,则该属性的值为“ F”。

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

To set flags on a message, we use the impa_setflag_full() function.

要在消息上设置标志,我们使用impa_setflag_full()函数。

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

The above code marks the message as “Read(\Seen)” and sets the flagged status to “F”. I always prefer using a UID instead of email sequence number as the second parameter, so I must set the optional fourth parameter with the constant ST_UID. You can provide other flags, such as Draft, Deleted, and Answered with this function too.

上面的代码将消息标记为“ Read(\ Seen)”,并将标记的状态设置为“ F”。 我总是更喜欢使用UID而不是电子邮件序列号作为第二个参数,因此我必须使用常量ST_UID设置可选的第四个参数。 您也可以使用此功能提供其他标志,例如草稿,已删除和已回答。

Although I have set the flags on just a single message, you can provide a range like “1,10” as the second parameter for setting flags on multiple messages if you’d like.

尽管我仅在一条消息上设置了标志,但是您可以根据需要提供“ 1,10”之类的范围作为在多条消息上设置标志的第二个参数。

删除电子邮件 (Deleting Email Messages)

The imap_delete() function is used to delete messages. It marks them for deletion, but doesn’t actually remove them from your account. The imap_expunge() function is responsible for actually deleting the marked messages.

imap_delete()函数用于删除消息。 它会将它们标记为删除,但实际上并没有将其从您的帐户中删除。 imap_expunge()函数负责实际删除标记的消息。

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

I’ve called the delete function with a UID instead of sequence number. Otherwise, I risk losing important messages because of changes in sequence numbers (remember from part one that sequence numbers are not unique).

我用UID而不是序列号调用了delete函数。 否则,由于序列号的更改,我可能会丢失重要的消息(请从第一部分中记住,序列号不是唯一的)。

查看电子邮件附件 (Viewing Email Attachments)

Next to reading and sending emails, working with email attachments is probably the next most important feature of an email client. We’ll focus on checking for email attachments, displaying them, and downloading them.

除了阅读和发送电子邮件之外,使用电子邮件附件可能是电子邮件客户端的下一个最重要的功能。 我们将重点检查电子邮件附件,显示它们并下载它们。

There are various methods for reading the structure of a message and identifying attachments. The library mentioned in the first part, the Receive Mail class developed by Mitul Koradia, has features for downloading them as well. But here I’ll use functions included in the comments section for the imap_fetchstructure() function which I think is the easiest way.

有多种方法可以读取邮件的结构并识别附件。 第一部分提到的库是Mitul Koradia开发的Receive Mail类 ,它也具有下载它们的功能。 但是在这里,我将对imap_fetchstructure()函数使用注释部分中包含的函数,我认为这是最简单的方法。

Before taking a look at some code, I’d like to show you the structure of an email with attachments as returned by imap_fetchstructure().

在看一些代码之前,我想向您展示imap_fetchstructure()返回的带有附件的电子邮件的结构。

stdClass Object
(
  [type] => 1
  [encoding] => 0
  [ifsubtype] => 1
  [subtype] => MIXED
  [ifdescription] => 0
  [ifid] => 0
  [ifdisposition] => 0
  [ifdparameters] => 0
  [ifparameters] => 1
  [parameters] => Array
    (
      [0] => stdClass Object
        (
            [attribute] => BOUNDARY
            [value] => bcaec54b516462cef304c7e9d5c3
        )
    )
  [parts] => Array
    (
      [0] => stdClass Object
        (
          [type] => 1
          [encoding] => 0
          [ifsubtype] => 1
          [subtype] => ALTERNATIVE
          [ifdescription] => 0
          [ifid] => 0
          [ifdisposition] => 0
          [ifdparameters] => 0
          [ifparameters] => 1
          [parameters] => Array
            (
              [0] => stdClass Object
                (
                  [attribute] => BOUNDARY
                  [value] => bcaec54b516462ceeb04c7e9d5c1
                )
            )
          [parts] => Array
            (
              [0] => stdClass Object
                (
                  [type] => 0
                  [encoding] => 0
                  [ifsubtype] => 1
                  [subtype] => PLAIN
                  [ifdescription] => 0
                  [ifid] => 0
                  [lines] => 1
                  [bytes] => 2
                  [ifdisposition] => 0
                  [ifdparameters] => 0
                  [ifparameters] => 1
                  [parameters] => Array
                    (
                      [0] => stdClass Object
                        (
                          [attribute] => CHARSET
                          [value] => ISO-8859-1
                        )
                    )
                )
              [1] => stdClass Object
                (
                  [type] => 0
                  [encoding] => 0
                  [ifsubtype] => 1
                  [subtype] => HTML
                  [ifdescription] => 0
                  [ifid] => 0
                  [lines] => 1
                  [bytes] => 6
                  [ifdisposition] => 0
                  [ifdparameters] => 0
                  [ifparameters] => 1
                  [parameters] => Array
                    (
                      [0] => stdClass Object
                        (
                          [attribute] => CHARSET
                          [value] => ISO-8859-1
                        )
                    )
                )
            )
        )
      [1] => stdClass Object
        (
          [type] => 3
          [encoding] => 3
          [ifsubtype] => 1
          [subtype] => ZIP
          [ifdescription] => 0
          [ifid] => 0
          [bytes] => 115464
          [ifdisposition] => 1
          [disposition] => ATTACHMENT
          [ifdparameters] => 1
          [dparameters] => Array
            (
              [0] => stdClass Object
                (
                  [attribute] => FILENAME
                  [value] => weekly-reports.zip
                )
            )
          [ifparameters] => 1
          [parameters] => Array
            (
              [0] => stdClass Object
                (
                  [attribute] => NAME
                  [value] => weekly-reports.zip
                )
            )
        )
    )
)

If you look carefully at the structure, you’ll see the attachment as the part with disposition equal to “ATTACHMENT”. This mail has 1 attachment, but it is entirely possible to have multiple attachments and thus multiple parts with “ATTACHMENT”. We can easily identify attachments by checking this parameter.

如果仔细看一下结构,您会发现附件是disposition等于“ ATTACHMENT”的部分。 这封邮件有1个附件,但是完全可以有多个附件,因此有多个带有“ ATTACHMENT”的部分。 通过检查此参数,我们可以轻松识别附件。

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

Inside the viewMailbox() function I have included the above lines. First we get the structure of each mail using imap_fetchstructure() function. It will return an object like the one shown previously. Then we call the getAttachments() function, which will provide the attachment details.

viewMailbox()函数内部,我包括了以上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;
}

First we check whether parts are set for the current email and then we have to traverse through each part recursively. We have to modify the part number and pass it to the recursive call. As you can see, subpart numbers are broken up into dotted segments. If you have 3 levels of a part number, it would be something like 1.0.1.

首先,我们检查是否为当前电子邮件设置了部分,然后我们必须递归遍历每个部分。 我们必须修改零件号并将其传递给递归调用。 如您所见,子零件号被分成虚线部分。 如果您有3个级别的零件编号,它将类似于1.0.1。

When further parts are not available, we check whether the disposition parameter is available and whether its value is “ATTACHMENT”. In such situations we get the structure of the given part using imap_bodystruct(). Both imap_bodystruct() and imap_fetchstructure() provides the same output. The only difference between the two is that we can use imap_bodystruct() to get specific part information instead of the entire structure.

当没有其他零件可用时,我们检查处置参数是否可用以及其值是否为“ ATTACHMENT”。 在这种情况下,我们使用imap_bodystruct()获得给定零件的结构。 imap_bodystruct()imap_fetchstructure()提供相同的输出。 两者之间的唯一区别是,我们可以使用imap_bodystruct()获得特定的零件信息,而不是整个结构。

Now we have the list of attachment details for the given email and we loop through all the attachments and display download links for them:

现在,我们有了给定电子邮件的附件详细信息列表,并循环浏览所有附件并显示它们的下载链接:

<?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>";
}

下载附件 (Downloading Attachments)

To download an attachment, we need the email’s UID, the part number, and the encoding type of the attachment. I’ve included those parameters in the download link created above. Once the link is clicked, the following function can be invoked:

要下载附件,我们需要电子邮件的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;
}

First we need to get the structure of the given part to identify the attachment name, which is done with imap_bodystruct(). You can see that I used imap_msgno() to get the sequence number from the UID; this is because imap_bodystruct() doesn’t accept a UID so we have to convert the UID into the sequence number.

首先,我们需要获取给定部件的结构以标识附件名称,这是通过imap_bodystruct() 。 可以看到,我使用imap_msgno( )从UID获取序列号。 这是因为imap_bodystruct()不接受UID,因此我们必须将UID转换为序列号。

Next we get the attachment content using imap_fetchbody(). It will only receive the contents of the given part number. Then we use the appropriate content decoding function according to the encoding type of the given attachment to decode it.

接下来,我们使用imap_fetchbody()获得附件内容。 它将仅接收给定部件号的内容。 然后,根据给定附件的编码类型,使用适当的内容解码功能对其进行解码。

Finally, we output the attachment content with appropriate headers so the browser will download the file.

最后,我们输出带有适当标题的附件内容,以便浏览器下载文件。

摘要 (Summary)

We’ve completed our look at PHP’s IMAP functions and you should now have an understanding sufficient enough to put together a simple working email reader. Be sure to learn about the other functions that are available and explore them as well to broaden your understanding.

我们已经完成了对PHP IMAP函数的研究,现在您应该已经足够了解,可以组成一个简单的工作电子邮件阅读器。 请务必了解可用的其他功能并进行探索,以加深您的理解。

Image via Fotolia

图片来自Fotolia

翻译自: https://www.sitepoint.com/exploring-phps-imap-library-2/

imap库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值