Подтвердить что ты не робот

Смутно с свойством SmtpClient.UseDefaultCredentials

В моем приложении 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="[email protected]" 
   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 на true или false, я все равно получаю сообщение об исключении. Единственный способ избежать исключения сообщения - удалить всю строку.

Это нормальное поведение? Можете ли вы объяснить, почему я получаю сообщение об исключении?

4b9b3361

Ответ 1

Итак, почему я явно устанавливаю свойство false, создавая исключение?

Причиной этого является то, что установщик для UseDefaultCredentials устанавливает для свойства Credentials значение null, если вы установите его на false, или он устанавливает его в свойство CredentialCache.DefaultNetworkCredentials, если установлено значение true. Свойство DefaultNetworkCredentials определено MSDN как:

Учетные данные, возвращаемые DefaultNetworkCredentials, представляют собой учетные данные для проверки подлинности для текущего контекста безопасности, в котором работает приложение. Для клиентского приложения обычно это учетные данные Windows (имя пользователя, пароль и домен) пользователя, запускающего приложение. Для приложений ASP.NET сетевыми учетными данными по умолчанию являются учетные данные пользователя вошедшего в систему пользователя или пользователя, который выдает себя за него.

Когда вы устанавливаете значение UseDefaultCredentials в true, оно использует ваш IIS-пользователь, и я предполагаю, что ваш пользователь IIS не имеет одинаковых учетных данных аутентификации в качестве вашей учетной записи для любого используемого SMTP-сервера. Установка UseDefaultCredentials в значение false null вне установленных учетных данных. Таким образом, в любом случае вы получаете эту ошибку.

Здесь посмотрите на установщик для UseDefaultCredentials, используя dotPeek:

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

Ответ 2

Я получал одно и то же сообщение, и это сводило меня с ума. Прочитав этот поток, я понял, что порядок имеет значение при настройке моих учетных данных. Это сработало:

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

Пока это порождает описанную вами ошибку:

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

Это просто FYI для кого-то другого, имеющего ту же проблему.

Ответ 3

Этот параметр позволяет клиенту использовать учетные данные по умолчанию для текущего зарегистрированного пользователя

Если вы установите значение true, то он попытается использовать учетные данные пользователя. Если вы установите для него значение false, то он будет использовать значения, явно установленные для свойства Credentials для клиента, и если они явно не установлены, то он попытается подключиться анонимно, как вы видите.

Ответ 4

Таким образом мы можем создать SMTP-клиент с или без NetworkCredentials. Я использую этот код для отправки писем. Мы должны использовать 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;
            }
        }