System.Net.Mail unable to Authenticate against some third party SMTP Servers

I recently ran into an issue where one of my customer was unable to send mail using System.Net.Mail(.Net 2.0), we always got the "Authentication failed" error.

We tried sending mail using Microsoft CDO for Windows 2000 Library(Cdosys) and System.Web.Mail and the mails went just fine. if Cdosys works System.Web.Mail(SWM) would normally work because SWM is essentially a wrapper over Cdosys. How can you send mails using Cdosys? Click here

Why is one API able to send mail and the other fails? We enabled Network Tracing in our .net code and below is what the logs show:

 System.Net.Sockets Verbose: 0 : [7240] 00000000 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : 220 mail.XYZYZYZ
System.Net.Sockets Verbose: 0 : [7240] 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : XYZXYZZ.com ESMT
System.Net.Sockets Verbose: 0 : [7240] 00000020 : 00 00 00 00 00 00 00 00 00 00 00 00 00       : P Gday mate..
System.Net.Sockets Verbose: 0 : [7240] Exiting Socket#32176063::Receive()        -> 45#45
System.Net.Sockets Verbose: 0 : [7240] Socket#32176063::Send()
System.Net.Sockets Verbose: 0 : [7240] Data from Socket#32176063::Send
System.Net.Sockets Verbose: 0 : [7240] 00000000 : 45 48 4C 4F 20 41 4B 41-53 48 42 0D 0A          : EHLO AKASHB..
System.Net.Sockets Verbose: 0 : [7240] Exiting Socket#32176063::Send()             -> 13#13
System.Net.Sockets Verbose: 0 : [7240] Socket#32176063::Receive()
System.Net.Sockets Verbose: 0 : [7240] Data from Socket#32176063::Receive
System.Net.Sockets Verbose: 0 : [7240] 00000000 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : 250-mail.XYZYZYZ
System.Net.Sockets Verbose: 0 : [7240] 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : XYZXYZZ.com..250
System.Net.Sockets Verbose: 0 : [7240] 00000020 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : -PIPELINING..250
System.Net.Sockets Verbose: 0 : [7240] 00000030 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : -SIZE 20971520..
System.Net.Sockets Verbose: 0 : [7240] 00000040 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : 250-VRFY..250-ET
System.Net.Sockets Verbose: 0 : [7240] 00000050 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : RN..250-AUTH PLA
System.Net.Sockets Verbose: 0 : [7240] 00000060 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : IN LOGIN..250-EN
System.Net.Sockets Verbose: 0 : [7240] 00000070 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : HANCEDSTATUSCODE
System.Net.Sockets Verbose: 0 : [7240] 00000080 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : S..250-8BITMIME.
System.Net.Sockets Verbose: 0 : [7240] 00000090 : 00 00 00 00 00 00 00 00-00 00                   : .250 DSN..
System.Net.Sockets Verbose: 0 : [7240] Exiting Socket#32176063::Receive()        -> 154#154
System.Net Verbose: 0 : [7240] SmtpLoginAuthenticationModule#61150033::Authenticate()
System.Net Verbose: 0 : [7240] Exiting SmtpLoginAuthenticationModule#61150033::Authenticate() 
System.Net.Sockets Verbose: 0 : [7240] Socket#32176063::Send()
System.Net.Sockets Verbose: 0 : [7240] Data from Socket#32176063::Send
System.Net.Sockets Verbose: 0 : [7240] 00000000 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : AUTH login Y2222
System.Net.Sockets Verbose: 0 : [7240] 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : Wwwwwwwwwwwwwwww
System.Net.Sockets Verbose: 0 : [7240] 00000020 : 00 00 00 00 00 00 00 00 00 00 00 00 00          : mmmmmmmmmmm..
System.Net.Sockets Verbose: 0 : [7240] Exiting Socket#32176063::Send()             -> 45#45
System.Net.Sockets Verbose: 0 : [7240] Socket#32176063::Receive()
System.Net.Sockets Verbose: 0 : [7240] Data from Socket#32176063::Receive
System.Net.Sockets Verbose: 0 : [7240] 00000000 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : 334 VXNlcm5hbWU6
System.Net.Sockets Verbose: 0 : [7240] 00000010 : 0D 0A                                           : ..
System.Net.Sockets Verbose: 0 : [7240] Exiting Socket#32176063::Receive()        -> 18#18
System.Net Verbose: 0 : [7240] SmtpLoginAuthenticationModule#61150033::Authenticate()
System.Net Verbose: 0 : [7240] Exiting SmtpLoginAuthenticationModule#61150033::Authenticate() 
System.Net.Sockets Verbose: 0 : [7240] Socket#32176063::Send()
System.Net.Sockets Verbose: 0 : [7240] Data from Socket#32176063::Send
System.Net.Sockets Verbose: 0 : [7240] 00000000 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : xxxxxxxxxxxxxxxx=
System.Net.Sockets Verbose: 0 : [7240] 00000010 : 0D 0A                                           : ..
System.Net.Sockets Verbose: 0 : [7240] Exiting Socket#32176063::Send()             -> 18#18
System.Net.Sockets Verbose: 0 : [7240] Socket#32176063::Receive()
System.Net.Sockets Verbose: 0 : [7240] Data from Socket#32176063::Receive
System.Net.Sockets Verbose: 0 : [7240] 00000000 : 33 33 34 20 55 47 46 7A-63 33 64 76 63 6D 51 36 : 334 UGFzc3dvcmQ6
System.Net.Sockets Verbose: 0 : [7240] 00000010 : 0D 0A                                           : ..
System.Net.Sockets Verbose: 0 : [7240] Exiting Socket#32176063::Receive()        -> 18#18
System.Net Verbose: 0 : [7240] SmtpLoginAuthenticationModule#61150033::Authenticate()
System.Net Verbose: 0 : [7240] Exiting SmtpLoginAuthenticationModule#61150033::Authenticate() 
System.Net Error: 0 : [7240] Exception in the SmtpClient#3888474::Send - Authentication failed. 

Note:Data in the logs has been altered to hide confidential information

To request LOGIN authentication, the client issues the AUTH command with the parameter LOGIN and the user name to be used for authentication, base64-encoded as specified in [RFC4648]. For example, if the client's user name was "Charlie", then the client would initiate AUTH LOGIN as follows (AUTH_LOGIN_COMMAND_USER):

AUTH LOGIN Q2hhcmxpZQ==<CR><LF>

If AUTH LOGIN is not supported, then the server should responds with a 504 error Message as specified in [RFC4954] section 4. If AUTH LOGIN is supported on the server, then the server responds with the AUTH_LOGIN_Password_Challenge:

334 UGFzc3dvcmQ6<CR><LF>

The client then responds with the password to be used for authentication, base64-encoded as specified in [RFC4648]. For example, if the client's password was "password", then client would respond with the following Login_Password_Response:

cGFzc3dvcmQ=<CR><LF>

If the authentication is successful, then the server issues a LOGIN_Succeeded_Response or a LOGIN_Failed_Response, corresponding to a 235 reply for success or a 535 reply for a failure [RFC4954].

In this case, even though the user name is passed with the AUTH LOGIN the server responds with the AUTH_LOGIN_Username_Challenge again:

334 VXNlcm5hbWU6<CR><LF>

Now since the client has already sent the user name, it instead of sending the user name, sends the password. The server then responds with the AUTH_LOGIN_Password_Challenge:

334 UGFzc3dvcmQ6<CR><LF>

The client then sends nothing and the Authentication fails! We can clearly see that the SMTP server is not respecting the user name sent with the AUTH LOGIN command. It is optional for the client to send the user name([initial-response]) with the AUTH LOGIN command, if sent the SMTP server should respect it. More details about the SMTP Service Extension for Authentication can be found in the [RFC4954].

Why did Cdosys and SWM work? Both the API’s do not send the user name along with the AUTH LOGIN and therefore everything works fine.

Is there a way we can change this behaviour of System.Net.Mail i.e. not send the user name along with the AUTH LOGIN? No.

What are the alternatives?

1)Use CDOSYS (Does not send the User Name with the AUTH Login)

2)Use System.Web.Mail (Does not send the User Name with the AUTH Login)

3)Contact the SMTP Server owner and have them fix the server.

Enjoy!