Recent

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

Gizmo

  • Hero Member
  • *****
  • Posts: 714
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 »
Lazarus 2.0.4 and fpc 3.0.4 - Linux Mint 19 LTS, Windows 10 64 and Mac OSX Catlina
Useful Page to remember : http://wiki.freepascal.org/Cross_compiling#From_Linux_x64_to_Linux_i386

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2519
    • 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 »
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2519
    • 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
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

Gizmo

  • Hero Member
  • *****
  • Posts: 714
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.
Lazarus 2.0.4 and fpc 3.0.4 - Linux Mint 19 LTS, Windows 10 64 and Mac OSX Catlina
Useful Page to remember : http://wiki.freepascal.org/Cross_compiling#From_Linux_x64_to_Linux_i386

jack616

  • Sr. Member
  • ****
  • Posts: 266
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: 81
    • 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
Debian Testing x64 with XFCE 4.14 - Lazarus trunk, FPC 3.0.4
Windows 10 x64 - Lazarus 2.0.10, FPC 3.2.0

 

TinyPortal © 2005-2018