问题
In my MVC4 application, I am using the SmtpClient
to send out email via Gmail's smtp.gmail.com
SMTP server.
I have configured my Web.Config file with the following settings:
<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>
The method that uses the SmtpClient and sends an email message looks like:
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);
}
The code above works as expected and is fine. What confuses me is the commented line client.UseDefaultCredentials = false;
- If I were to uncomment that line, I will receive an exception message that states:
The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required.
What's more is, it doesn't matter if I set the UseDefaultCredentials
property to true
or false
, I will still receive the exception message. The only way for me to avoid the exception message is to remove the line altogether.
Is this behavior normal? Can you explain why I am receiving the exception message?
回答1:
So why would me explicitly setting the property to false throw an exception?
The reason for this is because the setter for UseDefaultCredentials
sets the Credentials
property to null if you set it to false, or it sets it to the CredentialCache.DefaultNetworkCredentials
property if set to true. The DefaultNetworkCredentials
property is defined by MSDN as:
The credentials returned by DefaultNetworkCredentials represents the authentication credentials for the current security context in which the application is running. For a client-side application, these are usually the Windows credentials (user name, password, and domain) of the user running the application. For ASP.NET applications, the default network credentials are the user credentials of the logged-in user, or the user being impersonated.
When you set UseDefaultCredentials
to true, it's using your IIS user, and I'm assuming that your IIS user does not have the same authentication credentials as your account for whatever SMTP server you're using. Setting UseDefaultCredentials
to false null's out the credentials that are set. So either way you're getting that error.
Here's a look at the setter for UseDefaultCredentials
using dotPeek:
set
{
if (this.InCall)
{
throw new InvalidOperationException(
SR.GetString("SmtpInvalidOperationDuringSend"));
}
this.transport.Credentials = value
? (ICredentialsByHost) CredentialCache.DefaultNetworkCredentials
: (ICredentialsByHost) null;
}
回答2:
I was getting the same message and it was driving me crazy. After reading this thread I realized that the order mattered on setting my credentials. This worked:
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential(smtpSettings.Username, smtpSettings.Password);
While this generated the error you describe:
client.Credentials = new NetworkCredential(smtpSettings.Username, smtpSettings.Password);
client.UseDefaultCredentials = false;
This is just an FYI to anybody else having the same problem.
回答3:
This option will set the client to use the default credentials of the currently logged in user
If you set it to true, then it will try to use the user's credentials. If you set it to false, then it will use the values explicitly set for the Credentials property of the client, and if they aren't explicitly set, then it will try to connect anonymously as you are seeing.
回答4:
This is how we can create SMTP Client with or without NetworkCredentials. I am using this code to send emails. We should use client.UseDefaultCredentials only when we are not passing credentials and going by default.
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;
}
}
来源:https://stackoverflow.com/questions/12167381/confused-with-the-smtpclient-usedefaultcredentials-property