Troubleshooting “The server committed a protocol violation” when sending mail with SmtpClient

白昼怎懂夜的黑 提交于 2019-12-05 07:06:13
Mark Booth

This looks to me like SmtpClient authentication is somehow getting out of step.

Some authentication mechanisms are "Client: request auth with username and password, Server: success/fail" others are "Client: request auth with username, Server: request password, Client: reply with password, Server: success/fail".

It looks like SmtpClient is expecting the former, while your server is expecting the latter.

As dave wenta suggested, a log of a session would tell you what auth mechanism SmtpClient is trying to use, but it will also say what auth mechanisms the server supports.

What normally happens is that the server offers a number of authetication options, and the client choses which one it is going to use. The behaviour from there should be determined by the protocol chosen. I would hope that the SmtpClient class took care of that for you though, but I'm afraid I've never used that particular class.

Also remember - If you are going to post a log here, change to a throwaway password before you log the session, as a base64 encoded plain text password can be trivially changed back to human readable plain text password.

I had the same problem, for my case it was for setting user@domain instead of user, I mean

Old code

new NetworkCredential("UserName@domain.com", "Password");

New code

new NetworkCredential("UserName", "Password");

UGFzc3dvcmQ6 is "Password:" base 64 encoded (without quotes), meaning the password is probably wrong or not send encoded. Try base 64 encoding the password:

string password = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("Password));
dave wanta

Enable logging for System.Net.Mail. Then view the log file. This will show you exactly what is happening during the SMTP layer.

Here is a link with more info:

http://systemnetmail.com/faq/4.10.aspx

thousand of hit on google for UGFzc3dvcmQ6

it seem the server expect encrypted(with base64) username/password

Had the same problem. Solved it in the following steps: 1) find out, what the server offers for SMTP Authentication by connecting to the SMTP Server using Telnet or putty or any other terminal:

telnet xxx.yyy.zzz.aaa 587 

(xxx.yyy.zzz.aaa = IP address of the SMTP Server, 587 = port number)

< Server answers with "220 protocol + version + time"

ehlo testing

< Server displays list of capabilities e.g.

250-AUTH NTLM CRAM-MD5 LOGIN

The SMTP client tries to take the most secure protocol first. In my case:

1. System.Net.Mail.SmtpNegotiateAuthenticationModule
2. System.Net.Mail.SmtpNtlmAuthenticationModule
3. System.Net.Mail.SmtpDigestAuthenticationModule
4. System.Net.Mail.SmtpLoginAuthenticationModule

It looks as if the SMTP client tries NTLM while the server tries to run LOGIN.

With a hack (cf. https://blogs.msdn.microsoft.com/knom/2008/04/16/hacking-system-net-mail-smtpclient/), all protocols can be turned of except for the one the server assumes (LOGIN in this case):

FieldInfo transport = smtpClient.GetType().GetField("transport", BindingFlags.NonPublic | BindingFlags.Instance);

FieldInfo authModules = transport.GetValue(smtpClient).GetType().GetField("authenticationModules",BindingFlags.NonPublic | BindingFlags.Instance);

Array modulesArray = authModules.GetValue(transport.GetValue(smtpClient)) as Array;
foreach (var module in modulesArray)
{
    Console.WriteLine(module.ToString());
}
// System.Net.Mail.SmtpNegotiateAuthenticationModule
// System.Net.Mail.SmtpNtlmAuthenticationModule
// System.Net.Mail.SmtpDigestAuthenticationModule
// System.Net.Mail.SmtpLoginAuthenticationModule

// overwrite the protocols that you don't want
modulesArray.SetValue(modulesArray.GetValue(3), 0);
modulesArray.SetValue(modulesArray.GetValue(3), 1);
modulesArray.SetValue(modulesArray.GetValue(3), 2);

This can also happen when you simply don't provide the password. In my case I was using credentials from a web.config smtp block and on my deployment server (using octopus deploy) had forgotten to populate the password attribute.

For anyone else coming across this on google.. I fixed this by supplying my username in the "username" format instead of "DOMAIN\username"

$Credential = Get-Credential

Send-MailMessage -SmtpServer exchange.contoso.com -Credential $Credential -From 'user@contoso.com' -To 'recipient@domain.com' -Subject 'Test email' -Port 587 -UseSsl
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!