Теперь изучим, как можно получить отправленное письмо с помощью самого популярного протокола приема почты РОРЗ и Windows API. Протокол РОРЗ - это несколько команд, которые отправляются серверу в текстовом режиме Основные команды показаны в табл. 5.3.

Таблица 5.3. Основные команды протокола РОРЗ

Команда Описание

USER имя

Протокол РОРЗ требует авторизации, с помощью этой команды серверу

сообщается имя

PASS пароль

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

LIST .

Показать все сообщения на сервере

RETRn

Получить сообщение под номером п

DELEn

Удалить сообщение под номером п

QUIT

Завершение сеанса связи

Журнал чтения одного тестового сообщения с почтового сервера приведен в листинге 5.7.

Листинг 5.7. Пример протокола "общения" с сервером

<+0К РОРЗ Server ready <174414344.36913160@svin>
>user smirnandr
<+0K Password required for user smirnandr >pass wsfewfwef
<+0K snnrnandr@mail.ru maildrop has 1 messages (912 octets) >list
<+0K 1 messages (912 octets) <p has 1 messages (912 octets) <1 912
>retr 1
<+0K 912 octets
<Return-path: <russi a@cydsoft.com>
<Received: from [80.80.111.176] (port=25 helo=smtp.aaanet.ru)
<
by mxl3.mail.ru with esmtp
<
id lBnsqk-000855-00
<
for smirnandr@mail.ru;
Fri. 23 Jul 2004 09-44.07 +0400 <Received: from [80.80.99.95] (helo=notebook)
<
by smtp.aaanet ru with esmtp (Exim 4.30; FreeBSD)
<
id lBnssu-0000L2-NB
<
for smirnandr@mail.ru;
Fri. 23 Jul 2004 09.46:20 +0400 <Date: Fri. 23 Jul 2004 09:44:13 +0400
<From: cydrussia <russia<acydsoft.com> <X-Mailer- The Bat! (vl.53d) Personal <Reply-To: cydrussia <russia@cydsoft.com> <X-Priority: 3 (Normal)
<Message-ID: <1054074468.20040723094413@cydsoft.com> <To: smi rnandr@mai1.ru <Subject: Test Message <MWIE-Vers ion: 1.0
<Content-Type: text/plain;
charset=koi8-r <Content-Transfer-Encoding: 8bit <X-Spam: Not detected <
<Hello. <
<TestMessage <
<--
<Best regards.
<
cydrussia mailto:russia@cydsoft com
>dele 1 <+0K message 1 deleted >quit

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

Затем выполняется команда LIST. На нее сервер отвечает следующими сообщениями:

+0К 1 messages (912 octets) р has 1 messages (912 octets) 1 912

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

1 912
2 384
3 234

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

Рассмотрим сказанное на практике. Создайте новое приложение. На главной форме нам понадобятся следующие элементы:

• два поля ввода для указания адреса сервера и порта. В качестве порта чаще всего используется 110;
• компонент ТМето для отображения хода выполнения задачи;

• кнопка, по нажатии которой будем получать письма.

Пример внешнего вида главной формы будущей программы показан на рис. 5.8.

5.4. РОРЗ-клиент на Win API

Рис. 5.8. Форма будущего РОРЗ-клиента

Перейдем к практической реализации программы. Код, который должен выполняться по нажатии кнопки Получить, приведен в листинге 5.8. Первая часть практически не отличается от SMTP-клиента, где происходит соединение с сервером на указанном порте.

Листинг 5.8. Соединение с сервером

procedure TTCPC1ientForm.btRecvMessagesC1ick(Sender: TObject): var
wData- WSADATA:
sServerListen: TSOCKET: server_addr: sockaddMn;
begin
mmLog.Clear;

//////////////////////////// // СОЕДИНЕНИЕ С СЕРВЕРОМ // 1111111111111111111111111111

II Загрузка WinSock

if WSAStartup(MAKEWORD(1.1). wData) <> 0 then begin MessageBox(0. 'He могу загрузить WinSock'. 'Ошибка'. 0); exit:

end.

// Создание сокета

sServerListen .= socket(PF_INET. S0CK_STREAM. IPPROTOJP):

if sServerListen = INVALID_SOCKET then begin MessageBox(0. 'Ошибка создания сокета'. 'Ошибка', 0), exit:

end:
// Заполнение структуры адреса server_addr.sin_addr s_addr := htonl(INADDR_ANY);
server_addr sin_family := AF_INET: server_addr.sin_port := htons(StrToInt(edPort.Text)): server_addr.sin_addr := LookupName(edServer.Text);

// Соединение с сервером

if (connect(sServerListen, server_addr, sizeof(server_addr)) =
SOCKETJRROR) then
begin
TestWinSockError('Connect'): exit:

end, 111111111111111111111! 11111 II ПОЛУЧЕНИЕ ПИСЬМА № 1 // /////////////////////////// GetStr(sServerLi sten):

// Авторизация

SendStr(sServerListen. 'user smimandr'): GetStr(sServerL i sten):
SendStr(sServerListen, 'pass dfgfdggtf): GetStr(sServerListen):

Листинг 5.8 (продолжение) II Получаем список" сообщений

SendStKsServerListen. 'list');
Sleep(lOOO):
GetStr(sServerListen);

// Получаем первое сообщение

SendStr(sServerListen. 'retr Г);
Sleep(lOOO);
GetStr(sServerListen):
// Удаляем прочитанное первое сообщение SendStr(sServerListen. 'dele Г);
GetStr(sServerListen);

// Выход

SendStKsServerListen, 'quit'): CloseSocket(sServerListen):
end:

Отправка данных осуществляется при помощи уже знакомой процедуры SendStr. Мы написали ее при создании примера SMTP-клиента с возможностью отправки файлов (см. раздел 5.2 данной главы). Для приема сообщений от сервера в данном случае используется процедура GetStr (листинг 5.9).

Листинг 5.9. Функция получения строки

procedure GetStr(s:TSocket): var
sRecvBuff: array [0..5000] of char: TempStr: AnsiString;
begin
TestFuncError(recv(s. sRecvBuff. SizeOf(sRecvBuff). 0).

'Ошибка выхода'):

TempStr := sRecvBuff;
while Pos(#13. TempStr) > 0 do
begin
TCPClientForm.mmLog.Lines.Add('<'+Copy(TempStr. 1.
Pos(#13. TempStr)));
Delete(TempStr. 1. Pos(#13. TempStr)+l);
end:
Appli cati on.ProcessMessages:
end.

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

Далее запускается цикл, в котором полученные данные разбиваются на строки и добавляются в компонент Memo.

Вернемся к коду получения письма (см. листинг 5.8). Обратите внимание, что после отправки команд LIST и RETR вызывается функция S1 еер для создания задержки. Это необходимо для того, чтобы сервер успел нам ответить.

Если при ответах на простые команды нужно прислать ОК или ошибку, то для этих двух команд будут выполняться некоторые действия, которые отнимут время. Чтение произойдет неправильно, если не сделать задержку. В ответе будет содержаться только код правильности выполнения нашего запроса, а результата запроса (текста письма) еще не будет.

Письмо от сервера, которое мы получаем, приходит в текстовом виде. Если письмо содержит вложение, то вы должны найти последовательность boundary и по ней отделить текстовые данные от вложения. Помните, что вложений может быть несколько и они могут иметь разные значения параметра content type.

ПРИМЕЧАНИЕ -

Исходный код рассмотренного здесь примера находится на компакт-диске в каталоге Sources\ch05\POP.

5.3. Отправка файлов по почте || Оглавление || 5.5. Создание Proxy-сервера


Delphi в шутку и всерьез: что умеют хакеры



Новости за месяц

  • Декабрь
    2021
  • Пн
  • Вт
  • Ср
  • Чт
  • Пт
  • Сб
  • Вс
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31