node.jspugembednodemailer

Cannot display image in email template created with pug which is sent with nodemailer


My server.js contains following code to serve the image on server

app.use(express.static('public'));
app.use('/images', express.static('images'));

All the images are stored in '/public/images/' dir with '/public' directory in the root directory of the application.

I am able to view the image when I browse the URL: http://localhost:5001/images/user.jpg as shown below: User.jpg image displayed in browser

My baseMessage.pug template is as below:

   html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    title Document

    include _styles
  body
    .header
        | img(src='/public/images/user.jpg' , alt='logo')

    block content

    .footer
        | Regards,
        br
        | Company Name
        br
        | website: www.abc.com

When I submit the contactus form and I receive the email, the user.jpg image is not displayed in the email, instead the raw code is displayed in the email as shown in below image: image not displayed in email received, displays html code

If anybody can help me to display the image in an email locally?

Thanks & Regards in Advance for your Help.

Hi members, I am adding the updated code which is working correctly, as instructed by @traynor, so that other members get an idea, if they face similar situation. My working updated code is as below:

server.js

const path = require('path');    
// Function to serve all static files
// inside public directory.
app.use(express.static('public'));

contactusController.js

const contactUsModel = require('../models/contactUsModel');
const nodemailer = require("nodemailer");
const path = require('path');
require("dotenv").config();
const pug = require('pug')

mailOptions

const mailOptions = {
            from: process.env.EMAIL,
            to: process.env.EMAIL_TO,
            subject: `${name} Contacted!`,
            html: pug.renderFile(__dirname + '/../views/customerEnquiry.pug', {name: `${name}`,mobileNos:`${mobileNos}`,
              alternateMobileNos:`${alternateMobileNos}`,email:`${email}`,description:`${description}`}),
            attachments: [
                {
                  filename: 'user.jpg',
                  // add the correct path to the file
                  path: path.join(__dirname, '../public/images/user.jpg'),
                  cid: 'user',
                }
            ],
            
          };
          
          transporter.sendMail(mailOptions, (error, info) => {
              if (error) {
                console.log('Error occurred while sending email :', error);                    
              }
              console.log('Email sent successfully!');                 
             responseReturn(res, 201, {message: 'Thank you for contacting us. We will contact you soon!'}) 
          });
    }

Templates in views directory

i) views/_styles.pug

style.
    h2{
        color:black;        
    }
    h3{
        color:grey;
    }
    .footer{
        color:black;
        font-size:15px;
        font-weight: bold;
    }
    .header img {
        height: 111px;
        width: 183px;
    }

ii) views/baseMessage.pug

    html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    title New Enquiry

    include _styles
  body
    .header
        img(src='cid:user' , alt='logo')

    block content

    .footer
        | Regards,
        br
        | Company Name
        br
        | website: abc.com

iii) views/customerEnquiry.pug

extends baseMessage

block content
    h2 Client Details are as below:
    h3 Name: #{name}
    h3 Mobile: #{mobileNos}
    h3 Alternate Mobile Number: #{alternateMobileNos}
    h3 Email: #{email}
    h3 Description: #{description}

And the screenshot of email received with the image is as shown below: enter image description here

Hope the above steps may give an idea for one, who is facing a similar issue.


Solution

  • Try changing two things:

    1. as you're using pipe character (|) in front of the image tag, it's treated as plain text, so remove it, or move it/add text, depending on your layout, for example:

      .header
          img(src='/public/images/user.jpg' , alt='logo')
      

      or

      .header
          | some text before img, but not on the same line as img here
          img(src='/public/images/user.jpg' , alt='logo')
      
    2. you don't need to add images static folder, it's already done in previous setup with public folder (as it's a child folder), so remove app.use('/images', express.static('images'));, and then remove public from the path in the template:

       img(src='images/user.jpg', alt='logo')
      

    edit

    To use the template with nodemailer, try setting up attachments :

    nodemailer:

    attachments: [
      {
        filename: 'user.jpg',
        // add the correct path to the file
        path: path.join(__dirname, '../public/images/user.jpg'),
        cid: 'user',
      },
    ],
    

    template:

    img(src='cid:user', alt='logo')