Lately I've had several requests to create global event handlers to send emails when specific items happen. In v7 I had difficulties getting macros to resolve in email templates and it didn't get any better in version 8. This week, I finally sat down, did some research, wrote a test program and came up with the solution and thought I'd share with all of you.
If you're still using web.config keys in your Kentico website, you need to stop and start using Kentico's
Custom Settings. Custom settings are congifurable within the Kentico UI globally and per site which makes them very powerful for a multi-tenancy environment. This post isn't about Custom Settings though, this is about how to utilize the Macro API with Email Templates.
If you've read any of my answers or questions on the
Kentico DevNet you'll know I'm a big supporter of their documentation. Well with this particular issue, I wasn't able to find much in terms of good documentation and/or examples for how to properly resolve macros within email templates. My scenario is this, whenever a user is inserted, updated or deleted on a specific site an email needs to be generated and sent to specific people in an organization.
So I started out by creating a few
custom settings in my module so I can specify an email (or multiple) and select an email template I'll later create. Below are the simple settings I created.
So now I have my settings all ready. Lets take a look at the code. I've got a global handler to capture when a user is inserted, updated or deleted. Within those methods, I capture the event type and go out and gather the correct settings. Then I resolve the macros I need based on what is available within the user object I'm updating. See below:
protected static MacroResolver ResolveUserMacros(UserInfo ui)
{
// create a new instnace of the resolver
var resolver = MacroResolver.GetInstance();
// set all the available values within the template
resolver.SetNamedSourceData("firstname", ui.FirstName);
resolver.SetNamedSourceData("lastname", ui.LastName);
resolver.SetNamedSourceData("email", ui.Email);
resolver.SetNamedSourceData("username", ui.UserName);
resolver.SetNamedSourceData("fullname", ui.FullName);
resolver.SetNamedSourceData("county", ui.UserSettings.GetStringValue("County", ""));
resolver.SetNamedSourceData("classyear", ui.UserSettings.GetStringValue("ClassYear", ""));
resolver.SetNamedSourceData("homeaddress", ui.UserSettings.GetStringValue("HomeAddress", ""));
resolver.SetNamedSourceData("homecity", ui.UserSettings.GetStringValue("HomeCity", ""));
resolver.SetNamedSourceData("homestate", ui.UserSettings.GetStringValue("HomeState", ""));
resolver.SetNamedSourceData("homestate", ui.UserSettings.GetStringValue("HomeState", ""));
resolver.SetNamedSourceData("homezipcode", ui.UserSettings.GetStringValue("HomeZipCode", ""));
resolver.SetNamedSourceData("company", ui.UserSettings.GetStringValue("Company", ""));
resolver.SetNamedSourceData("workaddress", ui.UserSettings.GetStringValue("WorkAddress", ""));
resolver.SetNamedSourceData("workcity", ui.UserSettings.GetStringValue("WorkCity", ""));
resolver.SetNamedSourceData("workstate", ui.UserSettings.GetStringValue("WorkState", ""));
resolver.SetNamedSourceData("workstate", ui.UserSettings.GetStringValue("WorkState", ""));
resolver.SetNamedSourceData("workzipcode", ui.UserSettings.GetStringValue("WorkZipCode", ""));
resolver.SetNamedSourceData("workphone", ui.UserSettings.GetStringValue("WorkPhone", ""));
resolver.SetNamedSourceData("workemail", ui.UserSettings.GetStringValue("WorkEmail", ""));
resolver.SetNamedSourceData("positiontitle", ui.UserSettings.GetStringValue("PositionTitle", ""));
resolver.SetNamedSourceData("birthdate", ui.UserSettings.GetStringValue("Birthdate", ""));
return resolver;
}
My simple email template looks like so.
<p>
<strong>{% fullname %}</strong> ({% username %}) was updated
</p>
<strong>County:</strong> {% county %}<br />
<strong>Class:</strong> {% classyear %}<br />
<strong>Home Address:</strong> {% homeaddress %}<br />
<strong>Home City:</strong> {% homecity %}<br />
<strong>Home State:</strong> {% homestate %}<br />
<strong>Home Zip:</strong> {% homezipcode %}<br />
<strong>Home Phone:</strong> {% homephone %}<br />
<strong>Company:</strong> {% company %}<br />
<strong>Work Address:</strong> {% workaddress %}<br />
<strong>Work City:</strong> {% workcity %}<br />
<strong>Work State:</strong> {% workstate %}<br />
<strong>Work Zip:</strong> {% workzipcode %}<br />
<strong>Work Phone:</strong> {% workphone %}<br />
<strong>Work Email:</strong> {% workemail %}<br />
<strong>Title:</strong> {% positiontitle %}<br />
<strong>Birthdate:</strong> {% birthdate %}<br />
As you can see things look pretty simple now that it's all spelled out. What the documentation and some questions I found didn't show was how to set those macros effectively. What I did for the last few years was a simple string.Replace() method on the body text of the email template to find the ##macroKey## I created and replaced it with the correct value. It works but not ideal as you have to add all your other error handling around it as well.
Hope this has helped someone else as it's been a pain in my backside for the last few years.
Best of luck and Happy Coding!