Send mails from Delphi apps through PHP script

Sending mails from a client app is an interesting feature, it can be used for sending notifications or authentication codes. You can add this option to your Delphi (desktop and mobile) apps by calling a PHP web script through REST client.

The PHP script

The steps for writing a PHP script for sending mails (through the PHP built-in “mail()” function) are described in this tutorial :

Create PHP script for sending mails

Delphi client app

Let’s develop a GUI client app in Delphi (either in FMX or VCL), design the required controls and write the code for handling the mail variables.

You can use text controls like in a mail client app, or you can make the mail variables not visible to the user, by loading their values in the background then sending the mail.

REST service exploration

We will explore our REST service :

  • Open the Embarcadero REST Debugger.
  • In the base URL, enter the URL of your PHP mail script (like “https://mydomain.com/mail.php”), make sure that the URL’s protocol is ‘https’, otherwise it will not work on Android.
  • Select the POST method.
  • Go to the parameters tab, and add parameters for the mail variables : choose the kind “GET/POST”, name each parameter according to our PHP script request’s parameters, and set a test value, like in the table below.
    For long texts (like an HTML formatted text), the script can get the mail’s text from the request’s body, so we can also use the parameter kind “BODY”.
KindNameValue (example)
GET/POSTtotarget@domain.com
GET/POSTsubjectMail testing
GET/POST or BODYtxtThis is a test mail
GET/POSTfromsender@domain.com
or
Sender <sender@domain.com>

Now, send the request.

When a response is received, go to the body tab, and you will see a string containing the number “1” (if the mail was sent).

After you confirmed that our service is working, click on the button ‘Copy components’ to copy the REST client’s controls set and paste them in your Delphi app.

You will get these components (TRESTClient, TRESTRequest and TRESTResponse) in your clipboard (as DFM code) :

object RESTClient1: TRESTClient
  BaseURL = 'https://mydomain.com/mail.php'
  Params = <>
end
object RESTRequest1: TRESTRequest
  AssignedValues = [rvConnectTimeout, rvReadTimeout]
  Client = RESTClient1
  Method = rmPOST
  Params = <
    item
      Name = 'to'
      Value = 'target@domain.com'
    end
    item
      Name = 'subject'
      Value = 'Mail testing'
    end
    item
      Name = 'txt'
      Value = 'This is a test mail'
    end
    item
      Name = 'from'
      Value = 'Sender <sender@domain.com>'
    end>
Response = RESTResponse1 end object RESTResponse1: TRESTResponse end

Delphi implementation

Paste the copied components to your Delphi form, you will see a set of three non-visual components (TRESTClient, TRESTRequest and TRESTResponse).

You can change values of the parameters either :

  • On design time, in the object inspector, or
  • On runtime, you can set the value of each variable by accessing the parameter’s value. For example, for changing the ‘subject’ parameter’s value, you can use anyone of the following codes :
RESTRequest1.Params.Items[1].Value := 'New subject for test';

RESTRequest1.Params.ParameterByIndex(1).Value := 'New subject for test';

RESTRequest1.Params.ParameterByName('subject').Value := 'New subject for test';

Now, for sending the requests to our script, we will call the TRESTRequest procedure “Execute”.

For usage, we will implement an event, for getting the mail variables from TEdit controls, like this :

procedure TForm1.Button1Click(Sender: TObject);
begin

RESTClient1.ResetToDefaults;
RESTClient1.Accept := 'application/json, text/plain; q=0.9, text/html;q=0.8,';
RESTClient1.AcceptCharset := 'UTF-8, *;q=0.8';
RESTClient1.BaseURL := 'https://mydomain.com/mail.php';
RESTClient1.HandleRedirects := True;
RESTClient1.RaiseExceptionOn500 := False;

// Here we will pass the mail variables
RESTRequest1.Params.ParameterByName('to').Value := EditReceiver.Text;
RESTRequest1.Params.ParameterByName('subject').Value := EditSubject.Text;
RESTRequest1.Params.ParameterByName('txt').Value := Edit1.Text;

RESTRequest1.Client := RESTClient1;
RESTRequest1.Response := RESTResponse1;
RESTRequest1.SynchronizedEvents := False;
RESTResponse1.ContentType := 'application/json';

RESTRequest1.Execute;
end;

Bonus : set a separate function

You can create the whole set of REST Client controls on runtime from Object Pascal code, by writing a separate method (a function or a class function), on your project unit or on a spearate unit ready to be included in any project.

It is better to set a function (not a procedure) to use the script response as a result.

For creating a separate unit, go to the ‘New’ dialog and choose ‘Unit’.

Make sure to include the units “REST.Client” and “REST.Types” in the uses clauses.

unit PHPMail;
interface
uses
..., REST.Client, REST.Types, ...

type
  TExtra = class
     class function SendMail(sRecipient, sSubject, sText, sSenderAddress, sSenderName : string) : Boolean;
  end;


implementation

class function TExtra.SendMail(sRecipient, sSubject, sText, sSenderAddress, sSenderName: string): boolean;
var
LClient : TRESTClient;
LRequest : TRESTRequest;
LResponse : TRESTResponse;

begin
LClient := TRESTClient.Create('https://mydomain.com/mail.php');
LResponse := TRESTResponse.Create(nil);
LRequest := TRESTRequest.Create(nil);
LRequest.Client := LClient;
LRequest.Response := LResponse;
//LRequest.AssignedValues := [TAssignedValue.rvConnectTimeout, TAssignedValue.rvReadTimeout];
try
   try
   LRequest.Method := TRESTRequestMethod.rmPOST;
   LRequest.Params.AddItem('to', sRecipient, pkGETorPOST);
   LRequest.Params.AddItem('subject', sSubject, pkGETorPOST);
   LRequest.Params.AddItem('txt', sText, pkGETorPOST);
   if sSenderName <> ''
      then LRequest.Params.AddItem('from', sSenderName + ' <' + sSenderAddress +'>', pkGETorPOST)
      else LRequest.Params.AddItem('from', sSenderAddress, pkGETorPOST);
   LRequest.Execute;
   except
   Result := False;
   end;

finally
Result := (LRequest.Response.Content.Contains('1'));

LRequest.Free;
LResponse.Free;
LClient.Free;

end;
end.

And we will call the function simply like this :

TExtra.SendMail('target@domain.com', 'Mail test', 'Mail test text', 'sender@domain.com', 'Mr. S');

We can also use the function result to notify if the mail was sent, like this :

procedure ...
begin
if TExtra.SendMail('target@domain.com', 'Mail test', 'Mail test text', 'sender@domain.com', 'Mr. S')
   then ShowMessage('Mail sent successully')
   else ShowMessage('Mail sending failed');
end;

See also

Leave a Reply