最近,我一直在实现一些基于PHP/IMAP的电子邮件处理功能,并且除消息正文解码(在某些情况下)外,大多数功能都可以正常运行。

我认为,到目前为止,我已经半记了RFC 2822(“Internet消息格式”文档指南),通读了六个开源CMS的电子邮件处理代码,并阅读了不计其数的论坛帖子,博客帖子等。 。处理PHP中的电子邮件。

我还 fork 并完全重写了PHP,Imap的类,并且该类可以很好地处理电子邮件-我那里有一些有用的方法来检测自动响应程序(用于不在办公室,旧地址等),解码base64和8bit讯息等

但是,我根本无法可靠地工作(或有时根本无法工作)的一件事是当消息随Content-Transfer-Encoding: 7bit一起传入时。

似乎不同的电子邮件客户端/服务将7BIT解释为不同的意思。我收到了一些据信是7BIT的电子邮件,这些电子邮件实际上是Base64编码的。我得到了一些实际上被引用为可打印编码的代码。还有一些未进行任何形式的编码。还有一些是HTML,但未表示为HTML,它们也被列为7BIT ...

以下是使用7Bit编码接收到的消息正文的一些示例(片段):

1:

A random message=20

Sent from my iPhone

2:
PGh0bWwgeG1sbnM6dj0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTp2bWwi
IHhtbG5zOm89InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206b2ZmaWNlOm9m

3:
tangerine apricot pepper.=0A=C2=A0=0ALet me know if you have any availabili=
ty over the next month or so. =0A=C2=A0=0AThank you,=0ANames Withheld=0A908=
-319-5916=0A=C2=A0=0A=C2=A0=0A=C2=A0=0A=0A=0A______________________________=
__=0AFrom: Names Witheld =0ATo: Names Withheld=

这些都是,所有以“7Bit”编码发送(好吧,至少根据PHP/imap_*),但是在我可以将它们作为纯文本传递之前,显然它们需要更多的解码。有什么方法可以可靠地将所有假定为7Bit编码的消息转换为纯文本?

最佳答案

花了更多时间后,我决定写一些启发式检测程序,就像Max在对原始问题的评论中所建议的那样。

我在Imap.php中构建了一个更健壮的decode7Bit()方法,该方法会检查一堆常见的编码字符(例如=A0),并用等效的UTF-8替换它们,然后如果它们看起来像是base64编码的,则还会对其进行解码:

/**
 * Decodes 7-Bit text.
 *
 * PHP seems to think that most emails are 7BIT-encoded, therefore this
 * decoding method assumes that text passed through may actually be base64-
 * encoded, quoted-printable encoded, or just plain text. Instead of passing
 * the email directly through a particular decoding function, this method
 * runs through a bunch of common encoding schemes to try to decode everything
 * and simply end up with something *resembling* plain text.
 *
 * Results are not guaranteed, but it's pretty good at what it does.
 *
 * @param $text (string)
 *   7-Bit text to convert.
 *
 * @return (string)
 *   Decoded text.
 */
public function decode7Bit($text) {
  // If there are no spaces on the first line, assume that the body is
  // actually base64-encoded, and decode it.
  $lines = explode("\r\n", $text);
  $first_line_words = explode(' ', $lines[0]);
  if ($first_line_words[0] == $lines[0]) {
    $text = base64_decode($text);
  }

  // Manually convert common encoded characters into their UTF-8 equivalents.
  $characters = array(
    '=20' => ' ', // space.
    '=E2=80=99' => "'", // single quote.
    '=0A' => "\r\n", // line break.
    '=A0' => ' ', // non-breaking space.
    '=C2=A0' => ' ', // non-breaking space.
    "=\r\n" => '', // joined line.
    '=E2=80=A6' => '…', // ellipsis.
    '=E2=80=A2' => '•', // bullet.
  );

  // Loop through the encoded characters and replace any that are found.
  foreach ($characters as $key => $value) {
    $text = str_replace($key, $value, $text);
  }

  return $text;
}

这取自我在GitHub上拥有的Imap class for PHP的1.0-beta2版本。

如果您有任何想法可以提高效率,请告诉我。我最初尝试通过quoted_printable_decode()运行所有内容,但有时PHP会抛出模糊且无济于事的异常,因此我放弃了这种方法。

10-04 14:36