Опубликован: 10.10.2007 | Уровень: специалист | Доступ: платный
Лекция 2:

Протокол электронной почты

Тип среды Multipart

В случае составных объектов, когда один или более различных наборов данных объединяется в одном теле, в заголовке объекта должно присутствовать поле типа среды multipart. Тело должно тогда содержать одну или более частей, каждая из которых начинается с разделительной строки. За разделительной строкой следует заголовок, пустая строка и тело объекта. Таким образом, часть тела по своему синтаксису аналогична сообщению в RFC-822, но имеет другое назначение.

Часть тела является объектом и, следовательно, не должна интерпретироваться как сообщение RFC-822. Начнем с того, что части тела должны иметь заголовки. Допустимы части тела, которые начинаются с пустой строки. В таком случае отсутствие заголовка Content-Type обычно указывает, что соответствующее тело имеет тип содержимого text/plain;charset=US-ASCII.

Единственные поля заголовка, которые определяют назначение частей тела, имеют имена, начинающиеся с Content-. Все другие поля в заголовке части тела могут игнорироваться. Для экспериментальных или частных назначений могут создаваться поля с именами, начинающимися с X-. Информация, содержащаяся в этих полях, может теряться в некоторых шлюзах.

Различие между сообщением RFC-822 и частью тела не велико, но существенно. Шлюз между Интернет и почтовым сервером X.400, например, должен быть способен различать части тела, содержащие изображение, и инкапсулированное сообщение, тело которого представляет собой JPEG-образ. Для того, чтобы представить последнее, часть тела должна иметь Content-Type: message/rfc822, и ее тело после пустой строки должно представлять собой инкапсулированное сообщение со своим собственным полем заголовка Content-Type: image/jpeg. Применение подобного синтаксиса способствует преобразованию сообщений в части тела и обратно.

Как было заявлено ранее, каждая часть тела начинается со строки разграничителя. Разграничитель не должен появляться внутри любой инкапсулированной части или в качестве префикса любой строки. Это подразумевает, что генерирующий агент способен специфицировать уникальное значение пограничного параметра, которое не содержит в качестве префикса значения разграничительного параметра вкладываемой части.

Все существующие и будущие субтипы типа multipart должны использовать идентичный синтаксис. Субтипы могут отличаться по своей семантике и могут вводить дополнительные ограничения на синтаксис, но должны согласовываться с базовым синтаксисом типа multipart. Это требование гарантирует, что все агенты пользователя будут, по крайней мере, способны распознать и разделить части составного объекта, даже если они относятся к нераспознанным субтипам.

Как задано в определении поля Content-Transfer-Encoding [RFC-2045], никакие кодировки кроме 7bit, 8bit или binary не разрешены для объектов типа multipart. Граничные разделители и поля заголовков multipart всегда представляются как 7-битовые коды US-ASCII, а данные внутри частей тела могут быть закодированы по-разному и иметь свои поля Content-Transfer-Encoding для каждой из частей.

Поле Content-Type для составных объектов требует одного параметра — boundary. Строка-разделитель определяется как строка, содержащая два символа дефис ("-", десятичный код 45), за которыми следует значение пограничного параметра из поля заголовка Content-Type, опционный строчный пробел и заключительные CRLF.

Символы дефис служат для некоторой совместимости с ранним методом (RFC-934) инкапсуляции сообщений и для облегчения поиска границ для некоторых приложений. Однако следует заметить, что составные сообщения не вполне совместимы с инкапсуляцией, описанной в RFC-934. В частности, они не подчиняются RFC-934 регламентации использования кавычек для вложенных строк, которые начинаются с дефиса. Этот механизм был выбран помимо RFC-934, потому что при данной схеме происходит удлинение строк для каждого уровня закавычивания. Возрастание длины строк, а также то, что некоторые реализации SMTP осуществляют разрыв строк, делают механизм RFC-934 неприменимым для составных сообщений при большой глубине вложений.

Грамматика для параметров поля Content-type такова, что в строке Content-type часто приходится помещать пограничный параметр в кавычки. Это необходимо не всегда, но никогда не повредит. Программисты должны тщательно изучить грамматику, чтобы избежать генерации некорректных полей Content-type. Таким образом, типичное поле заголовка multipart Content-Type может выглядеть как:

Content-Type: multipart/mixed; boundary=gc0p4Jq0M2Yt08j34c0p

Но следующая запись некорректна: Content-Type: multipart/mixed; boundary=gc0pJq0M:08jU534c0p (из-за двоеточия) и должна вместо этого выглядеть как:

Content-Type: multipart/mixed; boundary="gc0pJq0M:08jU534c0p"

Это значение Content-Type указывает, что содержимое состоит из одной или более частей со структурой, которая синтаксически идентична сообщению RFC-822, за исключением того, что область заголовка может быть совершенно пустой, а каждая из частей начинается со строки

--gc0pJq0M:08jU534c0p

Пограничный разделитель должен размещаться в начале строки, т.e., следовать за CRLF, а начальный CRLF рассматривается объединенным со строкой пограничного разделителя, а не частью предшествующей секции. За границей может следовать нуль или более символов строчного пробела (HT, SP). Далее следует еще один CRLF и поля заголовка следующей части или два CRLF, что означает отсутствие полей заголовка следующей части. Если поле Content-Type отсутствует, предполагается объект типа message/rfc822 в сообщении multipart/digest, в противном случае text/plain.

Граничные разделители не должны появляться внутри инкапсулированного материала и не должны быть длиннее 70 символов, не считая двух начальных символов дефис.

Строка пограничного разделителя, следующая за последней частью тела, является уникальной и указывает, что далее не следует более никаких частей тела. Такая разделительная строка идентична предшествующим с добавлением двух символов дефис после значения граничного параметра.

--gc0pJq0M:08jU534c0p--

Сравнение пограничной строки должно сопоставлять значение пограничного параметра с началом каждой строки-кандидата. Полного совпадения всей строки-кандидата не требуется, достаточно наличия разграничителя, следующего за CRLF.

Имеется место для дополнительной информации перед пограничным разделителем и после оконечного разграничителя. Эти области следует в нормальной ситуации оставлять пустыми, а программные реализации должны игнорировать размещенную там информацию. Некоторые реализации используют эти ниши для пересылки сообщений принимающим программам.

Пограничный параметр в вышеприведенном примере может быть результатом работы алгоритма, специально созданного для генерации кодов, которые с крайне малой вероятностью могут встретиться в инкапсулируемых данных. Другой алгоритм способен выдать более читаемый код пограничного разделителя, что может потребовать предварительного просмотра инкапсулируемых данных. Простейшей строкой пограничного разделителя может служить "---", а закрывающим разделителем — "-----".

Ниже представлен простой пример составного сообщения, имеющего две части, каждая из которых содержит чистый текст, введенный явно и неявно:

From: Nathaniel Borenstein
To: Ned Freed
Date: Sun, 21 Mar 1993 23:56:48 -0800 (PST)
Subject: Sample message
MIME-Version: 1.0
Content-type: multipart/mixed; boundary="simple boundary"

Это преамбула. Она будет проигнорирована, но, тем не менее, это удобное место, чтобы отправитель мог поместить сообщение для принимающей стороны, которая не поддерживает MIME.

--simple boundary Это неявно введенный чистый US-ASCII-текст. Он не завершается на данной строке
--simple boundary Content-type: text/plain; charset=us-ascii. Это явно введенный чистый US-ASCII-текст. Он завершается на данной строке
--simple boundary Это эпилог. Он также игнорируется

Использование типа среды multipart в части тела в пределах другого составного объекта вполне допустимо. В таких случаях следует позаботиться о том, чтобы каждый из последовательно вложенных объектов использовал свой уникальный пограничный разделитель. Применение типа среды multipart при наличии только одной части тела может быть полезным в определенном контексте и вполне допустимо.

Практика показала, что тип multipart с единственной составной частью полезен для посылки сообщений с нетекстовым типом среды. Он имеет возможность формирования преамбулы как места, где можно поместить инструкции по декодированию. Кроме того, многие шлюзы SMTP перемещают или удаляют заголовки MIME, и хороший MIME-декодер таким путем может получить необходимую информацию даже в отсутствие заголовка Content-Type и корректно декодировать сообщение.

Единственным обязательным глобальным параметром для типа среды multipart является граничный параметр, состоящий из 1 - 70 кодов символьного набора, который надежен по отношению преобразований, осуществляемых почтовыми шлюзами. Значение параметра не должно завершаться пробелом. Формально это записывается в BNF-представлении следующим образом.

boundary := 0*69 bcharsnospace
bchars := bcharsnospace / " "
bcharsnospace := DIGIT / ALPHA / "’" / "(" / ")" / "+" / "_" /
   "," / "-" / "." / "/" / ":" / "=" / "?"

Вообще тело объекта multipart может быть специфицировано как:

dash-boundary := "--" boundary
; boundary берется из значения граничного параметра поля Content-Type.
multipart-body := [preamble CRLF]
dash-boundary transport-padding
CRLF
body-part *encapsulation
close-delimiter transport-padding
[CRLF epilogue]
transport-padding := *LWSP-char ; Отправители не должны генерировать
; транспортные заполнители ненулевой
; длины, но получатели должны уметь
; обрабатывать заполнители, введенные
; при транспортировке.
encapsulation := delimiter transport-padding CRLF body-part
delimiter := CRLF dash-boundary
close-delimiter := delimiter "--"
epilogue := discard-text
; Строки части тела не должны начинаться с дефис-границы, а разделитель
; не должен появляться где-либо в теле секции. Заметим, что семантика части
; тела отличается от семантики сообщения, как это описано в тексте.
OCTET := <любое значение октета 0-255 >

Введение пробелов (HT, SP) и комментариев RFC 822 между элементами, показанными выше, недопустимо, так как эти BNF не специфицируют структурированное поле заголовка.

В определенных транспортных зонах регламентации RFC 822, такие, как ограничение применения каких-либо символов, помимо печатных кодов US-ASCII, могут не действовать. Ослабление этих ограничений может рассматриваться как локальное расширение определения тел, например, чтобы включить октеты вне набора US-ASCII, так как эти расширения поддерживаются системой передачи и соответствующим образом документированы в поле заголовка Content-Transfer-Encoding. Однако заголовки ни в коем случае не могут содержать чего-либо помимо кодов US-ASCII.

Субтип message/rfc822 не имеет других условий завершения, кроме окончания массива данных. Аналогично, некорректно укороченный составной объект не может иметь завершающего разделителя, что может вызвать нарушение работы почтовой системы.

Существенно, чтобы такие объекты обрабатывались корректно, когда они сами вложены в другие составные структуры. Реализации MIME должны уметь распознавать граничные маркеры на любом уровне вложения.

Субтип mixed типа multipart предназначен для использования в условиях, когда части тела независимы и должны объединяться в определенном порядке. Любые субтипы multipart, которые не распознаны программой, должны восприниматься как субтип mixed.

Тип multipart/alternative синтаксически идентичен multipart/mixed, но имеет иную семантику. В частности, каждая часть тела является альтернативой одной и той же информации.

Системы должны распознавать, что содержимое различных частей взаимозаменяемы. Системы должны выбрать наилучший тип на основе локального окружения и в некоторых случаях — с использованием диалога с пользователем. Как и для multipart/mixed, порядок частей тела является существенным. В этом случае альтернативы появляются в порядке возрастания правдоподобия оригинальному содержимому. Вообще наилучшим выбором является последняя часть типа, поддерживаемая локальной средой приемной системы.

Multipart/alternative может использоваться, например, для посылки сообщения в любом формате таким образом, чтобы его было легко отобразить:

From: Nathaniel Borenstein
To: Ned Freed
Date: Mon, 22 Mar 1993 09:41:09 -0800 (PST)
Subject: Formatted text mail
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary=boundary42
--boundary42
Content-Type: text/plain; charset=us-ascii
... здесь следует версия сообщения в виде чистого текста ...
--boundary42
Content-Type: text/enriched
... здесь следует версия сообщения RFC 1896 в виде форматированного текста
(text/enriched) ...
--boundary42
Content-Type: application/x-whatever
... здесь следует наиболее причудливая версия сообщения ...
--boundary42--

В этом примере пользователи, чья почтовая система может работать с форматом application/x-whatever, увидят только причудливую версию сообщения, в то время как другие пользователи увидят версию с форматированным или чистым текстом, в зависимости от возможностей их системы.

Вообще, агенты пользователя, которые формируют объекты multipart/alternative, должны размещать части тела в порядке их предпочтения, то есть, предпочтительный формат следует последним. Посылающий агент пользователя должен поместить простейший формат текста первым, а форматированный — последним. Принимающие агенты должны воспринять самый последний формат, который они способны отобразить. В случае, когда одной из альтернатив является тип multipart, который содержит нераспознанные составные части, агент пользователя может отобразить эту альтернативу, более раннюю или даже обе версии сообщения.

Возможен вариант, когда агент пользователя способен распознать и отобразить разные форматы, — тогда он может предложить окончательный выбор самому пользователю. Это имеет смысл, например, если сообщение включает графическую и текстовую версии сообщения. Агент пользователя не должен автоматически отображать все версии, какие он воспринял, он должен отобразить последнюю или предоставить выбор оператору.

Каждая часть объекта multipart/alternative представляет одну и ту же информацию, версии не обязательно тождественны. Например, информация теряется, когда осуществляется трансляция ODA в PostScript или в чистый текст. Рекомендуется, чтобы каждая часть имела свое значение Content-ID в тех случаях, когда содержимое частей неэквивалентно. Например, там, где несколько частей типа message/external-body специфицируют способы доступа к идентичной информации, следует использовать одни и те же значения поля Content-ID. Возможен вариант, когда одно значение Content-ID может относиться к объекту multipart/alternative, в то время как одно или более других значений Content-ID будут относиться к частям внутри объекта.

Этот документ определяет субтип digest типа содержимого multipart. Этот тип синтаксически идентичен multipart/mixed, но их семантика различна. В частности, в дайджесте значение по умолчанию Content-Type для части тела меняется с text/plain на message/rfc822. Это сделано, чтобы допустить более читаемый формат дайджеста, совместимый с RFC-934.

Хотя можно специфицировать значение Content-Type для части тела в дайджесте, который отличается от message/rfc822, такая часть, как text/plain, содержащая описание материала в дайджесте, делает это нежелательным. Тип содержимого multipart/digest предназначен для использования при посылке группы сообщений. Если необходима часть text/plain, она должна быть включена как отдельная компонента сообщения multipart/mixed. Дайджест в этом формате может выглядеть как:

From: Moderator-Address
To: Recipient-List
Date: Mon, 22 Mar 1994 13:34:51 +0000
Subject: Internet Digest, volume 42
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="---- main boundary ----"
------ main boundary ----
...Вводный текст или содержимое таблицы...
------ main boundary ----
Content-Type: multipart/digest;
boundary="---- next message ----"
------ next message ----
From: someone-else
Date: Fri, 26 Mar 1993 11:13:32 +0200
Subject: my opinion
... здесь размещается тело...
------ next message ----
From: someone-else-again
Date: Fri, 26 Mar 1993 10:07:13 -0500
Subject: my different opinion
... здесь размещается следующее тело ...
------ next message ------
------ main boundary ------

Этот документ определяет субтип parallel типа содержимого multipart. Этот тип синтаксически идентичен multipart/mixed, но их семантика различна. В частности, в параллельном объекте порядок частей тела не играет роли.

Представление этого типа заключается в одновременном отображении всех частей с использованием имеющихся оборудования и программ. Однако программа-отправитель должна учесть то, что многие приемники почты не способны выполнять операции параллельно и отобразят все части сообщения последовательно.

Наталья Шульга
Наталья Шульга

Курс "информационная безопасность" .

Можно ли на него записаться на ПЕРЕПОДГОТОВКУ по данному курсу? Выдается ли диплом в бумажном варианте и высылается ли он по почте?

Нияз Сабиров
Нияз Сабиров

Здравствуйте. А уточните, пожалуйста, по какой причине стоимость изменилась? Была стоимость в 1 рубль, стала в 9900 рублей.

Антон Шавергин
Антон Шавергин
Россия
Степан Крупа
Степан Крупа
Украина, Львів, СЗШ №65, 2012