ELMAH - 从 Azure 应用程序设置中获取 SMTP 凭据

ELMAH - Get SMTP credentials from Azure Application Settings

我有一个 Azure Web 应用程序使用 ELMAH 来记录未处理的异常。

当我第一次部署它时,web.config 中定义了完整的 SMTP 设置,并且 ELMAH 电子邮件例外:

<system.net>
    <mailSettings>
        <smtp from="me@mydomain.com">
            <network host="smtp.mailprovider.com"
                 port="123"
                 userName="myUserName"
                 password="p@ssw0rd" />
        </stmp>
    </mailSettings>
</system.net>

用户名和密码已从 web.config 中删除,它们现在存储为应用程序设置,通过 Azure 门户进行配置。

我发送的大部分电子邮件仍然有效,因为电子邮件代码可以访问这些应用程序设置并在实例化 SmtpClient 时使用它们,例如:

var userName = WebConfigurationManager.AppSettings["smtp.userName"];
var password = WebConfigurationManager.AppSettings["smtp.password"];

var credentials = new NetworkCredential(userName, password);

using (var smtpClient = new SmtpClient { Credentials = credentials })
{
    await smtpClient.SendMailAsync(mailMessage);
}

让 ELMAH 使用存储在应用程序设置中的凭据的最佳方法是什么?

我能看到的选项:

创建 HTTP 请求可能有效,但如果 IMO 其他所有方法均无效,那应该是解决方案。拦截 Mailing 事件不起作用,因为您无权使用该事件中的凭据访问 SmtpClient。

我研究了从代码更新 SMTP 设置的不同方法。起初我认为我可以只获取对 smtp 部分的引用并更新属性,因为它们都有 setter。但是代码在 运行time.

时抛出配置异常

据我所知,在 smtp 部分更新用户名和密码的唯一方法是阅读 web.config,更新它并编写新版本。这是将更新写入 web.config 的示例:

var configuration = WebConfigurationManager.OpenWebConfiguration("~");
var section = configuration.GetSection("system.net/mailSettings/smtp") as SmtpSection;
section.Network.UserName = ConfigurationManager.AppSettings["myusername"];
section.Network.Password = ConfigurationManager.AppSettings["mypassword"];
configuration.Save();

代码实际上更新了 web.config。该代码在启动时可以是 运行,但这也会在本地修改您的 web.config 文件。另一种方法是 运行 将代码作为 post Azure 部署任务的一部分。

我最终创建了 Elmah 的自定义版本 ErrorMailModule,它源自标准版本,但基于 a discussion 中 Atif Aziz 的一些建议覆盖了 SendMail 方法Google 个群组。

唯一需要的更改是创建新模块,并将 Web.Config 切换为使用自定义模块而不是标准模块。


模块

using System;
using System.Net.Mail;

namespace Test
{
    public class ErrorMailModule : Elmah.ErrorMailModule
    {
        protected override void SendMail(MailMessage mail)
        {
            if (mail == null) throw new ArgumentNullException(nameof(mail));

            // do what you want with the mail
            // (in my case this fires up the email service, which 
            // gets the credentials from the Azure settings)
        }
    }
}

Web 配置更改

所需要做的就是将两次出现的 Elmah.ErrorLogModule, Elmah 更改为您自己的模块,在本例中为 Test.ErrorMailModule.

所以,而不是这个...

<system.web>
  <httpModules>
    <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
  </httpModules>
</system.web>
<system.webServer>
  <modules>
    <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
  </modules>
</system.webServer>

...你现在应该有这个:

<system.web>
  <httpModules>
    <add name="ErrorMail" type="Test.ErrorMailModule" />
  </httpModules>
</system.web>
<system.webServer>
  <modules>
    <add name="ErrorMail" type="Test.ErrorMailModule" preCondition="managedHandler" />
  </modules>
</system.webServer>

您仍然需要 errorMail 部分,因为 Elmah 仍负责创建电子邮件。我的看起来像这样:

<elmah>
  <errorMail from="user@domain.com" to="user@domain.com" subject="Custom Email Module"/>
</elmah>