Written to help others : SMTP Authentication with SSL with Synapse lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- Gizmo · 2015-02-01 00:04 I'm posting this merely in the hope it will save others the days (literally, days) of hair loss and frustration that I have endured. Situation : The simple need to send e-mails with attachments to SMTP Authenticated mail server that requires TLS\SSL with freepascal. All of the entries I found in this forum, Stackoverflow, and many of the Delphi related articles fail to mention a significant point. The need to have Synpase is a given. And adding that to Lazarus is not difficult. Even creating a basic "send e-mail as text" is also not difficult and a superb example is given here that uses the SendMail function : http://wiki.freepascal.org/Synapse#Sending_email There's also a great example of sending e-mail with attachments to "less fussy" SMTP servers here:  https://stackoverflow.com/questions/6765008/send-an-email-with- attachment-client-agnostic Ensure you add in your uses SMTPSend, MIMEPart, MIMEMess (SMTPSend being part of Synapse). However, what not one article said that I eventually worked out this evening after literally 3 days of debugging, is the function 'SendToRaw' in the unit SMTPSend (Synapse). Around the line 665 are a series of commented out lines, which, in this day and age should be enabled by default rather than disabled, as nearly every server requires authentication. Anyway, the lines are these : Code: [Select]begin   Result := False;   SMTP := TSMTPSend.Create;   try // if you need SOCKS5 support, uncomment next lines:     // SMTP.Sock.SocksIP := '127.0.0.1';     // SMTP.Sock.SocksPort := '1080'; // if you need support for upgrade session to TSL/SSL, uncomment next lines:     // SMTP.AutoTLS := True; // if you need support for TSL/SSL tunnel, uncomment next lines:    //  SMTP.FullSSL := True;    <-- THIS IS WHAT YOU MUST UNCOMMENT for GMAIL!!!!     SMTP.TargetHost := Trim(SeparateLeft(SMTPHost, ':')); ... So after adjustment, it should be : Code: [Select]begin   Result := False;   SMTP := TSMTPSend.Create;   try // if you need SOCKS5 support, uncomment next lines:     // SMTP.Sock.SocksIP := '127.0.0.1';     // SMTP.Sock.SocksPort := '1080'; // if you need support for upgrade session to TSL/SSL, uncomment next lines:     // SMTP.AutoTLS := True; // if you need support for TSL/SSL tunnel, uncomment next lines:     SMTP.FullSSL := True;      SMTP.TargetHost := Trim(SeparateLeft(SMTPHost, ':')); ... Once that code is enabled, SendToRaw will pass the appropriate SSL encryption stuff to GMail. The only last thing to do is ensure that in your calling routine, you add the port 465 to your SMTP Host string. e.g. 'smtp.gmail.com:465' instead of 'smtp.gmail.com', because, again, the SendToRaw function parses the string value, looks for the ':' and then converts the string representation of the number to an integer. If you do that with the example linked to above that incorporates MIMEness and attachments, or by using the example that I found here (SendAttach : http://forum.lazarus.freepascal.org/index.php?topic=23030.10;wap2) the mail will be sent. Below I have pasted the SendAttach and usage routines that now work for me, having uncommented that line in SendToRaw e.g. Code: [Select]function SendAttach(const MailFrom, MailTo, Subject, SMTPHost: string;   const MailData: TStrings; const Username, Password, AttachFile: string): Boolean; var   m:TMimemess;   l:tstringlist;   p: TMimepart; begin   m:=TMimemess.create;   l:=tstringlist.create;   try     SendToRaw('youraddress@somewhere.com',               'You@somewhere.com',               'your.smtp.server.com',               m.lines,               'yourusername',               'yourpassword',               'TargetPort');     p := m.AddPartMultipart('mixed', nil);     l.loadfromfile(AttachFile);     m.AddPartText(l,p);     m.AddPartBinaryFromFile(AttachFile,p);     m.header.from:=MailFrom;     m.header.tolist.add(MailTo);     m.header.subject:=Subject;     m.EncodeMessage;     Result := SendToRaw(MailFrom, MailTo, SMTPHost, m.lines, Username, Password);     if Result then ShowMessage('sent OK');   finally     m.free;     l.free;   end; end;                  Usage: Code: [Select] SendAttach('SendersAddress@gmail.com', 'TOAddress@yahoo.co.uk', 'Subject', 'smtp.gmail.com:465', slTextData,             'GMailUsername@gmail.com', 'GMailPassword', FilenameOfAttachment);      I really hope that helps someone out. Because what I have written is what I spent days searching for. I even went to the lengths of also installed XMailer, Indy and everything. And all I had to do was uncomment two lines in one of the library files. I would update the Wiki (http://wiki.freepascal.org/Synapse#Sending_attachments), but do not have an account. It would be helpful, I think, if someone with an account could update it. ---------------------------------------------------------------------- skalogryz · 2015-02-01 01:55 indeed, the problem of sending an email over secured servers seems to go round and round these days. And the only problem is because people are not reading docs and specs carefully enough  Note, that port parsing is explained there. Also, google suggests that it should be possible to connect using TSL only (port 587, autoTSL=true), rather than going full SSL (port 465) I'd recommend to use the lowest-approach possible, as shown here with allocating TSMTPSend object, rather than using wrapper functions for the best learning experience. Btw, the example shown above fails on MS outlook-365 servers (with "HELO should be sent first" error). The code need to be fixed, by setting autoTSL to true (before .login()) , instead of calling startTSL() explicitly) oddly enough. I've had to write a small equivalent of mailsend today. Synapse based, worked fine... anyone interested in seeing the code? So I'll stop using mailsend completely. ---------------------------------------------------------------------- skalogryz · 2015-02-01 05:18 ...but for gmail... I guess it would consider anything "lesssecure" unless XOAUTH2 authentication is used ---------------------------------------------------------------------- Gizmo · 2015-02-01 15:34 It's true - if I'd read the docs a bit more carefully I'd have worked it out, but it's the usual thing of hindsight being a wonderful thing. At the time I was struggling to work out quite how the library worked. I'm not all that use to modifying the routines of libraries, as they usually provide options by way of the parameters and I wrongly assumed, initially, that if a port like 465 was specified it would automatically trigger the appropriate SSL socket. Anyway, the links you have provided in addition to the sample code above will hopefully be helpful to others. ---------------------------------------------------------------------- jack616 · 2015-02-09 18:30 Would this issue have any bearing on a longstanding problem I'm having sending mail with a linux "mail" command  - google accepts the mail but it never gets delivered. Obviously I've done all the IP and domain checks - I'm not blocked anywahere and the server IP address has always been clean. I can only think I need something in the header - out of desperation I have dkim running and also amavisd-new scans the mail before sending. I can't find anything anywhere that tells me what google actually needs in an email header to forward it to the recipient. (If anyone has a link or info please let me know!) Would this SSL issue be part of the problem - I'm not sure if standard linux smtp would do this? everything else works fine and mail is delivered anywhere google doesnt get in the path so I'm thinking it may be a gmail issue like this one? jack ---------------------------------------------------------------------- krzynio · 2020-09-09 12:12 Hi! I usually start reading manuals from looking for examples. So, your job is really great and helpful. Thank you very much. ---------------------------------------------------------------------- geraldholdsworth · 2023-10-29 16:36 This never really helped me as I had already found that line. I am also reticent to modify existing libraries, so I copied the SendAsEx function, and merged it with the SendAs to create my own email sending function. This failed with SSL connections, until I delved deeper and found that I needed to include 'ssl_openssl' in the uses clause. This worked for me. So, my complete code, with the code to attach files, which others may find useful, is: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Emails; {$mode ObjFPC}{$H+} interface uses Classes,SysUtils,smtpsend,s ynautil,ssl_openssl,mimemess,mimepart,synachar; function SendEmail(LFrom,LTo,LSubject: String;LContent: TStrings;                 LServer,LPort,LUsername,LPassword: String;                   UseSSL: Boolean;LAttachments: TStrings): String;function TestServer(LServer,LPort,LUsername,LPassword: String;                  UseSSL: Boolean):Boolean; implementation function TestServer(LServer,LPort,LUsername,LPassword: String;                  UseSSL: Boolean):Boolean;var SMTP      : TSMTPSend;begin Result:=False; if LServer<>'' then begin  //Create the sender  SMTP:=TSMTPSend.Create;  try   //TLS Automatic   SMTP.AutoTLS:=True;   //Use SSL if box is ticked   SMTP.FullSSL:=UseSSL;   //SMTP Server details   SMTP.TargetHost:=LServer;   if LPort<>'' then SMTP.TargetPort:=LPort;   //Authentication   SMTP.Username:=LUsername;   SMTP.Password:=LPassword;   //Can we log in?   Result:=SMTP.Login;   //Log out of the server   SMTP.Logout;  finally   //Free up the control   SMTP.Free;  end; end;end; function SendEmail(LFrom,LTo,LSubject: String;LContent: TStrings;                 LServer,LPort,LUsername,LPassword: String;                   UseSSL: Boolean;LAttachments: TStrings): String;var OK        : Boolean; LError, s,t       : String; LMessage  : TStrings; SMTP      : TSMTPSend; Mime      : TMimeMess; P         : TMimePart;const XMailer = 'Emailer by Gerald J Holdsworth';begin if LServer<>'' then begin  LMessage:=TStringList.Create;  //Build the message header  if LAttachments.Count=0 then  begin  LMessage.Assign(LContent);  LMessage.Insert(0,'');  LMessage.Insert(0,'X-mailer: '+XMailer);  LMessage.Insert(0,'Subject: '+LSubject);  LMessage.Insert(0,'Date: '+Rfc822DateTime(now));  LMessage.Insert(0,'To: '+LTo);  LMessage.Insert(0,'From: '+LFrom);  end  //Add any attachments  else  begin   Mime:=TMimeMess.Create;   //Build a header   Mime.Header.CharsetCode:=UTF_8;   Mime.Header.ToList.Text:=LTo;   Mime.Header.Subject:=LSubject;   Mime.Header.From:=LFrom;   // Create a MultiPart part   P:=Mime.AddPartMultipart('mixed',Nil);   // Add as first part the mail text   Mime.AddPartTextEx(LContent,P,UTF_8,True,ME_8BIT);   // Add all attachments:   for s in LAttachments do Mime.AddPartBinaryFromFile(s,P);   // Compose message   Mime.EncodeMessage;   //Copy across to the main message body   LMessage.Assign(Mime.Lines);   //Free up the MIME message   Mime.Free;  end;  //Set the flag  OK:=False;  //Default error message  LError:='';  //Create the sender  SMTP:=TSMTPSend.Create;  try   //TLS Automatic   SMTP.AutoTLS:=True;   //Use SSL if box is ticked   SMTP.FullSSL:=UseSSL;   //SMTP Server details   SMTP.TargetHost:=LServer;   if LPort<>'' then SMTP.TargetPort:=LPort;   //Authentication   SMTP.Username:=LUsername;   SMTP.Password:=LPassword;   //Can we log in?   if SMTP.Login then   begin    //Set the 'From:' field    if SMTP.MailFrom(GetEmailAddr(LFrom),Length(LMessage.Text))then    begin     //Now split the 'To:' file into separate addresses     s:=LTo;     repeat      t:=GetEmailAddr(Trim(FetchEx(s,',','"')));//A comma separates the addresses      if t<>'' then OK:=SMTP.MailTo(t);      if not OK then Break; //Break out of the loop with an invalid address     until s='';     //All senders OK? Then continue     if OK then     begin      //Now send the message      OK:=SMTP.MailData(LMessage);    //Failed? Get the error      if not OK then LError:=SMTP.ResultString;     end else LError:='Invalid To Address(es)';    end else LError:='Invalid From address';    //Log out of the server    SMTP.Logout;   end else LError:='Login failure'; //Report a login failure  finally   //Free up the control   SMTP.Free;  end;  //And the message container  LMessage.Free;  //Report back to the user the result  if OK then Result:='Email sent OK'        else Result:='Email not sent: '+LError; end else Result:='No SMTP server provided';end; end.  I found it useful to have a function to test the server before sending an email (e.g., for putting in the server details on another form and having a simple "test" button). ---------------------------------------------------------------------- magleft · 2023-11-13 12:29 Although I have checked the username and password, I am unable to send a message via gmail. I have also set up gmail to send messages from other apps. I tried various things Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   showmessage(emails.SendEmail(mailFrom ,MailTo,  'Subject',                             Bodytxt,'smtp.gmail.com','587',                             username ,pass , True, FileAttach));  showmessage(emails.SendEmail(mailFrom ,MailTo,  'Subject',                             Bodytxt,'smtp.gmail.com','995',                             username ,pass , True, FileAttach));  showmessage(emails.SendEmail(mailFrom ,MailTo,'Subjectς',                             Bodytxt, 'smtp.gmail.com:587', '587',                             username , pass ,  True, FileAttach));  showmessage(emails.SendEmail(mailFrom ,MailTo,'Subject',                             Bodytxt, 'smtp.gmail.com:995', '995',                             username , pass ,  True, FileAttach));   The message I get is: Email not sent: Login failure I also tried, also without success, to send a message using the example given by synapse . Is there a parameter or setting needed to be able to send gmail messages? What am I doing wrong? ---------------------------------------------------------------------- rvk · 2023-11-13 12:37 Quote from: magleft on November 13, 2023, 01:29:33 pmEmail not sent: Login failure What password are you using?? The password of your Google account or did you create a special App Password? Google doesn't allow your normal password anymore for gMail in combination with software. You need to use an app password (which you can create in your Google account). ---------------------------------------------------------------------- magleft · 2023-11-13 12:45 Thanks. I tried to sign in with the password of your Google account. I will create a password on the Google account. ---------------------------------------------------------------------- magleft · 2023-11-17 17:59 Hello. When I put the password from the google account in windows it worked perfectly. When trying to send a message from my android device, it gave me an error message that failed to connect to the account. What could be wrong? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   showmessage(SendEmail(mailFrom ,MailTo, mailSubject, Bodytxt,                             outmailserver,mailport, username ,pass ,                             False, FileAttach)); ---------------------------------------------------------------------- rvk · 2023-11-17 18:30 Quote from: magleft on November 17, 2023, 06:59:29 pmWhen I put the password from the google account in windows it worked perfectly. In your own app on Windows with sendemail()? Did you use the app password? Does your Android app have openssl or equivalent installed? ---------------------------------------------------------------------- magleft · 2023-11-18 16:03 On Windows work perfect. Send emails with attachment . On Android i have create app password. Do you have any suggestion to install openssl or similar? ---------------------------------------------------------------------- rvk · 2023-11-19 07:57 Quote from: magleft on November 18, 2023, 05:03:21 pmDo you have any suggestion to install openssl or similar? No, I don't have experience with FPC on Android. You could look here https://forum.lazarus.freepascal.org/index.php?topic=46830.0 ---------------------------------------------------------------------- PBO · 2026-01-09 14:10 Thank you for this information, Phew!