Using INDY 10 SMTP with Office365
Asked Answered
A

1

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.

Anh answered 18/7, 2013 at 21:39 Comment(7)
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.Milkman
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.Milkman
Thank you for your help. Yes, I need help in both. A simple SMTP code is shown here delphi-treff.de/tutorials/netzwerk-und-internet/indy/… 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...Anh
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).Milkman
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).Milkman
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.Milkman
I posted code examples now.Milkman
M
19

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;
Milkman answered 19/7, 2013 at 0:9 Comment(4)
Thanks :) Now i figured it out. I forgot the PassProvider. But now it wokrs. Thanks. This will solve future problems with other providers.Anh
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.Castoff
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.Milkman
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: #38741421Rackety

© 2022 - 2024 — McMap. All rights reserved.