Search code examples
htmlnode.jsexpressejsnodemailer

Create dynamic html with ejs and node


I am trying to send dynamic mail to email IDs submitted using a form.
Below is my app.js code.

//Importing Packages
var express     = require('express');
var nodemailer  = require('nodemailer');
var bodyParser  = require('body-parser');


//Applying Express,Ejs to Node
app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended:true}));
//Creating Nodemailer Transport
var transporter = nodemailer.createTransport({
    host: 'smtp.zoho.com',
    port: 465,
    secure: true,
    auth: {
        user: 'noreply@*****.com',
        pass: '******'
    }
});

//Root Route Setup
app.get('/', function(req, res){
    res.render("landing")
});

//Route to send the mail
app.post('/send', function(req,res){
    //Setting up Email settings
    var mailOptions = {
        from: 'noreply@*****.com',
        to : req.body.mail,
        subject: 'Verify Your Email',
        generateTextFromHtml : true,
        html: { path: './tmpl.html'}
    };

    //Execute this to send the mail
    transporter.sendMail(mailOptions, function(error, response){
        if(error) {
            console.log(error);
        } else {
            console.log(response);
        }
    });
    res.send("Mail succesfully sent!")
});

//Server &Port Settings
app.listen(3333, function(){
    console.log("Server is running...")
});

Below is my Form page code, which is an ejs file

<form action="/send" method="POST">
    <input type="email" name="mail" placeholder="Enter your email">
    <input type="text" name="name" placeholder="Enter your name">
    <input type="submit">
</form>

and below is my html template which is being mailed to the ID submitted using the form.

<html>
<body>

    <h1>Hello World!</h1>
    <a href="http://www.google/com">Link</a>

</body>
</html>

How do I read the Name from the form and then include that in the Email, so that in each email, I can address to that person using a variable, like "Hello Mr {{name}}"

I am not able to figure out how to pass variable to the html file without emails blocking it as I am not able to use Javascript using Script tag inside the HTML file becuase almost all of the mail providers block JS in Email!

Can someone help me out with this please?


Solution

  • You can use the ejs templating engine you've already set up with express. Calling app.render() will render the template you specify as a string and pass it to its callback, plus whatever data you pass into it. So its a little ugly with callbacks, but this is a solution that doesnt add any dependencies.

    In short, make your email template an ejs file named verifyEmail.ejs, use app.render() to render it with data from the POST request body before sending the email from the app.render callback.


    // app.js
    
    app.post('/send', function(req,res){
        // Use the ejs rendering engine to render your email 
        // Pass in the 'name' variable that is used in the template file
        app.render('verifyEmail', {name: req.body.name}, function(err, html){ 
        if (err) {
            console.log('error rendering email template:', err) 
            return
        } else {
        //Setting up Email settings
            var mailOptions = {
                from: 'noreply@*****.com',
                to : req.body.mail,
                subject: 'Verify Your Email',
                generateTextFromHtml : true,
                // pass the rendered html string in as your html 
                html: html 
            };
    
            //Execute this to send the mail
            transporter.sendMail(mailOptions, function(error, response){
                if(error) {
                    console.log(error);
                    res.send('Mail Error! Try again')
                } else {
                    console.log(response);
    
                    res.send("Mail succesfully sent!")
                }
            });
          } 
        }); 
    });
    

    I added some error handling, and notifying the user if the email is not sent due to a server error. The way you were calling res.send() before would tell the user the email was sent successfully before it was even sent.


    Place your template folder in the same directory as your "landing" template, or wherever else your ejs files are.

    Insert data into your template by calling a variable between <%= %> tags. Populate it by passing a variable of the same name when rendering the template.

    From the ejs docs:

    ... everything inside <%= %> tags inserts itself into the returned HTML string.

    // views/verifyEmail.ejs
    
    <html>
    <body>
    
        <h1>Hello <%= name %></h1>
        <a href="http://www.google/com">Link</a>
    
    </body>
    </html>