(This post is a response to Richard Patchet's request for tips on how to actually use premailer)

First of all, premailer is a Python library that converts a document of HTML and tranforms its <style> tags into inline style attributes on the HTML itself. This comes very handy when you need to take a nicely formatted HTML newletter template and prepare it before sending because when you send HTML emails you can't reference an external .css file.

So, here's how to turn it into a command line script.

First, install, then write the script:

$ pip install premailer
$ touch ~/bin/run-premailer.py
$ chmod +x ~/bin/run-premailer.py

Now, you might want to do this differently but this should get you places:


#!/usr/bin/env python

from premailer import transform

def run(files):
    try:
        base_url = [x for x in files if x.count('://')][0]
        files.remove(base_url)
    except IndexError:
        base_url = None

    for file_ in files:
        html = open(file_).read()
        print transform(html, base_url=base_url)

if __name__ == '__main__':
    import sys
    run(sys.argv[1:])

To test it, I've made a sample HTML page that looks like this:


<html>
    <head>
        <title>Test</title>
        <style>
        h1, h2 { color:red; }
        strong {
          text-decoration:none
          }
        p { font-size:2px }
        p.footer { font-size: 1px}
        p a:link { color: blue; }
        </style>
    </head>
    <body>
        <h1>Hi!</h1>
        <p><strong>Yes!</strong></p>
        <p class="footer" style="color:red">Feetnuts</p>
        <p><a href="page2/">Go to page 2</a></p>
    </body>
</html>

Cool. So let's run it: $ run-premailer.py test.html


<html>
  <head>
    <title>Test</title>
  </head>
  <body>
        <h1 style="color:red">Hi!</h1>
        <p style="font-size:2px"><strong style="text-decoration:none">Yes!</strong></p>
        <p style="{color:red; font-size:1px} :link{color:red}">Feetnuts</p>
    <p style="font-size:2px"><a href="page2/" style=":link{color:blue}">Go to page 2</a></p>
    </body>
</html>

Note that premailer supports converting relative URLs, so let's actually using that:
$ run-premailer.py test.html https://www.peterbe.com


<html>
  <head>
    <title>Test</title>
  </head>
  <body>
        <h1 style="color:red">Hi!</h1>
        <p style="font-size:2px"><strong style="text-decoration:none">Yes!</strong></p>
        <p style="{color:red; font-size:1px} :link{color:red}">Feetnuts</p>
    <p style="font-size:2px"><a href="https://www.peterbe.com/page2/" 
     style=":link{color:blue}">Go to page 2</a></p>
    </body>
</html>

I'm sure you can think of many many ways to improve that. Mayhaps use argparse or something fancy to allow for more options. Mayhaps make it so that you can supply named .css files on the command line that get automagically inserted on the fly.

Comments

Michael M Davis

Peter, here I am 10 years later and I find your post provides me a critical solution. Although Gmail has started supporting class based CSS, I find that Slack does not.

Your script to run premailer will allow me to solve the issue foe my html emails sent to Slack.... until they get with the program.

Thank you!

Peter Bengtsson

Comments like that make it all worth it putting out what little open source contributions one can make. THanks!

Michael Davis

Hi Peter, I got it going with python3 I had to convert print to print( ) function. It worked for the simple html test sample. However, when I used a more complex html, my server just hung. Interestingly, I was able to process the same html successfully on the Mailchimp inliner site that I know was your inspiration for writing this. Do you have any tips for me to figure why I can't get it to work with the python script? Do you think it is related python3 which did not exist when you first posted this?

Michael Davis

Correction, I figured out why it was hanging. There was an external css link and I guess it tried to connect / resolve when the python was running. I got it to work perfectly as long as I leave this out.

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Poppins:300,400,700|Montserrat:300,400,700|Source+Sans+Pro:300,300i,700" type="text/css">

Is this a known issue? Perhaps linked css is not supported.

Peter Bengtsson

I'm sorry, I don't know. I haven't used it in 10 years.

Your email will never ever be published.

Related posts