【问题标题】:ELMAH - Get SMTP credentials from Azure Application SettingsELMAH - 从 Azure 应用程序设置获取 SMTP 凭据
【发布时间】:2017-01-16 15:24:35
【问题描述】:

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

当我第一次部署它时,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 使用存储在应用程序设置中的凭据的最佳方法是什么?

我可以看到的选项:

  • wiki 上有一个page 解释如何使用 ELMAH 的 ErrorTweetModule 将错误详细信息发送到任何 URL 的 HTTP 表单。然后,接收帖子的控制器可以使用存储的凭据通过电子邮件发送详细信息。
  • WebBase 有一个指向article 的链接,建议您无需身份验证即可直接向收件人的 SMTP 服务器发送电子邮件,但它说如果您设置了 DomainKeys,这可能无法正常工作,我这样做了。
  • 这个answer 链接到一个article,关于拦截Mailing 事件,以自定义消息。

【问题讨论】:

    标签: azure elmah


    【解决方案1】:

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

    我研究了通过代码更新 SMTP 设置的不同方法。起初我认为我可以获得对 smtp 部分的引用并更新属性,因为它们都有设置器。但是代码在运行时抛出了配置异常。

    据我所知,在 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 文件。另一种方法是将代码作为 Azure 部署后任务的一部分运行。

    【讨论】:

    • 我这样做了一段时间,但在启动时运行它会导致 IIS 回收应用程序池,从而清除 Session 数据(因此也清除 TempData)。 (请参阅我的问题here。)我切换到@Jonathan's solution 并解决了问题。
    【解决方案2】:

    根据 Atif Aziz 在 Google Groups 上 a discussion 中的一些建议,我最终创建了 Elmah 的 ErrorMailModule 的自定义版本,它源自标准版本,但覆盖了 SendMail 方法。

    所需的唯一更改是创建新模块,并将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)
            }
        }
    }
    

    网络配置更改

    只需将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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-26
      • 1970-01-01
      • 2020-10-20
      • 1970-01-01
      • 2020-08-01
      • 1970-01-01
      • 2020-08-13
      • 2010-10-15
      相关资源
      最近更新 更多