forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   FAQ (http://forum.boolean.name/forumdisplay.php?f=15)
-   -   SMTP. Отправляем письмо (http://forum.boolean.name/showthread.php?t=6220)

HAMANN 07.08.2008 01:17

SMTP. Отправляем письмо
 
Приступим!
Основная задача протокола SMTP (Simple Mail Transfer Protocol) заключается в том, чтобы обеспечивать передачу электронных сообщений (почту). Для работы через протокол SMTP клиент создаёт TCP соединение с сервером через порт 25. Затем клиент и SMTP сервер обмениваются информацией пока соединение не будет закрыто или прервано.
Ну давайте попробуем. Как и в прошлом туторе нашей жертвой будет mail.ru. Адрес: smtp.mail.ru, прослушиваемые порты 25, 2525 и 587. Будим юзать 25
Итак, наш код:
Код:

OpenTCPStream("smtp.mail.ru",25)
Print ReadLine$(tcp)
CloseTCPStream tcp
WaitKey()



Опа, все супер)). Продолжим.
Основной процедурой в SMTP является передача почты (Mail Procedure). Далее идут процедуры форвардинга почты (Mail Forwarding), проверка имён почтового ящика и вывод списков почтовых групп. Самой первой процедурой является открытие канала передачи, а последней - его закрытие.

Команды SMTP указывают серверу, какую операцию хочет произвести клиент. Команды состоят из ключевых слов, за которыми следует один или более параметров. Ключевое слово состот из 4-х символов и разделено от аргумента одним или несколькими пробелами. Каждая командная строка заканчивается символами CRLF (так как мы будем использовать ф-цию writeline(), то нам это не надо). Вот список основных команд:

HELO
MAIL FROM:
RCPT TO:
DATA
RSET
NOOP
QUIT


Резберем каждую команду.
Первая в нашем списке команда HELO.
Эта команда передает серверу наш IP адрес. У нее один единственный параметр, в котором нужно указать IP адрес или url адрес сервера. В нашем случае это smtp.mail.ru
Попробуем.
Код:

OpenTCPStream("smtp.mail.ru",25)
Print ReadLine$(tcp)
WriteLine tcp,"HELO smtp.mail.ru"
Print ReadLine$(tcp)
CloseTCPStream tcp
WaitKey()



Так, мы передали серверу наш IP адрес.
Что дальше? А дальше мы уже можем начинать отправку письма, НО smtp сервер mail.ru требует авторизацию пользователя. Это я прочитал на сайте :) . Поверим на слово. Авторизируемся ;).
Наш адрес электронной почты [email protected] с паролем 12344321. Он реально рабочий). А это очень важно!!! Пароль и Логин отправляется в зашифрованном виде, а именно в base64. Я на скорую руку настрочил ф-цию, так что не судите строго. Она для примера. И еще я взял ф-цию для перевода из 2-й системы счисления в 10-ную (это надо для base64)
Код:

Function encode_base64$(value$)
abc$="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"


For b=1 To Len(value$)
        char$=Left(value$,b)
        char$=Right(char$,1)
        ValueIn2$=ValueIn2$+Right(Bin$(Asc(char$)),8)
Next
;Print ValueIn2$

For b=1 To Len(ValueIn2$) / 6
        char$=Left(ValueIn2$,6*b)
        char$=Right(char$,6)
        num=ToInt(char$,2)
        res$=res$+Right(Left(abc$,num+1),1)
Next
If(6*(b-1)<>Len(ValueIn2$)) Then
        char$=Right(ValueIn2$,Len(ValueIn2$)-(6*(b-1)))
        len_char=6-Len(char$)
        For c=1 To (len_char)
                char$=char$+"0"
        Next
        res$=res$+Right(Left(abc$,ToInt(char$,2)+1),1)
EndIf




If(Len(value$)>3) And Len(value$) Mod 3 <> 0  Then
        Lenn=(Len(value$) Mod 3)
        For b=1 To 3-lenn
                res$=res$+"="
        Next
ElseIf (Len(value$)>3)
        Lenn=(Len(value$))
        For b=1 To 3-lenn
        res$=res$+"="
        Next
End If
Return res$
End Function

Function ToInt(inputnum$,base)
        If base=10 Return inputnum
        If base>10 Return 0
        l=Len(inputnum$)
        For i=0 To l-1
                  rightnum=Right(inputnum$,1)
 
                  If rightnum<base Then
                          If rightnum>0 Then
                                    intnum#=intnum#+base^i*rightnum
                          EndIf
                          Else Return 0
                  EndIf
                  inputnum$=Left$(inputnum$,Len(inputnum$)-1)
        Next
 
        Return intnum
End Function

Теперь о том, как нам авторизоваться.
Первое что нам надо, это дать серверу понять что мы хотим авторизоваться. Для этого надо передать команду AUTH LOGIN.
Попробуем, только давайте договоримся. Из за ф-ции base64 код уж больно грамоздкий получается. Я не буду ее вписывать в последующие примеры. Но знайте что она там должна присутствовать ;).
Код:

OpenTCPStream("smtp.mail.ru",25)
Print ReadLine$(tcp)
WriteLine tcp,"HELO smtp.mail.ru"
Print ReadLine$(tcp)
WriteLine tcp,"AUTH LOGIN"
Print ReadLine$(tcp)
CloseTCPStream tcp
WaitKey()



Черти что получаем в ответ. Это зашифрованное слово в base64. Если мы его декодируем то получим «Username:». Ага! Тоесть сервер ждет когда же мы отправим ему наш логин.
Ну что ж, отправим(помним, что логин и пароль передаются в base64):
Код:

OpenTCPStream("smtp.mail.ru",25)
Print ReadLine$(tcp)
WriteLine tcp,"HELO smtp.mail.ru"
Print ReadLine$(tcp)
WriteLine tcp,"AUTH LOGIN"
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“Boolean_pop3_ex”)
Print ReadLine$(tcp)
CloseTCPStream tcp
WaitKey()

Смотрим …



Угу, что же это за слово такое?! Ну давайте его декодируем. Получаем «Password:». То есть наш кодированный логин был принят и сервер ожидает когда мы отправим ему пароль(тоже в base64)
Go!
Код:

OpenTCPStream("smtp.mail.ru",25)
Print ReadLine$(tcp)
WriteLine tcp,"HELO smtp.mail.ru"
Print ReadLine$(tcp)
WriteLine tcp,"AUTH LOGIN"
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“Boolean_pop3_ex”)
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“12344321”)
Print ReadLine$(tcp)
CloseTCPStream tcp
WaitKey()

Посмотрим…



Так, все прошло успешно, мы авторизовались! ))))
Теперь можно приступить непосредственно к написанию письма.
При отправке почты передаём некоторые нужные данные (отправитель, получатель и само письмо)
И первая команда, которая нам потребуется, это MAIL FROM: . Эта команда указывает E-mail адрес отправителя, адрес долен быть тот, под которым авторизовались (в нашем случае [email protected]).
Потестим:
Код:

OpenTCPStream("smtp.mail.ru",25)
Print ReadLine$(tcp)
WriteLine tcp,"HELO smtp.mail.ru"
Print ReadLine$(tcp)
WriteLine tcp,"AUTH LOGIN"
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“Boolean_pop3_ex”)
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“12344321”)
Print ReadLine$(tcp)
WriteLine tcp,"MAIL FROM: [email protected]"
Print ReadLine$(tcp)
CloseTCPStream tcp
WaitKey()

Смотрим:



Собственно вот и ответ сервера. Все в норме)
Продолжаем.
Теперь нам нужно указать e-mail адрес получателя. А осуществим мы это с помощью команды RCPT TO: . Я буду отправлять письмо на свой e-mail: [email protected]
Испробуем команду:
Код:

OpenTCPStream("smtp.mail.ru",25)
Print ReadLine$(tcp)
WriteLine tcp,"HELO smtp.mail.ru"
Print ReadLine$(tcp)
WriteLine tcp,"AUTH LOGIN"
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“Boolean_pop3_ex”)
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“12344321”)
Print ReadLine$(tcp)
WriteLine tcp,"MAIL FROM: [email protected]"
Print ReadLine$(tcp)
WriteLine tcp,"RCPT TO: [email protected]"
Print ReadLine$(tcp)
CloseTCPStream tcp
WaitKey()

Смотрим:



И эта команда прокатила без ошибок. Можно продолжать.
А дальше следует команда DATA, без единого аргумента. Она сообщает серверу что мы начнем писать само письмо)
Тестим:
Код:

OpenTCPStream("smtp.mail.ru",25)
Print ReadLine$(tcp)
WriteLine tcp,"HELO smtp.mail.ru"
Print ReadLine$(tcp)
WriteLine tcp,"AUTH LOGIN"
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“Boolean_pop3_ex”)
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“12344321”)
Print ReadLine$(tcp)
WriteLine tcp,"MAIL FROM: [email protected]"
Print ReadLine$(tcp)
WriteLine tcp,"RCPT TO: [email protected]"
Print ReadLine$(tcp)
WriteLine tcp,"DATA"
Print ReadLine$(tcp)
CloseTCPStream tcp
WaitKey()

Результат:



Сервер воспринял команду. Так же он сообщил нам, что после того как мы введем текст письма, нам следует отправить знак «.» на отдельно строке.
Приступим.
Как более красиво и с понтами оформить письмо я расскажу в своем следующем туторе, а сегодня для меня была задача познакомить вас с основными командами протокола SMTP. Отправим что нить по проще.
Чтобы наше письмо не расценивалось как спам, надо указать от кого оно, тему, ну и укажем название нашего клиента)) пусть оно будет “ Boolean mail client ”
Итак, сначала надо указать от кого оно:
From: Boolean_ex <[email protected]>
Далее укажем кому:
To: [email protected]
Тепер тему письма:
Subject: Просто проверка
Ну и название нашего клиента:
X-Mailer: Boolean mail client
Ну а текст наш будет:
Ура, все работает!
Теперь надо это все отправить. Отправлять надо на отдельных строках.
Получается так:
Код:

WriteLine tcp,"From: Boolean_ex <[email protected]>"
WriteLine tcp,"To: [email protected]
WriteLine tcp,"Subject: Просто проверка”
WriteLine tcp,"X-Mailer: Boolean mail client”
WriteLine tcp,”Ура, все работает!”

Ах да, мы забыли поставить знак «.», Так как письмо мы уже дописали.
Код:

WriteLine tcp,"From: Boolean_ex <[email protected]>"
WriteLine tcp,"To: [email protected]
WriteLine tcp,"Subject: Просто проверка”
WriteLine tcp,"X-Mailer: Boolean mail client”
WriteLine tcp,”Ура, все работает!”
WriteLine tcp,”.”

Теперь вставим это в нашу программу:
Код:

OpenTCPStream("smtp.mail.ru",25)
Print ReadLine$(tcp)
WriteLine tcp,"HELO smtp.mail.ru"
Print ReadLine$(tcp)
WriteLine tcp,"AUTH LOGIN"
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“Boolean_pop3_ex”)
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“12344321”)
Print ReadLine$(tcp)
WriteLine tcp,"MAIL FROM: [email protected]"
Print ReadLine$(tcp)
WriteLine tcp,"RCPT TO: [email protected]"
Print ReadLine$(tcp)
WriteLine tcp,"DATA"
Print ReadLine$(tcp)
WriteLine tcp,"From: Boolean_ex <[email protected]>"
WriteLine tcp,"To: [email protected]
WriteLine tcp,"Subject: Просто проверка”
WriteLine tcp,"X-Mailer: Boolean mail client”
WriteLine tcp,”Ура, все работает!”
WriteLine tcp,”.”
Print ReadLine$(tcp)
CloseTCPStream tcp
WaitKey()

Фух, испробуем:



Ага, все удачно. Сервер выдал нам ид, значит письмо отправлено. Пойду взгляну в свой ящик ;)





Все супер. Но давайте будем порядочными людьми и попрощаемся с сервером. Командой QUIT
Код:

OpenTCPStream("smtp.mail.ru",25)
Print ReadLine$(tcp)
WriteLine tcp,"HELO smtp.mail.ru"
Print ReadLine$(tcp)
WriteLine tcp,"AUTH LOGIN"
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“Boolean_pop3_ex”)
Print ReadLine$(tcp)
WriteLine tcp,encode_base64$(“12344321”)
Print ReadLine$(tcp)
WriteLine tcp,"MAIL FROM: [email protected]"
Print ReadLine$(tcp)
WriteLine tcp,"RCPT TO: [email protected]"
Print ReadLine$(tcp)
WriteLine tcp,"DATA"
Print ReadLine$(tcp)
WriteLine tcp,"From: Boolean_ex <[email protected]>"
WriteLine tcp,"To: [email protected]
WriteLine tcp,"Subject: Просто проверка”
WriteLine tcp,"X-Mailer: Boolean mail client”
WriteLine tcp,”Ура, все работает!”
WriteLine tcp,”.”
Print ReadLine$(tcp)
WriteLine tcp,”QUIT”
Print ReadLine$(tcp)
CloseTCPStream tcp
WaitKey()



Вот собственно и все.
А нет…
Еще парочка команд:
RSET - указывает серверу прервать выполнение текущего процесса. Все сохранённые данные (отправитель, получатель и др) удаляются. Сервер должен отправить положительный ответ.
Ну думаю не надо примеров с ней.
И команда NOOP. Ничего не делает, тупо выдает положительный ответ. В общем то это все команды, с которыми я хотел познакомить вас сегодня. В следующем туторе я попытаюсь объяснить как отправить письмо с вложенными файлами и например в HTML формате. Все на этом, удачи ;)

HAMANN 07.08.2008 01:18

Ответ: SMTP. Отправляем письмо
 
Если что не понятно, пишите тут ;)


Часовой пояс GMT +4, время: 11:47.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot