Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Интернет и сети
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 26.03.2014, 00:13
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию Сокеты и почта

Кто-нибудь пробовал отправлять почту через сокеты? Никак не могу победить это дело.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #2  
Старый 26.03.2014, 19:34
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

было, но очень-очень давно. боюсь еще на дискетах исходники остались)
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #3  
Старый 26.03.2014, 19:54
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

А что конкретно не получается? Слышал, что SMTP сейчас всё чаще требуют какую-то замудренную авторизацию, которая может стать камнем преткновения.
__________________
Не стоит путать форумы с богадельнями. © Bargest
Ответить с цитированием
  #4  
Старый 26.03.2014, 23:15
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Нужна, как называют школяры, "скрытная" отправка. То есть, программа подключена по 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  
Старый 27.03.2014, 01:32
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

А что возвращается-то?

Добавлено позже: функция SendData кривая какая-то, будто еще под Turbo Pascal писана. Я бы написал так:
Код:
function SendData(St : AnsiString) : Boolean;
begin
  Result := send(Sock, St[1], Length(St) + 1, 0) > SOCKET_ERROR + 1;
end;
Ноль там надо отправлять в конце по правилам? Если не надо, прибавление единицы к Length(St) излишне.
__________________
Не стоит путать форумы с богадельнями. © Bargest

Последний раз редактировалось Freeman, 27.03.2014 в 01:37.
Ответить с цитированием
  #6  
Старый 27.03.2014, 02:28
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Хоть извращайся, хоть нет, а заказчику нужна отправка на почту.
Да 0 требуется, из-за этого и буфер.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #7  
Старый 27.03.2014, 02:59
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

Цитата:
Сообщение от angvelem
Да 0 требуется, из-за этого и буфер.
Так в AnsiString он и так есть. Зачем куда-то копировать? Моя строчка должна работать вместо твоих трех.

Добавлено позже: кстати, у 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;
То есть 0 не отправляется. Плохой код ты нашел.
__________________
Не стоит путать форумы с богадельнями. © Bargest

Последний раз редактировалось Freeman, 27.03.2014 в 03:13.
Ответить с цитированием
  #8  
Старый 27.03.2014, 03:40
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

По фигу что там у Borland-а. Любая команда после приветствия считается нераспознанной.
0 не отправляется, а служит признаком завершения строки - так принято у С-ников.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #9  
Старый 27.03.2014, 03:47
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

Цитата:
Сообщение от angvelem
0 не отправляется, а служит признаком завершения строки - так принято у С-ников.
Так это же сокеты а не Си. В них вроде бы перевод строки считается концом команды. С твоей же отправкой получается так:
Код:
'EHLO'#13#10
#0'STARTTLS'#13#10
__________________
Не стоит путать форумы с богадельнями. © Bargest
Ответить с цитированием
  #10  
Старый 27.03.2014, 03:56
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Получается всё правильно, в отладчике проверял.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #11  
Старый 27.03.2014, 04:40
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

В ответ на STARTTLS mail.yandex.ru мне возвращает "220 Go ahead", а не 250, как ожидается в коде.
__________________
Не стоит путать форумы с богадельнями. © Bargest
Ответить с цитированием
  #12  
Старый 27.03.2014, 04:55
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Я проверяю для Гугла.
Хм, Яндекс вернул - Ошибка синтаксиса.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.

Последний раз редактировалось angvelem, 27.03.2014 в 04:57.
Ответить с цитированием
  #13  
Старый 27.03.2014, 04:59
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

Без разницы. GMail мне возвращает '220 2.0.0 Ready to start TLS'. Это же по RFC, не они их сами выдумали.
__________________
Не стоит путать форумы с богадельнями. © Bargest
Ответить с цитированием
  #14  
Старый 27.03.2014, 05:00
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Через Telnet так и возвращает, в коде не хочет.
Насчёт выдумки, знакомый решил потестировать на своём сайте, так у него все команды через одно место, почти ни одна не совпала с RFC.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #15  
Старый 27.03.2014, 05:01
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

Цитата:
Сообщение от angvelem
Хм, Яндекс вернул - Ошибка синтаксиса.
И правильно, ибо нефиг. Я не считаю себя умнее Borland, поэтому процедура отправки у меня выглядит так:
Код:
function SendData(St : AnsiString) : Boolean;
begin
  Result := send(Sock, St[1], Length(St), 0) > SOCKET_ERROR + 1;
end;
Стоит добавить +1 к длине, как сразу получаю '502 5.5.2 Syntax error, command unrecognized.'
__________________
Не стоит путать форумы с богадельнями. © Bargest
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 13:58.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter