PHP IMAP如何获取邮件正文的纯文本部分?而不是包含各种<html>标签等内容。

3
我正在尝试编写一个脚本,从Exchange服务器下载电子邮件并将其插入到数据库中,但我在以良好的方式获取电子邮件的“文本部分”方面遇到了问题。 < p > 我正在尝试编写一个脚本,从Exchange服务器下载电子邮件并将其插入到数据库中,但我在以良好的方式获取电子邮件的“文本部分”方面遇到了问题。 < /p > < p > < code > phpcode < /code > < /p >
<?PHP
$user = "email@domain.com";
$password = "password123";
$mbox = imap_open("{exchange01:993/imap/ssl/novalidate-cert}", $user, $password);

$message = imap_fetchbody($mbox,1,1);

print_r($message);

if($mbox)
{
    imap_close($mbox);
};
?>

整个html主体都被打印出来了。我想这是可以预料的,但我不想有这种情况发生。

<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=iso-8859-1"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@font-face
    {font-family:"Cambria Math";
    panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
    {font-family:Calibri;
    panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
    {font-family:Verdana;
    panose-1:2 11 6 4 3 5 4 4 2 4;}
@font-face
    {font-family:"Neo Sans Std";}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
    {margin:0cm;
    margin-bottom:.0001pt;
    font-size:11.0pt;
    font-family:"Calibri",sans-serif;
    mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
    {mso-style-priority:99;
    color:#0563C1;
    text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
    {mso-style-priority:99;
    color:#954F72;
    text-decoration:underline;}
span.E-postmall17

我只需要邮件正文的文本内容(签名、图片等内容我可以忽略)。

难道没有更简单的方法吗?比如说将长字符串粗略地分割成从<body...</body...然后再进一步分割?肯定有其他人也想解决同样的问题,但我在花了一整天的时间尝试和Google搜索之后仍然找不到答案。

我猜最终我只能将整个HTML响应插入数据库字段中,希望一切顺利,但我还是不愿意这么做。

求助啊,Stackoverflow!你是我的救星

解决方案编辑:

虽然不是我想要的完美解决方案,但它确实有效(需要稍作修改)。

echo strip_tags($message, '<body>');

仅输出

<body...>
Yayh the text i want!
</body .....>

部分。非常感谢@ThisGuyHasTwoThumbs(在评论中)。

编辑:

最终代码大致如下:

<?PHP
$user = "email@domain.com";
$password = "password";
$mbox = imap_open("{exchange01:993/imap/ssl/novalidate-cert}", $user, $password);

$message = imap_fetchbody($mbox,1,1);

$message = strip_tags($message, '<body>');
$message = explode(">", $message);
$message = explode("<", $message[1]);
$message = str_replace("&nbsp;", "", $message[0]);
$message = html_entity_decode($message);
$message = trim($message);
//Or the above three combined in one row
#$message = trim(html_entity_decode( str_replace("&nbsp;", "", $message[0])));

echo $message;

if($mbox)
{
    imap_close($mbox);
};
?>

该操作将删除变量开头的第一个<body something something something>和结尾处的</body>,然后消除开头和结尾处的空格。同时,它还将转换html编码的“字母”为其对应的字符,并删除 &nbsp等标记。


您是否没有将邮件正文内容(即文本)与电子邮件代码分开存储? - treyBake
@ThisGuyHasTwoThumbs 嗯?据我所知,imap_fetchbody($mbox,1,1); 是下载邮件正文的正确方法,下载的内容是您在上面看到的内容(+更多HTML文本,最后一些<body> YAYH THE TEXT I WANT(带有一些更多的HTML垃圾)</body>。 - Tamazin
我更多的意思是,如果你将 $body 存储在一个变量中,那么你就拥有了 <body> 标签之间的所有内容,然后你可以使用 strip_tags 来摆脱其余的内容。 - treyBake
@ThisGuyHasTwoThumbs 哦..!正是我在寻找的,非常感谢!我已经为这个问题苦恼了几个小时 xD - Tamazin
不用担心 :)哈哈 - treyBake
3个回答

2

使用$message = imap_fetchbody($mbox,1,1.1);

将会返回邮件的纯文本部分,而非整个邮件内容。如果想要获取html部分,请使用1.2。

(empty) - 整个邮件 0 - 邮件头部 1 - 多部分/可选部分 1.1 - 文本/纯文本 1.2 - 文本/HTML 2 - MESSAGE/RFC822 (附加的整个邮件) 2.0 - 附加邮件头部 2.1 - 文本/纯文本 2.2 - 文本/HTML 2.3 - 文件名.ext

根据http://php.net/manual/en/function.imap-fetchbody.php上第二条评论所述,它还有一些很好的函数可以动态计算可用的邮件部分,因此您不必太担心邮件类型和数据。


不幸的是,那个方法不起作用。对于仅具有文本正文且没有任何MIME附件的电子邮件消息,imap-fetchbody()将为每个请求的部分编号返回以下内容:(空)- 整个消息 0 - 消息头 1 - 正文文本消息是这样的,所以我只能选择0或1(1.1、1.2、2、2.1、2.2等都不起作用)。即使电子邮件带有png图像和一些其他内容(带有签名等常规邮件)。 - Tamazin
如果我是你,我会循环遍历可用的部件,并检查因为几乎没有邮件客户端不提供a)MIME和b)将HTML拆分为纯文本正文部分。 - Dave
我尝试过了,但无法使其工作。使用:$structure = imap_fetchstructure($mbox, $email_number);我可以看到三个[部分],第一个是文本(在html中),另外两个是两个PNG。我正在使用Outlook将电子邮件发送到常规Exchange2010服务器。当然,我更喜欢直接获取“纯文本”,而不是HTML,然后根据自己的喜好进行格式设置...但是我没有做到这一点:( - Tamazin
很奇怪,因为 Outlook 默认会在 HTML 框中输入的任何内容上制作纯文本副本,并且始终(默认情况下)将它们制作为多部分 MIME 电子邮件。在旧时代,这会导致电子邮件膨胀问题,因为 Outlook 邮件与正常的电子邮件客户端相比要大得多。 - Dave
是的,我想现代版本的Outlook应该可以做到,但出于某种原因它似乎不起作用。必须进一步调查。如果我能找到原因,那么修复将很容易(下载纯文本)。 - Tamazin
检查Outlook设置。我没有在这台机器上安装它,因为我使用Linux,但我相信在Outlook中有一个选项,如果您想在整个公司范围内设置它,您可以通过GPO进行设置。 - Dave

1

是的,它确实解决了问题(除了在<body>标签之前和之后有很多空格)。虽然不是“完美”的解决方案,但已经足够好了。 - Tamazin
@Tamazin,我编辑了问题,以解决如何处理多余的空格。 - Goose
是的,我用 trim 方法和分割字符串的方式处理了它,以删除开头的 <body..> 部分和结尾的 </body> 部分。现在,我只需要正确编码我的瑞典字母 åäö,或许还要去掉 &nbsp 等乱七八糟的东西,然后作为一个快乐的程序员;D 谢谢! - Tamazin

0

您可以通过以下详细信息将电子邮件正文转换为纯文本:

$ClearText = preg_replace( "/\n\s+/", "\n", rtrim(html_entity_decode(strip_tags($body))) );

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