Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / MFC
Technical Blog

Inline CSS Styles for HTML Emails with HttpModule

Rate me:
Please Sign up or sign in to vote.
4.83/5 (5 votes)
12 Dec 2012CPOL2 min read 18.2K   8  
HTML-based emails are one of those evil things in the life of a web-developer that we would all rather never have to do... but alas, it needs to be done.

HTML-based emails are one of those evil things in the life of a web-developer that we would all rather never have to do... but alas, it needs to be done. One can do this in a variety of ways, but it is fairly common to use modern web-development technologies to generate the actual email bodies over HTTP before sending. We all know how to make web pages, right? How different could an HTML email be?

This always seems rather simple in spirit, but the problem is that email clients have a very non-standardized way of rendering HTML. The fact that you must write HTML for emails as if you were living in the late 90's is bad enough, but on top of that - many email clients remove CSS stylesheets from the HTML.

I have an ASP.net Razor project where I need to generate some HTML emails. I would like them to be maintainable style-wise and share a common layout page and css styles. What would be nice is if I could develop the web pages like normal with CSS stylesheets, but have the CSS inlined automatically.

CSS parsing does not sound like something I would like to do myself, so naturally, I looked to see what was out there. There are some great tools out there, but one clear winner:

PreMailer.Net: C# Library for moving CSS to inline style attributes, to gain maximum E-mail client compatibility.

PreMailer.Net is a C# implementation of Premailer's CSS inlining service built by Martin Normark. This was exactly what I needed! With this library, it should be super easy to do the inlining.

Martin did a great job with this by utilizing Fizzler, a CSS Selector Engine for HTML documents in .NET, and a CSS parser class from The Dynamic Programmer to do this. I believe a lot of the work was influenced by Premailer, which deserves a mention here:

Premailer: Pre-flight for HTML email

Premailer, written by Alex Dunae is the "original" Premailer library written in Ruby. Alex has been kind enough to put it up as a web service on his website, allowing anyone to inline CSS on the go - and provides some other HTML-email-specific type tools which are worth checking out.

Anyway, I decided to wrap an HttpModule around the PreMailer.Net library to automatically process the HTML from each response in a sub-folder of my application. The HttpModule would look something like this:

public class InlineCssModule : IHttpModule
{
    void IHttpModule.Init(HttpApplication context)
    {
        context.BeginRequest += new EventHandler(context_BeginRequest);
    }

    // Add our custome InlineCssFilter to Response.Filter
    static void context_BeginRequest(object sender, EventArgs e)
    {
        HttpApplication app = sender as HttpApplication;
        app.Response.Filter = new InlineCssFilter(app.Response.Filter);
    }

    private class InlineCssFilter : Stream
    {
        // The PreMailer object to do the CSS inlining magic
        private static PreMailer pm = new PreMailer();

        /* Stream Implementation abbreviated */

        // Take in the response stream, write out the modified response
        public override void Write(byte[] buffer, int offset, int count)
        {
            byte[] data = new byte[count];
            Buffer.BlockCopy(buffer, offset, data, 0, count);
            string html = System.Text.Encoding.Default.GetString(buffer);

            html = pm.MoveCssInline(html, true);

            byte[] outdata = System.Text.Encoding.Default.GetBytes(html);
            _sink.Write(outdata, 0, outdata.GetLength(0));
        }
    }
}  

(you can find the full HttpModule code in a github gist here)

Now, one simply needs to modify their config file to put it in the ASP.Net Pipeline:

<system.webServer>
    <modules>
        <add name="InlineCssModule" type="{namespace}.InlineCssModule"/>
    </modules>
</system.webServer>

As a result, writing this:

<html>
    <head>
        <style type="text/css">
            div {
                color: red;
            }
            .blue {
                color: blue;
            }
        </style>
    </head>
    <body>
        <div class="blue">I should be blue</div>
    </body>
</html>

renders the following HTML after the filters: (notice the lack of a stylesheet, and the presence of the style tags).

<html>
    <head>

    </head>
    <body>
        <div class="blue" style="color: blue;">I should be blue</div>
    </body>
</html>

Success!

This article was originally posted at http://www.intelligiblebabble.com/feed

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder
United States United States
My name is Leland Richardson. I love learning. At the time of writing this I am 23 years old and live in Houston, TX. I was born in West Palm Beach, Florida, grew up in St. Louis, Missouri, and went to school in Houston, Texas at Rice University.

At Rice I received two degrees: one in Physics and one in Mathematics. I love both. I never received any formal education on Computer Science, however, you will find that most of this blog will be about programming and web development. Nevertheless, I think being a good programmer is about being good at learning, and thinking logically about how to solve problems - of which I think my educational background has more than covered.

Since high-school, I had found that the easiest way to make money was by programming. Programming started off as a hobby and small interest, and slowly grew into a passion.

I have recently started working on a new startup here in Houston, TX. I wont bore you with the details of that just yet, but I am very excited about it and I think we can do big things. We plan to launch our project this year at SXSW 2013. What I will say for now, is that we would like to create a company of talented software developers who are similarly ambitious and want to create cool stuff (and have fun doing it).

Comments and Discussions

 
-- There are no messages in this forum --