static $strMyMP3Directory = "/home/ed/mp3"; # Укажите реальный каталог с MP3-файлами $objDir = dir($strMyMP3Directory);
$intNumFiles = 0; $arMP3Files = Array();
while (false !== ($strEntry = $objDir->read())) { if (eregi("\.mp3$", $strEntry)) {
$arMP3Files[] = $strMyMP3Directory . "/" . $strEntry;
};
};
Теперь можно использовать линейную коллекцию MP3+файлов. Так как физиче+ ская структура создаваемого приложения в своей основе упорядочена по именам ис+ полнителей, имеет смысл создать один массив с именами всех исполнителей в кол+ лекции MP3+файлов. Возможно, коллекция состоит из тысяч файлов, но, скорее всего, отдельных исполнителей в ней будет только несколько сотен.
Получение имени исполнителя из каждого файла ++++++ первая цель использования класса MP3_ID:
$objMP3ID = new MP3_Id(); $arArtists = Array(); $arTestArtists = Array();
for ($i=0; $i<=sizeof($arMP3Files)-1; $i++) { $strPath = $arMP3Files[$i];
$intResult = $objMP3ID->read ($strPath);
$strArtist = $objMP3ID->getTag ("artists", "Unknown Artist"); $strTestArtist = strtoupper(preg_replace("/[^A-Za-z0-9]/", "", $strArtist));
if (in_array($strTestArtist, $arTestArtists) == false) { array_push($arArtists, $strArtist); array_push($arTestArtists, $strTestArtist);
};
};
Следует отметить, что создается два массива ++++++ $arArtists, содержащий имена исполнителей, и $arTestArtists с измененной версией каждого имени, где все бук+ вы переведены в верхний регистр и удалены все не алфавитно+цифровые символы (включая пробелы). Это сделано по одной причине: необходимо убедиться, что каж+ дый исполнитель появляется в списке только один раз. Удаление пробелов и знаков препинания, а также перевод всех символов в верхний регистр позволяет с большой долей уверенности сравнить имя исполнителя, извлеченное из IDv3+тега, с тем име+ нем, которое уже встречалось в течение времени жизни цикла.
В качестве примера рассмотрим вымышленного исполнителя ‘‘Extreme Metal Grind+ ing’’. Предположим, что в коллекции имеется три композиции этого исполнителя, соз+ данных в разное время тремя различными программами. Имя исполнителя в IDv3+теге вполне может быть представлено тремя незначительно отличающимися способами, на+ пример, ‘‘Extreme Metal Grinding’’, ‘‘EXTREME ‘Metal’ Grinding’’ и ‘‘Extreme Metalgrind+ ing’’. Использованное в операторе $strTestArtist = strtoupper (preg_replace ("/[^A-Za-z0-9]/", "", $strArtist)) регулярное выражение и преобразова+ ние к верхнему регистру для каждого из этих тегов позволяет всегда получать один и тот же результат: EXTREMEMETALGRINDING. Вероятно, на экране такое имя будет выглядеть некрасиво, но оно хорошо подходит для сравнения и создания учетной за+ писи для этой группы исполнителей.
Итак, в цикле просматривается каждый MP3+файл и из него извлекается имя ис+ полнителя, к которому применяется регулярное выражение. Затем нужно проверить, присутствует ли измененное имя исполнителя в тестовом массиве. Если это не так, то имя исполнителя записывается в оба массива ++++++ в тестовый массив (сюда записывается
PEAR 583
измененное имя) и в реальный массив имен исполнителей (записываются исходные име+ на). Если имя записано в тестовом массиве, то нет необходимости добавлять его снова.
Теперь следует поместить каждую песню в один массив. Необходимо создать мас+ сив, упорядоченный по уникальным именам исполнителей, поэтому есть смысл соз+ дать ассоциативный массив, в котором ключами будут имена исполнителей. Так как каждому исполнителю, скорее всего, принадлежит несколько песен, значением каж+ дого элемента массива будет другой одномерный массив, в котором каждый элемент будет представлять одну песню. Поскольку желательно хранить как фактическое на+ звание каждой песни, так и имя соответствующего файла, следует представить каж+ дый элемент этого массива тоже в виде массива. Получающаяся в результате структура данных весьма сложна (при желании ее можно просмотреть с помощью функции var_dump()), но она идеально подходит для создания XML+кода и действительно очень упрощает код сценария radiorequest.php.
Имена всех исполнителей в только что созданном массиве обрабатываются с по+ мощью следующего цикла:
$arTracks = Array(); $arAlreadyAccountedForSongIndices = Array(); for ($i=0; $i<=sizeof($arArtists)-1; $i++) {
$strArtistName = $arArtists[$i]; $strTestArtistName = $arTestArtists[$i]; $arTracks[$strArtistName] = Array();
for ($j=0; $j<=sizeof($arMP3Files)-1; $j++) {
if (in_array($j, $arAlreadyAccountedForSongIndices) == false) { $strPath = $arMP3Files[$j];
$intResult = $objMP3ID->read ($strPath);
$strThisArtist = $objMP3ID->getTag ("artists", "Unknown Artist"); $strThisTestArtist = strtoupper(preg_replace("/[^A-Za-z0-9]/", "",
$strThisArtist));
if ($strThisTestArtist == $strTestArtistName) { array_push($arAlreadyAccountedForSongIndices, $j); $arSongHash["TITLE"] = $objMP3ID->getTag ("name", "Unknown Title"); $strSongFilename = str_replace("$strMyMP3Directory" . "/", "",
$arMP3Files[$j]);
$arSongHash["LINK"] = "radiorequest.php?requestfile=" . urlencode($strSongFilename);
array_push($arTracks[$strArtistName], $arSongHash);
};
};
};
};
По сути, в цикле обрабатывается список исполнителей (реальный список, а не тес+ товый), а в массиве создается ключ на основе имен исполнителей.
Затем для каждого ключа просматривается весь список MP3+файлов и проверяет+ ся, принадлежит ли каждая композиция данному исполнителю. Имя исполнителя, хранящееся под соответствующим индексом в тестовом массиве, сверяется с именем исполнителя в MP3+файле, которое предварительно обрабатывается регулярным вы+ ражением. Это, как уже было сказано, позволяет игнорировать различия в количестве пробелов, знаков препинания и регистре символов.
Чтобы определить, какие песни принадлежат тому или иному исполнителю, всю коллекцию приходится просматривать в цикле. Вследствие этого рассматриваемый сценарий может потреблять значительные ресурсы и работать медленно. Поэтому для повышения производительности необходимо связать каждый индекс массива MP3+ файлов ($arMP3Files) с исполнителем только один раз ++++++ композиция, для которой
создан MP3+файл, может быть написана только одним исполнителем, по крайней мере, ес+ ли рассматривать IDv3+теги. Выполняется проверка по искомому индексу, и если этот ин+ декс уже связан с исполнителем, то нет смысла тратить на него время. Как только принад+ лежность заданного MP3+файла определена (индекс j в исходном массиве $arMP3Files), этот индекс добавляется в другой массив $arAlreadyAccountedForSongIndices. В результате можно не проверять этот MP3+файл при последующих итерациях, если его принадлежность данному исполнителю уже установлена. Это значительно по+ вышает производительность, поскольку ограничивается количество необходимых операций чтения IDv3+тегов.
Если имя исполнителя проверяемой записи совпадает с именем исполнителя, чье авторство проверяется в текущий момент, то в массив с индексом текущего исполни+ теля добавляется соответствующий массив, представляющий эту запись. Добавляемый массив содержит название песни и ссылку (содержащую имя файла без пути) на стра+ ницу radiorequest.php. Идея заключается в том, что когда пользователь щелкает по этой ссылке, он фактически подтверждает, что хочет прослушать эту песню. Что+ бы гарантировать, что создаваемый URL будет корректно обрабатываться Web+ браузером, используется функция urlencode.
Наконец, для сортировки массива по ключам в алфавитном порядке используется функция ksort. Почти так же как и функция arsort, которая использовалась в пре+ дыдущем MP3_ID+приложении, ksort сохраняет в ассоциативном массиве внутрен+ нюю связь между каждым ключом и его значением:
ksort($arTracks);
Используя созданную структуру данных, можно выводить XML+код.
Так как генерируемый XML+код крайне прост, преимущества встроенной PHP5+ библиотеки libxml для поддержки XML не используются. Вместо этого XML+вывод создается так же, как если бы это был HTML+код. Однако вполне можно переписать соответствующую подпрограмму, так чтобы она использовала libxml2 (см. главу 8).
Весьма простая рекурсия позволяет обработать структуру данных и отправить вы+ вод непосредственно в браузер. Обоснование для использования в предыдущем блоке кода внешне громоздкой структуры данных теперь должно быть очевидным ++++++ можно конвертировать структуры данных в XML, используя всего несколько строк кода. В результате программист немного усложняет себе работу, но вместе с тем упрощает генерирование XML+кода. Это пригодится, если впоследствии придется по какой+ либо причине подправить XML+код ++++++ это можно будет легко сделать, не затрагивая многочисленных строк сложной логики.
Следующий фрагмент выводит XML+код в браузер:
<treemenu>
<? foreach ($arTracks as $artist_name => $arHash) { ?> <node text="<?=$artist_name?>" icon="folder.gif">
<? for ($i=0; $i<=sizeof($arHash)-1; $i++) { ?>
<node text="<?=htmlentities($arHash[$i]["TITLE"])?>" icon="document.gif" link="<?=htmlentities($arHash[$i]["LINK"])?>" />
<? }; ?> </node>
<? }; ?> </treemenu>
При генерации обоих значений (названия записи и ссылки) используется функция htmlentities, гарантирующая, что вывод будет полностью соответствовать XML+ стандарту. Это может в буквальном смысле исказить URL, но синтаксический анали+ затор компонента HTMLTree_Menu исправит это неудобство.
PEAR 585
Теперь можно открыть страницу radiogeneratexml.php в Web+браузере. Чтобы заставить Internet Explorer отображать страницу как XML (что сделает ее более удо+ бочитаемой и позволит разворачивать и сворачивать отдельные узлы), можно ис+ пользовать следующий трюк с URL:
http://your_server_name/radiogeneratexml.php/.xml
Web+сервер игнорирует лишние символы /.xml в конце, но Internet Explorer ‘‘пола+ гает’’, что пользователь определенно запрашивает XML+страницу и поэтому отобра+ жает ее как следует. (Непонятно, почему этот браузер не учитывает MIME+заголовок, для создания которого пришлось приложить определенные усилия в начале сценария.)
Чтобы полностью убедиться, что все работает, можно скопировать XML+код, вста+ вить его в файл treemenutest.xml, а затем открыть страницу treemenutest.php снова. Чтобы сделать это, просто откройте в браузере предыдущий URL. В окне дол+ жен появиться XML+код, в котором можно найти MP3+файлы. Если все выглядит нор+ мально, то можно считать, что большая часть работы сделана.
Как это работает: сценарий radiorequest.php
Файл radiorequest.php до сих пор был самым простым из двух файлов. Работа этого сценария будет понятна, если вы знаете, как работает radiogeneratexml.php.
Сценарий начинается с определения некоторых переменных:
<?php
static $strMyMP3Directory = "/home/ed/mp3"; # Укажите реальный каталог MP3-файлов static $strMyDJsEmailAddress = "ed@example.com";
?>
Очевидно, следует заменить e+mail+адрес и вставить путь к каталогу MP3+файлов на Web+сервере, как это было сделано в сценарии генерирования XML+кода.
Загрузить MP3*файлы и поэкспериментировать с ними можно, посетив сайт www.iuma.com. Для редактирования IDv3*тегов можно использовать Winamp (www.winamp.com) ****** MP3*проигрыватель, позволяющий также редактировать IDv3*теги.
Затем подключаются PEAR+объекты. Здесь нет необходимости использовать MP3_ID ++++++ только HTML_Treemenu и вспомогательный компонент:
require_once('HTML/TreeMenu.php'); require_once('xmlhtmltree.phpm');
Для создания URL, указывающего на XML+генератор, используется несложный трюк. В рассматриваемом примере можно предположить, что сценарий расположен на собственном сервере в том же каталоге, что и сценарий генератор XML+кода. URL сценария заказа известен, потому что он вызывается пользователем. Корректный URL для сценария+генератора идентичен данному URL, кроме слова request, кото+ рое заменено generatexml. Для этого в сценарии используется поиск и замена, в ре+ зультате которой формируется URL сценария+генератора.
Как только URL создан, содержимое соответствующей страницы извлекается так же, как содержимое файла локальной файловой системы ++++++ PHP достаточно развит, чтобы выполнить такой запрос. Затем полученный XML+вывод передается HTML_TreeMenu+ объекту так же, как в начале главы. Ниже приведен соответствующий фрагмент кода:
$strXMLURL = "http://" . $_SERVER["SERVER_NAME"] . str_replace("request", "generatexml", $_SERVER["SCRIPT_NAME"]);
$strXML = implode ('', file($strXMLURL));
$objXMLTree = new XMLHTMLTree("", $strXML); $objXMLTree->GenerateHandOffs(); $objXMLTree->ParseXML();
$objTreeMenu = $objXMLTree->GetTreeHandoff();
Затем подключается условная логика, определяющая поведение сценария при по+ лучении песни, заказанной пользователем. В XML+выводе генерируются ссылки для дерева навигации, которые выглядят следующим образом:
/radiorequest.php?requestfile=9991885931037.mp3
Сценарий radiorequest.php фактически выполняет две функции: он отобража+ ет дерево MP3+файлов, а также сообщение о том, что заказ выполнен успешно. В этом PHP+сценарии необходимо принимать во внимание запросы, в которые включен па+ раметр requestfile, определяющий имя запрашиваемого MP3+файла. Желательно не только знать, что заказ был сделан, но и убедиться в том, что заказ был достовер+ ным. Для этого применяется проверка существования файла:
$requestMade = false; $requestSuccessful = false;
if (!empty($_GET['requestfile'])) { $requestMade = true;
$strRequestFilename = $_GET["requestfile"];
$strFullPath = $strMyMP3Directory . "/" . $strRequestFilename; if (@filesize($strFullPath) > 0) {
Следует отметить, что проверка существования файла выполняется путем опреде+ ления полного пути к нему, после чего определяется его размер с помощью функции filesize. Размер, превышающий единицу, указывает на то, что файл действительно существует. Оператор @ используется потому, что попытка вызывать PHP+функцию filesize для несуществующего файла приводит к генерации неисправимой ошибки, в результате которой выполнение сценария прекращается, а это абсолютно нежелательно.
Если файл существует, то заказ песни считается успешным и сценарий отправляет диджею e+mail+сообщение, используя определенную в начале сценария переменную $strMyDJsEmailAddress, в которой записан необходимый адрес:
$requestSuccessful = true;
// Все работает. Можно отправлять письмо диджею. mail($strMyDJsEmailAddress, "Новый заказ", "Заказана песня. Файл: " .
$strFullPath);
} else {
$requestSuccessful = false;
};
};
Функция mail() позволяет определить необходимый e+mail+адрес, тему и тело со+ общения, а также другие параметры, которые подробно описаны в главе 15.
Теперь можно переходить к логике отображения, т.е. к блоку сценария, генери+ рующему HTML+код, который фактически отправляется браузеру пользователя.
Комбинация переменных $requestMade и $requestSuccessful используется для определения того, какую информацию отображать. Если заказа не было, то сце+ нарий приглашает пользователя сделать заказ и выводит меню, созданное HTML_TreeMenu+компонентом. Если заказ сделан, но выполнить его не удается, выво+ дится поясняющее сообщение и приглашение сделать другой заказ; при этом также выводится HTML_TreeMenu+меню. Если заказ сделан и его можно выполнить, то выво+ дится сообщение с благодарностью, а меню не выводится, потому что в целях данного упражнения предполагается, что пользователь не будет заказывать вторую песню.
PEAR 587
На практике, чтобы ограничить количество заказов от одного пользователя за один день, можно использовать какую+либо специальную методику, например, cookie+файлы.
Ниже приведен код отображения:
<HTML>
<HEAD>
<SCRIPT LANGUAGE="Javascript" SRC="TreeMenu.js"></SCRIPT> </HEAD>
<BODY>
<H1>Радио PHP</H1> <?php
if ($requestMade) {
?>
<B>Спасибо за заказ!</B> <BR><BR>
<?php
if ($requestSuccessful) {
?>
Ваш заказ принят, мы постараемся как можно быстрее поставить заказанную вами песню.
<?php
} else {
?>
К сожалению, мы не можем поставить заказанную вами песню.Возможно, она была недавно удалена из нашей коллекции. Пожалуйста, попробуйте заказать другую песню.
<?php
};
?>
<BR><BR>
<?php
};
?>
<?php
if (!($requestSuccessful)) {
?>
Закажите песню из приведенного ниже списка. Заказ будет отправлен нашему диджею.
Если песня давно не проигрывалась, то мы включим ее как можно быстрее!
<HR>
<?php $objTreeMenu->printMenu();
?>
<?php
};
?> </BODY> </HTML>
Меню генерируется в точности так же, как в первом примере этой главы. Наконец, следует включить упомянутый в начале HTML+кода JavaScript+файл, не+
обходимый для работы HTML_TreeMenu+компонента.
Резюме
Эта глава знакомит читателя с PEAR ++++++ репозиторием PHP+расширений и приложений.
Вглаве рассматривались темы поиска подходящих пакетов на Web+сайте проекта PEAR,
атакже методика их загрузки и установки; была описана структура проекта PEAR ++++++
знание организации репозитория впоследствии должно облегчить поиск необходи+ мых компонентов.
Читатель познакомился с методикой изучения интерфейсов новых PEAR+компонентов и оценки их пригодности для разрабатываемого проекта, отмечались некоторые ха+ рактерные особенности PEAR+пакетов, описаны способы их преодоления.
Вэтой главе вновь рассматривались PEAR+стандарты написания кода, которых придерживались авторы книги при написании примеров, а также логическое обосно+ вание, лежащее в основе этих стандартов.
Наконец, в главе был представлен пример создания функционального, полезного приложения с помощью нескольких PEAR+пакетов.
Вследующей главе рассматриваются встроенные в PHP почтовые функции и при+ меры использования нескольких PEAR+пакетов, предоставляющих некоторые разви+ тые функции обработки и диспетчеризации почты.
15
PHP5 и электронная почта
Одним из самых простых и наиболее распространенных требований к PHP+при+ ложению является возможность отправлять e+mail+сообщения. Электронная почта за очень короткое время стала одним из самых популярных средств коммуникации и PHP, естественно, предоставляет функции для реализации этого средства в приложениях. Детали работы почты в Internet могут быть весьма сложными, и в основном эта слож+ ность исходит не от PHP+программ, а скорее от различных технологий, платформ
ипротоколов, которые используются для доставки почты из одной точки в другую. И все же начать использовать PHP и e+mail можно с помощью нескольких простых функций.
Прежде чем рассматривать разработку сценариев для отправки e+mail в Windows
иLinux+платформах, следует изучить некоторые технические принципы, лежащие в основе отправки e+mail. Конечно, понимание того, как PHP5 взаимодействует с поч+ товым сервером, весьма важно, и чтобы читателю было проще понять это, в главе приводится пример создания несложного приложения для отправки почты, в кото+ ром используется функция mail(). Наконец, в этой главе рассматривается метод соз+ дания различных типов содержимого e+mail+писем с использованием формата MIME (Multipurpose Internet Mail Extension ++++++ многоцелевое расширение почты в Internet).
Основы e-mail
Чтобы использовать самые распространенные PHP+функции, PHP должен работать в операционной системе (например, Windows или Linux) и иметь доступ к службам Web+ сервера. Для использования e+mail+функций PHP также должен иметь доступ к MTA (Mail Transport Agent ++++++ почтовый транспортный агент), например, к Sendmail, сервер+ ному программному обеспечению, которое отправляет и получает e+mail+сообщения.
Несмотря на то что в PHP существует функция mail(), которая отправляет e*mail, в этом языке нет (на момент написания книги) официальных версий каких* либо PHP*функций или расширений, получающих почту. Расширение mailparse все еще находится в разработке.
Чаще всего в PHP используется MTA Sendmail; программист может даже не знать, что на используемом им сервере работает Sendmail ++++++ в сценарии работает функция mail(). В последующем разделе описываются некоторые технические вопросы, свя+ занные с почтовыми протоколами Internet. Однако если читателя главным образом интересует отправка почты и работа почтовой функции, то можно сразу перейти к разделу ‘‘Создание простого PHP+приложения для работы с e+mail’’.
Почтовые протоколы Internet
Как и в случае любого другого вида связи в Internet, в транспортировке почты за+ действован ряд протоколов. Internet+протоколы основываются на документах RFC (Requests For Comment ++++++ запросы на комментарии), которые в случае принятия формируют используемый по обоюдному согласию язык для осуществления связи. Отправка e+mail в Internet основывается на протоколе SMTP (Simple Mail Transfer Pro+ tocol ++++++ простой протокол отправки почты), RFC 821, разработанном Джонатаном Постелом (Jonathan Postel). В 2001 году рабочей группой по информационно+ вычислительным сетям (Network Working Group) была опубликована новая версия RFC 821, RFC 2821 под редакцией Дж. Кленсена (J. Klensen), AT&T Laboratories.
Коммуникационная модель (концептуальная структура информационного обмена) заключается в том, что пользователь (и файловая система пользователя) использует клиентскую программу (например, Outlook или Eudora) для подключения (в техниче+ ских терминах ++++++ для установки канала двухсторонней передачи) с SMTP+сервером. Затем сервер передает сообщение соответствующему получающему SMTP+серверу (основываясь на доменном имени завершающей части e+mail+адреса). Получающий SMTP+сервер от+ вечает за помещение данного сообщения в соответствующее место (которое обычно называется почтовым ящиком) или применение иных соответствующих функций.
В результате этого процесса почта перемещается от одного сервера к другому. Как получить почту от сервера? Для этого предназначены два протокола ++++++ POP3 и IMAP. Прежде чем доставить почту от удаленного сервера, они выполняют проверку реги+ страционной информации пользователя. Это можно представить себе как обычный почтовый ящик, ключ к которому вы передаете другому человеку. Если ключ подхо+ дит, то этот человек сможет доставить вам почту.
Структура e-mail-сообщения
E+mail+сообщение с правильной структурой имеет заголовки, за которыми следует тело сообщения. Кроме того, в сообщение также могут включаться отдельные файлы+ вложения. Заголовки включают в себя e+mail+адрес получателя, e+mail+адрес отправи+ теля, тему сообщения, список получателей копий данного сообщения и идентифика+ тор сообщения. Не все эти заголовки обязательны, а некоторые могут быть определе+ ны пользователем, что упрощает их фальсификацию.
В RFC 2822 представлено определение составных частей e+mail+адреса в Internet. (Некоторые RFC можно найти на странице www.faqs.org/rfcs/.) Этот стандарт определяет сообщение как состоящее из US+ASCII+символов, разделенных на строки, каждая из которых завершается символом перевода строки и возврата каретки (CRLF). Поля заголовков представляют собой строки символов, разделенные с помо+ щью специального синтаксиса. За заголовками следует тело сообщения, отделенное от заголовков пустой строкой (строка, в которой нет ничего кроме CRLF).
PHP5 и электронная почта 591
Поле заголовка представляет сбой строку символов, содержащую имя поля, двое+ точие и тело поля. Поля заголовков не обязательно должны следовать в каком+либо определенном порядке. Единственным обязательным полем является поле From, со+ держащее дату создания и адрес отправителя сообщения. В следующей таблице пред+ ставлены возможные заголовки.
Поле заголовка |
Описание |
|
|
Trace |
Включает в себя дату повторной отправки, адрес отправителя, адрес |
|
получателя и т.д. Используется, когда сообщение отправляется повторно |
|
(например, когда первая попытка доставки не удалась, сервер может |
|
попытаться отправить письмо позднее) |
From |
Обязательное поле. Содержит адрес отправителя. Следует, однако, учесть, |
|
что даже если это поле в сообщении присутствует, его точность |
|
не гарантируется. Если поле содержит несколько адресов, то в поле |
|
Sender должен присутствовать только один адрес. Дата создания |
|
включается в данные этого поля. Обратите внимание на заголовок |
|
From — это не то же самое поле, что необязательное поле “From:” |
Sender |
Содержит единственный адрес, с которого отправлено данное письмо |
Reply-to |
Содержит необязательный адрес для ответа |
To |
Содержит разделенный запятыми список адресатов |
Cc |
Содержит разделенный запятыми список адресатов, которым |
|
отправляются копии данного сообщения |
Bcc |
Содержит разделенный запятыми список адресатов, которым |
|
отправляются копии данного сообщения, при этом получатели не могут |
|
ни увидеть, ни узнать, каким Bcc-получателям отправлялось письмо |
Message-id |
Необязательное поле, но каждое сообщение должно его содержать. |
|
Содержит уникальный идентификатор сообщения |
In-reply-to |
Необязательное. Один или несколько идентификаторов сообщения |
References |
Необязательное. Один или несколько идентификаторов сообщения |
Subject |
Необязательное. Содержит короткую строку, определяющуютему |
|
сообщения |
Comments |
Необязательное. Комментарии о теле сообщения |
Keywords |
Необязательное. Разделенные запятыми ключевые слова, которые могут |
|
оказаться важными для пользователя |
Optional |
Необязательное. Поле должно лишь соответствовать инструкциям о |
|
форматировании, описанным в RFC 2822. Содержимое поля не уточняется |
Ниже приводится пример сообщения с заголовками и телом (тело усечено в целях экономии места) в текстовом формате. Это сообщение было получено и отображено как Web+страница, в виде HTML, хотя здесь показан только текст. В заголовке ‘‘From’’ указано имя пользователя почтовой программы (в данном случае mailer@mailer.lindows.com) и да+ та создания письма. В строке ‘‘Received:’’ указан IP+адрес и ‘‘родословная’’ e+mail+ сообщения. Кроме этого в письме есть строки ‘‘To:’’, ‘‘Date:’’, ‘‘From:’’ и ‘‘Subject:’’ (заголовок ‘‘From:’’ с двоеточием ++++++ не то же самое, что ‘‘From’’ в начале сообщения).
From mailer@mailer.lindows.com Thu Jan 22 17:52:58 2004 Received: from [130.94.123.236] (helo=mailer.lindows.com)
by mail1.servata.com with esmtp (Exim 3.35 #1 (Debian))