Работаем с почтой… вручную!

В детстве при получении в подарок новой игрушки, наверное, у многих возникало жгучее желание разобрать ее, посмотреть, что там внутри, узнать, как оно работает. И чем дороже, сложнее была игрушка, тем сильнее было такое желание. У некоторых с возрастом эта черта характера не исчезла.
В этой статье мы “разберем на части” электронную почту. Действительно, для работы с нею вовсе не обязательны почтовые программы, они просто делают весь процесс комфортней. Почтовые протоколы просты и рассчитаны скорее на человека, чем на компьютер, поэтому они легко реализуются независимо от платформы и оборудования.
Статья состоит из трех частей, в которых описываются формат сообщений электронной почты, протоколы ее получения и отправки. Для проверки этих знаний на практике нам понадобится компьютер с доступом в интернет.

Часть 1. Формат письма
На самом деле электронные письма совсем не такие, какими мы привыкли их видеть в почтовой программе. В них нет ни графики, ни шрифтов — только голый текст. Чтобы увидеть, что же представляет собой письмо, достаточно сохранить его на диск в формате MSG или EML, а потом открыть этот файл в любом текстовом редакторе, например, Блокноте.
Почтовое сообщение состоит из двух частей: заголовка и тела письма. Между ними расположена пустая строка. Каждое поле заголовка состоит, в свою очередь, из имени поля и значения, которые разделяются двоеточием. Полей заголовка может быть множество, но нам интересны только некоторые из них. Поля To: и From: указывают на получателя и отправителя письма соответственно, поле Subject: используется для передачи темы письма. ReplyTo: применяется для указания обратного адреса, а CC: — копии сообщения. Received: — такую строку добавляет каждый почтовый сервис, через который прошло письмо. По нему легко отследить путь письма. И, наконец, Date: — означает дату создания письма. Используется специальный стандарт с указанием часового пояса отправителя относительно Гринвича. (Например, Tue, 15 Jun 2004 10:05:59 +0400).
Существует множество нестандартизованных полей заголовка. Они начинаются с символа X. Это могут быть такие поля, как X-Mailer: — почтовая программа отправителя; X-MSMail-Priority:, X-Priority: — приоритет (важность) письма и так далее. Вы также можете придумать и использовать любое свое поле, начинающееся с X- .

Электронная почта не обладала бы столькими возможностями, если бы продолжала существовать в своем базовом варианте. Интересным дополнением к традиционной электронной почте является ее расширение MIME (Multupurpose Internet Mail Extentions). Оно не требует каких-либо переделок в почтовых серверах, но позволяет снять с электронной почты привычные ограничения и дает возможность пересылать любую информацию. Например, MIME позволяет создавать многосекционные письма. В каждой секции описывается тип информации, находящейся в ней (Content-Type:) и вид кодирования (Content-Transfer-Encoding:). Секции могут содержать как простой текст (Content-Type: text/plain) и текст в формате HTML (Content-Type: text/html), так и произвольные файлы в прикреплениях письма (attach).

Так как электронная почта изначально разрабатывалась как служба по пересылке обычного текста, это наложило ограничение на передаваемую информацию. Для передачи двоичной информации требуется специальное кодирование. Используется несколько методов кодирования: для текста с использованием только латинских букв, цифр и некоторых спецсимволов обычно используется Content-Transfer-Encoding: 7bit. Если сюда еще добавить русские буквы, то семи бит уже мало и приходится использовать Content-Transfer-Encoding: 8bit. Для передачи html-кода применяют Content-Transfer-Encoding: quoted-printable, когда некоторые проблемные символы заменяются их кодами. Чтобы отличить код от текста, перед ним ставится символ «=». Например, фраза “Привет!” предстанет в закодированном виде как “=CF=F0=E8=E2=E5=F2!”. Для двоичных файлов (архивы, изображения и прочее) используют Content-Transfer-Encoding: base64, когда каждые 6 байт преобра­зуются в 8 печатных символов. Поэтому, если к письму прикрепить файл размером в 300 Кбайт, оно “потянет” на все 400 Кбайт.
Вот пример обычного текстового письма:

From test@test.net (127.0.0.1) Tue, 15 Jun 2004 06:05:59 GMT For gates@microsoft.com
From: "Tester" <test @test.net>
To: "Bill Gates" <gates @microsoft.com>
Subject: Test
Date: Tue, 15 Jun 2004 10:05:59 +0400
X-MSMail-Priority: Normal
X-Priority: 3
X-Mailer: Microsoft Internet Mail 4.70.1155
MIME-Version: 1.0
Content-Type: text/plain; charset=KOI8-R
Content-Transfer-Encoding: 7bit
Just a test.</gates></test>

Часть 2. Получение почты
Электронную почту можно получать по протоколу POP3 (Post Office Protocol — Version 3). Команды протокола POP3 состоят обычно из четырех букв. После каждой команды сервер выдает ответ +OK в случае нормального завершения и -ERR — в случае ошибки. За работу POP3 отвечает­ 110-й порт.
Для общения с почтовым сервером нам понадобится программа telnet, которая есть в составе любой версии Windows. Итак, запускаем “Пуск” -> “Выполнить”, набираем telnet < имя_сервера> < порт>. Например:
telnet ezmail.ru 110
Сразу после подключения сервер выдаст строку приветствия. Он представился — теперь, согласно правилам хорошего тона, надо представиться нам. Для этого используется пара команд USER и PASS. Пример:

USER < ваш логин>
+OK
PASS < ваш пароль>
+OK 6 8098

Сразу за ответом +OK следует информация о количестве писем и их общем размере. Для получения списка писем нужно ввести команду LIST. В результате сервер выдаст список писем с указанием размера каждого письма. На сервере письма различаются при помощи специального идентификатора. Как и во всех многострочных ответах POP3, в конце списка находится строка с одной только точкой.

LIST
+OK 3 2032
1 425
2 1192
3 415
.

Теперь для обращения к какому-либо конкретному письму мы должны использовать его идентификатор. Для работы с письмами используются команды RETR, DELE и TOP. Команда RETR используется для получения письма с сервера. В качестве единственного параметра ей передается идентификатор письма, который выдала команда LIST.

RETR 1
+OK 417 bytes for admin
From test@test.net (lab1 [167.15.230.25]) Mon, 7 Jun 2004 11:11:44 GMT For test@mail.ru
From: "Test" <test @test.net>
To: </test><test @mail.ru>
Subject: =?KOI8-R?Q?=D0=D2=CF=D7=C5=D2=CB=C1?=
Date: Mon, 7 Jun 2004 15:11:44 +0400
X-Mailer: Microsoft Internet Mail 4.70.1155
MIME-Version: 1.0
Content-Type: text/plain; charset=KOI8-R
Content-Transfer-Encoding: 8bit

Проверка
.</test>

Команда DELE используется, чтобы пометить письмо для удаления (физически удаление происходит при завершении почтовой сессии). Единственный параметр этой команды — идентификатор письма.
Команда TOP применяется для тех случаев, когда целиком получать письмо не надо, достаточно лишь первых строк. Это может использоваться, например, для фильтрации спама по заголовкам писем, без скачивания письма целиком. Первый аргумент команды TOP — это идентификатор письма, а второй — количество строк тела письма, которые должны быть получены вместе с заголовком.
Ну и последняя команда POP3-протокола, которая нам понадобится, — это QUIT. Она сигнализирует серверу о завершении почтовой сессии. Приняв ее, сервер завершает соединение.
Вот пример типичной почтовой сессии по POP3-протоколу:

+OK POP3 server ready
USER admin
+OK
PASS password
+OK 1 425
LIST
+OK 1 425
1 425
.
RETR 1
+OK 425 bytes for admin
< тело письма>
.
DELE 1
+OK
QUIT
+OK

Для получения почты используют также более сложный протокол IMAP4 (Internet Message Access Protocol — version 4 rev1), но его рассмотрение не входит в рамки данной статьи.

Часть 3. Отправка почты
Отправка почты осуществляется по протоколу SMTP (Simple Mail Transfer Protocol), который тоже использует понятные текстовые команды. Подключение к SMTP-серверу осуществляется аналогичным образом, только для соединения используется 25-й порт. Но ответы сервера имеют другой формат, который кодируется трехзначным числом. Каждая цифра в коде ответа несет определенный­ смысл. Первая цифра означает, было ли вы­полнение команды успешно (2), неуспешно (5) или еще не закончилось (3). Вторая цифра­ показывает категорию ошибки, а третья идентифицирует конкретную ошибку. Основные­ коды, которые нам понадобятся: 220 (SMTP-сервер готов к работе); 250 (успешное завершение действия); 354 (ожидание ввода текста письма) и 221 (закрытие сессии).
После установления соединения SMTP-сервер представляется нам (220-й код). Логично, что и мы должны также представиться ему. Для этого используется команда HELO. Единственным ее аргументом является имя вашего компьютера. То есть вы говорите: “Привет, я — test.kirov.ru”.

220-proxy.kirov.ru ESMTP Sendmail 8.12.6/8.12.6; Mon, 14 Jun 2004 12:00:00 +0300 (MSK)
220-Use of this system for the delivery of UCE (a.k.a. SPAM), or any other
220-message without the express permission of the system owner is prohibited.
220 Use of this system for third party relaying is prohibited.
HELO test.kirov.ru
250 proxy.kirov.ru Hello test.kirov.ru [167.15.230.25], pleased to meet you

В ответ сервер должен выдать код 250, сообщая о том, что команда принята и обработана. Следующим шагом мы должны указать обратный адрес, на который письмо вернется в случае неудачи. Делается это при помощи команды MAIL FROM:

MAIL FROM: test@mail.ru
250 Ok

Далее необходимо указать получателя сообщения. Для этого используем команду RCPT TO:. Если получателей несколько, то команда RCPT вводится несколько раз.

RCPT TO:<tester @mail.ru>
250 Ok
RCPT TO:<test128 @mail.ru>
550 Unknown user
RCPT TO:<test123 @mail.ru>
250 Ok</test123></test128></tester>

После того как введены все RCPT, можно начинать передачу данных при помощи команды DATA.

DATA
354 Enter mail, end with "." on a line by itself

Сервер отвечает кодом 354, сигнализируя, что передача данных разрешена, и подсказывает, что конец передачи письма кодируется строкой, состоящей из одного только символа — точки. При успешном приеме тела письма сервер выдаст код 250.

DATA
354 send the mail data, end with .
To: test@mail.ru
From: test123@mail.ru
Subject: Письмо

Первая строка письма
Вторая строка письма
Третья строка письма
Последняя строка письма
.
250 Ok
QUIT
221 Bye

Завершается почтовая сессия, как и в протоколе POP3, командой QUIT. Сервер, в свою очередь, отвечает кодом 221. Этот код подтверждает клиенту, что соединение будет закрыто, после чего соединение действительно закрывается.
Вот пример полной почтовой SMTP-сессии:

220 BBN-UNIX.ARPA Simple Mail Transfer Service Ready
HELO USC-ISIF.ARPA
250 BBN-UNIX.ARPA
MAIL FROM:<smith @USC-ISIF.ARPA>
250 OK
RCPT TO:<jones @BBN-UNIX.ARPA>
250 OK
RCPT TO:<green @BBN-UNIX.ARPA>
550 No such user here
RCPT TO:<brown @BBN-UNIX.ARPA>
250 OK
DATA
354 Start mail input; end with <crlf>.</crlf><crlf>
To: Jones@BBN-UNIX.ARPA
From: Smith@USC-ISIF.ARPA
Subject: Test

Hi!
This is a test message.
.
250 OK
QUIT
221 BBN-UNIX.ARPA Service closing transmission channel</crlf></brown></green></jones></smith>

Теперь вы знаете об особенностях работы почтовых серверов, и в курсе, что делает почтовая программа во время получения и отправки почты. Если вам интересны подробности этих протоколов, ищите в интернете стандарты RFC0822 — формат письма; RFC1521, RFC2045 — MIME; RFC1225, RFC1725 — POP3 и RFC821, RFC2554 — SMTP а также RFC2060 — IMAP4.


Рекомендуем почитать: