Recently I was playing with ASP.NET MVC2 trying to find a neat solution for sending emails. This post is a sum-up of that little endeavour.
From it you will learn
- How to send HTML emails with MVCContrib and its EmailTemplateService
- How to test email sender without SMTP server
- How to use Ninject with MVC controllers
All those impatient readers out there, go ahead and download the source code of a small app that will be crafted in the rest of this post (zip comes along with MVCContrib source code, for some rich debugging experience).
How to send HTML emails with MVCContrib.
Email template service in MVCContrib (inspired by Castle MonoRail) is a fantastic feature. Usage is pretty simple:
var emailService = new MvcContrib.Services.EmailTemplateService();
var email = emailService.RenderMessage(controllerContext, viewName);
You provide a specially formatted view and the service generates a MailMessage ready to be sent out. Here's an example of how the view should look like:
from: <%= ViewData["from"] %>
to: <%= ViewData["to"] %>
subject: <%= ViewData["subject"] %>
Here goes the email text
How to test email sender without SMTP server.
Contrary to all expectations, you don't really need an SMTP server for testing. There's a config option that makes your SMTP client saving emails to a local folder, instead of sending them out.
Put this in your web.config and enjoy:
<specifiedPickupDirectory pickupDirectoryLocation="c:\Temp\" />
How to use Ninject with MVC controllers.
Ninject comes along with a neat Ninject.Mvc project for MVC development.
With that guy, DI in controllers becomes superlatively easy. Just inherit your application from NinjectHttpApplication and add this code:
protected override void OnApplicationStarted()
RegisterRoutes(RouteTable.Routes); //your route registration
//allow DI for all controllers in this assembly
protected override IKernel CreateKernel()
//define Ninjection rules in a separate module
return new StandardKernel(new DefaultBindingsModule());
private class DefaultBindingsModule : NinjectModule
public override void Load()
//controllers that use IEmailService, will get EmailService instances
And voila, your controllers will magically get instantiated with instances of EmailService - assuming you define controllers like that:
public class FooController : Controller
private readonly IEmailService _emailService;
public FooController(IEmailService emailService)
_emailService = emailService;
I recommend the following project structure:
Provide a base class EmailModel with common To, From, Subject etc properties. Derived classes will expose specific properties to substitute placeholders in concrete emails.
In a similar fashion, define Email.Master with common metadata ("to", "from", "subject" etc) and basic markup for the emails. Concrete email templates would have to deal only with their specific details.
Disclaimers and concerns.
MVCContrib uses regular expressions to retrieve "to", "from" and other metadata. A somewhat more robust and maintainable idea would be specifying that metadata in xml:
Another concern is that while it uses ViewEngine.FindView() along with IView.Render() to render the view on the fly - but it does not call ViewEngine.ReleaseView afterwards, so the email view isn't disposed properly.
Other than that, MVCContrib and its EmailTemplateService is a great approach for sending emails. Try it yourself!