如何使用imap扩展获取原始电子邮件数据?

13

我正在寻找一种方法来下载整个原始电子邮件数据(包括附件),类似于在Gmail中点击“显示原始邮件”的方式。

目前,我可以通过以下代码获取原始头和邮件正文的某些部分:

$this->MailBox = imap_open($mailServer, $userName, $password, OP_SILENT);
...
$email->RawEmail = imap_fetchbody($this->MailBox, $msgNo, "0");
$email->RawEmail .= "\n".imap_fetchbody($this->MailBox, $msgNo, "1");

我知道更改imap_fetchbody的第三个参数可能会返回编码的附件。我猜我需要在这里循环以逐个获取原始电子邮件部分,但停止循环的条件是什么?

有没有一种简单的方法可以一次获取整个电子邮件?

任何帮助都将不胜感激。

4个回答

19

在搜索同样的问题时,我遇到了这个问题。我知道解决方法一定比hakre提供的更简单,我在imap_fetchbody页面上找到了正确的答案,它是从5年前的帖子中获得的。

要获取完整的原始消息,只需使用以下代码:

$imap_stream = imap_open($server, $username, $password);
$raw_full_email = imap_fetchbody($imap_stream, $msg_num, "");

注意在 imap_fetchbody 的第三个参数中使用空字符串,这表示电子邮件的所有部分和子部分,包括头部和所有正文。


1
太棒了!它能获取附件吗? - VeeeneX
3
@VeeeneX 是的,它会获取所有东西。附件需要解码,通常是Base64编码。现在的电子邮件提供商允许使用OneDrive/GoogleDrive发送“附件”,但这些不是真正的附件,它们将不会被获取。 - Gonçalo Baltazar
这是最佳解决方案 - 只需一行代码即可检索完整消息,然后将其馈送到解析器中。$raw_full_email = imap_fetchbody($handle, $num, ""); $Parser = new PhpMimeMailParser\Parser(); $Parser->setText($raw_full_email); - Tramov
有其他人从这个 PHP Warning: imap_fetchbody(): Bad message number in ... 收到错误吗? - MrMesees

9

内容翻译:

如果您不关心邮件的结构,那么 hakre 给出的回答是过于详细了,您将不需要 imap_fetchstructure

对于简单的“显示源代码”,您只需要 imap_fetchheaderimap_body

示例:

$conn = imap_open('{'."$mailServer:$port/pop3}INBOX", $userName, $password, OP_SILENT && OP_READONLY);
$msgs = imap_fetch_overview($conn, '1:5'); /** first 5 messages */
foreach ($msgs as $msg) {
    $source = imap_fetchheader($conn, $msg->msgno) . imap_body($conn, $msg->msgno);
    print $source;
}

4

我的答案是"过度完备",如果您不需要整个电子邮件的结构,请参阅Boy Baukema的答案以获取更直接的"查看源代码"方法。

如果要全部获取,则需要获取:

由于mime消息可以具有多个正文,因此您需要逐个处理每个部分。为了减少对服务器的负载,请使用FT_PREFETCHTEXT选项进行imap_fetchheader。一些示例代码关于imap_fetchstructure在另一个答案中显示处理imap连接和迭代消息部分。


2
向下滚动,使用“imap_fetchbody($ imap_stream,$ msg_num,”“)”更简单,而且效果非常好! - Kapitein Witbaard
我也不确定这是否回答了问题,因为它没有涉及边界。 - MrMesees

0

一个常见的错误是使用"\n"PHP_EOL

根据RFC RFC821、RFC2060、RFC1939,应该使用"\r\n"。 虽然一些邮件服务器会自动转换这些错误,但Cyrus不会,并会抛出一个好的错误。

PHP_EOL是一个依赖于系统的常量,在Linux上是"\n",在Mac上是"\r",在Windows上是"\r\n",例如。

此外,imap_fetchheader()包含预期的尾随"\r\n"。因此,正确的示例应该是:

 $source = imap_fetchheader($conn, $msg->msgno) . imap_body($conn, $msg->msgno);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接