Отправка сообщение на email

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

san7667
новенький
Сообщения: 42
Зарегистрирован: 18.06.2023 16:57:37

Отправка сообщение на email

Сообщение san7667 »

Добрый день, подскажите пожалуйста кто знает, живой действующий пример отправки сообщения на почту email самый простой..
какой-нибудь алгоритм или процедуру.
В интернете нашел https://www.cyberforum.ru/delphi-networ ... b340417620, но он давно не работает...
Аватара пользователя
Sharfik
энтузиаст
Сообщения: 836
Зарегистрирован: 20.07.2013 01:04:30

Сообщение Sharfik »

С примером не помогу. Пробовал сам отправлять и по разному, кое какие способы работали. Но во всех случаях нужно учитывать один момент - сейчас почтовый сервера mail.ru, yandex и т.п. не позволяют по простому через них отправлять почту. Либо срабатывает отправка пары писем, а потом бан.
Alex2013
долгожитель
Сообщения: 3214
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

С почтой все хорошо в Инди (Indy10 ) https://www.indyproject.org
( в Лазарусе проще всего ставить через "Сетевой диспетчер пакетов" )
Есть и примеры http://digital-flame.ru/2015/09/22/delp ... lozheniya/
+ Нужно кинуть на форму IdPop3 и idSMTP
Зы
Можно и по другому но это реально вариант из серии "проще не бывает".
Зы Зы
Тоже с шифрованием SSL
https://psvlab.blogspot.com/2010/04/ssl ... n-ssl.html
https://www.cyberforum.ru/lazarus/thread1064373.html
Аватара пользователя
Снег Север
долгожитель
Сообщения: 3069
Зарегистрирован: 27.11.2007 15:14:47
Контактная информация:

Сообщение Снег Север »

У меня на работе инди под делфи великолепно отправляли тысячи писем через гугл и через почту служебного IIS сервера. Тысячи - это не фигура речи, отправка использовалась в продаваемых программах телемаркетинга у многих десятков клиентов. По ссылкам в предыдущем сообщении, примерно то же, что у меня было.
san7667
новенький
Сообщения: 42
Зарегистрирован: 18.06.2023 16:57:37

Сообщение san7667 »

Вопрос такой, если собирать из под линукса, это реально сделать?
Я так понял множество примеров для win...
Аватара пользователя
Снег Север
долгожитель
Сообщения: 3069
Зарегистрирован: 27.11.2007 15:14:47
Контактная информация:

Сообщение Снег Север »

Под линухом может быть только проблема с библиотеками openssl - они в каждой сборке именются по-разному, надо лезть в исходники инди и смотреть названия подключаемых файлов. Всё остальное - так же точно, как в винде.
Аватара пользователя
Ichthyander
энтузиаст
Сообщения: 701
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань
Контактная информация:

Сообщение Ichthyander »

https://github.com/risoflora/brookfreep ... ns/xmailer
Отправляет одной функцией

Код: Выделить всё

program demo;

{$mode objfpc}{$H+}

uses
  XMailer, SysUtils;

begin
  try
    SendMail('from="Your Name <test@host.com>" to=dest1@host.com;dest2@host.com ' +
      'subject="Your subject." message="Your message." user=user@host.com ' +
      'password=abc123 host=smtp.host.com:465 ssl=true tls=true');
    Write('E-mail sent successfully!');
  except
    on E: Exception do
      Write(E.Message);
  end;
end.
Alex2013
долгожитель
Сообщения: 3214
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

Ichthyander писал(а):https://github.com/risoflora/brookfreepascal/tree/main/plugins/xmailer
Отправляет одной функцией
И что это реально надежно ? Бо мучают меня смутные сомнения....
Аватара пользователя
Ichthyander
энтузиаст
Сообщения: 701
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань
Контактная информация:

Сообщение Ichthyander »

Alex2013 писал(а):И что это реально надежно ? Бо мучают меня смутные сомнения....
Ну не знаю. Работает у меня на веб-сервере. Тестил на Windows. Что может быть проблемного-то?
san7667
новенький
Сообщения: 42
Зарегистрирован: 18.06.2023 16:57:37

Сообщение san7667 »

Ichthyander писал(а):https://github.com/risoflora/brookfreepascal/tree/main/plugins/xmailer
Отправляет одной функцией

Код: Выделить всё

program demo;

{$mode objfpc}{$H+}

uses
  XMailer, SysUtils;

begin
  try
    SendMail('from="Your Name <test@host.com>" to=dest1@host.com;dest2@host.com ' +
      'subject="Your subject." message="Your message." user=user@host.com ' +
      'password=abc123 host=smtp.host.com:465 ssl=true tls=true');
    Write('E-mail sent successfully!');
  except
    on E: Exception do
      Write(E.Message);
  end;
end.

Не совсем понял куда это пихать)))
На гит хабе ничего не пойму что с этим делать..
Если не сложно, разжуйте для особо одаренных ))
Аватара пользователя
Ichthyander
энтузиаст
Сообщения: 701
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань
Контактная информация:

Сообщение Ichthyander »

1) Получить либу локально.
  • Если есть git, то

    Код: Выделить всё

    git clone https://github.com/risoflora/brookfreepascal.git
    ,
  • либо скачать через Open Package Manager (он там тоже есть),
  • либо скачать непосредственно с сайта GitHub: Кнопка Code - далее download zip.
2) Далее в папке plugins/xmailer/pkg находим файл xmailerpkg.lpk и добавляем в зависимости вашего проекта.
3) Добавляем модуль Xmailer в блок Uses вашего модуля Unit

P.S. В зависимости от ОС и установленных либ может потребоваться добавить библиотеки OpenSSL в папку программу (для работы защищенных протоколов). Или просто установить в систему
Alex2013
долгожитель
Сообщения: 3214
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

Ichthyander писал(а):
Alex2013 писал(а):И что это реально надежно ? Бо мучают меня смутные сомнения....
Ну не знаю. Работает у меня на веб-сервере. Тестил на Windows. Что может быть проблемного-то?
Например кодировки и шифрование . :idea:
Аватара пользователя
*Rik*
постоялец
Сообщения: 453
Зарегистрирован: 19.04.2011 12:18:51
Откуда: Урал
Контактная информация:

Сообщение *Rik* »

Я использую Synapse, работает под Windows и Linux, любые варианты работы с почтой smtp, imap, pop3 и вообще с сетью TCP, HTTP, FTP. Для работы с SSL нужно в раздел uses в своей программе добавить модуль из поставки synapse в котором прописана поддержка SSL нужной версии и собрать с ними свой проект, я использую 1.1.1, пробовал 3.0, не все сайты поддерживают, откатился на 1.1.1
Для Windows OpenSSL брать тут:
https://slproweb.com/products/Win32OpenSSL.html
можно установить в системный каталог, либо взять 2 файла libcrypto-1_1-x64.dll и libssl-1_1-x64.dll и положить рядом со своей программой.

Для Linux поставить нужную версию из репозитория.

Здесь исчерпывающие сведения об использовании библиотеки на все случаи жизни.
https://webdelphi.ru/category/kniga-synaose/
san7667
новенький
Сообщения: 42
Зарегистрирован: 18.06.2023 16:57:37

Сообщение san7667 »

Снег Север писал(а):Под линухом может быть только проблема с библиотеками openssl - они в каждой сборке именются по-разному, надо лезть в исходники инди и смотреть названия подключаемых файлов. Всё остальное - так же точно, как в винде.
Нашел библиотеки для линукса:

Код: Выделить всё

wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2u.tar.gz
tar -xf openssl-1.0.2u.tar.gz
cd openssl-1.0.2u
./config shared
make
cp *.so /путь к проекту
Все, что остается - показать Indy, где искать эти библиотеки:

Код: Выделить всё

IdOpenSSLSetLibPath(ExtractFilePath(ParamStr(0)));
Но у меня не находит компонент IdOpenSSLSetLibPath..

Как показать indy что библиотеки лежат в папке с проектом???

Добавлено спустя 1 час 15 минут 27 секунд:
Разобрался.
Что бы увидел функцию IdOpenSSLSetLibPath нужно подключить модуль:

Код: Выделить всё

uses IdSSLOpenSSLHeaders;
delphius
постоялец
Сообщения: 131
Зарегистрирован: 18.03.2020 12:40:11

Сообщение delphius »

san7667 писал(а):Добрый день, подскажите пожалуйста кто знает, живой действующий пример отправки сообщения на почту email самый простой..
какой-нибудь алгоритм или процедуру.
Неожиданно для себя тоже не нашел в интернете актуальных примеров на free pascal отправки простого почтового сообщения по smtp без использования TLS.

Написал простой кроссплатформенный пример на чистом fcl (без использования Indy, Synapse и тп.), так как все необходимое есть и хорошо работает очень давно.
Компилировал и проверял под Windows 10 и под Linux Mint (Ubuntu).

Код: Выделить всё

program socketmail;

{$mode objfpc}{$H+}

uses
  sockets, // работа с Sockets
  resolve, // Преобразование доменных имен в IP адреса и обратно с помощью DNS
  base64; // base64 кодирование/декодирование

function SendMail(const SmtpServer, SenderEmail, Password, RecipientEmail, MailSubject, MailBody: string; SmtpPort: Integer): Boolean;
var
  CSocket: TSocket;
  Address: TInetSockAddr;
  Buffer: array[0..1023] of Char;
  BytesRead: Integer;
  IPAddr: string;
  MailContent, Base64Encoded: string;
  hrs: THostResolver;

  procedure SendCommand(Socket: TSocket; const Command: string);
  begin
    WriteLn('Client: ', Command);
    fpsend(Socket, PChar(Command + #13#10), longword(Length(Command) + 2), 0);
    BytesRead := fprecv(Socket, @Buffer[0], SizeOf(Buffer), 0);
    Buffer[BytesRead] := #0;
    WriteLn('Server: ', Buffer);
  end;

begin
  Result := False; // По умолчанию считаем, что отправка не удалась

  // Создание сокета
  CSocket := fpsocket(AF_INET, SOCK_STREAM, 0);
  if CSocket = -1 then
  begin
    WriteLn('Error creating socket.');
    Exit;
  end;

  // Преобразование доменного имени SMTP сервера в IP адрес
  hrs := THostResolver.Create(nil);
  if hrs.NameLookup(SmtpServer) then
  begin
    IPAddr := hrs.AddressAsString;
    WriteLn('Resolved IP Address: ', IPAddr);
  end
  else
  begin
    WriteLn('Failed to resolve the hostname: ', SmtpServer);
    Exit;
  end;

  // Подключение к SMTP серверу
  with Address do
   begin
      sin_family := AF_INET; //TCP/IP
      sin_port:= htons(word(SmtpPort)); //Порт
      sin_addr:=StrToNetAddr(hrs.AddressAsString); // IP адрес
   end;

  hrs.Free; // Освобождаем переменную

  if fpconnect(CSocket, @Address, SizeOf(Address)) < 0 then
  begin
    WriteLn('Error connecting to SMTP server.');
    Exit;
  end;

  // Отправка команды EHLO
  SendCommand(CSocket, 'EHLO client');

  // Производим аутентификацию, отправляя команды AUTH LOGIN
  SendCommand(CSocket, 'AUTH LOGIN');

  // Отправка логина (email отправителя) в формате Base64
  Base64Encoded := EncodeStringBase64(SenderEmail);
  if Base64Encoded = '' then
  begin
    WriteLn('Error encoding login.');
    Exit;
  end;
  SendCommand(CSocket, Base64Encoded);

  // Отправка пароля в формате Base64
  Base64Encoded := EncodeStringBase64(Password);
  if Base64Encoded = '' then
  begin
    WriteLn('Error encoding password.');
    Exit;
  end;
  SendCommand(CSocket, Base64Encoded);

  // Отправка команды MAIL FROM
  MailContent := 'MAIL FROM: <' + SenderEmail + '>';
  SendCommand(CSocket, MailContent);

  // Отправка команды RCPT TO
  MailContent := 'RCPT TO: <' + RecipientEmail + '>';
  SendCommand(CSocket, MailContent);

  // Отправка команды DATA
  SendCommand(CSocket, 'DATA');

  // Отправка данных письма
  MailContent :=
    'Subject: ' + MailSubject + #13#10 +
    'From: <' + SenderEmail + '>' + #13#10 +
    'To: <' + RecipientEmail + '>' + #13#10 +
    #13#10 +
    MailBody + #13#10 +
    '.';

  SendCommand(CSocket, MailContent);

  // Отправка команды QUIT
  SendCommand(CSocket, 'QUIT');

  // Закрытие сокета
  CloseSocket(CSocket);

  Result := True; // Отправка прошла успешно
end;

begin
  if SendMail('smtp.rambler.ru', 'yourlogin@rambler.ru', 'yourpassword', 'adressto@mail.com', 'Test Mail', 'This is a test email sent using sockets.', 25) then
    WriteLn('Mail sent successfully.')
  else
    WriteLn('Error sending mail.');
end.
а также пример на чистом fcl под windows с помощью WinSock2:

Код: Выделить всё

program socketmail;

{$mode objfpc}{$H+}

uses
  WinSock, // WinSock2 Socket Library for Win32
  base64; // base64 encoder & decoder

function SendMail(const SmtpServer, SenderEmail, Password, RecipientEmail, MailSubject, MailBody: string; SmtpPort: Integer): Boolean;
var
  CSocket: TSocket;
  Address: TSockAddrIn;
  Buffer: array[0..1023] of Char;
  BytesRead: Integer;
  IPAddr: string;
  HostEnt: PHostEnt;
  Addr: TInAddr;
  WSAData: TWSAData;
  MailContent, Base64Encoded: string;

  procedure SendCommand(Socket: TSocket; const Command: string);
  begin
    WriteLn('Client: ', Command);
    Send(Socket, PChar(Command + #13#10), Length(Command) + 2, 0);
    BytesRead := Recv(Socket, Buffer[0], SizeOf(Buffer), 0);
    Buffer[BytesRead] := #0;
    WriteLn('Server: ', Buffer);
  end;

begin
  Result := False; // По умолчанию считаем, что отправка не удалась

  // Инициализация WinSock
  if WSAStartup($202, WSAData) <> 0 then
  begin
    WriteLn('Error initializing WinSock.');
    Exit;
  end;

  // Создание сокета
  CSocket := Socket(AF_INET, SOCK_STREAM, 0);
  if CSocket = INVALID_SOCKET then
  begin
    WriteLn('Error creating socket.');
    Exit;
  end;

  // Преобразование доменного имени SMTP сервера в IP адрес
  HostEnt := gethostbyname(PChar(SmtpServer));
  if HostEnt <> nil then
  begin
    Addr := PInAddr(HostEnt^.h_addr_list^)^;
    IPAddr := inet_ntoa(Addr);
  end
  else
  begin
    WriteLn('Host not found: ' + SmtpServer);
    Exit;
  end;

  // Подключение к SMTP серверу
  Address.sin_family := AF_INET;
  Address.sin_port := htons(u_short(SmtpPort));
  Address.sin_addr.s_addr := inet_addr(PChar(IPAddr));

  if connect(CSocket, Address, SizeOf(Address)) < 0 then
  begin
    WriteLn('Error connecting to SMTP server.');
    Exit;
  end;

  // Отправка команды EHLO
  SendCommand(CSocket, 'EHLO client');

  // Производим аутентификацию, отправляя команды AUTH LOGIN
  SendCommand(CSocket, 'AUTH LOGIN');

  // Отправка логина (email отправителя) в формате Base64
  Base64Encoded := EncodeStringBase64(SenderEmail);
  if Base64Encoded = '' then
  begin
    WriteLn('Error encoding login.');
    Exit;
  end;
  SendCommand(CSocket, Base64Encoded);

  // Отправка пароля в формате Base64
  Base64Encoded := EncodeStringBase64(Password);
  if Base64Encoded = '' then
  begin
    WriteLn('Error encoding password.');
    Exit;
  end;
  SendCommand(CSocket, Base64Encoded);

  // Отправка команды MAIL FROM
  MailContent := 'MAIL FROM: <' + SenderEmail + '>';
  SendCommand(CSocket, MailContent);

  // Отправка команды RCPT TO
  MailContent := 'RCPT TO: <' + RecipientEmail + '>';
  SendCommand(CSocket, MailContent);

  // Отправка команды DATA
  SendCommand(CSocket, 'DATA');

  // Отправка данных письма
  MailContent :=
    'Subject: ' + MailSubject + #13#10 +
    'From: <' + SenderEmail + '>' + #13#10 +
    'To: <' + RecipientEmail + '>' + #13#10 +
    #13#10 +
    MailBody + #13#10 +
    '.';

  SendCommand(CSocket, MailContent);

  // Отправка команды QUIT
  SendCommand(CSocket, 'QUIT');

  // Закрытие сокета
  CloseSocket(CSocket);

  // Очистка WinSock
  WSACleanup;

  Result := True; // Отправка прошла успешно
end;

begin
  if SendMail('smtp.rambler.ru', 'yourlogin@rambler.ru', 'yourpassword', 'adressto@mail.com', 'Test Mail', 'This is a test email sent using sockets.', 25) then
    WriteLn('Mail sent successfully.')
  else
    WriteLn('Error sending mail.');
end.
Оба примера отлично отправляют сообщения на любые адреса через почту Rambler.

По поводу мнений о том, что все крупные почтовые сервисы требуют безопасного подключения по smtp, зарегистрировал бесплатный ящик на Rambler, в помощи написано, что подключение по smtp может осуществляться на smtp.rambler.ru в том числе без шифрования. Главное, не забыть включить в настройках почты переключатель "Доступ к почтовому ящику с помощью почтовых клиентов."

Тестовые сообщения успешно отправляются на любые адреса.
Понятно, что это просто пример, но он позволяет понять "кухню" изнутри...

При необходимости, можно расширить для отправки вложений и т.п., добавить обработку ответов с сервера.

Если нужен позарез TLS, то можно конечно заморочиться с Schannel (MS SSPI SSL), но OpenSSL будет гораздо проще, ценой двух dll в папке с программой.

Приведенные примеры сделаны в процедурном стиле с помощью модуля sockets из состава rtl, если требуется объектно-ориентрованный подход, то можно использовать надстройку над sockets (для windows она использует winsock) из состава fpc-net модуль sscockets.
Модуль "sockets" из состава RTL (Run-Time Library) и модуль "ssockets" из состава FCL-Net (Free Component Library for Network) предоставляют функциональность для работы с сокетами. Однако есть некоторые различия между ними:

1. Модуль "sockets" из состава RTL:
- Этот модуль предоставляет базовые функции для работы с сокетами, которые являются стандартными для языка Free Pascal.
- Включает простые процедуры и функции для создания, связывания, прослушивания и подключения сокетов.
- Модуль "sockets" предоставляет сокеты на низком уровне, что означает, что вам придется самостоятельно управлять деталями работы с сокетами, такими как настройка соединения и обработка данных.
2. Модуль "ssockets" из состава FCL-Net:
- Этот модуль также предоставляет функции для работы с сокетами, но на более высоком уровне абстракции.
- Включает классы и компоненты для работы с сетевыми протоколами, такими как TCP и UDP, а также предоставляет удобные методы для обмена данными.
- Модуль "ssockets" предоставляет более удобный и объектно-ориентированный интерфейс, что делает код более читаемым и позволяет сосредотачиваться на бизнес-логике, а не на низкоуровневых деталях работы с сокетами.

Основное различие между модулем "sockets" из RTL и модулем "ssockets" из FCL-Net заключается в уровне абстракции и удобстве использования. Модуль "sockets" предоставляет базовую функциональность на низком уровне, в то время как модуль "ssockets" абстрагирует сложности работы с сокетами и предоставляет более удобный интерфейс для программистов, что облегчает создание сетевых приложений на Free Pascal.
В ходе изысканий использовал smtp4dev - фейковый smtp email server для разработки и тестирования
Наткнулся на интересный набор маленьких утилит для отправки почты, в том числе из консоли
И попалась интересная программа Stunnel - прокси, предназначенная для добавления функциональности TLS кодирования для существующих клиентов и серверов, без изменения их кода.
Ну и как еще одно решение - использование smtp релея, своего или стороннего.
Последний раз редактировалось delphius 26.07.2023 19:47:07, всего редактировалось 4 раза.
Ответить