CFA LogoCFA Logo Computer
Загрузка поиска
Новости Компьютеры Прайс-лист [Новое] Прайс-лист [Б/У] Для ноутбуков Конфигуратор ПК Заказ, Оплата, Доставка Сервис объявления Драйвера Статьи Как нас найти Контакты
Новости
RSS канал новостей
То, что энтузиасты ждали так долго, наконец-то случилось, и компания NVIDIA анонсировала свой новый ...
Официальный анонс графического ускорителя GeForce GTX 1080 Ti состоялся 1 марта, и партнеры NVIDIA ...
Компания ASRock представила мировой общественности материнскую плату H110-STX MXM, которая рассчитана ...
Компания MSI в рамках серии Arsenal Gaming представляет пользователям материнские платы линейки ...
По данным наших коллег, в этом месяце компания Huawei официально представит свой новый смартфон. ...
Самое интересное
Программаторы 25 SPI FLASH Адаптеры Optibay HDD Caddy Драйвера nVidia GeForce Драйвера AMD Radeon HD Игры на DVD Сравнение видеокарт Сравнение процессоров

АРХИВ СТАТЕЙ ЖУРНАЛА «МОЙ КОМПЬЮТЕР» ЗА 2003 ГОД

Сокетовое нутро почты

Артем Cosmic ШМАНЦЫРЕВ cosmic@mail.zp.ua

В статье «Консольный почтальон» (см. МК 33-34 (256-257)) мы рассмотрели возможность приема и передачи электронной почты вручную при помощи программы telnet в случае отсутствия почтового клиента в гипотетическом интернет-клубе. Теперь, чтобы не мучить больше клавиатуру набором малопонятных команд, мы напишем свой почтовый клиент, будем его повсюду носить на дискетке и проверять, проверять, проверять…

Любой программист, занимающийся программированием сети (локальной или глобальной — неважно), рано или поздно сталкивается с загадочным словом «winsock», без которого почему-то не получается корректно подключиться к серверу или закачать файл на соседний компьютер. Вот и мы вплотную подошли к тому пределу, переступив который, вы научитесь программировать сетевые приложения любой сложности, используя при этом минимум функций, которые, однако, весьма могущественны.

Winsock — это интерфейс сетевого программирования для операционных систем семейства Microsoft Windows, основанный на принципах сокетов (sockets), разработанных командой Berkeley Software Distribution (BSD) из университета Беркли (штат Калифорния, США). Портированием идей этого интерфейса на платформу Windows впервые занялся Мартин Холл из компании JSB Corporation в сентябре 1991 года. В дальнейшем развитием этого столь удачного начинания занялись более 40 компаний по всему миру, в результате чего традиционно выиграл конечный пользователь, получивший возможность программировать приложения с универсальной сетевой архитектурой.

В сегодняшней статье я постараюсь дать вам, уважаемые читатели, полное представление о функционировании электронной почты на «низком уровне» — на уровне программирования почтовых протоколов при помощи Winsock в среде программирования Borland Delphi. На мой взгляд, Delphi лучше всего подходит для реализации поставленной задачи в силу интуитивности и ясности исходного кода — для программиста не будет проблемой перенести код на другой язык программирования или портировать в другую операционную систему. В дальнейшем предполагается, что вы знакомы с этим языком программирования, поэтому особо подробных разъяснений относительно исходного кода я давать не буду.

Для начала давайте запасемся программным обеспечением, необходимым для написания и отладки нашего приложения (пусть оно будет иметь название Simple@Mail — простое мыло :-)). Для этого нам необходима среда разработки Borland Delphi версий 5, 6 или 7, почтовый сервер (лучшим, на мой взгляд, является Courier Mail Server (CMS), скачать который можно по ссылке http://courierms.narod.ru/download/cms200b2.zip, 510 Кб) и, наконец, для экспериментов с сервером нам может понадобится программа telnet, которая должна находиться в системной папке Windows.

Если вы имеете unlimited-доступ к Интернет, то почтовый сервер можете не скачивать, а смело экспериментировать с почтой своего провайдера или любым бесплатным почтовым сервером. В любом другом случае настоятельно рекомендую скачать CMS, дабы сэкономить себе нервы и деньги :-). Сервер можно просто запускать, не настраивая, но единственным пользователем тогда окажется человек по имени admin, с паролем в виде единички и почтовым адресом admin@local.domain. Если по каким-либо причинам вас такие параметры не устраивают, вы можете создать свой домен и в нем прописать своего пользователя (Рис. 1).

Но давайте ближе к делу. Открываем IDE Delphi, создаем новое приложение (File > New > Application) и размещаем на появившемся окне элементы управления соответственно Рис. 2.

Рис. 1.   Рис. 2.

Как видно по рисунку, все элементы управления на форме имеют интуитивно понятные имена. Это сделано затем, чтобы вам в будущем не приходилось путаться в исходном коде, т.е. чтобы четко знать, какой элемент за что отвечает. Согласитесь, это удобнее, чем все время вспоминать, для чего предназначена кнопка с именем Button1, а для чего — Button64 :-).

Теперь в секции uses-модуля главной формы проекта в конце имеющегося списка допишите юнит Winsock — в нем содержатся все функции интерфейса Windows Socket, которые будут нами сегодня использоваться. Я принципиально не использую VCL, поставляемую с Delphi — с ней сложнее обрабатывать ошибки, да и размер скомпилированного файла она увеличивает достаточно ощутимо.

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

Чтобы переслать команду серверу и принять его ответ, мы напишем две функции —WSSendString и WSRecvString:

Для управления интерфейсом Winsock существуют стандартные процедуры, позволяющие производить самые необходимые действия: создание сокета, соединение с сервером, прием/передача данных, закрытие соединения.

Передача строки (в нашем случае — команды серверу) осуществляется функцией send, в качестве параметров принимающей созданный сокет, заполненный буфер (массив байт, в котором посимвольно содержится команда), размер буфера и специальные флаги. В принципе, для пересылки команды можно просто использовать функцию send «в чистом виде», однако это приведет к ненужному увеличению исходного кода, так как к каждой строке придется прибавлять символы перевода строки (с кодом 13 и 10) и преобразовывать ее в массив байт. Кроме того, в соответствии с принятыми стандартами (RFC 1939 и RFC 821), размер команды (точнее, строки, содержащей команду) не должен превышать 1000 символов.

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

Функция возвращает строку, содержащую ответ сервера. Единственное ограничение составляет размер строки — 1024 байт, — поэтому сообщения размером более 1 Кб (например, сообщения с прикрепленными файлами) принять не удастся. Для этого нужно использовать асинхронные сокеты, а это уже тема отдельной статьи.

Кроме функций приема/передачи, нам нужна будет процедура занесения уже полученных сообщений в список lstMessages. Вот ее исходный текст:

Здесь производится поиск файлов с расширением .msg в текущем каталоге; при успешном нахождении таковых имена их заносятся в список. Эту процедуру нужно вызывать при загрузке формы и при окончании каждой транзакции получения писем.

Далее переходим к программированию событий.

В нашей программе действия будут производиться только с двумя элементами управления — кнопкой btnGet и списком lstMessages. Все остальные элементы управления будут пассивными — то есть мы будем с ними работать, реализовывая интерфейс ввода параметров соединения и вывода сообщений, не обрабатывая при этом их события.

Для того чтобы определить событие для элемента управления, необходимо выделить элемент, выбрать вкладку Events окошка Object Inspector в Delphi и в поле необходимого события написать имя процедуры, которая будет выполняться при выполнении этого события. Для кнопки btnGet и для списка lstMessages нам необходимо определить события OnClick (нажатие на кнопку и выбор пункта в списке) с именами btnGetClick (для кнопки) и lstMessagesClick (для списка).

В процедуре нажатия кнопки (TForm1.btnGetClick) объявляем следующие переменные и метку lbEnd (чтобы избежать излишнего повторения исходного кода, мы будем использовать ненавистный многим оператор goto — и пусть все, кто безгрешны, кинут в нас камень :-)):

После объявления переменных и метки следует инициализировать сокетные структуры и соединиться с сервером. Весь следующий код мы будем писать между операторами begin и end в процедуре нажатия кнопки (это для тех, кто в танке :-)):

Итак, все структуры заполнены необходимой информацией, библиотека winsock инициализирована успешно, создан сокет, и мы уже подключились к серверу. Вся последующая работа будет происходить в диалоговом режиме — мы посылаем запрос серверу, получаем и анализируем его ответ и, если не возникло ошибки, производим следующую операцию (а результат заносим в список lstState). Кстати, в данном случае мы можем подключиться к серверу, только зная его IP-адрес — попытка использования доменного имени неизбежно вызовет ошибку. О том, как этого избежать, мы поговорим позже.

В соответствии с RFC, POP3-сервер может отвечать двояко: строкой, начинающейся с символов +ОК в случае успеха или с -ERR в случае неудачи. В дальнейшем нужно анализировать ответ сервера, исходя из текущего запроса, — например, сервер может ответить -ERR, если пароль, указанный в команде pass xxx, не соответствует указанному имени пользователя. Поэтому я, для экономии места, опишу лишь последовательность команд, которые необходимо отправить серверу для авторизации:

Если авторизация прошла успешно, необходимо запросить статистику сервера, чтобы узнать количество сообщений (команда stat):

Теперь в цикле нужно принять сообщения (команда retr) и сохранить их в файлы с уникальными именами (при этом используется стандартное расширение .msg):

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

Итак, все сообщения приняты и сохранены в файлы с уникальными именами, которые тут же помещены в список lstMessages. Теперь нужно при выборе сообщения в списке вывести его текст в поле memMessage. За это отвечает следующая процедура:

Естественно, какую-либо ощутимую конкуренцию монстрам TheBat! или Outlook Express наша программа не составит :-), однако принять и прочитать сообщение с POP3-сервера мы уже можем. Теперь дело за доставкой. Однако мой сегодняшний лимит печатных знаков уже исчерпан, поэтому работой с SMTP-серверами мы, возможно, займемся в следующий раз.

До встречи!

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






Данную страницу никто не комментировал. Вы можете стать первым.

Ваше имя:
Ваша почта:

RSS
Комментарий:
Введите символы: *
captcha
Обновить






Рейтинг@Mail.ru
Хостинг на серверах в Украине, США и Германии. © www.sector.biz.ua 2006-2015 design by Vadim Popov