Inline CSS style to elements for HTML email in Java
It's from http://stackoverflow.com/questions/4521557/automatically-convert-style-sheets-to-inline-style, added a little code to process selector such as "a:hover".
import java.io.IOException;
import java.util.StringTokenizer;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import com.google.common.base.Strings;
/**
* Css inliner for email,from
* http://stackoverflow.com/questions/4521557/automatically-convert-style-sheets-to-inline-style
*
* @author dennis<xzhuang@avos.com>
* @date 2013-1-9
*/
public class AutomaticCssInliner {
/**
* Hecho por Grekz, http://grekz.wordpress.com
*/
public static Document inlineStyles(String html) throws IOException {
// Document doc = Jsoup.connect("http://mypage.com/inlineme.php").get();
Document doc = Jsoup.parse(html);
String style = "style";
Elements els = doc.select(style);// to get all the style elements
for (Element e : els) {
String styleRules = e.getAllElements().get(0).data().replaceAll("\n", "").trim(), delims =
"{}";
StringTokenizer st = new StringTokenizer(styleRules, delims);
while (st.countTokens() > 1) {
String selector = st.nextToken(), properties = st.nextToken();
// Process selectors such as "a:hover"
if (selector.indexOf(":") > 0) {
selector = selector.substring(0, selector.indexOf(":"));
}
if (Strings.isNullOrEmpty(selector)) {
continue;
}
Elements selectedElements = doc.select(selector);
for (Element selElem : selectedElements) {
String oldProperties = selElem.attr(style);
selElem.attr(
style,
oldProperties.length() > 0 ? concatenateProperties(oldProperties,
properties) : properties);
}
}
e.remove();
}
return doc;
}
private static String concatenateProperties(String oldProp, String newProp) {
oldProp = oldProp.trim();
if (!newProp.endsWith(";")) {
newProp += ";";
}
return newProp + oldProp; // The existing (old) properties should take precedence.
}
}
Written by dennis zhuang
Related protips
2 Responses
Hi, sorry to comment on an old post, but when trying to inline css for emailing, I found your code and try it. unfortunatelly it fails on media queries because there is embedded {} inside the style element : ex :
<style>
.appleLinks, .appleLinksWhite { text-decoration: none !important; }
@media (max-width: 640px) { body[yahoo] .inner { width:100% !important; padding:0; }
</style>
Have you produced any new developpement or alternative ? regards
After hours of trying different manual java code solutions and not being satisfied with results (responsive media query handling issues mostly), I stumbled upon https://github.com/mdedetrich/java-premailer-wrapper which works great as a java solution. But you might be better off running your own "premailer" server. While there is a public api to premailer, I wanted to have my own instance running that I can hit as hard as I want:
https://github.com/TrackIF/premailer-server
Easy to run on ec2 with just a few clicks: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_Ruby_sinatra.html
git clone https://github.com/TrackIF/premailer-server.git
cd premailer-server
eb init (choose latest ruby)
eb create premailer-server --sample
eb deploy
curl --data "html=<your html>" http://your.eb.url