Принцип кодирования в uuencode и base64
Скачать исходник к данной статье - 5Кб
При необходимости послать по электронной почте нетекстовый файл его сначала нужно преобразовать в закодированную форму, которая не запутала бы Ваш почтовый сревер или то ПО электронной почты, которое работает у получателя. Существуют несколько способов такого преобразования. Наиболее известны из них два. Ранее использовался uuencode, теперь стандартом является base64. В большинстве случаев нужно пользоваться вторым способом, особенно если для передачи сообщение используется протокол MIME. Однако, некоторые старые приложения электронной почты не понимают MIME или base 64, поэтому тут приведены оба способа.
Вроде бы технические детали этих способов кодирования отображены в документах rfc2045, 2046, 2049. (Гм, только по ним я не разобрался, хотя достаточно сносно владею английским). Основополагающая идея обоих методов состоит в преобразовании двоичных файлов в ASCII файл, который может быть нормально передан и обработан сервером электронной почты. Это делается путем разбивки исходного файла на группы из 3 байтов, и последующего деления каждой трехбайтной группы на 4 группы по 6 бит. (в трех байтах 24 бита). Эти 6 битов ( с их помощью можно представить любое число от 0 до 63) затем отображаются в конкретный диапазон печатаемых символов ASCII и затем вновь собираются в строку ASCII, которую можно включить в сообщение электронной почты. У получателя сообщения выполняется обратный процесс, в ходе которого воссоздается исходный файл.
Для кодирования в base64 используются символы: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
для uuencode используются следующие символы: `!"#$%&'()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
Различия между base64 и uuencode обусловлены способом форматирования закодированных файлов.
При UU-кодировании из файла читаются группы по 45 байт, они кодируются описанным ваше способом. То есть, каждые три байта превращаются в 4, каждый байт из этих четырех - номер символа в строке `!"#$%&'()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ (будем называть эту строку uu-строкой) причем ноль соответствует первому символу. В начале результирующей строки должен быть символ, номер которого в uu-строке совпадает с количеством байт в исходной группе.
То есть, если была прочитана группа 45 байт, то в результирующей строке сначала стоит символ 'M' (его номер 46, но нумерация в uu-строке идет с нуля) Если же была прочитана группа из меньшего количества байт, например из 5 байт (это означает, что кодируемый файл закончился, и из требуемых 45 в файле остались непрочитанными только 5 байт, например в случае, когда размер файла 50 байт) то первым должден стоять символ '%'(его номер 5, если начинать считать с нуля). Если количество прочитанных байт меньше 45 и не разбивается на группы по три байта, то последняя группа доукомплектовывается нулями.
После первого символа идет закодированная строка (60 символов, если было прочитано 45 байт). за ними должен идти признак конца строки. В принципе достаточно '\n' но можно и "\r\n". Таким образом исходный файл был закодирован. Полученные строки можно отправлять. Итак, при кодировании в uu-encode нужно форматировать результирующие данные в строки по 61 байт, первый из которых обозначает количество байт в исходной строке.
Теперь немного о правилах отсылки вложений, закодированных в uu-encode. Прямо в теле письма нужно написать begin 600 filename.ext далее идет сам закодированный файл. Затем, после последней строки, с новой строки символ '`' и с новой строки "end"
например:
text begin 644 notepad.exe Codeddata ` end
продолжение текста письма.
(Экспериментально проверено, что можно также писать begin 600 filename)
Теперь о кодировании в base64. При кодировании в base64 требуется форматировать закодированные данные в строки по 76 символов. Для реализации этого удобно читать по 57 байт, кодировать их в строку 76 символов. Самое интересное, как всегда, это последняя строка. Каждая группа из 4 символов в закодированной строке соответствует 3 байтам. Исключение составляют последние 4 символа. Они могут соответствовать 1, 2 или 3 -м байтам. Нужно указать, сколько байтов закодировано. При uu кодировании для этого использовался первый символ строки. Но он же необоснованно применялся в начале каждой полной строки. При кодировании base64 применяется следующий подход: Если последние 4 символа соответствуют 2 байтам, то строку нужно завершить одним знаком =, если они соответствуют одному исходному,то двумя знаками =. Если трем байтам, то ни одного знака =. То есть, в последней группе из 4 символов последние два могут быть знаками =, или последний симовол может быть знаком =. Для вычисления количества знаков =, зная размер исходного файла, можно использовать такую формулу pad=(3-len%3)%3. (Предоставляю читателям самим удостовериться, почему она правильная).
Для отправки писем с вложениями, закодированными base64 всегда используется протокол MIME (Его я здесь описывать не буду).
В общем я думаю идея ясна. В исходнике вы найдете небольшую программку, в которой реализованы функции uu-кодирования и base64- кодирования, а также uu-декодирования. (декодирования файлов, закодированных base64 мне честно говоря писать влом, но может, со временем, решусь и на сей подвиг;)) Также эта прога отправляет письмо с использованием протокола MIME и двумя вложенными файлами, закодированными разными способами. Для тех, кто захочет посмотреть как отправлять письмо без MIME, просто удалите или закомменируйте все между ">>>" и "При написании этой статьи (если это можно так назвать) была использована книга "CGI/Perl" К. Пэтчетта и М. Райта а также почтовый клиент TheBat!1.53. Кстати, зебат, весьма удобная вещь, особенно для отладки. Просто берёшь письмо, вкладываешь в него файл потом жмешь F9 (view source) и видишь, как должно быть сформатировано письмо.
Прога (исходник, здесь прилагаемый) написана в демонстрационных целях, поэтому совсем непохожа на законченный программный продукт. Я ее прогонял для проверки правильности кодирования, кодирует и отсылает все нормально (по крайней мере mail.ru понимает) но гонял я ее только по шагам в debug режиме;)) Более нормальную прогу найдете на этом сайте на странице "Набор почтовых утилит"
Оставить комментарий
Комментарии
зачем в формуле pad=(3-len%3)%3 последнее получение остатка от деления на 3?
len%3<3 всегда. следовательно 3-len%3 тождественно равно (3-len%3)%3. или я ошибаюсь?
Я давно искал инфу по этой теме: чтобы было коротко и самое главное.
Спасибо Автору!