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

Posted

技术标签:

【中文标题】如何使用 imap 扩展获取原始电子邮件数据?【英文标题】:How to get raw email data with the imap extension? 【发布时间】:2012-05-04 20:03:59 【问题描述】:

我正在寻找一种下载整个原始电子邮件数据(包括附件)的方法,类似于您在 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 的第三个参数可能会返回编码的附件。我想我这里需要一个循环来部分获取原始电子邮件,但是停止循环的条件是什么?

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

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

我的回答是“过度完成”,如果您不需要电子邮件。

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

标头imap_fetchheader。 获取邮件的正文数量imap_fetchstructure。 每个矿井头都有imap_fetchmime。 它拥有imap_fetchbody的每个实体。

由于 mime-message 可以有多个正文,您需要一个接一个地处理每个部分。要减少服务器的负载,请使用imap_fetchheaderFT_PREFETCHTEXT 选项。一些示例 code about imap_fetchstructure in another answer 显示了处理 imap 连接并通过封装对消息的部分进行迭代。

【讨论】:

向下滚动,使用imap_fetchbody($imap_stream, $msg_num, "") 更简单,而且效果很好! 我也不确定这是否回答了这个问题,因为它没有界限。【参考方案2】:

我在搜索相同问题时遇到了这个问题。我知道它必须比 hakre 的解决方案更容易,并且我在 post from 5 years ago 的 imap_fetchbody 页面上找到了正确答案。

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

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

注意空字符串作为imap_fetchbody 的第三个参数,这表示电子邮件的所有部分和子部分,包括标题和所有正文。

【讨论】:

太棒了!它会获取附件吗? @VeeeneX 是的,它会获取所有内容。附件确实需要解码,它们通常是 base64 编码的。现在电子邮件提供商允许使用 OneDrive/GoogleDrive 发送“附件”,这些不是真正的附件,它们不会被获取。 这是最好的解决方案——只用一行来检索完整的消息,这样您就可以将其输入解析器。 $raw_full_email = imap_fetchbody($handle, $num, ""); $Parser = new phpMimeMailParser\Parser(); $Parser->setText($raw_full_email); 有没有其他人从这个PHP Warning: imap_fetchbody(): Bad message number in ...得到错误?【参考方案3】:

hakre 的回答过于完整,如果您不真正关心结构,那么您将不需要imap_fetchstructure。

对于一个简单的“显示源”,您应该只需要 imap_fetchheader 和 imap_body。

示例:

$conn = imap_open(''."$mailServer:$port/pop3INBOX", $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】:

一个常见的错误是使用"\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);

【讨论】:

以上是关于如何使用 imap 扩展获取原始电子邮件数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何理解 IMAP 电子邮件文本中的等号“=”符号?

如何配置 Logstash IMAP 插件以从 SMTP 服务器获取电子邮件

如何使用 IMAP 发送邮件?

IMAP:如何将邮件从一个文件夹移动到另一个文件夹

如何确定是不是通过 imap base64 编码获取邮件?

php imap 从电子邮件地址获取