How to send Email in Delphi?

Today in most of software program it is required to send mail to others with attached data. As some time we need to update clients about their account details, status or any other information through mail. So Delphi provides so many easiest ways to send mail from our Delphi application. I have collected some of ways which are very useful for Delphi developers. In Delphi we don't required any third party components to send mails. We can send mail to single or group of peoples with CC, BCC and attachments. Even we can send HTML mails from Delphi.

So here are the ways...

1. ShellExecute
Sends Email using default mail client software installed on user's system. But it will not work with attachment for every mail client. And you have to use ShellAPI unit in uses list.

ShellExecute(Self.Handle,
             nil,
             'mailto:' +
             'jiten.g.s001@gmail.com' +
             '?Subject=Test Message Subject' +
             '&Body=Test Message Body',
             nil,
             nil,
             SW_NORMAL);

2. Sending through MS-OutLook mail client with attachment
We can use Delphi's OLE technique to send mail with attachment. But this approach requires Ms OutLook must to be installed in user's system. And need to use OleCtrls, ComObj units

procedure TForm1.btnSendMailClick(Sender: TObject);
const
  olMailItem = 0;
var
  Outlook: OLEVariant;
  MailItem: Variant;
  MailInspector : Variant;
  stringlist : TStringList;
begin
 try
   Outlook:=GetActiveOleObject('Outlook.Application') ;
  except
   Outlook:=CreateOleObject('Outlook.Application') ;
  end;
  try
    Stringlist := TStringList.Create;
    MailItem := Outlook.CreateItem(olMailItem) ;
    MailItem.Subject := 'subject here';
    MailItem.Recipients.Add('jiten.g.s001@gmail.com');
    MailItem.CC:='ABC@GMAIL.COM';
    MailItem.Attachments.Add('c:\FILE1.txt');
    Stringlist := TStringList.Create;
    StringList.Add('body here');
    MailItem.Body := StringList.text;
    MailItem.Send;   //SENDS A MAIL WITH OUT OUTLOOK WINDOW. USE "SAVE" FOR DRAFT

  // TO SHOW OUTLOOK DIALOG. BUT YOU HAVE SET MAILITEM.SEND AS COMMENT 
    MailInspector := MailItem.GetInspector;
    MailInspector.display(FALSE); //true means modal
    MailInspector.Send;
}
  finally
    Outlook := Unassigned;
    StringList.Free;
  end;
end;

3. MAPI (Messaging Application Programming Interface)
Delphi provides Windows API MAPI methods and functions to send mail by using MAPI. But this approach only works if the end user have MAPI complient Email software installed on that system. You also need to add MAPI unit in uses clause.

function SendMAPIEmail(const aTo, aCC, aBCC, aAtts: array of string; const body, subject, SenderName, SenderEmail: string;
  ShowError: Boolean = true): Integer;
var
  SM: TFNMapiSendMail;
  MAPIModule: HModule;
  Msg: MapiMessage;
  lpSender: MapiRecipDesc;
  Recips: array of MapiRecipDesc;
  Att: array of MapiFileDesc;
  p1, p2, p3, LenTo, LenCC, LenBCC, LenAtts: Integer;
  sError: String;
begin
  try
    FillChar(Msg, SizeOf(Msg), 0);
    { get the length of all arrays passed to this function }
    LenTo := length(aTo);
    if Trim(aCC[0]) <> '' then
      LenCC := length(aCC)
    else
      LenCC := 0;
    if Trim(aBCC[0]) <> '' then
      LenBCC := length(aBCC)
    else
      LenBCC := 0;
    if Trim(aAtts[0]) <> '' then
      LenAtts := length(aAtts)
    else
      LenAtts := 0;
    { ... }
    Setlength(Recips, LenTo + LenCC + LenBCC);
    Setlength(Att, LenAtts);
    { to }
    for p1 := 0 to LenTo - 1 do
    begin
      FillChar(Recips[p1], SizeOf(Recips[p1]), 0);
      Recips[p1].ulReserved := 0;
      Recips[p1].ulRecipClass := MAPI_TO;
      { Upgrade }
      Recips[p1].lpszName := pAnsichar(AnsiString(aTo[p1]));
      Recips[p1].lpszAddress := '';
    end;
    { cc }
    for p2 := 0 to LenCC - 1 do
    begin
      FillChar(Recips[p1 + p2], SizeOf(Recips[p1 + p2]), 0);
      Recips[p1 + p2].ulReserved := 0;
      Recips[p1 + p2].ulRecipClass := MAPI_CC;
      { Upgrade }
      Recips[p1 + p2].lpszName := pAnsichar(AnsiString(aCC[p2]));
      Recips[p1 + p2].lpszAddress := '';
    end;
    { bcc }
    for p3 := 0 to LenBCC - 1 do
    begin
      FillChar(Recips[p1 + p2 + p3], SizeOf(Recips[p1 + p2 + p3]), 0);
      Recips[p1 + p2 + p3].ulReserved := 0;
      Recips[p1 + p2 + p3].ulRecipClass := MAPI_BCC;
      { Upgrade }
      Recips[p1 + p2 + p3].lpszName := pAnsichar(AnsiString(aBCC[p3]));
      Recips[p1 + p2 + p3].lpszAddress := '';
    end;
    { atts }
    for p1 := 0 to LenAtts - 1 do
    begin
      FillChar(Att[p1], SizeOf(Att[p1]), 0);
      Att[p1].ulReserved := 0;
      Att[p1].flFlags := 0;
      Att[p1].nPosition := Cardinal($FFFFFFFF);
      { Upgrade }
      Att[p1].lpszPathName := pAnsichar(AnsiString(aAtts[p1]));
      Att[p1].lpszFileName := '';
      Att[p1].lpFileType := nil;
    end;
    { fill the message }
    with Msg do
    begin
      ulReserved := 0;
      if subject <> '' then
        { Upgrade }
        lpszSubject := pAnsichar(AnsiString(subject));
      if body <> '' then
        { Upgrade }
        lpszNoteText := pAnsichar(AnsiString(body));
      if SenderEmail <> '' then
      begin
        lpSender.ulRecipClass := MAPI_ORIG;
        if SenderName = '' then
          lpSender.lpszName := pAnsichar(AnsiString(SenderEmail))
        else
          lpSender.lpszName := pAnsichar(AnsiString(SenderName));
        lpSender.lpszAddress := pAnsichar(AnsiString(SenderEmail));
        lpSender.ulEIDSize := 0;
        lpSender.lpEntryID := nil;
        lpOriginator := @lpSender;
      end
      else
        Msg.lpOriginator := nil;
      Msg.lpszMessageType := nil;
      Msg.lpszDateReceived := nil;
      Msg.lpszConversationID := nil;
      Msg.flFlags := 0;
      Msg.nRecipCount := LenTo + LenCC + LenBCC;
      Msg.lpRecips := @Recips[0];
      Msg.nFileCount := LenAtts;
      Msg.lpFiles := @Att[0];
    end;
    MAPIModule := LoadLibrary(PWideChar(MAPIDLL));
    if MAPIModule = 0 then
      Result := -1
    else
      try
        @SM := GetProcAddress(MAPIModule, 'MAPISendMail');
        if @SM <> nil then
        begin
          Result := SM(0, application.Handle, Msg, { MAPI_DIALOG or } MAPI_LOGON_UI, 0);
        end
        else
          Result := 1;
      finally
        FreeLibrary(MAPIModule);
      end;
    if Result <> SUCCESS_SUCCESS then
    begin
      case Result of
        MAPI_E_ACCESS_DENIED:
          sError := 'Access denied.';
        MAPI_E_AMBIGUOUS_RECIPIENT:
          sError := 'Ambiguous recipient.';
        MAPI_E_ATTACHMENT_NOT_FOUND:
          sError := 'Attachment not found.';
        MAPI_E_ATTACHMENT_OPEN_FAILURE:
          sError := 'Attachment open failure.';
        MAPI_E_ATTACHMENT_WRITE_FAILURE:
          sError := 'Attachment write failure.';
        MAPI_E_BAD_RECIPTYPE:
          sError := 'Bad recipient type.';
        MAPI_E_DISK_FULL:
          sError := 'Disk full.';
        MAPI_E_FAILURE:
          sError := 'Failure';
        MAPI_E_INSUFFICIENT_MEMORY:
          sError := 'Insufficient Memory.';
        MAPI_E_INVALID_EDITFIELDS:
          sError := 'Invalid Editfields.';
        MAPI_E_INVALID_MESSAGE:
          sError := 'Invalid message.';
        MAPI_E_INVALID_RECIPS:
          sError := 'Invalid recipients.';
        MAPI_E_INVALID_SESSION:
          sError := 'Invalid session.';
        MAPI_E_LOGIN_FAILURE:
          sError := 'Login failure.';
        MAPI_E_MESSAGE_IN_USE:
          sError := 'Message in use.';
        MAPI_E_NETWORK_FAILURE:
          sError := 'Network failure.';
        MAPI_E_NO_MESSAGES:
          sError := 'No messages.';
        MAPI_E_NOT_SUPPORTED:
          sError := 'Not supported.';
        MAPI_E_TEXT_TOO_LARGE:
          sError := 'Text too large.';
        MAPI_E_TOO_MANY_FILES:
          sError := 'Too many files.';
        MAPI_E_TOO_MANY_RECIPIENTS:
          sError := 'Too many recipients.';
        MAPI_E_TOO_MANY_SESSIONS:
          sError := 'Too many sessions.';
        MAPI_E_TYPE_NOT_SUPPORTED:
          sError := 'Type not supported.';
        MAPI_E_UNKNOWN_RECIPIENT:
          sError := 'Unknown Recipient';
        MAPI_E_USER_ABORT:
          sError := 'User Aborted';
      end;
      if sError <> '' then
      begin
        MessageDlg('Could not send email.  ' + sError, mtInformation, [mbOk], 0);
  Exit;
      end;
    end;
  finally
  end;
end;

4. Using INDY components (TIDSMTP, TIdMessage)
Delphi provides indy component TIDSMTP to send emails from our application. We just need to put these components on our form and need to set some properties. You can find this component in Indy Clients tab and Indy Misc tab of component palate.
TIDSMTP - component is used to connect and communicate with a SMTP server
TIDMessage - component is used to store and encode Email message details like body, to, cc, bcc, and attachments.

In this example I have used GMAIL SMTP server to send mails. So please change host name to different when required.

Put following Indy components on your form. Then all the setting are done at runtime on Send button click.

// add following units to Uses clause //
Uses
  IdEMailAddress, IdGlobal, IdAttachmentFile;    
....
var
    IdSMTP1: TIdSMTP;
    IdMessage1: TIdMessage;
    IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL; // to allow SSL authenticate //
....
procedure TFormEmail.btnSendEmailClick(Sender: TObject);
var
  Attachmentfile: TIdAttachmentFile;
begin
// IO HANDLER SETTINGS //
  With IdSSLIOHandlerSocketOpenSSL1 do
  begin
    Destination := 'smtp.gmail.com:587';
    Host := 'smtp.gmail.com';
    MaxLineAction := maException;
    Port := 587;
    SSLOptions.Method := sslvTLSv1;
    SSLOptions.Mode := sslmUnassigned;
    SSLOptions.VerifyMode := [];
    SSLOptions.VerifyDepth := 0;
  end;
//SETTING SMTP COMPONENT DATA //
  IdSMTP1.Host := 'smtp.gmail.com';
  IdSMTP1.Port := 587;
  IdSMTP1.Username := yourGmailaddress@gmail.com; // please change to your gmail address //
  IdSMTP1.Password := 'yourGmailPassword';
  IdSMTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
  IdSMTP1.AuthType := satDefault;
  IdSMTP1.UseTLS := utUseExplicitTLS;
// SETTING email MESSAGE DATA //
  IdMessage1.Clear;
// add recipient list //
  with IdMessage1.Recipients.Add do
  begin
    Name := 'Recipient 1';
    Address := Recipient1@email.com; // please change email address as required //
  end;
// add CC list //
  with IdMessage1.CCList.Add do
  begin
    Name := 'CC Recipient 1';
    Address := CCRecipient1@email.com; // please change email address as required //
  end;
//add BCC list //
  with IdMessage1.BCCList.Add do
  begin
    Name := 'BCC Recipient 1';
    Address := BCCRecipient1@email.com; // please change email address as required //
  end;
//add Attachment to mail //
  Attachmentfile := TIdAttachmentFile.Create(IdMessage1.MessageParts,'C:\File1.txt');
  IdMessage1.From.Address :=  yourGmailaddress@gmail.com; // please change to your gmail address //;
  IdMessage1.Subject := 'Test Email Subject';
  IdMessage1.Body := 'Test Email Body';
  IdMessage1.Priority := mpHigh;
  TRY
    IdSMTP1.Connect();
    IdSMTP1.Send(IdMessage1);
    ShowMessage('Email sent');
    IdSMTP1.Disconnect();
  except on e:Exception do
    begin
      ShowMessage(e.Message);
      IdSMTP1.Disconnect();
    end;
  END;
  AttachmentFile.Free;
end;

Comments

  1. Thanks for the article. What version of Delphi do you use? I use Delphi 7, there is no object TIdSSLIOHandlerSocketOpenSSL, only found TIdSSLIOHandlerSocket.
    I got an error in declaration of class TIdSSLIOHandlerSocketOpenSSL when compiling the code, saying : Undeclared identifier: 'TIdSSLIOHandlerSocketOpenSSL'

    ReplyDelete
    Replies
    1. thank you worked very well on delphi 10.2 managed to find TIdSSLIOHandlerSocketOpenSSL and it sent the message, on gmail you might have to switch on Less secure app access

      Delete
  2. Contact MS Office setup with MS Office setup Assistance Experts If you want to know, how to Improve Unsaved MS Office Data? Dial Office.com/setup and update your MS Office setup to use all functions. https://office-setup.us/

    ReplyDelete
  3. Nice Information...
    Thanks for Sharing...
    The AT&T company started to provide the AT&T Email Login Service after it got partnered with the SBCGlobal company and the Yahoo company. Sometimes, the AT&T email login may also be known as the SBCGlobal email login.

    ReplyDelete
  4. Great Article, Thanks but let us know about to send an HTML (HTML body) which is consist by images. Thanks again.

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Good morning!
    Thank you very much for your article, which helped me a lot to integrate my Delphi application with OutLook, automatically generating emails.
    Hugs

    ReplyDelete

Post a Comment

Popular posts from this blog

ShellExecute in Delphi

Drawing Shapes in Delphi