ELMAH - Get SMTP credentials from Azure Application Settings

二次信任 提交于 2019-12-23 12:47:51

问题


I've got an Azure Web App using ELMAH to log unhandled exceptions.

When I first deployed it, the web.config had the full SMTP setup defined in it, and ELMAH emailed exceptions:

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

The username and password have since been removed from the web.config, and they're now stored as application settings, configured through the Azure Portal.

Most of the emails I send still work fine, as the email code can access these application settings and use them when instantiating the SmtpClient, e.g.:

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);
}

What's the best way to get ELMAH to use the credentials stored in the application settings?

Options I can see:

  • There is a page on the wiki explaining how to use ELMAH's ErrorTweetModule to do an HTTP form post with the error details to any URL. The controller receiving the post could then use the stored credentials to email the details on.
  • The WebBase has a link to an article suggesting you can send emails directly to the recipient's SMTP server without authentication, but it says this may not work if you have DomainKeys set up, which I do.
  • This answer links to an article about intercepting the Mailing event, to customise the message.

回答1:


I ended up creating a custom version of Elmah's ErrorMailModule, derived from the standard one, but overriding the SendMail method, based on some advice from Atif Aziz in a discussion on Google Groups.

The only changes required were to create the new module, and switch the Web.Config to use the custom module instead of the standard one.


Module

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 Config Changes

All that's required is to change the two occurrences of Elmah.ErrorLogModule, Elmah to your own module, in this case Test.ErrorMailModule.

So, instead of this...

<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>

...you should now have this:

<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>

You will still need the errorMail section, as Elmah is still responsible for creating the email. Mine looks like this:

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



回答2:


Creating a HTTP request could work, but that should be the solution if everything else doesn't work IMO. Intercepting the Mailing event doesn't work, since you do not have access to the SmtpClient with the credentials in that event.

I've looked at different ways to update the SMTP settings from code. At first I though that I could just get a reference to the smtp section and update the properties, since they all have setter. But the code throw a configuration exception on runtime.

From what I can find, the only way to update the username and password in smtp section, is to read the web.config, update it and write the new version. Here's an example of writing updates to 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();

The code actually updates the web.config. The code can be run at startup, but that would modify your web.config file locally as well. Another approach would be to run the code as part of a post deployment task with Azure.



来源:https://stackoverflow.com/questions/39395268/elmah-get-smtp-credentials-from-azure-application-settings

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!