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
のどちらに設定しても、例外メッセージが表示されます。例外メッセージを回避する唯一の方法は、行を完全に削除することです。
この動作は正常ですか?例外メッセージが表示される理由を説明してください。
では、なぜプロパティを明示的にfalseに設定すると、例外がスローされるのでしょうか。
これは、UseDefaultCredentials
のセッターがfalseに設定した場合はCredentials
プロパティをnullに設定し、trueに設定した場合はCredentialCache.DefaultNetworkCredentials
プロパティに設定するためです。 DefaultNetworkCredentials
プロパティは MSDNで定義されています :
DefaultNetworkCredentialsによって返される資格情報は、アプリケーションが実行されている現在のセキュリティコンテキストの認証資格情報を表します。クライアント側アプリケーションの場合、これらは通常、アプリケーションを実行しているユーザーのWindows資格情報(ユーザー名、パスワード、およびドメイン)です。 ASP.NETアプリケーションの場合、既定のネットワーク資格情報は、ログインしているユーザー、または偽装されているユーザーのユーザー資格情報です。
UseDefaultCredentials
をtrueに設定すると、IISユーザーが使用され、IISユーザーはアカウントと同じ認証資格情報を持っていないことを前提としています使用しているSMTPサーバーに関係なく。UseDefaultCredentials
をfalse nullに設定すると、設定されている資格情報が削除されます。どちらの方法でも、エラーが発生します。
dotPeek を使用したUseDefaultCredentials
のセッターを次に示します。
set
{
if (this.InCall)
{
throw new InvalidOperationException(
SR.GetString("SmtpInvalidOperationDuringSend"));
}
this.transport.Credentials = value
? (ICredentialsByHost) CredentialCache.DefaultNetworkCredentials
: (ICredentialsByHost) null;
}
私は同じメッセージを受け取り、それは私を夢中にさせていました。このスレッドを読んだ後、資格情報の設定に順序が重要であることに気付きました。これはうまくいきました:
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential(smtpSettings.Username, smtpSettings.Password);
これにより、説明するエラーが生成されました。
client.Credentials = new NetworkCredential(smtpSettings.Username, smtpSettings.Password);
client.UseDefaultCredentials = false;
これは、同じ問題を抱えている他の人への参考情報です。
このオプションは、現在ログインしているデフォルトの資格情報を使用するようにクライアントを設定しますser
Trueに設定すると、ユーザーの資格情報を使用しようとします。 falseに設定すると、クライアントのCredentialsプロパティに設定された値explicitlyが使用され、明示的に設定されていない場合は、表示されているとおりに匿名で接続しようとします。 。
これは、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;
}
}