Отправка почты средствами Delphi. Tcp - IdTcpServer послать первым сообщение клиенту Delphi - Stack Overflow на русском Отправка сообщений делфи

Посылка сообщений

Так же как система Windows посылает свои сообщения различным окнам, в самом приложении также может появиться необходимость обмена сообщениями между его собственными окнами и элементами управления. Для посылки сообщений существует несколько способов: метод PerForm() (работающий независимо от API Windows), а также функции API Win32 SendMessage() и PostMessage().

Метод PerForm(), которым обладают все потомки класса TControl:

function TControl.Perform(Msg: Cardinal; WParam, LParam: Longint): Longint;

Чтобы послать сообщение форме или элементу управления, применяется следующий синтаксис:

RetVal:= ControlName.PerForm(MessageID, wParam, lParam);

При вызове PerForm() управление вызывающей программе не возвратится, пока сообщение не будет обработано. Этот метод передает сообщение, минуя систему передачи сообщений API Windows.

Функции API SendMessage() и PostMessage(), объявленные в модуле Windows следующим образом:

function SendMessage(hWnd: HWND; Msg: UINT; wParam: WPARAM;

lParam: LPARAM): LRESULT; stdcall;

function PostMessage(hWnd: HWND; Msg: UINT;

wParam: WPARAM; lParam: LPARAM): BOOL; stdcall;

hWnd – дескриптор окна получателя сообщения; Msg – идентификатор сообщения; wParam и lParam – дополнительные данные.

Функция SendMessage() подобно методу PerForm() посылает сообщение непосредственно процедуре окна и ожидает его обработки, а функция PostMessage() помещает сообщение в очередь сообщений и возвращает управление вызвавшей ее программе, не дожидаясь результатов обработки.

Функция SendMessage() возвращает значение, полученное в результате обработки сообщения. Функция PostMessage() – возвращает значение, которое показывает, удалось ли поместить сообщение в очередь сообщений.

Пользовательские сообщения

При разработке приложений может возникнуть ситуация, при которой приложению потребуется послать специальное сообщение либо самому себе, либо другому приложению для выполнения некоторых действий. Для сообщений, придуманных пользователем, в Windows зарезервированы значения от WM_USER до $7FFF.

Пример пользовательского сообщения:

TestMsg = WM_USER + 100; // идентификатор сообщения

TForm1 = class(TForm)

// метод обработки сообщения:

procedure MyMessage(var Msg: TMessage); message TestMsg;

procedure TForm1.MyMessage(var Msg: TMessage);

ShowMessage("Работает сообщение TestMsg");

Msg.Result:= 1; // возвращаемый результат

Примеры посылки сообщения форме:

if Form1.PerForm(TestMsg, 0, 0) = 1 then

if SendMessage(Form1.Handle, TestMsg, 0, 0) = 1 then

ShowMessage("Сообщение успешно обработано");

if PostMessage(Form1.Handle, TestMsg, 0, 0) then

ShowMessage("Сообщение помещено в очередь сообщений");

События Delphi

Событие – это то, что происходит в процессе работы программы. С точки зрения языка Delphi, событие – это свойство процедурного типа, и его значением является указатель на некоторый метод. Присвоить такому свойству значение означает указать адрес метода, который будет выполняться в момент наступления события. Такие методы называются обработчиками событий.

Использование событий позволяет к существующему классу добавить новую функциональность без создания класса-потомка.

Свойства событий стараются начинать со слова "On", за которым следует имя события.

Взаимосвязь сообщений и событий

Delphi представляет собой интерфейс для взаимодействия с сообщениями Windows, по крайней мере – с некоторой их частью. Многие события компонентов библиотеки VCL непосредственно связаны с сообщениями Windows типа WM_XXX.

При разработке приложений может возникнуть ситуация, при которой приложению потребуется послать сообщение либо самому себе, либо другому пользовательскому приложению. У некоторых предыдущее утверждение вызовет недоумение: зачем при ложению посылать сообщение самому себе, если можно просто вызвать соответствую щую процедуру? Это хороший вопрос, и на него существует несколько ответов. Во первых, использование сообщений представляет собой механизм поддержки реального полиморфизма, поскольку не требует наличия каких либо знаний о типе объекта полу чающего сообщение. Таким образом, технология работы с сообщениями имеет ту же мощь, что и механизм виртуальных методов, но обладает существенно большей гибко стью. Во вторых, сообщения допускают необязательную обработку - если объект получатель не обработает поступившее сообщение, то ничего страшного не произой дет. И, в третьих, сообщения позволяют осуществлять широковещательное обращение к нескольким получателям и организовывать параллельное прослушивание, что доста точно трудно реализовать с помощью механизма вызова процедур.

Использование сообщений внутри приложения

Заставить приложение послать сообщение самому себе очень просто - достаточно либо воспользоваться функциями интерфейса API Win32 SendMessage() или Post- Message(), либо методом Perform(). Сообщение должно обладать идентификато ром в диапазоне от WM_USER+100 до $7FFFF (этот диапазон Windows резервирует для сообщений пользователя). Например:const

SX_MYMESSAGE = WM_USER + 100;

SomeForm.Perform(SX_MYMESSAGE, 0, 0);

SendMessage(SomeForm.Handle, SX_MYMESSAGE, 0, 0);

PostMessage(SomeForm.Handle, SX_MYMESSAGE, 0, 0);

Затем, для перехвата этого сообщения, создайте обычную процедуру обработчик, выполняющую в форме необходимые действия:

TForm1 = class(TForm)

procedure SXMyMessage(var Msg: TMessage); message SX_MYMESSAGE;

procedure TForm1.SXMyMessage(var Msg: TMessage);

MessageDlg(‘She turned me into a newt!’,

mtInformation, , 0);

Как видно из примера, различия в обработке собственного сообщения и стандарт ного сообщения Windows невелики. Они заключаются в использовании идентифика торов в диапазоне от WM_USER+100 и выше, а также в присвоении каждому сообще нию имени, которое каким то образом будет отражать его смысл.

Никогда не посылайте сообщений, значение WM_USER которых превосходит $7FFF, ес- ли не уверены абсолютно точно, что получатель способен правильно обработать это сообщение. Поскольку каждое окно может независимо выбирать используемые им значения, весьма вероятно появление трудноуловимых ошибок, если только заранее не составить таблицы идентификаторов сообщений, с которыми будут работать все отправители и получатели сообщений.

Обмен сообщениями между приложениями

При необходимости организовать обмен сообщениями между двумя или более приложениями в них следует использовать функцию API RegisterWindowMessage(). Этот метод гарантирует, что для заданного типа сообщений каждое приложение бу дет использовать один и тот же номер сообщения (message number).

Функция RegisterWindowMessage() принимает в качестве параметра строку с за

вершающим нулевым символом и возвращает для нового сообщения идентификатор вдиапазоне $C000 – $FFFF. Это означает, что вызова данной функции с одной и той же строкой в качестве параметра в любом приложении будет достаточно, чтобы га рантировать одинаковые номера сообщений во всех приложениях, принимающих участие в обмене. Еще одно преимущество такой функции состоит в том, что система гарантирует уникальность идентификатора, назначенного любой заданной строке. Это позволяет посылать широковещательные сообщения всем существующим в сис теме окнам, не опасаясь нежелательных побочных эффектов. Недостатком данного метода является некоторое усложнение обработки подобных сообщений. Суть заклю чается в том, что идентификатор сообщения становится известным только при рабо те приложения, поэтому использование стандартных процедур обработки сообщений оказывается невозможным. Для работы с подобными сообщениями потребуется пе реопределить стандартные методы WndProc() или DefaultHandler() элементов управления либо соответствующие процедуры класса окна.

НА ЗАМЕТКУ

Число, возвращаемое функцией RegisterWindowMessage(), создается динамически и может принимать различные значения в разных сессиях Windows, а значит, не может быть определено до момента выполнения программы.

Широковещательные сообщения

Любой класс, производный от класса TWinControl, позволяет с помощью метода Broadcast() послать широковещательное сообщение (broadcast message) любому элементу управления, владельцем которого он является. Эта технология используется в тех случа ях, когда требуется послать одно и то же сообщение группе компонентов. Например, чтобы послать пользовательское сообщение по имени um_Foo всем элементам управле ния, принадлежащим объекту Panel1, можно воспользоваться следующим кодом:

Message:= UM_FOO;

Разработать программу, которая будет предоставлять интерфейс для использования стандартной для Win2000/XP команды передачи сообщений net send. Дать возможность указать пользователю адрес получателя, текст сообщения и количество отправляемых сообщений. Также предусмотреть возможность установки блокировки на получение сообщений от других компьютеров.

Разработка формы

Создайте новый проект Delphi. Измените заголовок формы (свойство Caption) на Net Sender. Разместите вдоль левого края формы один над другим три компонента Label категории Standard и присвойте их свойству Caption значения IP-адрес:, Сообщение: И Количество:.

Рядом с каждой из меток разместите по компоненту Edit категории Standard . Самый верхний назовите ip (свойство Name), а свойству Text присвойте значение 192.168.0.1.; среднее поле назовите txt, а свойству Text присвойте какой-либо текст сообщения по умолчанию; самое нижнее поле назовите how, а свойству Text присвойте значение 1.

Под перечисленными компонентами разместите компонент Checkbox категории Standard . Присвойте ему имя secure, свойству Caption присвойте значение Отключить прием сообщений, а свойству Checked - значение True.

В самом низу формы разместите кнопку (компонент Button категории Standard ), присвоив ее свойству Caption значение Send. Также нам понадобится таймер (компонент Timer категории System ), для которого свойству Interval следует присвоить значение 10.

Полученная форма должна соответствовать рис. 15.1.

Рис. 15.1. Форма для программы отправки сообщений в локальной сети

Разработка программного кода

Прежде всего напишем собственную процедуру bomb, которая будет считывать все настройки и отправлять сообщение. Объявите эту процедуру как закрытый член класса формы:

Также нам понадобится глобальная переменная i типа integer:

Теперь создадим реализацию процедуры bomb в разделе implementation:

procedure TForm1.bomb() ;
if how.Text= "" then how.Text:= "1";
if ip.Text = "" then ip.Text:= "127.0.0.1"; {если ip-адрес не указан, то отправляем на локальный компьютер}
WinExec(PChar("net send " + ip.Text + """ + txt.Text + """), 0); //отправка сообщения

В этой процедуре выполняется проверка: все ли необходимые поля заполнены. Если нет текста сообщения, то устанавливаем знак "!"; если не указан IP-адрес, то отправляем сообщение на локальный компьютер с адресом 127.0.0.1; если не указано количество сообщений, то отправляем одно сообщение. Сообщения отправляются с помощью стандартной команды net send, которая имеет следующий синтаксис:

net send ip-адрес сообщение.

Теперь обработаем событие таймера OnTimer:

h: HWND; //хранит идентификатор окна
if not secure.Checked then //если флажок не установлен
Timer1.Enabled:= False; //отключаем мониторинг
if secure.Checked then //если флажок установлен
//ищем окна с сообщениями
h:= FindWindow(nil, "Служба сообщений "); //закрываем все найденные окна
if h <>

Если установлен флажок Отключить прием сообщений, то мы начинаем мониторинг окон, заголовок которых говорит о том, что это - сообщение, и закрываем все найденные окна. Если флажок не установлен, то мониторинг отключается.

Для того чтобы можно было переключаться между этими двумя режимами, необходимо создать обработчик события secure.OnClick:

if secure.Checked then //если флажок установлен…
Timer1.Enabled:= True; //…включаем мониторинг

При нажатии кнопки Send мы будем просто вызывать процедуру bomb:

Для того чтобы облегчить пользователю жизнь, сделаем так, чтобы отправка сообщения осуществлялась также по нажатии клавиши в любом текстовом поле ввода. Для этого необходимо создать обработчик события OnKeyPress для каждого из полей. Код этого обработчика для поля ip, который затем можно назначить полям txt и how:

if key = #13 then //если нажата клавиша
bomb; //отправка сообщения

Полный исходный код модуля

Полный код модуля программы отправки сообщений по локальной сети представлен в листинге 15.1.

Листинг 15.1. Модуль программы отправки сообщений по локальной сети

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;

procedure Timer1Timer(Sender: TObject);
procedure secureClick(Sender: TObject);
procedure ipKeyPress(Sender: TObject; var Key: Char);
procedure txtKeyPress(Sender: TObject; var Key: Char);
procedure howKeyPress(Sender: TObject; var Key: Char);
procedure Button1Click(Sender: TObject);


//проверяем, не пустое ли текстовое сообщение
if txt.Text = "" then txt.Text:= "!";
//если количество не указано, то отправляем одно сообщение
if how.Text= "" then how.Text:= "1";
if ip.Text = "" then ip.Text:= "127.0.0.1"; {если ip-адрес не указан, то отправляем на локальный компьютер}
//отправляем указанное количество сообщений
for i:=1 to StrToInt(how.Text) do
WinExec(PChar("net send " + ip.Text + """ + txt.Text + """), 0); //отправка сообщения

procedure TForm1.Timer1Timer(Sender: TObject);
h: HWND; //хранит идентификатор окна
if not secure.Checked then //если флажок не установлен
Timer1.Enabled:= False; //отключаем мониторинг
if secure.Checked then //если флажок установлен
//ищем окна с сообщениями
h:= FindWindow(nil, "Служба сообщений "); //закрываем все найденные окна
if h <> 0 then PostMessage(h, WM_QUIT, 0, 0);

procedure TForm1.secureClick(Sender: TObject);
if secure.Checked then //если флажок установлен…
Timer1.Enabled:= True; //…включаем мониторинг

procedure TForm1.ipKeyPress(Sender: TObject; var Key: Char);
if key = #13 then //если нажата клавиша
bomb; //отправка сообщения

procedure TForm1.Button1Click(Sender: TObject);

⊚ Все файлы проекта и исполняемый файл рассмотренной программы находятся на прилагаемом к книге компакт-диске в папке Chapter 15.

Зачастую, программы на delphi используют средствами email. В этой статье будет полностью рассказано, как отправляется ваше письмо другому пользователю. при помощи delphi. При этом, будем использовать только стандартные компоненты делфи.

Для начала создадим новый проект и назовём его \»Отправка писем средствами delphi\». Затем, на форму необходимо перенести несколько компонентов 1x Memo, 3x Edit, 2x Botton, а также необходимо перенести IdSMTP, IdAntiFreeze, IdMessage. Далее, на событие onclick любой кнопки пишем:

//выбираем SMTP сервер. В данный момент стоит yandex. IdSMTP1.Host:= "smtp.yandex.ru"; //ваш логин (для некоторых необходимо писать с доменом). IdSMTP1.Username:= "[email protected]"; //пароль от почты. IdSMTP1.Password:= "qwerty123"; //порт, рекомендуем использовать 587. IdSMTP1.Port:=587; //в Edit2 будет вписываться тема письма. IdMessage1.Subject:= Edit2.Text; //в Edit1 будет адрес получателя. IdMessage1.Recipients.EMailAddresses:= Edit1.Text; //ваш email с которого идёт отправка. IdMessage1.From.Address:= "[email protected]"; //в memo1 будет текст который вы ходите послать. IdMessage1.Body.Text:= memo1.Text ; //в Edit3 будет ваша электронная подпись (Имя). IdMessage1.From.Name:= Edit3.Text; //соединяемся IdSMTP1.connect; //отправляем IdSMTP1.Send(IdMessage1); //отсоединяемся IdSMTP1.Disconnect;

Если IdMessage отображает знаки вопроса

Данный баг связан с тем, что Вы вписываете русские буквы, а компонент memo не может их грамотно прочитать, для этого необходимо указать кодировку Utf8.

// устанавливаем кодировку IdMessage1.Charset:="UTF-8"; // переводим текст в нужную кодировку IdMessage1.Body.Text:=UTF8Encode(memo1.text);

Отправка и прием почты реализуются при помощи Delphi довольно просто. Для отправки почты нам понадобится компонент idSMTP со страницы Indy Clients палитры компонентов Delphi.

Этот компонент реализует все необходимое для отправки электронной почты по протоколу SMTP (Simple Mail Transfer Protocol - простой протокол передачи почты), использующий 25 порт, по которому посылаются команды и текст письма. Этапы отправки электронной почты следующие:

1) соединение с SMTP сервером по 25 порту;
2) подготовка тела письма, определение отправителя и получателя письма;
3) отправка письма на SMTP сервер;

Разместив на форме компонент idSMTP, займёмся его настройкой. Настройку порта можно произвести в инспекторе объектов, установив свойство Port в значение 25, или в коде программы сделать то же самое:

IdSMTP1.Port:=25;

Соединение с сервером

Для соединения с SMTP сервером, который будет осуществлять отправку нашей почты, нужно указать его URL, для сервера mail.ru это производится следующим образом:

IdSMTP1.Host:= ′smtp.mail.ru′;

Соединение с сервером производится методом Connect:


procedure Connect(const ATimeout: Integer); override;

где ATimeout - необязательный параметр, задает максимальное время в миллисекундах ожидания ответа с SMTP сервера, по истечении которого попытка установить соединение прекращается.

Например,

IdSMTP1.Connect(5000);

Если при соединении с сервером требуется авторизация, то значение свойства AuthenticationType нужно установить в atLogin, при этом в инспекторе объектов также нужно определить свойства Username(имя пользователя. К примеру, Username почтового ящика [email protected] - delphi) и Password(пароль на ящик), или сделать то же программно:

IdSMTP1.AuthenticationType:=atLogin;
IdSMTP1.Username:=′delphi′;
IdSMTP1.Password:=′something′;

IdSMTP1.AuthenticationType:=atNone;

После применения метода Connect, нужно анализировать логическое свойство Connected, которое в случае удачного соединения устанавливается в True. После этого при помощи метода Send можно отправлять сообщение:

if Connected=True then IdSMTP1.Send(Msg);

Структура письма

Метод Send отправляет тело сообщения, представляющего собой структуру типа TIdMessage;

Структура письма реализуется в Delphi отдельным компонентом TIdMessage, расположенным на палитре компонентов Indy Misc и выглядит следующим образом

TidMessage Структура TIdMessage определяется следующим образом:

С темой сообщения, я думаю, все понятно. Свойство

конкретно определяются названия электронных учетных записей, которым адресуется письмо. Названия должны указываться через разделитель вида "," то есть через запятую. Например:

например,

например,

Свойство Text содержит информацию обоих свойств. Тело письма представляет собой объект типа TStrings:

где Collection - объект класса TIdMessageParts, представляющее собой коллекцию приложений к электронному письму.
контстанта AFileName типа TFileName - представляет собой обычную текстовую строку с указанием правильного пути к файлу, например "C:file.zip", по умолчанию имеет значение ′′.

Таким образом, продолжая наш пример, строкой вида