Форум: "WinAPI";
Текущий архив: 2002.03.18;
Скачать: [xml.tar.bz2];
ВнизE-Mail & Winsock. Найти похожие ветки
← →
BWG (2002-01-14 19:00) [0]Мастера!
Понимаю, что тема избита, но так никто толком не ответил на вопрос: как написать процедуру отправки E-Mail, используя один только Winsock API. Помогите чем можите!
← →
BWG (2002-01-15 04:53) [1]Неужели никто не знает?
Или просто лень ответить?
← →
paul_shmakov (2002-01-15 11:07) [2]вот, только что набросал. пример показывает посылку самого простого письма. остальные поля в заголовке (типа Subject) и диалог с smtp сервером см. в rfc.
да и коды, которые сервер возвращает - это я так, на примере сейчас посмотрел - точно не помню. так что за дополнительной информацией RFC 0821.
program mail;
uses Windows, SysUtils, Winsock;
function SendMail(const From: string; const Receiver: string; const Text: string;
const SmtpHost: string; SmtpPort: Word = 25): Boolean;
var
S: TSocket;
WSData: TWSAData;
function ConnectToSmtp: Boolean;
var
Sin: SockAddr_in;
IP: DWord;
He: PHostent;
begin
Result := false;
IP := inet_addr(PChar(SmtpHost));
if INADDR_NONE = IP then
begin
He := gethostbyname(PChar(SmtpHost));
if not Assigned(He) then
Exit;
IP := PDWord(PDWord(He^.h_addr_list)^)^;
end;
S := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if INVALID_SOCKET <> S then
begin
FillChar(Sin, SizeOf(Sin), 0);
Sin.sin_family := AF_INET;
Sin.sin_port := htons(SmtpPort);
Sin.sin_addr.s_addr := IP;
Result := SOCKET_ERROR <> connect(S, Sin, SizeOf(Sin));
if not Result then
closesocket(S);
end;
end;
function SendCommand(Text: string): Boolean;
var
Buffer: PChar;
Size: Integer;
begin
Text := Text + #10;
Size := Length(Text);
GetMem(Buffer, Size + 1);
try
StrCopy(Buffer, PChar(Text));
Result := send(S, Buffer^, Size, 0) <> SOCKET_ERROR;
finally
FreeMem(Buffer);
end;
end;
function ReceiveResponse: Integer;
var
Response: string;
C: Char;
begin
Result := 0;
Response := "";
repeat
if SOCKET_ERROR = recv(S, C, SizeOf(C), 0) then
Exit;
Response := Response + C;
until C = #10;
if Pos(" ", Response) > 0 then
Result := StrToIntDef(Copy(Response, 1, Pos(" ", Response) - 1), 0)
else
Result := StrToIntDef(Response, 0);
end;
begin
Result := false;
WSAStartup($0101, WSData);
try
if ConnectToSmtp then
try
ReceiveResponse;
Result :=
SendCommand("helo delphimail") and (250 = ReceiveResponse) and
SendCommand("mail from: " + From) and (250 = ReceiveResponse) and
SendCommand("rcpt to: " + Receiver) and (250 = ReceiveResponse) and
SendCommand("data") and (354 = ReceiveResponse) and
SendCommand(Text + #10"."#10) and (250 = ReceiveResponse) and
SendCommand("quit") and (250 = ReceiveResponse);
finally
closesocket(S);
end;
finally
WSACleanup;
end;
end;
begin
SendMail("<billy@microsoft.com>", "<paul_shmakov@mail.ru>", "Hello from Billy!", "smtp.mail.ru");
end.
← →
BWG (2002-01-16 17:20) [3]Не работает этот код. Уже застрелился понимать почему. Исправил в
function SendCommand(Text: string): Boolean;
строкуText := Text + #10;
наText := Text + №13#10;
, строкуSendMail("<billy@microsoft.com>", "<paul_shmakov@mail.ru>", "Hello from Billy!", "smtp.mail.ru");
на строкуSendMail("<one@prog.ru>", "<bwgblackraven@narod.ru>", "Date: "+ DateTimeToStr(now)+#13#10+"From: one@prog.ru"+#13#10+ "To: <bwgblackraven@narod.ru>"+#13#10+"Subject: Mail"+ #13#10#13#10+"The test", "smtp.narod.ru")
. Все равно не работает!
Помогите понять: ПОЧЕМУ?
← →
Polevi (2002-01-17 08:43) [4]Коды возврата проверял ?
← →
BWG (2002-01-17 13:35) [5]Нет вроде. Надо бы... Пошел проверять...
← →
Polevi (2002-01-17 13:43) [6]У меня работает без всяких исправлений (кроме аргументов ф-ии)
← →
paul_shmakov (2002-01-17 13:45) [7]может не работать по той причине, что smtp.narod.ru не позволяет вход без авторизации. попробуй telnet-ом туда подсоединиться. диалог у вас с ним примерно такой должен получиться:
220 ESMTP MAIL.RU Thu, 17 Jan 2002 13:31:42 +0300
helo delphimail
250 mx10.port.ru Hello delphimail [10.0.0.1]
mail from: <billy@microsoft.com>
250 <billy@microsoft.com> is syntactically correct
rcpt to: <paul_shmakov@mail.ru>
250 <paul_shmakov@mail.ru> verified
data
354 Enter message, ending with "." on a line by itself
hello from billy!!!
.
250 OK id=16R9qY-0007Ut-00
quit
221 mx10.port.ru closing connection
если это пройдет, то значит и программа должна работать. приведенная выше функция - это реализация этого диалога на сокетах.
правда, скорее всего потребуется авторизация :(
кстати, то, что Вы исправили #10 на #13#10 - это правильно (сейчас rfc посмотрел).
SMTP RFC 0821
http://www.ietf.org/rfc/rfc0821.txt?number=0821
← →
paul_shmakov (2002-01-17 13:57) [8]ну и на любителей более новая версия протокола:
smtp rfc 2821
http://www.ietf.org/rfc/rfc2821.txt?number=2821
← →
BWG (2002-01-17 14:24) [9]Протестировал так:
program TestMail;
{$APPTYPE CONSOLE}
uses
SysUtils, Winsock, Windows;
function SendMail(const From: string; const Receiver: string; const Text: string;
const SmtpHost: string; SmtpPort: Word = 25): Boolean;
var
S: TSocket;
WSData: TWSAData;
function ConnectToSmtp: Boolean;
var
Sin: SockAddr_in;
IP: DWord;
He: PHostent;
begin
Result := false;
IP := inet_addr(PChar(SmtpHost));
if INADDR_NONE = IP then
begin
He := gethostbyname(PChar(SmtpHost));
if not Assigned(He) then
Exit;
IP := PDWord(PDWord(He^.h_addr_list)^)^;
writeln("IP is ",IP);
end;
S := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if INVALID_SOCKET <> S then
begin
FillChar(Sin, SizeOf(Sin), 0);
Sin.sin_family := AF_INET;
Sin.sin_port := htons(SmtpPort);
Sin.sin_addr.s_addr := IP;
Result := SOCKET_ERROR <> connect(S, Sin, SizeOf(Sin));
if Result then writeln("Connected ok");
if not Result then
closesocket(S);
end;
end;
function SendCommand(Text: string): Boolean;
var
Buffer: PChar;
Size: Integer;
begin
Text := Text + #13#10;
Size := Length(Text);
GetMem(Buffer, Size + 1);
try
StrCopy(Buffer, PChar(Text));
Result := send(S, Buffer^, Size, 0) <> SOCKET_ERROR;
writeln("command > ",text," > result > ",result);
finally
FreeMem(Buffer);
end;
end;
function ReceiveResponse: Integer;
var
Response: string;
C: Char;
begin
Result := 0;
Response := "";
repeat
if SOCKET_ERROR = recv(S, C, SizeOf(C), 0) then
begin
writeln("Socket error!");
Exit;
end;
Response := Response + C;
until C = #10;
if Pos(" ", Response) > 0 then
Result := StrToIntDef(Copy(Response, 1, Pos(" ", Response) - 1), 0)
else
Result := StrToIntDef(Response, 0);
writeln("Resp. result > ",result);
end;
begin
Result := false;
WSAStartup($0101, WSData);
try
if ConnectToSmtp then
try
ReceiveResponse;
//Result :=
SendCommand(#32+"helo msiers");// and (250 = ReceiveResponse) and
ReceiveResponse;
SendCommand("mail from: " + From);// and (250 = ReceiveResponse) and
ReceiveResponse;
SendCommand("rcpt to: " + Receiver);// and (250 = ReceiveResponse) and
ReceiveResponse;
SendCommand("data");// and (354 = ReceiveResponse) and
ReceiveResponse;
SendCommand(Text + #13#10+".");// and (250 = ReceiveResponse) and
ReceiveResponse;
SendCommand("quit");// and (250 = ReceiveResponse);
finally
closesocket(S);
end;
finally
WSACleanup;
end;
end;
begin
writeln("Started");
SendMail("<bwgblackraven@narod.ru>", "<bwgblackraven@narod.ru>", "Date: "+
DateTimeToStr(now)+#13#10+"From: one@prog.ru"+#13#10+
"To: <bwgblackraven@narod.ru>"+#13#10+"Subject: Mail"+
#13#10#13#10+"The test", "smtp.narod.ru");
writeln("Sended");
readln;
end.
Получил такой пинок:
220
550
503
503
503
550
По RFC 503 - Bad sequence of commands
И что не верно?
← →
BWG (2002-01-17 14:27) [10]Смена сервера на smtp.yandex.ru не помогла. Хотя он авторизации точно не требует.
← →
Polevi (2002-01-17 14:31) [11]Ты пробовал тоже самое сделать телнетом ?
← →
BWG (2002-01-17 16:11) [12]Что "то же самое"?
← →
paul_shmakov (2002-01-17 16:22) [13]503 - это уже после. главное здесь 550
550 Requested action not taken: mailbox unavailable
[E.g., mailbox not found, no access]
к сожалению, почему-то у меня сейчас не получается соединиться telnet-ом ни с smtp.narod.ru, ни с smtp.yandex.ru - толи сервера висят, толи файервол у нас не пускает, хотя с smtp.mail.ru все нормально.
← →
BWG (2002-01-17 16:31) [14]Все Яндекс к фене полетел...
← →
paul_shmakov (2002-01-17 16:37) [15]2 BWG © (17.01.02 16:11)
Что "то же самое"?
подключиться telnet-ом к smtp.narod.ru на 25 порт и ввести вручную все команды (перед этим не забудьте включить Local Echo в Terminal/Preferences).
ваш возможный диалог с сервером я уже приводил чуть выше (paul_shmakov © (17.01.02 13:45)).
если руками все это получиться, то и программно все должно работать.
← →
BWG (2002-01-17 17:06) [16]Не пойму чего-то. То ли получается, то ли нет. Может у меня ручки кривые.
Попробуйте, please, кто-нибудь вышеуказанныйBWG © (17.01.02 14:24)
код и намыльте о результатах. Не работает он у меня.
И телнет говорит " 550" когда я mail from отправляю.
Прочитайте мне, please, manual.
С уважением, Алексей.
← →
Bachin (2002-01-17 18:02) [17]Уменя такой диалог. Только не пойму, где он пустую команду откопал :(
220 profix.kiev.ua ESMTP Sendmail 8.12.1/8.12.1; Thu, 17 Jan 2002 16:59:17 +0200 (EET)
helo delphimail
250 profix.kiev.ua Hello bachin.profix.com [196.1.4.13], pleased to meet you
mail from: <bachin@prifix.kiev.ua>
250 2.1.0 <bachin@prifix.kiev.ua>... Sender ok
rcpt to: <bachin@usb.kherson.ua>
250 2.1.5 <bachin@usb.kherson.ua>... Recipient ok
data
354 Enter mail, end with "." on a line by itself
test message
.
250 2.0.0 g0HExHVN029445 Message accepted for delivery
quit
500 5.5.1 Command unrecognized: ""
FALSE
← →
paul_shmakov (2002-01-17 18:33) [18]2 Bachin:
все нормально, вот только что-то он на quit ругнулся (???)
а в остальном все именно так и должно быть
← →
BWG (2002-01-17 21:50) [19]Ладно.
Пошел разбираться.
← →
BWG (2002-01-18 20:50) [20]Заставить работать Яндекс (
smtp.yandex.ru port 25
) удалось. Отправил все без вопросов. Этот код - ни в какую не хочет работать!
← →
BWG (2002-01-19 12:10) [21]Кстати: подскажите хороший Telnet-клиент (F reeware).
← →
Anatoly Podgoretsky (2002-01-19 19:14) [22]Start|Run|Telnet
← →
BWG (2002-01-19 19:29) [23]2 Anatoly Podgoretsky © (19.01.02 19:14) Это хороший, да? Я даже оттуда лог не могу скопировать!
Так вот, повторяю свою мысль. По словам Павла Шумакова если с помощью телнета удалось подулючиться - значит и код будет работать. С помощью телнета подключиться удалось. Код - ни в какую!
Помогите!!!
← →
Anatoly Podgoretsky (2002-01-19 21:48) [24]Для того что бы сказать хороший или нет сперва надо дать определение этого. Меня в большинстве случаев устраивает, в некоторых других я использую TereTerm, но чаще именно первый.
← →
Ghost. (2002-01-19 21:55) [25]Вообще 550 озачает, что почтовый ящик недоступен..ты навертное это знаешь и без меня, а на счет телнета мысль очень хорошая я тоже так делал...когда отпртавлял через маил ру и только с помощью телнета разобрался, чо если отправляешь не с их ящика или не на их ящик север возращает ошибку 553 и оказалось, что если ввести любой адрес (чужой) но их сертвера все пройдет нормально и получатель получит письмо с левого ящика..попробуй телетом всю тртанзакцию провести
← →
paul_shmakov (2002-01-20 01:56) [26]2 BWG:
Так вот, повторяю свою мысль. По словам Павла Шумакова если с помощью телнета
Шмаков я :)
удалось подулючиться - значит и код будет работать. С помощью телнета подключиться удалось. Код - ни в какую!
ну запустите под отладчиком и оттрассируйте. код делает (должен делать) именно то, что и человек, набирающий команды в окне telnet-терминала.
код вполне может глючить - я его за пару минут написал специально для ответа на Ваш вопрос.
← →
BWG (2002-01-20 08:31) [27]Хорошо, хорошо.
Сейчас полностью оттестирую и тогда выложу все результаты.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2002.03.18;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.005 c