Исключение с использованием учетных данных SMTP по умолчанию для Office365. Клиент не прошел аутентификацию для отправки анонимной почты во время MAIL FROM

Я использую NLog для отправки журналов в виде электронной почты с настраиваемой почтовой целью. Я посылаю из моих Office365 настройки учетной записи по умолчанию в моем web.config(моего основного проекта) следующим образом:

  <system.net>
    <mailSettings>
      <smtp deliveryMethod="Network" from="[email protected]">
        <network defaultCredentials="false" host="smtp.office365.com" port="587" userName="[email protected]" 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

У меня четырежды проверены учетные данные, и они верны. Кто-нибудь знает, что еще может вызвать это исключение?

UPDATE: Оказывается, свойство 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

Я могу использовать это как обходной путь. Но что дает? Почему учетные данные по умолчанию будут пустыми?

Ответ 1

Хотя обходной путь, который я упомянул в обновлении ответа, действительно сработал, я не был доволен вручную извлечением этих значений. Решение для меня состояло в удалении строки

smtpClient.UseDefaultCredentials = true;

из исходного кода, который я опубликовал. Оказывается, что smtpClient инициализируется учетными данными по умолчанию, установленными в файле web.config, а удаленная строка переписывает их пустыми строками из CredentialCache.DefaultCredentials. Я все еще не знаю, почему CredentialCache.DefaultCredentials пуст или когда он должен быть заполнен из web.config, но это было причиной моей проблемы.

Если у кого-то есть более глубокое понимание этого, напишите лучший ответ!

Ответ 2

Благодаря этому сообщению я смог решить наши проблемы. Мы перенесли почтовые ящики на O365 из гибридной установки в Rackspace. Почтовый ящик, используемый для отправки, ранее не был учетной записью Exchange, но стал после миграции.

mySmtpClient = New SmtpClient("smtp.office365.com")
mySmtpClient.Port = 587
mySmtpClient.EnableSsl = True
mySmtpClient.Credentials = New System.Net.NetworkCredential("[email protected]", "password", "domain.com")
mySmtpClient.Send(Msg)

Предыдущая настройка не требовала от нас предоставления порта или включения ssl или даже помещения домена в параметры учетных данных. Надеюсь, это поможет людям, которые должны работать со сценариями VB, автоматизируя электронные письма через SMTP с Office 365.

Ответ 3

При выполнении этой интеграции стороннего поставщика хостинга вам также необходимо предоставить доменное имя.

SmtpClient client = new SmtpClient(SMTPSettings.Url, SMTPSettings.Port);
client.Credentials = new System.Net.NetworkCredential(SMTPSettings.UserName, SMTPSettings.Password, SMTPSettings.Domain);

Ответ 4

У меня была одна и та же проблема, для меня это работало, чтобы использовать 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("[email protected]", psw);