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

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

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

  1. 8-битовое представление. Любой октет (за исключением CR или LF, которые являются частью последовательности разрыва строки CRLF) канонического (стандартного) формата данных может быть представлен с помощью символа "=", за которым следуют две шестнадцатеричные цифры, характеризующие значение октета. Для этих целей используются цифры шестнадцатеричного алфавита "0123456789ABCDEF". Должны применяться прописные буквы; использование строчных букв недопустимо. Так, например, десятичное значение 12 (ASCII FF) может быть представлено как "=0C", а десятичное значение 61 (ASCII символ знака равенства) представляется с помощью "=3D". Это правило должно выполняться всегда за исключением случаев, когда правила допускают альтернативное кодирование
  2. Литеральное представление. Октеты с десятичными кодами в интервале 33 - 60 включительно и 62 - 126, включительно могут представляться ASCII-символами, которые соответствуют этим октетам (с "!" до "<" и с ">" до "~" соответственно)
  3. Пробелы. Октеты со значениями кодов 9 и 32 могут отображаться с помощью ASCII-символов TAB (HT) и пробел, соответственно, но не должны использоваться в конце строки. За любым символом TAB (HT) или пробел в кодируемой строке должен следовать печатный символ. В частности, символ "=" в конце каждой кодируемой строки, обозначающий "мягкий" разрыв строки (смотри правило #5), может следовать за одним или более символами TAB(HT) или SP. Отсюда следует, что октет, равный 9 или 32, появляющийся в конце кодируемой строки должен быть представлен в форме, указанной правилом #1. Это правило необходимо, так как некоторые MTA (Message Transport Agents, программы, которые передают сообщения от одного пользователя другому) дополняют строки пробелами, а другие удаляют пробелы ( HT или SP ) в конце строки. Следовательно, при декодировании тела, представленного в форме закавыченных печатных последовательностей, любые HT или SP должны быть удалены
  4. Разрывы строк. Разрыв строки в теле текста, представленный последовательностью CRLF в канонической форме, для закавыченной печатной строки отмечается CRLF. Последовательности типа "=0D", "=0A", "=0A=0D" и "=0D=0A" появляются в нетекстовых данных, представленных в виде закавыченных строк печатных символов. Заметим, что многие реализации могут выбрать для кодирования непосредственно локальное представление различных типов содержимого, а не преобразование в каноническую форму, кодирование и только затем преобразование в локальное представление. В частности, такая техника может быть применена к простому тексту в системах, которые используют для межстрочных разрывов последовательности, отличные от CRLF. Такая оптимизация конкретной программной реализации вполне допустима, но только когда комбинированный шаг канонизация-кодирование эквивалентен выполнению всех трех шагов отдельно
  5. Мягкие разрывы строки. Кодирование с помощью закавыченных строк печатных символов требует, чтобы строки содержали не более 76 символов. Если нужно закодировать более длинные строки, вводятся мягкие разрывы строк. Символ равенства в конце строки как раз и обозначает такой разрыв

Пусть имеется следующий текст, который надо преобразовать:

Now’s the time for all folk to come to the aid of their country.

Он может быть представлен следующим образом с помощью закавыченных строк печатных символов:

Now’s the time =
for all folk to come=
to the aid of their country.

Это предоставляет механизм, с помощью которого длинные строки преобразуются таким образом, как они должны быть запомнены агентом пользователя. Ограничение в 76 символов не учитывает завершающие строку CRLF, но содержит все прочие символы, включая знаки равенства. Так как символ дефис ("-") может отображаться в закавыченных строках самим собой, нужно следить за тем, чтобы при инкапсуляции закодированного фрагмента в одном или более составных объектов пограничные разделители не появились в закодированном теле. Хорошей стратегией является выбор в качестве границы последовательности символов "=_", которая не может встретиться в закавыченной строке печатных символов.

Преобразование в закавыченные строки печатных символов представляет собой компромисс между читабельностью и надежностью при транспортировке. Тела, закодированные с помощью закавыченных строк печатных символов, пропускаются без проблем большинством почтовых шлюзов. Проблемы могут возникать только со шлюзами, осуществляющими трансляцию в коды EBCDIC. Кодирование с помощью base64 обеспечивает более высокий уровень надежности. Методом получения разумно высокой надежности транспортировки через шлюзы EBCDIC является представление символов !"#$@[\]^'{|}~ согласно правилу #1.

Так как закавыченные последовательности печатных символов предполагаются ориентированными на строчное представление, разрывы между строками могут видоизменяться в процессе транспортировки. Если изменение кодов разрыва строк может вызвать искажения или сбои, следует использовать кодирование с помощью base64.

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

  1. Символ "=", за которым следует две шестнадцатеричные цифры, одна или обе из которых являются строчными символами (abcdef), является нелегальным. Надежные реализации могут распознавать их как прописные буквы
  2. Символ "=", за которым следует символ, не являющийся ни шестнадцатеричной цифрой (включая abcdef), ни CR из комбинации CRLF, является нелегальным. Это не может стать частью ASCII-текста, включенного в сообщение, без преобразования в закавыченную последовательность печатных кодов. Разумным решением для надежной реализации может быть: включить символ "=" и следующие за ним коды в декодированную последовательность без какого-либо преобразования и, если возможно, дать сигнал агенту пользователя, что декодирование в этом месте оказалось невозможным
  3. Символ "=" не может быть последним или предпоследним символом в кодируемом объекте. Решением проблемы можно считать способ, предложенный в пункте (2)
  4. Управляющие символы, отличные от TAB или CR и LF (в качестве части CRLF), не должны присутствовать. То же справедливо для октетов с десятичными значениями больше, чем 126. Если такие коды обнаруживаются в приходящих закавыченных последовательностях печатных символов, корректная реализация может исключить их из декодированных данных и предупредить пользователя о том, что обнаружен нелегальный символ
  5. Закодированные строки не должны быть длиннее 76 символов, не считая завершающие CRLF. Если во входном потоке обнаружены более длинные строки, надежная реализация может их декодировать, но должна предупредить пользователя об ошибке

Если двоичные данные закодированы в виде закавыченных последовательностей печатных символов, следует позаботиться о том, чтобы символы CR и LF были представлены в виде "=0D" и "=0A", соответственно. В частности, последовательность CRLF в двоичных данных должна кодироваться как "=0D=0A". В противном случае, если CRLF была бы представлена как жесткий разрыв строки, она может декодироваться некорректно на платформах с различными способами обработки разрывов строки. С формальной точки зрения, закавыченные последовательности печатных символов подчиняются следующей грамматике.

quoted-printable := qp-line *(CRLF qp-line)
qp-line := *(qp-segment transportpadding CRLF) qp-part transport-padding
qp-part := qp-section ; Максимальна длина 76 символов
qp-segment := qp-section *(SPACE / TAB) "=" ; Максимальна длина 76 символов
qp-section := [*(ptext / SPACE / TAB) ptext]
ptext := hex-octet / safe-char
safe-char := <любой октет с десятичным кодом от 33 до 60 включительно, и от 62 до 126> ; Символы, не включенные в список "mail-safe" RFC 2049, не рекомендуются к применению
hex-octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F") ; Октет должен использоваться для символов с кодами > 127, =, SP или TAB в конце строк, и рекомендуется для любого символа не указанного в списке "mailsafe" документа RFC 2049
transport-padding := *LWSP-char ; Составители не должны генерировать заполнители ненулевой длины, но получатели должны быть способны обрабатывать заполнители, добавленные при транспортировке

Добавление LWSP между элементами, показанное в данном BNF-представлении, не допустимо, так как данное BNF не специфицирует структурированных полей заголовка.

Транспортное кодирование на основе Base64 создано для представления произвольной последовательности октетов в форме, которая не обязательно должна быть приемлемой для прочтения человеком. Алгоритмы кодирования и декодирования просты. Это кодирование сходно с тем, что используется в почтовом приложении PEM (Privacy Enhanced Mail), как это определено в RFC-1421.

Здесь используется 65-символьный субнабор ASCII, для каждого печатного символа выделено по 6 бит. Дополнительный 65-ый символ "=", используется для обозначения специальных функций обработки.

Этот субнабор имеет важное свойство, которое заключается в том, что он представляется идентично во всех версиях ISO 646, включая US-ASCII, и все символы субнабора имеют аналоги во всех версиях EBCDIC. Другие популярные кодировки, такие, как применяемые утилитой uuencode, Macintosh binhex 4.0 [RFC-1741] и base85, специфицированная как часть уровня 2 PostScript, имеют отличающиеся свойства и, следовательно, не выполняют условий переносимости, которым должно удовлетворять двоичное транспортное кодирование электронной почты.

При кодировании входные 24-битовые группы преобразуются в 4 символа. Входная группа формируется из трех 8-битовых кодов и обрабатывается слева направо. Эти 24 бита рассматриваются в дальнейшем как 4 6-битовые группы, каждая из которых транслируется в одно число из алфавита base64. Когда кодируется битовый поток с использованием base64, предполагается, что старший бит передается первым. То есть, первый бит потока станет старшим битом первого 8-битового байта, а 8-ой бит станет его последним битом.

Каждая 6-битовая группа используется как индекс массива из 64 печатных символов. Символ, на который указывает индекс, берется из массива и помещается в выходной поток. Эти символы представлены в таблице 1.10, из их перечня исключены коды, имеющие особое значение для протокола SMTP (например, ".", CR, LF), а также разграничитель секций составного сообщения "-" (RFC-2046).

Таблица 1.10. Коды Base64
Код символа (6 бит) ASCII символ Код символа (6 бит) ASCII символ Код символа (6 бит) ASCII символ Код символа (6 бит) ASCII символ
0 A 10 Q 20 g 30 W
1 B 11 R 21 h 31 X
2 C 12 S 22 i 32 Y
3 D 13 T 23 j 33 Z
4 E 14 U 24 k 34 0
5 F 15 V 25 l 35 1
6 G 16 W 26 m 36 2
7 H 17 X 27 n 37 3
8 I 18 Y 28 o 38 4
9 J 19 Z 29 p 39 5
A K 1A a 2A q 3A 6
B L 1B b 2B r 3B 7
C M 1C c 2C s 3C 8
D N 1D d 2D t 3D 9
E O 1E e 2E u 3E +
F P 1F f 2F v 3F /

Закодированный выходной поток должен иметь формат последовательности из одной или более строк длиной не более 76 символов каждая. Все разрывы строк или другие символы, не содержащиеся в таблице 1.10, должны игнорироваться декодирующим программным обеспечением. В данных, представленных в кодах base64, символы, отличные от тех, что содержатся в таблице 1.10, разрывы строк и другие пробелы обычно указывает на ошибку передачи, которая вызовет предупреждение или даже выбрасывание сообщения.

Если число бит в группе меньше 24, используется специальная обработка. Неполная битовая группа дополняется нулями справа до 24. Заполнение в конце информационной группы осуществляется с использованием символа "=". Так как последовательность кодов base64 представляет собой поток октетов, возможны следующие случаи:

  1. последний блок кодируемых данных кратен 24 битам; здесь, завершающий выходной блок будет содержать в себе 4 символа и никакого заполнителя;
  2. завершающий блок кодируемых данных содержит ровно 8 бит; здесь, оконечный выходной блок будет содержать два символа, за которыми будут следовать два символа заполнителя; или
  3. последний блок кодируемой информации содержит ровно 16 бит; здесь, оконечный блок на выходе будет иметь три символа плюс один символ заполнителя "=".

Так как "=" используется для дополнения, его наличие указывает на то, что мы достигли конца массива данных. Такая уверенность невозможна, когда число переданных октетов кратно трем и нет ни одного символа "=". Любые символы, не входящие в алфавит base64, должны игнорироваться.

Следует позаботиться о том, чтобы использовались корректные октеты в качестве разделителей строк при работе с base64. В частности, разрывы строк должны быть преобразованы в последовательности CRLF до выполнения кодирования base64.

При создании агента пользователя высокого уровня, может быть желательно, разрешить одному телу сообщения ссылаться на другое. Тела могут быть помечены с помощью поля заголовка "Content-ID", которое синтаксически идентично полю "Message-ID":

id := "Content-ID" ":" msg-id

Подобно значениям Message-ID, значения Content-ID должны генерироваться уникальными.

Значение Content-ID может использоваться для идентификации MIME-объектов в нескольких контекстах, в частности, для кэширования данных с доступом через механизм message/external-body. Хотя заголовок Content-ID является обычно опционным, его применение является обязательным в приложениях, которые генерируют данные опционного типа среды MIME message/external-body. По этой причине каждый объект message/external-body должен иметь поле Content-ID, чтобы разрешить кэширование таких данных.

Часто оказывается желательным установить соответствие между описательной информацией и данным телом. Например, может быть полезным пометить тело типа image как изображение старта космического корабля. Такой текст может быть помещен в поле заголовка Content-Description. Это поле всегда является опционным.

description := "Content-Description" ":" *text

Предполагается, что описание дается с использованием символьного набора US-ASCII, хотя механизм, специфицированный в RFC 2047, может быть использован и для значений Content-Description, не соответствующих стандарту US-ASCII.

Будущие документы могут содержать дополнительные поля заголовков MIME для различных целей. Любое новое поле заголовка, которое описывает содержимое сообщения, должно начинаться со строки "Content-", чтобы такие поля можно было с гарантией отличить от обычных полей заголовков сообщения, следующих стандарту RFC-822. MIME-extension-field := <Любое поле заголовка RFC-822, которое начинается со строки "Content-">

Используя поля заголовка MIME-Version, Content-Type и Content-Transfer-Encoding, можно подключить стандартным образом произвольные типы данных и добиться совместимости с требованиями документа RFC-822. Никакие ограничения, введенные документами RFC-821 или RFC-822, не нарушаются, — были приняты меры, чтобы исключить проблемы, связанные с дополнительными ограничениями из-за свойств некоторых механизмов пересылки почты по Интернет (см. RFC-2049).

Евгений Виноградов
Евгений Виноградов

Прошел экстерном экзамен по курсу перепордготовки "Информационная безопасность". Хочу получить диплом, но не вижу где оплатить? Ну и соответственно , как с получением бумажного документа?

Илья Сидоркин
Илья Сидоркин

Добрый день! Подскажите пожалуйста как и когда получить диплом, после сдичи и оплаты?????

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