使用不兼容的SMTP服务器进行身份验证

本文关键字:身份验证 服务器 SMTP 不兼容 | 更新日期: 2023-09-27 18:18:46

我应该通过SMTP服务器发送一封电子邮件。此SMTP服务器需要身份验证。但是,如果我使用. net SmtpClient的默认身份验证机制,504 Unrecognized Authentication Type的身份验证将失败。

当使用PuTTy时,我能够成功验证:

250 AUTH LOGIN PLAIN
AUTH LOGIN
334 VXNlcm5hbWU6
Some base64 encoded username
334 UGFzc3dvcmQ6
Some base64 encoded password
235 Authentication Successful

SmtpClient使用稍微不同的方法,其中用户名通过AUTH LOGIN命令传入:

250 AUTH LOGIN PLAIN
AUTH LOGIN Some base64 encoded username
504 Unrecognized Authentication
MAIL FROM: ...

它似乎忽略了504,因为它正在发送MAIL FROM命令。阅读互联网上的一些资源,允许使用AUTH LOGIN命令发送用户名:

然而,存在一个不同的RFC兼容版本的这种行为,其中客户端最初发送用户id已经与AUTH LOGIN方法

问题很可能在SMTP服务器端,但我无法控制它。

是否可以让SmtpClient单独发送命令?


using (var client = new SmtpClient(_configuration.Host, _configuration.Port))
{
    client.UseDefaultCredentials = false;
    client.ServicePoint.MaxIdleTime = 1;
    client.EnableSsl = false;
    client.Credentials = new NetworkCredential(_configuration.Username, _configuration.Password, _configuration.Domain);
    var from = new MailAddress(string.Format("{0}@{1}", _configuration.Sender, _configuration.Domain));
    var to = new MailAddress(string.Format("{0}@{1}", to, _configuration.Domain));
    var message = new MailMessage(from, to)
    {
        Body = body
    };
    client.Send(message);
}

DIY

只是为了好玩(而不是为了制作),我试着做我自己的交流:

using (var connection = new TcpClient(_configuration.Host, _configuration.Port))
using (NetworkStream stream = connection.GetStream())
{
    string header = Read(stream);
    Reply(stream, "EHLO " + Environment.MachineName);
    while (!Read(stream).ToUpperInvariant().Contains("AUTH LOGIN PLAIN"))
    {
    }
    Reply(stream, "AUTH LOGIN");
    string requestUsername = Read(stream);
    Reply(stream, Convert.ToBase64String(Encoding.ASCII.GetBytes(_configuration.Username)));
    string requestPassword = Read(stream);
    Reply(stream, Convert.ToBase64String(Encoding.ASCII.GetBytes(_configuration.Password)));
    string authSucces = Read(stream);
    Reply(stream, string.Format("MAIL FROM: <{0}@{1}>", _configuration.Sender, _configuration.Domain));
    string senderOk = Read(stream);
    Reply(stream, string.Format("RCPT TO: <{0}@{1}>", to, _configuration.Domain));
    string rcptOk = Read(stream);
    Reply(stream, "DATA");
    string sendData = Read(stream);
    Reply(stream, body);
    Reply(stream, string.Empty);
    Reply(stream, ".");
    Reply(stream, string.Empty);
    stream.Close();
    connection.Close();
}
private string Read(NetworkStream stream)
{
    var data = new byte[1024];
    int received = stream.Read(data, 0, data.Length);
    string contents = Encoding.ASCII.GetString(data, 0, received);
    return contents;
}
private void Reply(NetworkStream stream, string reply)
{
    reply = reply + Environment.NewLine;
    stream.Write(Encoding.ASCII.GetBytes(reply), 0, reply.Length);
    stream.Flush();
}

这个效果很好。所以这绝对是关于SmtpClient和实际的Smtp服务器如何通信。


工作

原来我们一直在与一个实现SMTP协议的系统进行通信,他们做错了。因此,我们决定自己进行沟通,直到供应商修复了他们的代码。幸运的是,它只用于内部目的,并且交流是非常可预测的。我们正在使用diy代码,并进行了一些重构和清理。

使用不兼容的SMTP服务器进行身份验证

我有同样的问题,这是我的解决方案/解决方案:使用System.Web.Mail而不是System.Net.Mail发送电子邮件。我知道这不是最好的解决方案,因为这个库已经被弃用了,但在供应商修复代码之前,它可能会有所帮助。

System.Web.Mail.MailMessage msg = new System.Web.Mail.MailMessage();
    msg.Body = message.Body;
    string smtpServer = "mail.business.it";
    string userName = "username";
    string password = "password";
    int cdoBasic = 1;
    int cdoSendUsingPort = 2;
    if (userName.Length > 0)
    {
        msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserver", smtpServer);
        msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", 25);
        msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusing", cdoSendUsingPort);
        msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", cdoBasic);
        msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", userName);
        msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", password);
    }
    msg.To = message.Destination;
    msg.From = "me@domain.it";
    msg.Subject = message.Subject;
    msg.BodyFormat = MailFormat.Html;//System.Text.Encoding.UTF8;
    SmtpMail.SmtpServer = smtpServer;
    SmtpMail.Send(msg);
相关文章: