Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/248.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何从多部分电子邮件中获取文本内容?_Php_Email Parsing - Fatal编程技术网

Php 如何从多部分电子邮件中获取文本内容?

Php 如何从多部分电子邮件中获取文本内容?,php,email-parsing,Php,Email Parsing,那么,我如何才能将电子邮件的纯文本区域输入到我的文件或脚本中,以便进一步处理 提前谢谢。stackoverflow很棒 要隔离电子邮件正文的纯文本部分,您必须采取四个步骤: 1。获取MIME边界字符串 我们可以使用正则表达式搜索标题(假设它们位于单独的变量中,$headers): 正则表达式将搜索包含边界字符串的内容类型标题,然后将其捕获到第一个标题中。然后将捕获组复制到变量$boundary中 2。将电子邮件正文拆分为多个部分 一旦我们有了边界,我们就可以将正文分割成不同的部分(在您的消息正文

那么,我如何才能将电子邮件的纯文本区域输入到我的文件或脚本中,以便进一步处理


提前谢谢。stackoverflow很棒

要隔离电子邮件正文的纯文本部分,您必须采取四个步骤:

1。获取MIME边界字符串

我们可以使用正则表达式搜索标题(假设它们位于单独的变量中,
$headers
):

正则表达式将搜索包含边界字符串的
内容类型
标题,然后将其捕获到第一个标题中。然后将捕获组复制到变量
$boundary

2。将电子邮件正文拆分为多个部分

一旦我们有了边界,我们就可以将正文分割成不同的部分(在您的消息正文中,每次出现正文时,正文的前面都会有
--
)。根据该协议,第一个边界之前的所有内容都应忽略

$matches = array();
preg_match('#Content-Type: multipart\/[^;]+;\s*boundary="([^"]+)"#i', $headers, $matches);
list(, $boundary) = $matches;
这将给我们留下一个包含所有线段的数组,忽略第一个边界之前的所有内容

3。确定哪一段是纯文本。

纯文本段将有一个MIME类型为
text/plain的
内容类型
标题。现在,我们可以在每个段中搜索具有该标题的第一个段:

$email_segments = explode('--' . $boundary, $message);
array_shift($email_segments); // drop everything before the first boundary
因为我们寻找的是一个常量,所以我们可以使用(在字符串中查找子字符串的第一个实例,不区分大小写)而不是正则表达式。如果找到
内容类型
标题,我们就得到了片段

4。从段中删除任何标题

现在我们需要从找到的段中删除任何头,因为我们只需要实际的消息内容。这里可以显示四种类型:
内容类型
,正如我们前面看到的,
内容ID
内容处置
内容传输编码
。标头由
\r\n
终止,因此我们可以使用它来确定标头的结尾:

foreach ($email_segments as $segment)
{
  if (stristr($segment, "Content-Type: text/plain") !== false)
  {
    // We found the segment we're looking for!
  }
}
正则表达式末尾的
s
使点与任何换行符匹配
*?
将收集尽可能少的字符(即
\r\n
之前的所有字符);
是一个打开的
*

在这一点之后,
$text
将包含您的电子邮件内容

因此,要将其与您的代码结合起来:

$text = preg_replace('/Content-(Type|ID|Disposition|Transfer-Encoding):.*?\r\n/is', "", $segment);
有一个答案:

您只需更改以下两行:

<?php
// read from stdin
$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd))
{
    $email .= fread($fd, 1024);
}
fclose($fd);

$matches = array();
preg_match('#Content-Type: multipart\/[^;]+;\s*boundary="([^"]+)"#i', $email, $matches);
list(, $boundary) = $matches;

$text = "";
if (isset($boundary) && !empty($boundary)) // did we find a boundary?
{
  $email_segments = explode('--' . $boundary, $email);

  foreach ($email_segments as $segment)
  {
    if (stristr($segment, "Content-Type: text/plain") !== false)
    {
      $text = trim(preg_replace('/Content-(Type|ID|Disposition|Transfer-Encoding):.*?\r\n/is', "", $segment));
      break;
    }
  }
}

// At this point, $text will either contain your plain text body,
// or be an empty string if a plain text body couldn't be found.

$savefile = "savehere.txt";
$sf = fopen($savefile, 'a') or die("can't open file");
fwrite($sf, $text);
fclose($sf);
?>

这是完整的电子邮件吗?它缺少
内容类型:multipart/mixed
标题,该标题应指定边界字符串是什么(找到的代码需要该字符串)。这只是保存到文件中的电子邮件的一部分。这是我使用第一个代码示例所能得到的最简单的信息。边界标头对于能够解析电子邮件非常重要,因为它指定了电子邮件的每个部分的开始和结束位置。没有它,你所能做的就是猜测,你知道他们怎么说假设…;)例如,对于您引用的电子邮件,应该有如下标题:
Content-Type:multipart/mixed;boundary=“----=\u NextPart_000_0163_01CB4EA5.46466520”
来自不同的基于pc的电子邮件客户端或流行的免费电子邮件帐户的边界是相同的吗?我将标题变量添加到文件中并编辑了我的问题,以便为你们这些家伙/女孩添加这些信息……我想,我开始理解了。。所以,为了测试我会在//空变量之后替换所有内容吗???不完全是。这取决于您想做什么(例如,您可能希望继续拆分头或收集“特殊”头)。我的代码要求您有一个标题文本块和一个消息文本块,但您可以将我代码中的
$headers
$message
替换为
$email
,根据您的代码,它应该包含整个电子邮件。啊,我不明白!如何在上面的代码示例中实现这一点,以便对其进行测试?我能把你的片段放在写文件之前吗?然后写$text而不是$message?我真的很感谢你对这个初学者的帮助和耐心。我更新了我的代码,以便在电子邮件中阅读(按照你的代码)并处理它。我的代码片段应该按照您想要的方式工作,而无需进行任何修改。如果你想对这封邮件做任何其他的事情,我将把它留给你(或者你可以在这里问另一个问题以获得进一步的帮助)。这是一篇旧文章,但我想我会根据我发现的一个bug添加一个快速更新。在步骤3中,我发现正则表达式与多部分头不匹配,因为它们后面并不总是有回车符。如果您删除该preg中的“\r”,我相信它适用于所有情况(因为如果有,它将被“*?”捕获)。因此,新的一个看起来像$text=trim(preg|u replace('/Content-(Type | ID | Disposition | Transfer-Encoding):.*?\n/is',“”,$segment))@詹姆斯·加里斯不再(在撰写本评论时)
foreach ($email_segments as $segment)
{
  if (stristr($segment, "Content-Type: text/plain") !== false)
  {
    // We found the segment we're looking for!
  }
}
$text = preg_replace('/Content-(Type|ID|Disposition|Transfer-Encoding):.*?\r\n/is', "", $segment);
<?php
// read from stdin
$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd))
{
    $email .= fread($fd, 1024);
}
fclose($fd);

$matches = array();
preg_match('#Content-Type: multipart\/[^;]+;\s*boundary="([^"]+)"#i', $email, $matches);
list(, $boundary) = $matches;

$text = "";
if (isset($boundary) && !empty($boundary)) // did we find a boundary?
{
  $email_segments = explode('--' . $boundary, $email);

  foreach ($email_segments as $segment)
  {
    if (stristr($segment, "Content-Type: text/plain") !== false)
    {
      $text = trim(preg_replace('/Content-(Type|ID|Disposition|Transfer-Encoding):.*?\r\n/is', "", $segment));
      break;
    }
  }
}

// At this point, $text will either contain your plain text body,
// or be an empty string if a plain text body couldn't be found.

$savefile = "savehere.txt";
$sf = fopen($savefile, 'a') or die("can't open file");
fwrite($sf, $text);
fclose($sf);
?>
require_once('/path/to/class/rfc822_addresses.php');
require_once('/path/to/class/mime_parser.php');