How can I send HTML mails with included CSS with PHPMailer?

31,975

Solution 1

There's is a way...

    $body = <<< YOUR_HTML_WITH_CSS_STYLE_TAGS
<html>
<head>
    <style>
        body * {width:1px;}
        #adiv {padding:2px;}
        .aclass {margin:3px;}
    </style>
</head>
<body>
    <div>
        some html
    </div>
    <div id="adiv">
        <p class="aclass">
        </p>
    </div>
</body>
</html>
YOUR_HTML_WITH_CSS_STYLE_TAGS;
    $doc = new DOMDocument();
    @$doc->loadHTML($body);
    $xpd = new DOMXPath($doc);
    0&&$node = new DOMElement();
    $result = $xpd->query('//img');
    foreach($result as $node){
        $attr = $node->getAttribute('src');
        $re = '/(http:\/\/.*?)?(\/.*+)/i';
        if(preg_match_all($re, $attr, $matches)){
            if(!empty($matches[1][0])&&0)
                continue;
            $attr = 'http://'.$_SERVER['HTTP_HOST'].$matches[2][0];
        }
        $node->setAttribute('src',$attr);
    }
    false&&$node=new DOMElement()&&$child=new DOMElement();
    $result = $xpd->query('//style/..');
    foreach($result as $node){
        foreach($node->childNodes as $child){
            if(strtolower($child->nodeName)=='style'){
                $node->removeChild($child);
                $css = $child->textContent;
                $re = '/(.*?)\{([^}]+)\}/';
                if(preg_match_all($re, $css, $matches)){
                    foreach($matches[1] as $idx=>$css_selector){
                        $css_text = $matches[2][$idx];
                        $css_text = preg_replace('/\s+/',' ',$css_text);
                        $css = new CSSQuery($doc);
                        foreach($css->query($css_selector) as $selected_node){
                            $style = $selected_node->getAttribute('style');
                            $selected_node->setAttribute('style', $style?$css_text:$style.';'.$css_text);
                        }
                    }
                }
            }
        }
    }
    $body = $doc->saveHTML();

That code will generate an HTML output in $body like this:

<html>
<head>
</head>
<body>
    <div style="width:1px;">
        some html
    </div>
    <div id="adiv" style="width:1px;padding:2px;">
        <p class="aclass" style="width:1px;margin:3px;">
        </p>
    </div>
</body>
</html>

The CSSQuery class can be found at phpclasses.org. This implementation is based on the fact that most webmails will only allow to add style by an inline tag attribute style and not through style tags or link tags.

It's pretty much limited and with a restricted syntax because of the regular expression it's kind of simple, but it's still better than write by your own the inline style attributes in each HTML tag.

Solution 2

CSS support in e-mail is very limited, at least. The biggest issue is that different clients support different sets of CSS-properties.

You provide very little context for us to work with.

  • How is your e-mail showing? Is CSS not parsed at all? Is your CSS showing on-screen as text?
  • How does your CSS look?
  • How does your e-mail template look?

For more information on CSS support in e-mail, please refer to this excellent overview.

Solution 3

Here is a really good SitePoint article on HTML emails, "How to Code HTML Email Newsletters".

Solution 4

Some Email Clients will strip out the <head> section so put your <style></style> tags within the <body>.

Solution 5

HTML and CSS is fraught with pain and frustration. Nothing to do with PHP, it's apparent that most implementations coughoutlookcough were and remain archaic.

This is the only area where I would advise this (and someone else might have a better understanding/plan*), but you should look at cutting the CSS and writing mid-90's style html with <table>, <font> and <hr> tags (oh my)

** please share :)*

Share:
31,975
gizmo
Author by

gizmo

Updated on July 05, 2020

Comments

  • gizmo
    gizmo almost 4 years

    I've problem with sending HTML mails with PHPMailer. I make a Smarty template and I got all the HTML code from it. But when I send mail, I got the mail without included CSS (it's only background-color, font or something like that). In PHPMailer I set that the mail is HTML.

    Is there any way to send HTML mail with included CSS?

  • gizmo
    gizmo over 15 years
    I have CSS into the html header inside the mail . But thx for advice
  • gizmo
    gizmo over 15 years
    as I said, it is included in head of the template
  • gizmo
    gizmo over 15 years
    well the CSS is really minimalistic and yes I have <table>, but only I really want is to change background color or some basic things.
  • gizmo
    gizmo over 15 years
    1. CSS is not showing at all, only the HTML is rendered 2. my css looks: pastebin.com/m5787d770 3. and complete template looks: pastebin.com/m346a5475 Thank you for the link, I appreciate it.
  • Rhys
    Rhys over 15 years
    what email client are you using?
  • gizmo
    gizmo over 15 years
    I saw that gmail doesn't support <style> at all :)
  • gizmo
    gizmo over 15 years
    I will do like that, I think it's the only option now :)
  • ADTC
    ADTC over 7 years
    Ambitious, but appears to fail with larger HTML: [:error] PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4096 bytes) in .../CSSQuery.php on line 709. This line is if (is_array($arr)).
  • useless
    useless over 7 years
    note that this is a very old thread, I dont even recommend myself to do this. nowadays gmail even supports media queries. so this is completely outdated. also 128Mb is not much memory.
  • ADTC
    ADTC over 7 years
    Yeah, I resorted to another approach, that is to generate the HTML email using a dedicated PHP file and the ob_start()/ob_get_clean() combo. To workaround the issue of having to use inline styles, I created PHP variables to hold common styles and injected them wherever necessary. Re: email client support: It's good that Gmail has better support for CSS in emails, but that's not good enough when we don't know what email client the recipient will be using. Unlike browsers that have a more predictable update cycle, you may have clients who still use Outlook 1995.
  • useless
    useless over 7 years
    I dont like to promote pages, but there is a very good tool i used for that, it's called litmus. it really helps you to test emails designs for multiple platforms, webmails, etc. Unfortunately it's paid.