Recent

Author Topic: Written to help others : SMTP Authentication with SSL with Synapse  (Read 15975 times)

Gizmo

  • Hero Member
  • *****
  • Posts: 831
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.
« Last Edit: February 01, 2015, 01:11:30 am by Gizmo »

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #1 on: February 01, 2015, 02:55:19 am »
 :D
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  ;D 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.
« Last Edit: February 01, 2015, 02:59:07 am by skalogryz »

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #2 on: February 01, 2015, 06:18:42 am »
...but for gmail... I guess it would consider anything "lesssecure" unless XOAUTH2 authentication is used

Gizmo

  • Hero Member
  • *****
  • Posts: 831
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #3 on: February 01, 2015, 04:34:34 pm »
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

  • Sr. Member
  • ****
  • Posts: 268
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #4 on: February 09, 2015, 07:30:02 pm »
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

  • Jr. Member
  • **
  • Posts: 99
    • Krzynio's home page
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #5 on: September 09, 2020, 02:12:28 pm »
Hi! I usually start reading manuals from looking for examples. So, your job is really great and helpful. Thank you very much.  :D
Ubuntu 23.10 x64, / Windows 11 PL - latest updates
Lazarus 2.2.6, FPC 3.2.2

geraldholdsworth

  • Full Member
  • ***
  • Posts: 195
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #6 on: October 29, 2023, 05:36:10 pm »
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][+][-]
  1. unit Emails;
  2.  
  3. {$mode ObjFPC}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.  Classes,SysUtils,smtpsend,synautil,ssl_openssl,mimemess,mimepart,synachar;
  9.  
  10. function SendEmail(LFrom,LTo,LSubject: String;LContent: TStrings;
  11.                    LServer,LPort,LUsername,LPassword: String;
  12.                    UseSSL: Boolean;LAttachments: TStrings): String;
  13. function TestServer(LServer,LPort,LUsername,LPassword: String;
  14.                     UseSSL: Boolean):Boolean;
  15.  
  16. implementation
  17.  
  18. function TestServer(LServer,LPort,LUsername,LPassword: String;
  19.                     UseSSL: Boolean):Boolean;
  20. var
  21.  SMTP      : TSMTPSend;
  22. begin
  23.  Result:=False;
  24.  if LServer<>'' then
  25.  begin
  26.   //Create the sender
  27.   SMTP:=TSMTPSend.Create;
  28.   try
  29.    //TLS Automatic
  30.    SMTP.AutoTLS:=True;
  31.    //Use SSL if box is ticked
  32.    SMTP.FullSSL:=UseSSL;
  33.    //SMTP Server details
  34.    SMTP.TargetHost:=LServer;
  35.    if LPort<>'' then SMTP.TargetPort:=LPort;
  36.    //Authentication
  37.    SMTP.Username:=LUsername;
  38.    SMTP.Password:=LPassword;
  39.    //Can we log in?
  40.    Result:=SMTP.Login;
  41.    //Log out of the server
  42.    SMTP.Logout;
  43.   finally
  44.    //Free up the control
  45.    SMTP.Free;
  46.   end;
  47.  end;
  48. end;
  49.  
  50. function SendEmail(LFrom,LTo,LSubject: String;LContent: TStrings;
  51.                    LServer,LPort,LUsername,LPassword: String;
  52.                    UseSSL: Boolean;LAttachments: TStrings): String;
  53. var
  54.  OK        : Boolean;
  55.  LError,
  56.  s,t       : String;
  57.  LMessage  : TStrings;
  58.  SMTP      : TSMTPSend;
  59.  Mime      : TMimeMess;
  60.  P         : TMimePart;
  61. const
  62.  XMailer = 'Emailer by Gerald J Holdsworth';
  63. begin
  64.  if LServer<>'' then
  65.  begin
  66.   LMessage:=TStringList.Create;
  67.   //Build the message header
  68.   if LAttachments.Count=0 then
  69.   begin
  70.   LMessage.Assign(LContent);
  71.   LMessage.Insert(0,'');
  72.   LMessage.Insert(0,'X-mailer: '+XMailer);
  73.   LMessage.Insert(0,'Subject: '+LSubject);
  74.   LMessage.Insert(0,'Date: '+Rfc822DateTime(now));
  75.   LMessage.Insert(0,'To: '+LTo);
  76.   LMessage.Insert(0,'From: '+LFrom);
  77.   end
  78.   //Add any attachments
  79.   else
  80.   begin
  81.    Mime:=TMimeMess.Create;
  82.    //Build a header
  83.    Mime.Header.CharsetCode:=UTF_8;
  84.    Mime.Header.ToList.Text:=LTo;
  85.    Mime.Header.Subject:=LSubject;
  86.    Mime.Header.From:=LFrom;
  87.    // Create a MultiPart part
  88.    P:=Mime.AddPartMultipart('mixed',Nil);
  89.    // Add as first part the mail text
  90.    Mime.AddPartTextEx(LContent,P,UTF_8,True,ME_8BIT);
  91.    // Add all attachments:
  92.    for s in LAttachments do Mime.AddPartBinaryFromFile(s,P);
  93.    // Compose message
  94.    Mime.EncodeMessage;
  95.    //Copy across to the main message body
  96.    LMessage.Assign(Mime.Lines);
  97.    //Free up the MIME message
  98.    Mime.Free;
  99.   end;
  100.   //Set the flag
  101.   OK:=False;
  102.   //Default error message
  103.   LError:='';
  104.   //Create the sender
  105.   SMTP:=TSMTPSend.Create;
  106.   try
  107.    //TLS Automatic
  108.    SMTP.AutoTLS:=True;
  109.    //Use SSL if box is ticked
  110.    SMTP.FullSSL:=UseSSL;
  111.    //SMTP Server details
  112.    SMTP.TargetHost:=LServer;
  113.    if LPort<>'' then SMTP.TargetPort:=LPort;
  114.    //Authentication
  115.    SMTP.Username:=LUsername;
  116.    SMTP.Password:=LPassword;
  117.    //Can we log in?
  118.    if SMTP.Login then
  119.    begin
  120.     //Set the 'From:' field
  121.     if SMTP.MailFrom(GetEmailAddr(LFrom),Length(LMessage.Text))then
  122.     begin
  123.      //Now split the 'To:' file into separate addresses
  124.      s:=LTo;
  125.      repeat
  126.       t:=GetEmailAddr(Trim(FetchEx(s,',','"')));//A comma separates the addresses
  127.       if t<>'' then OK:=SMTP.MailTo(t);
  128.       if not OK then Break; //Break out of the loop with an invalid address
  129.      until s='';
  130.      //All senders OK? Then continue
  131.      if OK then
  132.      begin
  133.       //Now send the message
  134.       OK:=SMTP.MailData(LMessage);
  135.       //Failed? Get the error
  136.       if not OK then LError:=SMTP.ResultString;
  137.      end else LError:='Invalid To Address(es)';
  138.     end else LError:='Invalid From address';
  139.     //Log out of the server
  140.     SMTP.Logout;
  141.    end else LError:='Login failure'; //Report a login failure
  142.   finally
  143.    //Free up the control
  144.    SMTP.Free;
  145.   end;
  146.   //And the message container
  147.   LMessage.Free;
  148.   //Report back to the user the result
  149.   if OK then Result:='Email sent OK'
  150.         else Result:='Email not sent: '+LError;
  151.  end else Result:='No SMTP server provided';
  152. end;
  153.  
  154. end.
  155.  

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

  • Full Member
  • ***
  • Posts: 108
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #7 on: November 13, 2023, 01:29:33 pm »

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][+][-]
  1.   showmessage(emails.SendEmail(mailFrom ,MailTo,  'Subject',
  2.                                Bodytxt,'smtp.gmail.com','587',
  3.                                username ,pass , True, FileAttach));
  4.   showmessage(emails.SendEmail(mailFrom ,MailTo,  'Subject',
  5.                                Bodytxt,'smtp.gmail.com','995',
  6.                                username ,pass , True, FileAttach));
  7.   showmessage(emails.SendEmail(mailFrom ,MailTo,'Subjectς',
  8.                                Bodytxt, 'smtp.gmail.com:587', '587',
  9.                                username , pass ,  True, FileAttach));
  10.   showmessage(emails.SendEmail(mailFrom ,MailTo,'Subject',
  11.                                Bodytxt, 'smtp.gmail.com:995', '995',
  12.                                username , pass ,  True, FileAttach));
  13.  
  14.  

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?
windows 10 64

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #8 on: November 13, 2023, 01:37:36 pm »
Email 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

  • Full Member
  • ***
  • Posts: 108
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #9 on: November 13, 2023, 01:45:05 pm »
Thanks. I tried to sign in with the password of your Google account. I will create a password on the Google account.
windows 10 64

magleft

  • Full Member
  • ***
  • Posts: 108
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #10 on: November 17, 2023, 06:59:29 pm »
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][+][-]
  1.   showmessage(SendEmail(mailFrom ,MailTo, mailSubject, Bodytxt,
  2.                                outmailserver,mailport, username ,pass ,
  3.                                False, FileAttach));
  4.  
windows 10 64

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #11 on: November 17, 2023, 07:30:23 pm »
When 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

  • Full Member
  • ***
  • Posts: 108
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #12 on: November 18, 2023, 05:03:21 pm »
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?
windows 10 64

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: Written to help others : SMTP Authentication with SSL with Synapse
« Reply #13 on: November 19, 2023, 08:57:54 am »
Do 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

 

TinyPortal © 2005-2018