7

I'm not familar with the INDY SMTP component. I want to send a mail with INDY and Office 365. Here is a nice topic which helped me a lot: What do the SMTP Indy component security and authentication properties do? But I did not figured out how to use SASL. Office365 adress is smtp.office365.com with port 587 and TLS. So I added an SMTP and an OpenSSL-IOHandler to my form and setted the properties. But I didn't work, the app is just freezing. I need to know how to use SASL with Office365.

Thanks.

Community
  • 1
  • 1
Timestop
  • 73
  • 1
  • 2
  • 8
  • SASL and TLS are completely separate and unrelated things. SASL is designed to protect user credentials that are transmitted over a connection. TLS is designed to encrypt the connection itself, regardless of what is transmitted over it. So what do you actually need help with? Using TLS to establish a socket connection to Office35, or using SASL to authenticate with Office365 after the connection is established, or both? Please be more specific. – Remy Lebeau Jul 18 '13 at 23:26
  • You did not provide the actual settings you used, or show the actual code that is using `TIdSMTP`. So there is no way to diagnose your problem. – Remy Lebeau Jul 18 '13 at 23:27
  • Thank you for your help. Yes, I need help in both. A simple SMTP code is shown here http://www.delphi-treff.de/tutorials/netzwerk-und-internet/indy/smtp-tidsmtp/ My code looks nearly the same. But I dont know how to set TLS and SASL up correctly. For TLS I added an INDY OpenSSL-IOHandler, linked it with the TIdSMTP and setted TLS as SSL Option and under "UseTLS" property utUseExplicitTLS. OpenSSL is also installed. But I don't know which SASL-Options Office365 uses and how to set it up with Indy. I will post some code. Btw. I am new and don't understand how to use the code tags... – Timestop Jul 18 '13 at 23:46
  • That tutorial example does not utilize TLS or SASL. As for your code, instead of trying to figure out which SASL to use, just enable them all (or at least the most commonly used ones - CRAM-MD5, CRAM-SHA1, NTLM, etc) and let `TIdSMTP` decide for you which SASL to use based on Office365's actual capabilities it reports when `TIdSMTP` connects to it (you must have `TIdSMTP.UseEHLO` set to True for that to work). – Remy Lebeau Jul 18 '13 at 23:50
  • When I login to Office365 using `TIdSMTP` and `TLS=utUseExplicitTLS` on port 587, it connects just fine without freezing, and the only SASL that it reports support for is `LOGIN` (`LOGIN` is not secure, but the use of TLS makes up for that). There is a momentary freeze while it tries to validate my credentials, but then it unfreezes and throws an authentication error, as expected (since I don't have an Office365 account). – Remy Lebeau Jul 18 '13 at 23:57
  • There are actually 2 ways to use the `LOGIN` SASL with `TIdSMTP`: 1) set `TIdSMTP.AuthType=satDefault` and use `TIdSMTP.Username` and `TIdSMTP.Password`, 2) set `TIdSMTP.AuthType=satSASL`, attach `TIdSASLLogin` to the `TIdSMTP.SASLMechanisms` collection, and attach a `TIdUserPassProvider` to `TIdSASLLogin`. – Remy Lebeau Jul 18 '13 at 23:59
  • I posted code examples now. – Remy Lebeau Jul 19 '13 at 00:15

1 Answers1

18

Office365 only supports the LOGIN SASL on TLS port 587.

The following code works fine for me when I just tried it (all of these settings can also be set up at design-time as well):

  1. setting the TIdSMTP.AuthType property to satDefault, which uses the SMTP AUTH LOGIN command:

    var
      idSMTP1: TIdSMTP;
    begin
      idSMTP1 := TIdSMTP.Create(nil);
      try
        idSMTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(idSMTP1);
        idSMTP1.UseTLS := utUseExplicitTLS;
        TIdSSLIOHandlerSocketOpenSSL(idSMTP1.IOHandler).SSLOptions.Method := sslvSSLv3;
    
        idSMTP1.Host := 'smtp.office365.com';
        idSMTP1.Port := 587;
    
        idSMTP1.AuthType := satDefault;
        idSMTP1.Username := ...;
        idSMTP1.Password := ...;
    
        try
          idSMTP1.Connect;
          try
            idSMTP1.Authenticate;
          finally
            idSMTP1.Disconnect;
          end;
          ShowMessage('OK');
        except
          on E: Exception do
          begin
            ShowMessage(Format('Failed!'#13'[%s] %s', [E.ClassName, E.Message]));
            raise;
          end;
        end;
      finally
        idSMTP1.Free;
      end;
    
  2. setting the TIdSMTP.AuthType property to satSASL and using TIdSASLLogin, which uses the same SMTP AUTH LOGIN command:

    var
      idSMTP1: TIdSMTP;
      idSASLLogin: TIdSASLLogin;
      idUserPassProvider: TIdUserPassProvider;
    begin
      idSMTP1 := TIdSMTP.Create(nil);
      try
        idSMTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(idSMTP1);
        idSMTP1.UseTLS := utUseExplicitTLS;
        TIdSSLIOHandlerSocketOpenSSL(idSMTP1.IOHandler).SSLOptions.Method := sslvSSLv3;
    
        idSMTP1.Host := 'smtp.office365.com';
        idSMTP1.Port := 587;
    
        idSASLLogin := TIdSASLLogin.Create(idSMTP1);
        idUserPassProvider := TIdUserPassProvider.Create(idSASLLogin);
    
        idSASLLogin.UserPassProvider := idUserPassProvider;
        idUserPassProvider.Username := ...;
        idUserPassProvider.Password := ...;
    
        idSMTP1.AuthType := satSASL;
        idSMTP1.SASLMechanisms.Add.SASL := idSASLLogin;
    
        try
          idSMTP1.Connect;
          try
            idSMTP1.Authenticate;
          finally
            idSMTP1.Disconnect;
          end;
          ShowMessage('OK');
        except
          on E: Exception do
          begin
            ShowMessage(Format('Failed!'#13'[%s] %s', [E.ClassName, E.Message]));
            raise;
          end;
        end;
      finally
        idSMTP1.Free;
      end;
    

Update: Office365 no longer supports SSL v3, you must use TLS v1.x now:

(idSMTP1.IOHandler).SSLOptions.Method := sslvTLSv1;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks :) Now i figured it out. I forgot the PassProvider. But now it wokrs. Thanks. This will solve future problems with other providers. – Timestop Jul 19 '13 at 00:36
  • Hi @Remy I'm unfortunately getting the following error using the above code: **EIdOSSLConnectError** `'Error connecting with SSL. EOF was observed that violates the protocol'` The exception is raised on the `idSMTP1.Authenticate;` line. This is then followed by this exception: **EIdTLSClientTLSHandShakeFailed** `'SSL negotiation failed.'` Any help would be greatly appreciated. – jamesmstone Mar 24 '16 at 04:17
  • You must have the `UseTLS` property set to `utUseExplicitTLS`. That causes `Authenticate()` to send a `STARTTLS` command to encrypt the connection before sending the authentication credentials (common for port 587). The error means the server is accepting the `STARTTLS` command but is then disconnecting the socket connection during the SSL/TLS handshake before it completes. The server probably doesn't like how you have configured OpenSSL. Maybe it doesn't like the protocol version(s) selected, or the certificate/validation settings. Hard to say without seeing the actual handshake. – Remy Lebeau Mar 24 '16 at 05:33
  • This answer is correct, but at the time of commenting (2016-08) Office365 had changed requirements. The modifications needed to make this run now can be found in the answer to my question here: http://stackoverflow.com/questions/38740921/cannot-use-secure-smtp-connection-to-office365-with-delphi-2010-and-indy-10-5-5 – Larry Lustig Aug 03 '16 at 21:42