Модераторы: Snowy, Poseidon, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> winsock+smtp+socks, 501 NULL characters are not allowed in  
:(
    Опции темы
cable
Дата 11.8.2010, 09:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 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
PM MAIL   Вверх
Snowy
Дата 11.8.2010, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 53
Всего: 484



Много кода, лень смотреть.
Но очевидно, что использование _buff: array [0..255] of Char; - сразу ошибка.
Рекомендую вынести отправку и приём в отдельные функции, а не юзать send напрямую.
Второе - не указана версия дельфи.
Если ниже 2009, то можно прямо строку и использовать в качестве буфера, а не перегонять в кастрированный массив.
Ну а сама суть проблемы - отправка нулевого символа в текстовый протокол.
Тут сразу нужно смотреть, что отправляется. Юзай сниффер или маппер для проверки.
Явно какой-то мусор в порт шлётся.
PM MAIL   Вверх
cable
Дата 11.8.2010, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 11.8.2010

Репутация: нет
Всего: нет



если можно дайте поподробней  справку или может киньте код  для примера 
PM MAIL   Вверх
Snowy
Дата 12.8.2010, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 53
Всего: 484



Вот возьми маппер и смотри, что ты шлёшь.
PM MAIL   Вверх
cable
Дата 12.8.2010, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 11.8.2010

Репутация: нет
Всего: нет



Цитата(Snowy @ 12.8.2010,  11:06)
Вот возьми маппер и смотри, что ты шлёшь.


спасибо но мне не как не запустить его 
он точно под виндовс 7 работает
если не трудно сделай скрин правильной настройки 
PM MAIL   Вверх
Matematik
Дата 12.8.2010, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1027
Регистрация: 11.3.2006

Репутация: 24
Всего: 50



Код

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);
  




Догадайся, что будет если строка больше 256 символов?
Можно просто
Код

send(socket, Pointer(str)^, length(str), 0);


Плюс - никак не проверяется результат send\recv - 100% вероятность получить баги.

Код

 //Текст письма
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;

Ужас. smile 

Тут надо всё переписывать, и лучше с использованимем оболочки над winsock (Synapse, Indy etc)
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0899 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.