Существует четыре шага, которые вам нужно будет сделать, чтобы изолировать текстовую часть вашего письма:
1.Получить граничную строку MIME
Мы можем использовать регулярное выражение для поиска в ваших заголовках (предположим, они находятся в отдельной переменной $headers
):
$matches = array();
preg_match('#Content-Type: multipart\/[^;]+;\s*boundary="([^"]+)"#i', $headers, $matches);
list(, $boundary) = $matches;
регулярное выражение будет искать заголовок Content-Type
, который содержит граничную строку, а затем захватывать его в первую группу захвата .Затем мы копируем эту группу захвата в переменную $boundary
.
2.Разделите тело письма на сегменты
Как только у нас будет граница, мы можем разделить тело на различные части (в теле вашего сообщения перед каждым телом будет добавляться --
),Согласно спецификации MIME все до первой границы должно игнорироваться.
$email_segments = explode('--' . $boundary, $message);
array_shift($email_segments); // drop everything before the first boundary
Это оставит нас с массивом, содержащим все сегменты, со всем до игнорирования первой границы.
3.Определите, какой сегмент представляет собой простой текст.
Сегмент, который представляет собой простой текст, будет иметь заголовок Content-Type
с MIME-типом text/plain
.Теперь мы можем искать в каждом сегменте первый сегмент с таким заголовком:
foreach ($email_segments as $segment)
{
if (stristr($segment, "Content-Type: text/plain") !== false)
{
// We found the segment we're looking for!
}
}
Поскольку мы ищем константу, мы можем использовать stristr
(который находитпервый экземпляр подстроки в строке, без учета регистра) вместо регулярного выражения.Если заголовок Content-Type
найден, у нас есть наш сегмент.
4.Удалите все заголовки из сегмента
Теперь нам нужно удалить все заголовки из найденного сегмента, так как нам нужен только фактический контент сообщения.Здесь могут отображаться четыре MIME-заголовка : Content-Type
, как мы видели ранее, Content-ID
, Content-Disposition
и Content-Transfer-Encoding
.Заголовки заканчиваются на \r\n
, поэтому мы можем использовать это для определения конца заголовков:
$text = preg_replace('/Content-(Type|ID|Disposition|Transfer-Encoding):.*?\r\n/is', "", $segment);
Модификатор s
в конце регулярного выражения делает точкусопоставлять любые новые строки..*?
будет собирать как можно меньше символов (т. Е. Все до \r\n
);?
- это ленивый модификатор на .*
.
И после этого $text
будет содержать содержимое вашего сообщения электронной почты.
Так что поставить еговсе вместе с вашим кодом:
<?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);
?>