Cherka Trova
Доброго времени суток. Вот такая проблемка возникла. Может, кому-то приходилось сталкиваться. Ответ нужен быстрый..
Скрипт на php достает из ящика письмо, выделяет из него тело в формате, приведенном ниже (письмо сформировано в Ms Outlook в формате html со вставленными картинками и прикрепленным документом).
Задача: сформировать письмо, идентичное по отображению этому и сохранить его тело в файл для дальнейшей рассылки другим скриптом.
Заранее спасибо за ответы.
формат письма
Скрипт на php достает из ящика письмо, выделяет из него тело в формате, приведенном ниже (письмо сформировано в Ms Outlook в формате html со вставленными картинками и прикрепленным документом).
Задача: сформировать письмо, идентичное по отображению этому и сохранить его тело в файл для дальнейшей рассылки другим скриптом.
Заранее спасибо за ответы.
формат письма
Сохраняешь полученное в файл, разделив headers и body любым удобным тебе разделителем.
Для отсылки просто читаешь файл и функции mail() отдаёшь headers и body вычитанные из файла.
Никаких преобразований не понадобятся.
оно не отправляется нормально
А как именно отправляется?
www.liogrand.com/mail/headers.dat - Заголовки (если нужно вытянуть что-то еще, скажите..)
www.liogrand.com/mail/body.txt - Тело (сравните с тем, что я вам дал, один в один)
Проблема в заголовках. Самый главный для такого вида письма заголовок Content-Type: multipart/alternative;
boundary="----=_NextPart_002_0004_01C85E16.5BF9FB20" вы отправляете в теле, а не в заголовках.
------=_NextPart_000_0002_01C85E16.5BF9FB20
Ведь она обрамляет все письмо..
В заголовках необходимо передать значение "Content-Type: multipart/alternative; boundary=РАЗДЕЛИТЕЛЬ1"
Этот заголовок говорит о том, что содержание писмо состоит из нескольких альтернативных кусков, которые отображаются в зависимости от настироек клиента. Например, можно в одином пистме оиправить несколько кусков в разных кодировках. Каждый кусок такого писма является самостоятельным полноценным телом, то есть содержит собственный набор заголовков. В самом теле разделитель начинается с "--". Кроме того, для обознаячение окончания действия разделителя используюется закрывающий разделитель, не только начинается, но и заканчивается на "--" Пример всего этого:
//Основные завголоки я пропускаю
Content-Type: multipart/alternative; boundary="=1261023517="
--=1261023517=
MIME-Version: 1.0
Content-Type: text/plain; charset="cp1251"
Content-Transfer-Encoding: base64
0+Lg5uDl7PvpIOjn5ODy5ev8IEFkU2Vuc2UsDQrM+yDv7vH76+Dl7CDC4Owg/fLuIO/o8fzs7iwg
9/Lu4fsg8e7u4fno8vwg7
--=1261023517=
MIME-Version: 1.0
Content-Type: text/html; charset="cp1251"
Content-Transfer-Encoding: base64
PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBYSFRNTCAxLjAgVHJhbnNpdGlvbmFs
Ly9FTiIgImh0dHA6Ly93d3cudzMub3JnL1RSL3hodG1sMS9EVEQveGh0bWwxLXRyYW5zaXRpb25h
bC5kdGQiPg0KPGh0bWwgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIGxhbmc9
ImVuIiBkaXI9Imx0ciI+DQo8aGVhZD4NCjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIg
Y29udGVudD0iIGNoYXJzZXQ9d2luZG93cy0xMjUxIiAvPg0KPHRpdGxlPkFkU2Vuc2UgTmV3c2xl
dHRlcjwvdGl0bGU+DQoNCjwvaGVhZD4NCg0KPGJvZHk
--=1261023517=--
Далее. Для того чтобы картинки выводились не после письма как вложения, а в самом тексте, необходимо указывать заголовок Content-Type: multipart/related; boundary=РАЗДЕЛИТЕЛЬ2;type="text/html". Здесь, РАЗДЕЛИТЕЛЬ2 - это уже дроугой разделитель, который используется в этом альтернативном блоке письма. Правила его использования точно такие же. Дальше, вставляем там где надо саму картинку: <img height="100" width="204" src="cid:ИДЕНТИФИКАТОР"> Послпо окончании контента, выводим наш внутренний разделитель "РАЗДЕЛИТЕЛЬ2" и после этого набор завголовков такого типа:
Content-Disposition: inline; filename=image.gif
Content-Transfer-Encoding: base64
Content-Type: image/gif;name="image.gif"
Content-Id: <ИДЕНТИФИКАТОР>
А после этого, собственно сам контент картинки. Не забываем потом закрыть внетренний разделитель, а потом и внешний. Да, и не забваем, что весь контент у меня указывается как кодированный base64, а следовательно в тело письма его надо вставлять именно кодированным, в том числе и контент картинки.
Хорошо, но почему не первую часть
Тут вы правы, я не доглядел - вынести в заголовки обязательно первый, высший уровень разделения. Когда программа определяет такой заголовок, она получает инструкцию на разбиение письма и поиск дополнительных заголовков в теле. В противном слуае, она выводит все "as is".
В любом случае спасибо за разъяснения..
Вопрос на маленькое уточнение: если я передам в mail() в headers строку "MIME=Version 1.0" Дублировать ее уже не надо будет, так?
И еще: обязательно ли в письме должна присутствовать строка, которую мы видим стоящей первой?
"Это составное сообщение в формате MIME."
PS: Сейчас как раз этим и занимаюсь. Насчет переноса заголовка я немного поторопился - судя по всему тело в порядке, а вы где-то теряете еще один заголовок, который описывает самы верхнгий уровень разделения. ИМХО, как все форматы от мелкомягкого, тут все переусложнено.
Вопрос на маленькое уточнение: если я передам в mail() в headers строку "MIME=Version 1.0" Дублировать ее уже не надо будет, так? Нет, не надо. Точнее говоря, в каждом отдельном куске тела, можно и повторять.
/* Header должны содержать MIME-Version, Content-Type */
$header = "Date: Wed, 23 Jan 2008 23:19:08 +0300\n";
$header .= "To: [email protected]\n";
$header .= "From: =?koi8-r?B?6czY0SDsxdfJzg==?= <[email protected]>\n";
$header .= "Reply: =?koi8-r?B?6czY0SDsxdfJzg==?= <[email protected]>\n";
$header .= "Sender: =?koi8-r?B?6czY0SDsxdfJzg==?= <[email protected]>\n";
$header .= "Subject: Test\n";
$header .= "MIME-Version: 1.0\n";
$header .= "Content-Type: multipart/mixed; boundary=\"----=_NextPart_001_0003_01C85E16.5BF9FB20\"\n\n"; // boundary получаем из body простым regexp, надеюсь это не надо расписывать?
/* Читаем из файла body */
$body = file_get_contents("body");
/* посылаем и проверяем - ушло ли? */
$ret = mail("[email protected]", "test", $body, $header);
var_dump($ret);
?>
Content-Type: multipart/mixed;boundary="----=_NextPart_000_0002_01C85E16.5BF9FB20"
То есть в принципе тоже самое что предлагал Kuroi Kitsune, только с самым верхним разделителем.
в заголовке письма стоит multipart/alternative . Как думаешь, может это сработать?
multipart/alternative
--Разделитель1
text/plain
--Разделитель1
multipart/related
--Разделитель2
text/html
--Разделитель2
image/jpg
--Разделитель2
image/png
--Закрываем Разделитель2--
Закрываем Разделитель1--
--Разделитель_0
Content-Type: multipart/alternative;
boundary="Разделитель_1"
--Разделитель_1
Content-Type: text/plain;
charset="koi8-r"
Content-Transfer-Encoding: quoted-printable
(текст простой)
-- Разделитель_1
Content-Type: text/html;
charset="koi8-r"
Content-Transfer-Encoding: quoted-printable
(текст с html)
--Разделитель_1--
--Разделитель_0
Content-Type: image/jpeg;
name="mailhead.jpg"
Content-Transfer-Encoding: base64
Content-ID: .....
(тело картинки раз)
--Разделитель_0
Content-Type: image/jpeg;
name="www.jpg"
Content-Transfer-Encoding: base64
Content-ID: ......
(тело картинки 2)
--Разделитель_0--
Как видите, она сильно отличается от того, что требуется. И придется как-то куски извлекать целиком вместе с заголовками и их по новой расставлять в разделителях.
Картинки отображаются аттачами и одновременно вклеиваются в текст (а в мозиловской птыце не вклеиваются вовсе). Шефа это категорически не устраивает.
$headers ="Date: Wed, 23 Jan 2008 23:19:08 +0300
To: [email protected]
From: =?koi8-r?B?6czY0SDsxdfJzg==?= <[email protected]>
Reply: =?koi8-r?B?6czY0SDsxdfJzg==?= <[email protected]>
Sender: =?koi8-r?B?6czY0SDsxdfJzg==?= <[email protected]>
Subject: =?koi8-r?B?7s/Xz9PUySBMSU8gR1JBTkQ=?=
Content-Type: multipart/mixed;
boundary=\"----=_NextPart_000_0002_01C85E16.5BF9FB20\"";
$content = "Это составное сообщение в формате MIME.
------=_NextPart_000_0002_01C85E16.5BF9FB20
Content-Type: multipart/related;
boundary=\"----=_NextPart_001_0003_01C85E16.5BF9FB20\"
------=_NextPart_001_0003_01C85E16.5BF9FB20
Content-Type: multipart/alternative;
boundary=\"----=_NextPart_002_0004_01C85E16.5BF9FB20\"
------=_NextPart_002_0004_01C85E16.5BF9FB20
Content-Type: text/plain;
charset=\"koi8-r\"
Content-Transfer-Encoding: base64
тут простой текст
------=_NextPart_002_0004_01C85E16.5BF9FB20
Content-Type: text/html;
charset=\"koi8-r\"
Content-Transfer-Encoding: quoted-printable
тут контент html
------=_NextPart_002_0004_01C85E16.5BF9FB20--
------=_NextPart_001_0003_01C85E16.5BF9FB20
Content-Type: image/jpeg;
name=\"image001.jpg\"
Content-Transfer-Encoding: base64
Content-ID: <[email protected]>
Тут контент картинки
------=_NextPart_001_0003_01C85E16.5BF9FB20--
------=_NextPart_000_0002_01C85E16.5BF9FB20
Content-Type: application/msword;
name=\"=?koi8-r?B?58nE0sHXzMnLwSAxLmRvYw==?=\"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename=\"=?koi8-r?B?58nE0sHXzMnLwSAxLmRvYw==?=\"
Тут контент файла
------=_NextPart_000_0002_01C85E16.5BF9FB20--";
mail("", "", $content, $headers);
?>
Все приходит. =)
Content-Type: multipart/mixed;
boundary=\"----=_NextPart_000_0002_01C85E16.5BF9FB20\"
Content-Type: multipart/related;
boundary=\"----=_NextPart_001_0003_01C85E16.5BF9FB20\"
видимо, я опять сильно туплю...