Thursday, November 13, 2008

Dynamically Modifying Web.Config's MailSettings

Most modern ASP.Net websites need to send e-mails. One reason is that the Password Recovery control within the Memberships & Roles infrastructure needs to send the user an e-mail with a temporary password when he forgets his.

Typically, when e-mails are sent, this section of web.config is examined for SMTP credentials:

<system.net>
<mailSettings>
<smtp>
<network host="shawmail.vc.shawcable.net" password="" userName="" />
</smtp>
</mailSettings>
</system.net>

Note: The credentials shown above are just examples

If your site is only going to be run from one server then it's perfectly fine to manually edit this section in web.config and never think about it again.

But I have a situation where a website I'm developing is going to be deployed from multiple servers to different audiences, each managed by a separate Website Administrator. The skill levels of Web Admins vary greatly, so I really don't like them fiddling deep inside the web.config file.

Instead, I've setup some special application variables that are defined near the top of web.config:


<appSettings>
<add key="SMTPserver" value="<span style=">mySMTPserver"/>
<add key="SMTPusername" value="<span style=">smtpUsername"/>
<add key="SMTPpassword" value="<span style=">smtpPassword"/>
</appSettings>

Notice how this trio directly matches with the previous set. I needed to find a way to allow the web admin to modify these app variables and have the changes reflected in the other part of web.config.

I found the solution here. For my app I added this code to Global.asax:

void UpdateMailSettings()
{
bool modified = false; // Default assumption

// Retrieve the current 'web.config' file
System.Configuration.Configuration config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");

// And within it, get the 'mailSettings' section, if it exists
System.Net.Configuration.MailSettingsSectionGroup mailSettings = (System.Net.Configuration.MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings");

string server = BusinessObjects.Tools.GetAppSettingsValue("SMTPserver");
if (mailSettings.Smtp.Network.Host != server)
{
mailSettings.Smtp.Network.Host = server;
modified = true;
}

string username = BusinessObjects.Tools.GetAppSettingsValue("SMTPusername");
if (mailSettings.Smtp.Network.UserName != username)
{
mailSettings.Smtp.Network.UserName = username;
modified = true;
}

string password = BusinessObjects.Tools.GetAppSettingsValue("SMTPpassword");
if (mailSettings.Smtp.Network.Password != password)
{
mailSettings.Smtp.Network.Password = password;
modified = true;
}

if (modified)
config.Save();
}

It works great! Be aware that whenever web.config is modified, the application is restarted. But because this code is executed right at the beginning, web.config is only modified once - if necessary - and then never again.

In the future I will likely create a user-friend Admin screen within the app to allow them to modify all the editable application variables from there.

No comments:

Post a Comment