mjmlio / mjml

MJML: the only framework that makes responsive-email easy

Home Page:https://mjml.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Extra quotes in CSS url() from <mj-section /> background-url

habovh opened this issue ยท comments

Hi! ๐Ÿ‘‹

Firstly, thanks for your work on this project! ๐Ÿ™‚

Today I used patch-package to patch mjml-section@4.15.3 for the project I'm working on.

I've been facing issues on Gmail with the background-url attribute on the <mj-section> component.

While it is displayed without any issue in Apple Mail (macOS) desktop, a strange behaviour happens when viewing the same email on Gmail in a web browser.

Here's a screenshot summary of the issue:

Please ignore the flag icon issue on Gmail, that's due to Gmail not supporting SVG.

Description Screenshot
Apple Mail, with or without this fix Screenshot 2024-02-26 at 19 04 50
Gmail, without fix. Notice it's the same image appearing twice, though with a different crop. Screenshot 2024-02-26 at 19 04 35
Gmail, with fix Screenshot 2024-02-26 at 19 04 12

I'll open a PR later today.

In the meantime, here is the diff that solved my problem as this might help somebody encountering the same issue:

diff --git a/node_modules/mjml-section/lib/index.js b/node_modules/mjml-section/lib/index.js
index 6fca6e8..dbcb70d 100644
--- a/node_modules/mjml-section/lib/index.js
+++ b/node_modules/mjml-section/lib/index.js
@@ -91,7 +91,7 @@ let MjSection = exports.default = /*#__PURE__*/function (_BodyComponent) {
   }, {
     key: "getBackground",
     value: function getBackground() {
-      return makeBackgroundString([this.getAttribute('background-color'), ...(this.hasBackground() ? [`url('${this.getAttribute('background-url')}')`, this.getBackgroundString(), `/ ${this.getAttribute('background-size')}`, this.getAttribute('background-repeat')] : [])]);
+      return makeBackgroundString([this.getAttribute('background-color'), ...(this.hasBackground() ? [`url(${this.getAttribute('background-url')})`, this.getBackgroundString(), `/ ${this.getAttribute('background-size')}`, this.getAttribute('background-repeat')] : [])]);
     }
   }, {
     key: "getBackgroundString",

This issue body was partially generated by patch-package.

@iRyusa I actually just opened #2834 with a small repro setup if you'd like to check it out!

I should also say that any kind of web browser preview worked fine in all cases, quotes or no quotes. Only Gmail has an issue.

I'm closing this for now as we don't seem to find any way to reproduce ? (cf in PR) Feel free to reopen if you find something

I put together a minimal repro setup that effectively results in the erroneous behaviour shown in my original post. Maybe you'll be able to identify the cause of the issue.

MJML input
<mjml>
  <mj-head>
    <mj-attributes>
      <mj-text padding="0" />
      <mj-image padding="0" />
      <mj-breakpoint width="480px" />
      <mj-table padding-left="0" padding-right="0" />
    </mj-attributes>
    <mj-style inline="inline">
      .shadow {
        -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.05);
        -moz-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.05);
        box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.05);
      }

      .hotel-logo img {
        background: #98989a;
      }
    </mj-style>
  </mj-head>
  <mj-body>
    <mj-wrapper
      border-radius="8px"
      css-class="shadow"
      padding="20px"
    >
      <mj-section
        padding="0"
        background-url="https://cdn.allsquaregolf.com/pictures/pictures/001/379/920/large/travel_package_115_picture.jpg"
        background-size="cover"
        background-position="center center"
        background-repeat="no-repeat"
        background-color="#d0d0d3"
        border-radius="12px"
      >
        <mj-group>
          <mj-column width="20%" padding="10px" vertical-align="bottom">
            <mj-image
              align="left"
              src="https://cdn.allsquaregolf.com/pictures/pictures/001/371/500/sq_me/hotel_2971878_logo.jpg"
              border-radius="8px"
              css-class="hotel-logo"
              border="1px solid #eeeeee"
            />
          </mj-column>
          <mj-column width="80%" padding="10px" padding-bottom="180px">
            <mj-image
              src="https://cdn.allsquaregolf.com/resources/assets/png/countries/4x3/pt.png"
              border-radius="2px"
              width="20px"
              border="2px solid #eeeeee"
              css-class=""
              align="right"
            />
          </mj-column>
        </mj-group>
      </mj-section>
    </mj-wrapper>
  </mj-body>
</mjml>
HTML Output
<!doctype html>
<html lang="und" dir="auto" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">

<head>
  <title></title>
  <!--[if !mso]><!-->
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <!--<![endif]-->
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style type="text/css">
    #outlook a {
      padding: 0;
    }

    body {
      margin: 0;
      padding: 0;
      -webkit-text-size-adjust: 100%;
      -ms-text-size-adjust: 100%;
    }

    table,
    td {
      border-collapse: collapse;
      mso-table-lspace: 0pt;
      mso-table-rspace: 0pt;
    }

    img {
      border: 0;
      height: auto;
      line-height: 100%;
      outline: none;
      text-decoration: none;
      -ms-interpolation-mode: bicubic;
    }

    p {
      display: block;
      margin: 13px 0;
    }

  </style>
  <!--[if mso]>
    <noscript>
    <xml>
    <o:OfficeDocumentSettings>
      <o:AllowPNG/>
      <o:PixelsPerInch>96</o:PixelsPerInch>
    </o:OfficeDocumentSettings>
    </xml>
    </noscript>
    <![endif]-->
  <!--[if lte mso 11]>
    <style type="text/css">
      .mj-outlook-group-fix { width:100% !important; }
    </style>
    <![endif]-->
  <style type="text/css">
    @media only screen and (min-width:480px) {
      .mj-column-per-100 {
        width: 100% !important;
        max-width: 100%;
      }

      .mj-column-per-20 {
        width: 20% !important;
        max-width: 20%;
      }

      .mj-column-per-80 {
        width: 80% !important;
        max-width: 80%;
      }
    }

  </style>
  <style media="screen and (min-width:480px)">
    .moz-text-html .mj-column-per-100 {
      width: 100% !important;
      max-width: 100%;
    }

    .moz-text-html .mj-column-per-20 {
      width: 20% !important;
      max-width: 20%;
    }

    .moz-text-html .mj-column-per-80 {
      width: 80% !important;
      max-width: 80%;
    }

  </style>
  <style type="text/css">
    @media only screen and (max-width:479px) {
      table.mj-full-width-mobile {
        width: 100% !important;
      }

      td.mj-full-width-mobile {
        width: auto !important;
      }
    }

  </style>
</head>

<body style="word-spacing:normal;">
  <div style lang="und" dir="auto">
    <!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="shadow-outlook" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
    <div class="shadow" style="-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.05); -moz-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.05); box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.05); margin: 0px auto; border-radius: 8px; max-width: 600px;">
      <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;border-radius:8px;">
        <tbody>
          <tr>
            <td style="direction:ltr;font-size:0px;padding:20px;text-align:center;">
              <!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:560px;" width="560" bgcolor="#d0d0d3" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><v:rect style="width:560px;" xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false"><v:fill origin="0, 0" position="0, 0" src="https://cdn.allsquaregolf.com/pictures/pictures/001/379/920/large/travel_package_115_picture.jpg" color="#d0d0d3" type="frame" size="1,1" aspect="atleast" /><v:textbox style="mso-fit-shape-to-text:true" inset="0,0,0,0"><![endif]-->
              <div style="background:#d0d0d3 url('https://cdn.allsquaregolf.com/pictures/pictures/001/379/920/large/travel_package_115_picture.jpg') center center / cover no-repeat;background-position:center center;background-repeat:no-repeat;background-size:cover;margin:0px auto;border-radius:12px;max-width:560px;">
                <div style="line-height:0;font-size:0;">
                  <table align="center" background="https://cdn.allsquaregolf.com/pictures/pictures/001/379/920/large/travel_package_115_picture.jpg" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#d0d0d3 url('https://cdn.allsquaregolf.com/pictures/pictures/001/379/920/large/travel_package_115_picture.jpg') center center / cover no-repeat;background-position:center center;background-repeat:no-repeat;background-size:cover;width:100%;border-radius:12px;">
                    <tbody>
                      <tr>
                        <td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
                          <!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="width:560px;" ><![endif]-->
                          <div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0;line-height:0;text-align:left;display:inline-block;width:100%;direction:ltr;">
                            <!--[if mso | IE]><table border="0" cellpadding="0" cellspacing="0" role="presentation" ><tr><td style="vertical-align:bottom;width:112px;" ><![endif]-->
                            <div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:bottom;width:20%;">
                              <table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%">
                                <tbody>
                                  <tr>
                                    <td style="vertical-align:bottom;padding:10px;">
                                      <table border="0" cellpadding="0" cellspacing="0" role="presentation" style width="100%">
                                        <tbody>
                                          <tr>
                                            <td align="left" class="hotel-logo" style="font-size:0px;padding:0;word-break:break-word;">
                                              <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;">
                                                <tbody>
                                                  <tr>
                                                    <td style="width:90px;">
                                                      <img alt src="https://cdn.allsquaregolf.com/pictures/pictures/001/371/500/sq_me/hotel_2971878_logo.jpg" style="background: #98989a; border: 1px solid #eeeeee; border-radius: 8px; display: block; outline: none; text-decoration: none; height: auto; width: 100%; font-size: 13px;" width="90" height="auto">
                                                    </td>
                                                  </tr>
                                                </tbody>
                                              </table>
                                            </td>
                                          </tr>
                                        </tbody>
                                      </table>
                                    </td>
                                  </tr>
                                </tbody>
                              </table>
                            </div>
                            <!--[if mso | IE]></td><td style="vertical-align:top;width:448px;" ><![endif]-->
                            <div class="mj-column-per-80 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:80%;">
                              <table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%">
                                <tbody>
                                  <tr>
                                    <td style="vertical-align:top;padding:10px;padding-bottom:180px;">
                                      <table border="0" cellpadding="0" cellspacing="0" role="presentation" style width="100%">
                                        <tbody>
                                          <tr>
                                            <td align="right" class style="font-size:0px;padding:0;word-break:break-word;">
                                              <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;">
                                                <tbody>
                                                  <tr>
                                                    <td style="width:20px;">
                                                      <img alt src="https://cdn.allsquaregolf.com/resources/assets/png/countries/4x3/pt.png" style="border:2px solid #eeeeee;border-radius:2px;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:13px;" width="20" height="auto">
                                                    </td>
                                                  </tr>
                                                </tbody>
                                              </table>
                                            </td>
                                          </tr>
                                        </tbody>
                                      </table>
                                    </td>
                                  </tr>
                                </tbody>
                              </table>
                            </div>
                            <!--[if mso | IE]></td></tr></table><![endif]-->
                          </div>
                          <!--[if mso | IE]></td></tr></table><![endif]-->
                        </td>
                      </tr>
                    </tbody>
                  </table>
                </div>
              </div>
              <!--[if mso | IE]></v:textbox></v:rect></td></tr></table></td></tr></table><![endif]-->
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    <!--[if mso | IE]></td></tr></table><![endif]-->
  </div>
</body>

</html>
Gmail screenshot macOS Mail.app screenshot
Screenshot 2024-03-06 at 19 52 31 Screenshot 2024-03-06 at 19 52 42

Happening on MJML 4.15.3, and fixed by the changes from #2834.

This is super weird... I'm sending using Mandrill, maybe that's where the issue comes from? But to be honest it's so popular that I would expect the issue to have been raised already...

Found the issue.

It seems that somehow the single quotes within the style attribute get escaped to &#039;, resulting in Gmail not parsing the style attribute properly.

Here's an extract from the RAW email as it was received by the client (both Mail.app and Gmail website):

<div style="background:#d0d0d3 url(&#039;https://cdn.allsquaregolf.com/pictures/pictures/001/379/920/large/travel_package_115_picture.jpg&#039;) center center / cover no-repeat;background-position:center center;background-repeat:no-repeat;background-size:cover;margin:0px auto;border-radius:12px;max-width:560px;">
                <div style="line-height:0;font-size:0;">
                  <table align="center" background="https://cdn.allsquaregolf.com/pictures/pictures/001/379/920/large/travel_package_115_picture.jpg" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#d0d0d3 url(&#039;https://cdn.allsquaregolf.com/pictures/pictures/001/379/920/large/travel_package_115_picture.jpg&#039;) center center / cover no-repeat:;background-position:center center;background-repeat:no-repeat;background-size:cover;width:100%;border-radius:12px;border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;">

So I guess I need to escalate this issue to Mandrill. Good news is that quotes are optional as per the specs, but they definitely shouldn't be escaped this way.

Sorry about the false alarm, I really thought I could be contributing here because I very much like MJML but oh well.

For anyone using Mailchimp and/or Mandrill, you may reference this issue in a support request. You can also mention the ticket number I just opened to raise their awareness of the issue.

Mailchimp transactional support ticket number: 12275845.