|
#1
|
||||
|
||||
Сокеты и почта
Кто-нибудь пробовал отправлять почту через сокеты? Никак не могу победить это дело.
Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#2
|
||||
|
||||
было, но очень-очень давно. боюсь еще на дискетах исходники остались)
Пишу программы за еду. __________________ |
#3
|
||||
|
||||
А что конкретно не получается? Слышал, что SMTP сейчас всё чаще требуют какую-то замудренную авторизацию, которая может стать камнем преткновения.
Не стоит путать форумы с богадельнями. © Bargest |
#4
|
||||
|
||||
Нужна, как называют школяры, "скрытная" отправка. То есть, программа подключена по Com-порту к железке и при некоторых критических действиях должна отсылать пользователю уведомление. Набираю команды в Telnet-е, всё нормально, на те же команды из программы получаю ответ - Нераспознанная команда. Взял довольно распространённый в сети код и пытаюсь экспериментировать с ним.
Код:
function CreateMailMessage : Boolean; type TaPInAddr = array[0..10] of PInAddr; PaPInAddr = ^TaPInAddr; var WSAData : TWSAData; Host : TSockAddrIn; Sock : TSocket; HostE : PHostEnt; Server : AnsiString; function SendData(St : AnsiString) : Boolean; var Buf : array[0..1023] of AnsiChar; begin FillChar(Buf, SizeOf(Buf), 0); MoveMemory(@Buf[0], @St[1], Length(St)); Result := send(Sock, Buf, Length(St) + 1, 0) > SOCKET_ERROR + 1; end; function RecvData(accept : AnsiString) : BOOL; var Buf : array[0..1023] of AnsiChar; begin res := recv(Sock, Buf, SizeOf(Buf), 0); Result := (Res = SOCKET_ERROR) or (Copy(Buf, 0, 3) = accept); end; begin Result := False; WSAStartUp(257, WSAData); try Sock := socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if Sock = INVALID_SOCKET then Exit; try Server := Copy(Settings.Mail, Pos('@', Settings.Mail) + 1, Length(Settings.Mail)); HostE := GetHostByName(PAnsiChar('smtp.' + Server)); if HostE = NIL then Exit; FillChar(Host, SizeOf(TSockAddrIn), 0); Host.sin_family := AF_INET; Host.sin_port := htons(25); Host.sin_addr.S_addr := inet_addr(inet_ntoa(PInAddr(HostE.h_addr_list^)^)); if connect(Sock, Host, SizeOf(Host)) > 0 then Exit; if not RecvData('220') then Exit; // EHLO SendData('EHLO ' + Server + #13#10); if not RecvData('250') then Exit; SendData('STARTTLS'#13#10); if not RecvData('250') then // Тут уже сбой Exit; SendData('AUTH LOGIN'#13#10); if not RecvData('250') then Exit; // MAIL FROM: SendData('MAIL FROM:' + Settings.Mail + #13#10); if not RecvData('250') then Exit; // RCPT TO: SendData('RCPT TO:' + Settings.Mail + #13#10); if not RecvData('250') then Exit; // DATA SendData('DATA' + #13#10); if not RecvData('354') then Exit; SendData('Subject: ' + 'MAP monitoring - Error' + #13#10#13#10 + 'Test' + #13#10 + '.'); if not RecvData('250') then Exit; SendData('QUIT' + #13#10); Result := True; finally closesocket(sock); end; finally WSACleanup; end; Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#5
|
||||
|
||||
А что возвращается-то?
Добавлено позже: функция SendData кривая какая-то, будто еще под Turbo Pascal писана. Я бы написал так: Код:
function SendData(St : AnsiString) : Boolean; begin Result := send(Sock, St[1], Length(St) + 1, 0) > SOCKET_ERROR + 1; end; Не стоит путать форумы с богадельнями. © Bargest Последний раз редактировалось Freeman, 27.03.2014 в 01:37. |
#6
|
||||
|
||||
Хоть извращайся, хоть нет, а заказчику нужна отправка на почту.
Да 0 требуется, из-за этого и буфер. Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#7
|
||||
|
||||
Цитата:
Добавлено позже: кстати, у Borland: Код:
function TBaseSocket.SendBuf(var Buf; BufSize: Integer; Flags: Integer): Integer; begin DoSend(pchar(@Buf), BufSize); Result := ErrorCheck(Send(FSocket, Buf, BufSize, Flags)); if Result <> SOCKET_ERROR then inc(FBytesSent, Result); end; function TBaseSocket.Sendln(s: string; const eol: string): Integer; begin s := s + eol; Result := SendBuf(pchar(s)^, length(s), 0); end; Не стоит путать форумы с богадельнями. © Bargest Последний раз редактировалось Freeman, 27.03.2014 в 03:13. |
#8
|
||||
|
||||
По фигу что там у Borland-а. Любая команда после приветствия считается нераспознанной.
0 не отправляется, а служит признаком завершения строки - так принято у С-ников. Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#9
|
||||
|
||||
Цитата:
Код:
'EHLO'#13#10 #0'STARTTLS'#13#10 Не стоит путать форумы с богадельнями. © Bargest |
#10
|
||||
|
||||
Получается всё правильно, в отладчике проверял.
Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#12
|
||||
|
||||
Я проверяю для Гугла.
Хм, Яндекс вернул - Ошибка синтаксиса. Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. Последний раз редактировалось angvelem, 27.03.2014 в 04:57. |
#14
|
||||
|
||||
Через Telnet так и возвращает, в коде не хочет.
Насчёт выдумки, знакомый решил потестировать на своём сайте, так у него все команды через одно место, почти ни одна не совпала с RFC. Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#15
|
||||
|
||||
Цитата:
Код:
function SendData(St : AnsiString) : Boolean; begin Result := send(Sock, St[1], Length(St), 0) > SOCKET_ERROR + 1; end; Не стоит путать форумы с богадельнями. © Bargest |