Search code examples
javascriptnode.jsnodemaileremail-templates

email-templates Images are shown in preview but not in Gmail


I'm using email-template package for sending styled emails. Everything seems to work fine in preview of email (preview option is given in package itself. it renders sent email preview in tab if placed true). but when I get email in my gmail account images are not visible. I can tell that paths / images in the setting / code exists because in preview everything is placed just right.

    smtpTransport = nodemailer.createTransport(
      smtpTransport({
        host: 'smtp.gmail.com',
        port: 465,
        secure: true,
        jsonTransport: true,
        auth: {
          user: '[email protected]',
          pass: '123123',
        },
      })
    );
    
    smtpTransport.use('compile', base64ToS3());
    
    const templateWrapper = new Email({
      transport: smtpTransport,
      send: true,
      preview: true,
      views: {
        options: {
          extension: 'ejs',
        },
        root: path.join(__dirname, 'email/html/events'),
      },
      juice: true,
      juiceSettings: {
        tableElements: ['TABLE'],
      },
      juiceResources: {
        preserveImportant: true,
        webResources: {
          relativeTo: path.join(__dirname, 'email/assets'),
          images: true,
        },
      },
    });

Here is my HTML template:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Efys - Welcome</title>
    <style>
      html {
        box-sizing: border-box;
      }
      *,
      *:before,
      *:after {
        box-sizing: border-box;
      }
      body {
        font-family: sans-serif;
        -webkit-font-smoothing: antialiased;
        font-size: 0.8rem;
        line-height: 1.4;
        margin: 0;
        padding: 0;
        -ms-text-size-adjust: 100%;
        -webkit-text-size-adjust: 100%;
      }
      .bg-brand-color-blue-dark {
        background-color: #033e75;
      }
      .bg-brand-color-gold-light {
        background-color: #f0ede6;
      }
      .bg-brand-color-gold-dark {
        background-color: #d0a345;
      }
      .bg-white {
        background-color: #ffffff;
      }

      .brand-color-gold-dark {
        color: #d0a345;
      }
      .brand-color-gold-light {
        color: #f0ede6;
      }
      .brand-color-blue-dark {
        color: #033e75;
      }
      .text-color-white {
        color: #ffffff;
      }
      .text-color-black {
        color: #000000;
      }

      .display-block {
        display: block;
      }
      .margin-top-0rem {
        margin-top: 0;
      }
      .margin-top-1rem {
        margin-top: 1rem;
      }
      .margin-top-2rem {
        margin-top: 2rem;
      }
      .margin-bottom-2rem {
        margin-bottom: 2rem;
      }
      .padding-full-1rem {
        padding: 1rem;
      }
      .padding-full-2rem {
        padding: 2rem;
      }
      .padding-top-2rem {
        padding-top: 2rem;
      }
      .padding-bottom-5rem {
        padding-top: 5rem;
      }

      .border-solid-black {
        border: 1px solid #000000;
      }
      .border-radius-half {
        border-radius: 0.5rem;
      }
      .border-radius-1rem {
        border-radius: 1rem;
      }
      .whitespace {
        white-space: normal;
      }
      .font-size-x1 {
        font-size: 1rem;
      }
      .font-size-x2 {
        font-size: 2rem;
      }

      a,
      a:visited {
        color: blue;
      }
      .text-decoration-none {
        text-decoration: none;
      }
      ol {
        padding-left: 15px;
      }
      p {
        margin-top: 1rem;
        margin-bottom: 0;
      }
      .strong {
        font-weight: bold;
      }
      h3 {
        margin-bottom: 0;
      }
      h3 + p {
        margin-top: 0;
      }
      .inline-icon {
        margin-right: 5px;
      }

      .flexbox {
        display: flex;
      }
      .flex-row {
        flex-direction: row;
      }
      .flex-nowrap {
        flex-wrap: nowrap;
      }
      .flexbox .cell {
        width: 50%;
      }
      .flexbox .cell:nth-child(2) {
        text-align: right;
      }

      .maximum-width {
        width: 100%;
        max-width: 36.25rem;
        margin: 0 auto;
      }
      .logo {
        width: 100%;
        max-width: 36.25rem;
        margin: 0 auto;
      }
      .logo img {
        border: 0 none;
        outline: 0 none;
        width: 100%;
        height: auto;
      }

      @media only screen and (max-width: 480px) {
        .footer > .flexbox .cell {
          width: 100%;
          text-align: center;
        }
        .footer > .flexbox .cell:nth-child(2) {
          text-align: center;
          margin-top: 1rem;
        }
        .footer > .flex-nowrap {
          flex-wrap: wrap;
        }
        .inner-cell.flexbox {
          display: block;
          max-width: 100%;
          margin: 0 auto;
        }
      }
    </style>
  </head>
  <body>
    <div
      class="wrapper display-block bg-brand-color-blue-dark padding-full-1rem"
    >
      <!-- logo -->
      <div class="logo display-block" style="margin: 0 auto;">
        <img
          class="display-block"
          src="efy-registration-header.jpg"
          alt="abc def"
          style="border-top-left-radius: 1rem; border-top-right-radius: 1rem;"
        />
      </div>

      <!-- content -->
      <div
        class="content display-block maximum-width bg-white text-color-black padding-full-2rem"
        style="border-bottom-left-radius: 1rem; border-bottom-right-radius: 1rem;"
      >
        <p class="strong">Dear <%= clientName %>,</p>

        <p>
          You have successfully registered for <%= efyTitle %> on <%= efyDay %> at <%= startTime %>
        </p>
        <p>Your Reference ID is: <%= referenceId %></p>
                <% if (displayAddress) { %>
            <p>Zoom link: <%= address %></p>
                <% } else { %>
            <p>
              Zoom link: You should receive an email update with the link to the
              live efy
            </p>
                <% } %>
        <h3>Zoom Instructions</h3>
        <p>To join a Zoom meeting on a computer or mobile device:</p>
        <ol>
          <li>
            Download the Zoom app from their Download Center
            <a href="https://zoom.us/download" target="_blank"
              >https://zoom.us/download</a
            >. Otherwise, you will be prompted to download and install Zoom when
            you click a join link.
          </li>
        </ol>
      </div>

      <!-- footer -->
      <div
        class="footer maximum-width text-color-white"
        style="margin: 1rem auto 5rem;"
      >
        <div
          class="flexbox flex-row flex-nowrap"
          style="justify-content: center; align-items: flex-end;"
        >
          <div class="cell">
            <div class="flexbox flex-row flex-nowrap inner-cell">
              <div class="col" style="margin-right: 0.5em;">
                <img
                  src="logo_icon.png"
                  alt="abc def"
                  width="50"
                  height="auto"
                />
              </div>
              <div class="col">
                Villa 1, Alwasl Rd. <br />
                Alsafa 2 <br />
                Dubai, United Arab Emirates
              </div>
            </div>

            <p>
              <span class="strong brand-color-gold-dark">T.</span>
              <a
                href="tel:+97143809298"
                class="text-decoration-none strong"
                style="color: #FFFFFF;"
                >+971 (0)4 380 9296</a
              >
            </p>
            <p class="margin-top-0rem">
              <span class="strong brand-color-gold-dark">E.</span>
              <a
                href="mailto:[email protected]"
                class="text-decoration-none strong"
                style="color: #FFFFFF;"
                >[email protected]</a
              >
            </p>
          </div>

          <div class="cell">
            <p>
              <span class="inline-icon"
                ><a href="#"
                  ><img
                    src="icon-facebook.png"
                    width="40"
                    height="auto"/></a
              ></span>
              <span class="inline-icon"
                ><a href="#"
                  ><img
                    src="icon-twitter.png"
                    width="40"
                    height="auto"/></a
              ></span>
              <span class="inline-icon"
                ><a href="#"
                  ><img
                    src="icon-instagram.png"
                    width="40"
                    height="auto"/></a
              ></span>
              <span class="inline-icon"
                ><a href="#"
                  ><img
                    src="icon-linkedin.png"
                    width="40"
                    height="auto"/></a
              ></span>
            </p>
            <p class="brand-color-gold-dark strong">@example.com</p>
            <p class="margin-top-0rem">
              <span class="strong brand-color-gold-dark">W.</span>
              <a
                href="//example.com"
                class="text-decoration-none strong"
                style="color: #FFFFFF;"
                >example.com</a
              >
            </p>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

Solution

  • When you load an HTML page and use the image like below

    <img
      src="icon-linkedin.png"
      width="40"
      height="auto"
    />
    

    It actually tells the browser that, load the image from the same directory from where you loaded the HTML page.

    Here comes the problem. When your email is loaded in the Gmail it will also tell browser the same and the browser will not be able to locate the image.

    Solution:

    If you are sending it from the backend. Then upload the image in any public url. You can upload the image in you frontend hosting and find the link. Then use the link directly. Your image need to be accessible publicly.

    If you do not have any other option or hosting. Upload the image in any public github/gitlab repo and use the link.