Новичок
Профиль
Группа: Участник
Сообщений: 4
Регистрация: 11.8.2010
Репутация: нет Всего: нет
|
делаю почтовый клиент на дельфи 7 типа bat чтоб через соксы работал всё делаю на winsock возникла проблема для меня оказалась не решимой прошу выших коментариев проблема такова шлю на smtp.mail.ru некоторые соксы нормально проходят а большинство ответ приходит от маил 501 NULL characters are not allowed in SMTP commands скажите где в коде можно поправить чтонибудь чтоб всё работало нормально соксы все проверял перед отправкой на bat клиенте Код | unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,WinSock, StdCtrls, XPMan, ComCtrls,inifiles, Buttons;
const b64 : array [0..63] of char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; type TAByte = array [0..maxInt-1] of byte; TPAByte = ^TAByte; TARR = array of string; TForm1 = class(TForm) Edit1: TEdit; Edit2: TEdit; Label1: TLabel; XPManifest1: TXPManifest; Edit3: TEdit; RichEdit1: TRichEdit; Edit5: TEdit; SpeedButton1: TSpeedButton; SpeedButton2: TSpeedButton; TextMemo: TMemo; Edit6: TEdit; Edit7: TEdit; SubjectEdit: TEdit; Edit8: TEdit; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; Edit9: TEdit;
procedure FormCreate(Sender: TObject); function AddColorText(Text: String; Color: TColor): String; procedure SpeedButton1Click(Sender: TObject); procedure FormShow(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure SocketsErrors; private procedure AddToLog (event:string); function SendToSocket (socket:TSocket; str:string):integer; function ReadFromSocket (socket:TSocket):String; public { Public declarations } end;
var Form1: TForm1; ws:TWSAData; SL: tstringlist; SL1: tstringlist; threads:integer; x:integer; c:integer; c1:integer; fs:dword; f:textfile; N:integer; pn, psn: Integer;
implementation
{$R *.dfm}
function B64Encode(data:string) : string; overload; var ic,len : integer; pi, po : TPAByte; c1 : dword; begin len:=length(data); if len > 0 then begin SetLength(result, ((len + 2) div 3) * 4); pi := pointer(data); po := pointer(result); for ic := 1 to len div 3 do begin c1 := pi^[0] shl 16 + pi^[1] shl 8 + pi^[2]; po^[0] := byte(b64[(c1 shr 18) and $3f]); po^[1] := byte(b64[(c1 shr 12) and $3f]); po^[2] := byte(b64[(c1 shr 6) and $3f]); po^[3] := byte(b64[(c1 ) and $3f]); inc(dword(po), 4); inc(dword(pi), 3); end; case len mod 3 of 1: begin c1 := pi^[0] shl 16; po^[0] := byte(b64[(c1 shr 18) and $3f]); po^[1] := byte(b64[(c1 shr 12) and $3f]); po^[2] := byte('='); po^[3] := byte('='); end; 2 : begin c1 := pi^[0] shl 16 + pi^[1] shl 8; po^[0] := byte(b64[(c1 shr 18) and $3f]); po^[1] := byte(b64[(c1 shr 12) and $3f]); po^[2] := byte(b64[(c1 shr 6) and $3f]); po^[3] := byte('='); end; end; end else result := ''; end;
procedure TForm1.SocketsErrors; var _errorCode:integer; _errorText:string;
begin _errorCode:=WSAGetLastError();
case _errorCode of WSANOTINITIALISED: _errorText:= 'Сетевая библиотека не была инициализирована!!! Обратитесь к разработчику'; WSAENETDOWN: _errorText:= 'Связь прервана - возможно отошел сетевой кабель'; WSAEADDRINUSE: _errorText:= 'Указанные адрес/порт уже используется!!!'; WSAEINVAL: _errorText:= 'Сокет уже связан с адресом'; WSAENOBUFS: _errorText:= 'Слишком много соединений. Недостачно памяти!'; WSAENOTSOCK: _errorText:= 'Ошибочный дескриптор сокета'; WSAEISCONN: _errorText:= 'Сокет уже подключен'; WSAEMFILE: _errorText:= 'Отсутствуют допустимые дескрипторы'; WSAETIMEDOUT: _errorText:= 'Время ожидания ответа истекло'; end;
addToLog(_errorText);
end; function TForm1.AddColorText(Text: String; Color: TColor): String; begin RichEdit1.SelAttributes.Color := Color; RichEdit1.SelText := Text; RichEdit1.SelAttributes.Color := clblue;
end;
function LookupName(str: String): TInAddr; var _hostEnt:PHostEnt; _inAddr:TInAddr; begin if (str[1] in ['a'..'z']) or (str[2] in ['a'..'z']) then begin _hostEnt := getHostByName(pchar(str)); FillChar(_inAddr, sizeOf(_inAddr), 0); if _hostEnt<>nil then begin with _hostEnt^, _inAddr do begin s_un_b.s_b1 := h_addr^[0]; s_un_b.s_b2 := h_addr^[1]; s_un_b.s_b3 := h_addr^[2]; s_un_b.s_b4 := h_addr^[3]; end; end; end else _inAddr.s_addr := inet_addr(pchar(str)); Result:= _inAddr; end;
procedure TForm1.FormCreate(Sender: TObject);
begin
if WSAStartup(makeword(1,1), ws) <> 0 then begin ShowMessage('Ошибка при инициализации WinSock. Продолжение невозможно'); Application.Terminate; end;
AddToLog('Программа готова к работе!'); end;
procedure TForm1.AddToLog(event: string);
begin
RichEdit1.Lines.Add(event); end;
function TForm1.SendToSocket(socket: TSocket; str: string):integer; var _buff:array [0..255] of Byte; begin
str := str+#13+#10; CopyMemory(@_buff, pchar(str), length(str)); result:=send(socket, _buff, length(str),0); RichEdit1.Lines.Add(AddColorText(''+Copy(str, 1, length(str)-2),clRed)); end;
function TForm1.ReadFromSocket(socket: TSocket): String; var _buff: array [0..255] of Char; _Str:AnsiString; _ret:integer; begin fillchar(_buff, sizeof(_buff), 0); Result:=''; _ret := recv(socket, _buff, 1024, 0); if _ret = -1 then begin Result:=''; Exit; end;
_Str := _buff; while pos(#13, _str)>0 do begin Result := Result+Copy(_str, 1, pos(#13, _str)); Delete(_str, 1, pos(#13, _Str)+1); end; Application.ProcessMessages; end;
procedure TForm1.SpeedButton1Click(Sender: TObject); var sock:LongWord; block:u_long; SockAddrIn:TSockAddrIn; timeout:ttimeval; fds:TFDSet; rc,len:integer; login,pass:string; I,J:integer; _str:string;
z:integer; z1:integer; H: String; P: String;
socks5_req:record // привет ver:byte; nmet:byte; met:byte; end; socks5_resp:record //ответ на привет ver:byte; met:byte; end; socks5_req_TPC:record // куда подключаться ver:byte; cmd:byte; rsv:byte; atyp:byte; ip:u_long; port:u_short; end; socks5_resp_TPC:record // подключились ver:byte; cmd:byte; rsv:byte; atyp:byte; ip:u_long; port:u_short; end;
begin RichEdit1.Lines.Clear; //очистка мемо
//приветствие socks5_req.ver:=5; socks5_req.nmet:=1; socks5_req.met:=0;
//запрос соединения socks5_req_TPC.ver:=5; socks5_req_TPC.cmd:=1; socks5_req_TPC.rsv:=0; socks5_req_TPC.atyp:=1;
socks5_req_TPC.ip:=Integer(LookupName(form1.edit2.Text)); socks5_req_TPC.port := htons(strtoint(form1.edit5.Text));
block:=1; sock:=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if sock=LongWord(-1) then exit; SockAddrIn.sin_family := AF_INET; SockAddrIn.sin_port := htons(strtoint(P)); SockAddrIn.sin_addr := LookupName(H);
ioctlsocket(sock, FIONBIO, block); // переводим сокет в неблокируемый режим
if connect(sock, SockAddrIn, SizeOf(SockAddrIn))=SOCKET_ERROR then // пытаемся подключиться
begin if WSAGetLastError=WSAEWOULDBLOCK then // проверяем что сокет перешел в неблокируемый режим begin FD_ZERO(fds); FD_SET(sock,fds); timeout.tv_sec:=strtoint(form1.Edit1.Text); // наш таймаут timeout.tv_usec:=0; rc:=select(0, nil, @fds, nil, @timeout); // ожидаем end; end; block:=0; ioctlsocket(sock, FIONBIO, block); // переводим сокет обратно в блокируемый режим if rc=0 then begin // сработал таймаут CloseSocket(sock);
end else begin
//////////////////////////////////////////////////////////////////////
send(sock,socks5_req,3,0); // шлем привет len := recv(sock, socks5_resp,2,0); // считали данные
if len > 0 then // если есть чтото begin //смотрим результат if (socks5_resp.ver=5) and(socks5_resp.met=0) then //успех begin
RichEdit1.Lines.Add('Cоединились с прокси');
send(sock, socks5_req_TPC,14,0); // запрос на соединение с smtp сервом len := recv(sock, socks5_resp_TPC,14,0); // считали данные if len > 0 then if socks5_resp_TPC.cmd=0 then //успех begin
/////////////////////////////////////////////////////////////////////////
AddToLog(ReadFromSocket(sock)); SendToSocket(sock,'EHLO '+(H)); AddToLog(ReadFromSocket(sock));
SendToSocket(sock, 'AUTH LOGIN'); AddToLog(ReadFromSocket(sock)); SendToSocket(sock, b64encode(login)); //логин пароль base64
AddToLog(ReadFromSocket(sock));
SendToSocket(sock, b64encode(pass));
AddToLog(ReadFromSocket(sock));
SendToSocket(sock, 'MAIL FROM:<'+(login)+'>');
AddToLog(ReadFromSocket(sock));
SendToSocket(sock, 'RCPT TO:<'+edit7.Text+'>');
AddToLog(ReadFromSocket(sock));
//Заполняем заголовок письма SendToSocket(sock, 'DATA');
AddToLog(ReadFromSocket(sock));
//От кого SendToSocket(sock, 'From:<'+(login)+'>');
//Кому SendToSocket(sock, 'To:<'+edit7.Text+'>');
//Тема письма SendToSocket(sock, 'Subject: '+SubjectEdit.Text);
//Кодировка письма
SendToSocket(sock, 'Mime-Version: 1.0'+#13+#10+'Content-Type: text/plane; charset="windows-1251"');
//Программа отправитель
SendToSocket(sock, 'X-Mailer: Microsoft Outlook Express');
//Текст письма For I:=0 to TextMemo.Lines.Count-1 do begin _str:=TextMemo.Lines.Strings[i]; while _str<>'' do begin j:=SendToSocket(sock, _str);
if j=SOCKET_ERROR then break;
Delete(_str, 1, j); end; end;
sendToSocket(sock,#13+#10+'.'); AddToLog(ReadFromSocket(sock));
sendToSocket(sock, 'QUIT'); AddToLog(ReadFromSocket(sock)); CloseSocket(sock);
|
Это сообщение отредактировал(а) cable - 11.8.2010, 14:43
|