1

我正在尝试编写一个 PHP 程序,该程序使用 IMAP PHP 扩展来运行一个非常大的收件箱(超过 70,000 封电子邮件),并将指定日期范围内的所有电子邮件移动到一个文件夹中。我一直在尝试获取位于所需范围内的邮件时遇到问题。

首先,我尝试在 imap_search() 中使用 SINCE 和 BEFORE 条件将所有所需的 ID 号放入一个数组中,然后创建一个列出这些 ID 号的字符串以输入 imap_mail_move()。但我一直遇到的问题是 imap_search() 实际上从未返回指定范围内的所有电子邮件。例如,我运行了以下代码:

    echo "Beginning search. \n";
    $mail = imap_search($this->mbox, 
                   'SINCE "$startDate" BEFORE "$endDate"');
    echo "Search complete. \n";
    if (!$mail){echo "The inbox is empty. \n"; die();}

    $count = 0;
    foreach($mail as $i)
    {
        $count = $count + 1;
    }
    echo "Found $count emails. \n";

同时指定一个我知道可以容纳 600 封电子邮件的日期范围,而 imap_search() 只列出了其中的 259 封。当我将范围扩大到包含大约 75,000 封电子邮件的整个收件箱时,imap_search() 只返回了其中的 25,112 封。

当这不起作用时,我尝试了一种不同的、更慢的方法来获取所需日期范围内的所有电子邮件。我使用 imap_search() 收集收件箱中的所有电子邮件,然后遍历每封电子邮件,将电子邮件标题中包含的日期与定义我的时间间隔的日期进行比较,如果 ID 在范围内,则将其添加到字符串中。我运行了以下代码:

    // Get all mail in the INBOX
    $mail = imap_search($this->mbox, "ALL");
    if (!$mail){echo "The inbox is empty. \n"; die();}

    // Create a string list of all message IDs 
    //that fall in the specified range
    $processed = 0;
    $IDsequence = '';
    foreach($mail as $messageID)
    {
        $date = imap_headerinfo($this->mbox, $messageID)->date;
        try {$dateObject = new DateTime($date);}
        catch (Exception $e) {echo $e->getMessage(); echo "\n";}
        $dateObject->setTimezone($TimeZone); 
        if ($dateObject <= $IntervalEndDate && $dateObject >=
                          $IntervalStartDate)
        {
            $IDsequence = $IDsequence . "," . strval($messageID);
        }
        $processed = $processed + 1;
        if ($processed % 100 == 0)
        { echo "Processed $processed emails. \n"; }

    }
    // If we got at least one message, cut off the first comma.
    if (strlen($IDsequence) > 1){
        $IDsequence = substr($IDsequence, 1, strlen($IDsequence)-1);
    }
    else
    {
        echo "No e-mail to move. \n";
        die();
    }
    echo "Beginning copy. \n";
    imap_mail_copy($this->mbox, $IDsequence, $TargetFolder);
    echo "Copy complete. \n";
    //imap_expunge($this->mbox);
    imap_close($this->mbox);

在遍历超过 25,000 封电子邮件后,它开始打印错误消息“对象不存在”,引用我从电子邮件标题中收集日期的代码行。我在这里注意到故障仍然发生在大约 25,000 封电子邮件的某个地方,因此可能两种方法都出于相同的原因而中断。我怀疑我在消息 ID 上做错了(例如,我假设 75,000 封电子邮件的消息 ID 是“1”到“75,000”)。

出了什么问题?有没有办法收集大量在某个日期范围内的电子邮件并移动它们?

4

1 回答 1

0

或许邮箱中只有 25,112 封邮件,而另外约 50,000 封邮件在另一个邮箱中。例如,我知道 GMail 可能会报告收件箱的粗略总数,但这些邮件中有很大一部分实际上是存档的。

此时您可能需要进行完整性检查。:)

于 2013-06-24T23:27:11.533 回答