提取邮件内容
Posted
技术标签:
【中文标题】提取邮件内容【英文标题】:Extracting mail's content 【发布时间】:2016-04-20 23:47:00 【问题描述】:我需要创建一个应用来提取我们的客户发送给我们进行验证的增值税号。他们不再发送电子邮件。这是为了创建扩展统计信息。
我需要的是在我需要的内容之前没有任何标题的邮件正文,也就是增值税号,就这么简单。
这是我创建最近 30 封电子邮件列表的脚本:
<?
if (!function_exists('imap_open')) die('No function');
if ($mbox = imap_open(<confidential>))
$output = "";
$messageCount = imap_num_msg($mbox);
$x = 1;
for ($i = 0; $i < 30; $i++)
$message_id = ($messageCount - $i);
$fetch_message = imap_header($mbox, $message_id);
$mail_content = quoted_printable_decode(imap_fetchbody($mbox,$message_id, 1));
iconv(mb_detect_encoding($mail_content, mb_detect_order(), true), "UTF-8", $mail_content);
$output .= "<tr>
<td>".$x.".</td>
<td>
".$fetch_message->from[0]->mailbox."@".$fetch_message->from[0]->host."
</td>
<td>
".$fetch_message->date."
</td>
<td>
".$fetch_message->subject."
</td>
<td>
<textarea cols=\"40\">".$mail_content."</textarea>
</td>
</tr>";
$x++;
$smarty->assign("enquiries", $output);
$smarty->display("module_mail");
imap_close($mbox);
else
print_r(imap_errors());
?>
我曾使用 imap_fetchbody、imap_header 等来检索所需的内容,但事实证明,大多数电子邮件在内容之前都有其他内容(如标题),即。
--=-Dbl2eWTUl0Km+Tj46Ww1
Content-Type: text/plain;
------=_NextPart_001_003A_01D14F7A.F25AB3D0
Content-Type: text/plain;
--=-ucRIRGamiKb0Ot1/AkNc
Content-Type: text/plain;
我需要删除邮件消息中包含的增值税号之前的所有内容,但我不知道该怎么做。有些电子邮件没有这些标题,有些则有。而且由于我们正在与来自欧洲各地的客户合作,这真的让我感到困惑并且无能为力。
另一个问题是,一些客户只是从各种网站复制粘贴增值税号,这意味着这些增值税号通常以原始样式(粗体/背景/更改颜色等)粘贴。这可能是我下面 PS 的原因。
我将不胜感激能帮助我解决这个问题的每一个帮助。
提前谢谢你。
附言。只是为了记录。使用imap_fetchbody($mbox,$message_id, 1)
我需要使用1
来获取全部内容。将1
更改为其他任何内容都会导致根本不显示任何电子邮件内容。字面意思。
【问题讨论】:
Youn 可能会使用正则表达式:safaribooksonline.com/library/view/regular-expressions-cookbook/… 但如果用户从带有自身编号的 html 的网站复制,例如&nbsp;
而不是空格或 @,这仍然会失败987654328@标签等。您是否有理由不能在公司网站上创建一个简单的表单,以便控制数据的格式?
在 **se 中多么痛苦!你能做一些中途测量的形式吗,比如创建一个表单,而不是提交,创建并点击一个mailto:
链接?这样用户的电子邮件客户端会打开预先形成的内容?
如果做不到这一点,我至少会在您的网站上创建一个具有输入框的页面,通过上述正则表达式获取并验证数字,然后将预先格式化的响应吐出到文本区域,例如our VAT number: #######
带有复制和粘贴结果的说明。有了这个,我会尝试使用上述正则表达式从电子邮件中捕获数字,如果失败,发送自动回复,要求客户访问上述页面
【参考方案1】:
您定义为“噪音”的电子邮件部分只是电子邮件格式的一部分。 在某种程度上,就像您正在阅读网页的 html 代码一样。
所有这些位都是边界。电子邮件的那些元素就像 html 中的标签 就像 html 一样,它们开始并关闭。
所以在你的情况下:
Content-Type: multipart/alternative; boundary="=-Dbl2eWTUl0Km+Tj46Ww1" // define type of email structure and boudary
--=-Dbl2eWTUl0Km+Tj46Ww1 // used to start the section
Content-Type: text/plain; // to define the type of content of the section
// here there is your VAT presumbly
--=-Dbl2eWTUl0Km+Tj46Ww1-- // used to close the section
可能的解决方案
实际上,您至少有 2 个解决方案。
自己制作一个自定义解析器或使用名为 Mailparse 的 PECL
库。
手动制作解析器:
$mail_lines = explode($mail_content, "\n");
foreach ($mail_lines as $key => $line)
// jump most of the headrs
if ($key < 5)
continue;
// skip tag lines
if (strpos($line, "--"))
continue;
// skip Content lines
if (strpos($line, "Content"))
continue;
if (empty(trim($line)))
continue;
////////////////////////////////////////////////////
// here you have to insert the logic for the parser
// and extend the guard clauses
////////////////////////////////////////////////////
邮件解析:
安装邮件解析sudo pecl install mailparse
。
提取增值税:
$mail = mailparse_msg_create();
mailparse_msg_parse($mail, $mail_content);
$struct = mailparse_msg_get_structure($mail);
foreach ($struct as $st)
$section = mailparse_msg_get_part($mail, $st);
$info = mailparse_msg_get_part_data($section);
print_r($info);
【讨论】:
【参考方案2】:您必须使用imap_fetchstructure()
来查找邮件的纯文本部分。
以下代码可以为您提供text/plain
子部分的节号(例如“1.1”)
function getTextPart($struct)
if ($struct->type==0) return "1";
if ($struct->type==1)
$num=1;
foreach ($struct->parts as $part)
if (($part->type==0)&&($part->subtype="PLAIN"))
return $num;
else if ($part->type==1)
$found=getTextPart($part);
if ($found) return "$num.$found";
$num++;
return NULL;
使用示例:
if ($imap)
$messageCount = imap_num_msg($imap);
for ($i = 1; $i < 30; $i++)
$struct=imap_fetchstructure($imap, $i);
$part=getTextPart($struct);
$body=imap_fetchbody($imap, $i, $part);
print_r($body);
【讨论】:
以上是关于提取邮件内容的主要内容,如果未能解决你的问题,请参考以下文章
使用 OpenSSL 解码/提取 smime.p7m 文件内容(带有嵌入文件的电子邮件)?