Исключение с использованием учетных данных 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);