与SmtpClient.UseDefaultCredentials属性混淆

时间:2012-08-28 20:54:44

标签: asp.net-mvc smtpclient

在我的MVC4应用程序中,我使用SmtpClient通过Gmail的smtp.gmail.com SMTP服务器发送电子邮件。

我已使用以下设置配置了我的Web.Config文件:

<system.net>
 <mailSettings>
  <smtp deliveryMethod="Network">
   <network enableSsl="true" 
   defaultCredentials="false" 
   host="smtp.gmail.com" 
   port="587" 
   userName="xxMyUserNamexx@gmail.com" 
   password="xxMyPasswordxx" />
  </smtp>
 </mailSettings>
</system.net>

使用SmtpClient并发送电子邮件的方法如下:

public void SendMail(string fromDisplayName, string fromEmailAddress, string toEmailAddress, string subject, string body)
{
    MailAddress from = new MailAddress(fromEmailAddress, fromDisplayName);
    MailAddress to = new MailAddress(toEmailAddress);
    MailMessage mailMessage = new MailMessage(from, to);
    mailMessage.Body = body;
    mailMessage.Subject = subject;

    SmtpClient client = new SmtpClient();
    //client.UseDefaultCredentials = false;
    client.Send(mailMessage);
}

上面的代码按预期工作,很好。令我感到困惑的是注释行client.UseDefaultCredentials = false; - 如果我要取消注释该行,我将收到一条异常消息,指出:

  

SMTP服务器需要安全连接,否则客户端不需要   认证。服务器响应为:5.5.1需要身份验证。

更重要的是,如果我将UseDefaultCredentials属性设置为truefalse并不重要,我仍会收到异常消息。我避免异常消息的唯一方法是完全删除该行。

这种行为是正常的吗?你能解释我收到异常消息的原因吗?

4 个答案:

答案 0 :(得分:23)

  

那么为什么我明确地将属性设置为false会抛出异常?

这是因为UseDefaultCredentials的setter将Credentials属性设置为null(如果将其设置为false),或者如果设置为true则将其设置为CredentialCache.DefaultNetworkCredentials属性。 DefaultNetworkCredentials属性为defined by MSDN as

  

DefaultNetworkCredentials返回的凭据表示运行应用程序的当前安全上下文的身份验证凭据。对于客户端应用程序,这些应用程序通常是运行应用程序的用户的Windows凭据(用户名,密码和域)。对于ASP.NET应用程序,默认网络凭据是登录用户或被模拟用户的用户凭据。

当您将UseDefaultCredentials设置为true时,它正在使用您的IIS用户,并且我假设您的IIS用户与您正在使用的任何SMTP服务器的帐户没有相同的身份验证凭据。将UseDefaultCredentials设置为false将输出的凭据设置为null。所以无论哪种方式,你都会收到这个错误。

以下是UseDefaultCredentials使用dotPeek

的setter设置
set
{
    if (this.InCall)
    {
        throw new InvalidOperationException(
            SR.GetString("SmtpInvalidOperationDuringSend"));
    }
    this.transport.Credentials = value 
        ? (ICredentialsByHost) CredentialCache.DefaultNetworkCredentials 
        : (ICredentialsByHost) null;
  }

答案 1 :(得分:14)

我收到同样的消息,这让我发疯了。读完这个帖子后,我意识到订单在设置我的凭据时很重要。这很有效:

client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential(smtpSettings.Username, smtpSettings.Password);

虽然这会产生您描述的错误:

client.Credentials = new NetworkCredential(smtpSettings.Username, smtpSettings.Password);
client.UseDefaultCredentials = false;

对于遇到同样问题的其他人来说,这只是一个FYI。

答案 2 :(得分:0)

此选项会将客户端设置为使用当前登录的用户的默认凭据

如果将其设置为true,则会尝试使用用户的凭据。如果将其设置为false,则它将使用为客户端的Credentials属性设置的值显式,如果未明确设置,则会尝试匿名连接,如您所见

答案 3 :(得分:0)

这是我们使用或不使用NetworkCredentials创建SMTP客户端的方法。我正在使用此代码发送电子邮件。我们应该只在我们没有传递凭证并默认使用时才使用client.UseDefaultCredentials。

        private SmtpClient InitializeSMTPClient()
        {
            var client = new SmtpClient(_smtpServer, _smtpPort);

            client.UseDefaultCredentials = _useSMTPDefaultCredentials;

            if (_useSMTPDefaultCredentials)
                return client;

            var credentials = new NetworkCredential(_smtpUsername, _smtpPassword);
            client.Credentials = credentials;

            return client;
        }



        SMTPEmailResult SendSMTPEmail(List<string> to_email, List<string> ccEmails, string subject, string message)
        {
            try
            {
                using (var client = InitializeSMTPClient())
                {
                    var mail_message = GetMailMessage(to_email, ccEmails, subject, message);
                    log.Debug("Sending SMTP email.");
                    client.Send(mail_message);
                    log.Debug("SMTP email sent successfully.");
                    return SMTPEmailResult.SendSuccess;
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                return SMTPEmailResult.SendFailed;
            }
        }