使用默认SMTP凭据在Office365上出现异常——客户端未经身份验证无法发送匿名邮件在MAIL FROM期间。

12

我正在使用NLog将日志作为电子邮件发送,使用自定义邮件目标。我的发送方式来自于我的Office365帐户,该帐户已在我的Web.config文件(主项目的配置文件)中设置为默认值,具体如下:

  <system.net>
    <mailSettings>
      <smtp deliveryMethod="Network" from="myusername@mydomain.com">
        <network defaultCredentials="false" host="smtp.office365.com" port="587" userName="myusername@mydomain.com" password="mypassword" enableSsl="true" />
      </smtp>
    </mailSettings>
  </system.net>

我使用以下方式覆盖了Write方法,使用我的日志目标(在我的NLog实现包中):

    protected override void Write(LogEventInfo logEvent) 
    { 
        try
        {
            using (var mail = new MailMessage())
            {
                this.SetupMailMessage(mail, logEvent, this.Layout.Render(logEvent));

                using (SmtpClient smtpClient = new SmtpClient())
                {
                    smtpClient.UseDefaultCredentials = true;
                    smtpClient.Send(mail);
                }
            }
        }
        catch (Exception exception)
        {
            throw new NLogRuntimeException("An error occurred when sending a log mail message.", exception);
        }
    }
当系统试图从该账户发送邮件时,会抛出以下 System.Net.Mail.SmtpException:
SMTP 服务器要求建立安全连接或客户端未经身份验证。服务器响应为:5.7.57 SMTP;在 MAIL FROM 期间客户端未被授权发送匿名邮件。
我已经四次检查了凭据,它们是正确的。有人知道还有什么原因会导致这个异常吗?
更新:事实证明 CredentialCache.DefaultCredentials 属性中充满了空字符串。但是,当我使用下面的代码手动提取设置时,可以从 web.config 获取设置。
SmtpSection settings = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp");
smtpClient.Credentials = new NetworkCredential(settings.Network.UserName, settings.Network.Password);
smtpClient.Host = settings.Network.Host;
smtpClient.Port = settings.Network.Port;
smtpClient.EnableSsl = settings.Network.EnableSsl;

var creds = CredentialCache.DefaultCredentials;  // Is empty

我可以将此用作解决方法。但是这是怎么回事?为什么默认凭据会为空?


SetupMailMessage设置了一个发件人地址吗? - Alex K.
不,我希望它使用在 web.config 中设置的默认发件地址。尽管我也尝试手动添加发件地址(例如 mailMessage.From = new MailAddress("myusername@mydomain.com");)来查看是否是问题所在,但仍然抛出了相同的异常。 - 08Dc91wk
在切换到Office 365之后,我使用ELMAH时遇到了相同的问题。我已经在XML中将defaultCredentials设置为false,但是在使用XML配置时似乎没有影响。 - Cody
这正是我遇到的问题。在某个时刻,尽管在 .config 中指定了用户名和密码,但它们不再被填充。 - Huy Hoang
4个回答

10
< p >感谢这篇文章,我成功解决了我们的问题。我们从Rackspace的混合设置中迁移到了O365的邮箱。发送邮件使用的邮箱在迁移前不是Exchange账户,但在迁移后成为了Exchange账户。< /p >
mySmtpClient = New SmtpClient("smtp.office365.com")
mySmtpClient.Port = 587
mySmtpClient.EnableSsl = True
mySmtpClient.Credentials = New System.Net.NetworkCredential("email@domain.com", "password", "domain.com")
mySmtpClient.Send(Msg)

以前的设置不需要我们提供端口或启用SSL,甚至不需要在凭据参数中放置域。希望这对那些需要使用VB脚本自动发送Office 365 SMTP电子邮件的人有所帮助。


8

虽然我在答案更新中提到的解决方法确实有效,但我对于手动提取这些值并不满意。对我来说,解决方案是删除该行代码

smtpClient.UseDefaultCredentials = true;

从我发布的原始代码中,看来smtpClient是使用我在web.config中设置的默认凭据进行初始化的,上述已删除的行将它们用来自CredentialCache.DefaultCredentials的空字符串覆盖了。 我仍然不知道为什么CredentialCache.DefaultCredentials为空或者这是什么时候从web.config中填充的,但这是我的问题来源。
如果有人对此有更深入的见解,请发布更好的答案!

1
在第三方托管提供商上进行此集成时,您还需要提供域名。
SmtpClient client = new SmtpClient(SMTPSettings.Url, SMTPSettings.Port);
client.Credentials = new System.Net.NetworkCredential(SMTPSettings.UserName, SMTPSettings.Password, SMTPSettings.Domain);

0

我遇到了相同的问题,解决方法是使用System.Security.SecureString来代替字符串存储密码,示例如下:

        System.Security.SecureString psw = new System.Security.SecureString();

        string PasswordGmail = "XXXXXX";

        foreach (char item in PasswordGmail.ToCharArray())
        {
            psw.AppendChar(item);
        }

        client.Credentials = new System.Net.NetworkCredential("XXXX@xxx.com", psw); 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接