将变量传递给 nodemailer 中的 html 模板

Pass variable to html template in nodemailer

我想使用 html 模板通过 nodemailer 发送电子邮件。在该模板中,我需要动态注入一些变量,但我真的做不到。我的代码:

var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');

smtpTransport = nodemailer.createTransport(smtpTransport({
    host: mailConfig.host,
    secure: mailConfig.secure,
    port: mailConfig.port,
    auth: {
        user: mailConfig.auth.user,
        pass: mailConfig.auth.pass
    }
}));
var mailOptions = {
    from: 'my@email.com',
    to : 'some@email.com',
    subject : 'test subject',
    html : { path: 'app/public/pages/emailWithPDF.html' }
};
smtpTransport.sendMail(mailOptions, function (error, response) {
    if (error) {
        console.log(error);
        callback(error);
    }
});

假设我想要 emailWithPDF.html 这样的东西:

Hello {{username}}!

我找到了一些例子,哪里是这样的:

...
html: '<p>Hello {{username}}</p>'
...

但我想将它放在单独的 html 文件中。可能吗?

如果您使用的是 Nodemailer 2.0.0 或更高版本,请查看此文档: https://community.nodemailer.com/2-0-0-beta/templating/ 他们在那里解释了如何使用这样的模板进行外部渲染:

// external renderer
var EmailTemplate = require('email-templates').EmailTemplate;
var send = transporter.templateSender(new EmailTemplate('template/directory'));

他们还给出了这个例子:

// create template based sender function
// assumes text.{ext} and html.{ext} in template/directory
var sendPwdReminder = transporter.templateSender(new EmailTemplate('template/directory'), {
    from: 'sender@example.com',
});

你在哪里看到如何传递变量。

您将需要 email-templates 模块:https://github.com/crocodilejs/node-email-templates 和您选择的模板引擎。

另外,在 email-templates 的文档中,您将找到如何创建文件结构以便找到您的模板:

html.{{ext}} (required) - for html format of email

text.{{ext}} (optional) - for text format of email style.

{{ext}}(optional) - styles for html format subject.

{{ext}}(optional) - for subject of email

See supported template engines for possible template engine extensions (e.g. .ejs, .jade, .nunjucks) to use for the value of {{ext}} above.

You may prefix any file name with anything you like to help you identify the files more easily in your IDE. The only requirement is that the filename contains html., text., style., and subject. respectively.

您可以做的是使用节点中的 fs 模块读取 HTML 文件,然后使用 handlebars 替换 html 字符串中您想要更改的元素

var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var handlebars = require('handlebars');
var fs = require('fs');

var readHTMLFile = function(path, callback) {
    fs.readFile(path, {encoding: 'utf-8'}, function (err, html) {
        if (err) {
           callback(err); 
           throw err;
            
        }
        else {
            callback(null, html);
        }
    });
};

smtpTransport = nodemailer.createTransport(smtpTransport({
    host: mailConfig.host,
    secure: mailConfig.secure,
    port: mailConfig.port,
    auth: {
        user: mailConfig.auth.user,
        pass: mailConfig.auth.pass
    }
}));

readHTMLFile(__dirname + 'app/public/pages/emailWithPDF.html', function(err, html) {
    var template = handlebars.compile(html);
    var replacements = {
         username: "John Doe"
    };
    var htmlToSend = template(replacements);
    var mailOptions = {
        from: 'my@email.com',
        to : 'some@email.com',
        subject : 'test subject',
        html : htmlToSend
     };
    smtpTransport.sendMail(mailOptions, function (error, response) {
        if (error) {
            console.log(error);
            callback(error);
        }
    });
});

这可以在没有模板的情况下完成。

尝试将其更改为:

`Hello ${username}!`

确保这些不是引号而是反引号。

您可以使用 Web 请求 通过 handlebars 或任何其他引擎构建 html 模板。

创建模板

首先,您必须为电子邮件正文创建一个 html 模板。在这个例子中,我使用了车把 hbs 文件。

使用 html 进行设计并在消息中添加您需要的变量:

   <!DOCTYPE html>
   <html>
    <head>
        <meta name="viewport" content="width=device-width">
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Welcome Email Template</title>
    </head>
    <body>
     <p style="font-size: 14px; font-weight: normal;">Hi {{data.name}}</p>
    </body>
   </html>

创建模板请求

您必须创建对此视图的访问权限。然后创建一个请求,我们可以在其中将模板名称作为 url 参数发送,以使请求可参数化为其他模板。

const web = express.Router()

web.post('/template/email/:template', function(req, res) {
  res.render(`templates/email/${req.params.template}`, {
    data: req.body        
  })
})

邮件功能

您终于可以在向模板发出请求后发送电子邮件了。您可以使用如下函数:

const nodemailer = require('nodemailer')
const request = require("request")

function sendEmail(toEmail, subject, templateFile) {
    var options = {
        uri: `http://localhost:3000/template/email/${templateFile}`,
        method: 'POST',
        json: { name: "Jon Snow" } // All the information that needs to be sent
    };  
    request(options, function (error, response, body) {
        if (error) console.log(error)
        var transporter = nodemailer.createTransport({
            host: mailConfig.host,
            port: mailConfig.port,
            secure: true,
            auth: {
                user: mailConfig.account,
                pass: mailConfig.password
            }
        })
        var mailOptions = {
            from: mailConfig.account,
            to: toEmail,
            subject: subject,
            html: body
        }       
        transporter.sendMail(mailOptions, function(error, info) {
            if (error) console.log(error)
        })
    })
}

对于那些使用 pug 作为模板引擎的人

这是一种使用 pug 的渲染功能在单独的文件中渲染模板的快速方法:

// function to send an e-mail. Assumes you've got nodemailer and pug templating engine installed. 
// transporter object relates to nodemailer, see nodemailer docs for details
const nodemailer = require('nodemailer');
const pug = require('pug');
function send_some_mail(iterable){
var message = {
  from: 'from@example.com',
  to: 'to@example.com',
  subject: 'Message title',
  html: pug.renderFile(__dirname + 'path_to_template.pug', {iterable: iterable})
};
transporter.sendMail(message, function(err, info){...})
}

// template.pug
each item in iterable
li
  p #{item.name}

有关详细信息,请参阅 https://pugjs.org/api/getting-started.html。请注意,这将导致每次发送消息时都重新编译模板。这对于偶尔发送电子邮件来说很好。如果您发送大量电子邮件,您可以缓存已编译的模板来解决这个问题。如果需要,请查看 pug 文档以了解该设置。

我在我所有的项目中都使用它。更干净,最新且易于理解。回调地狱不存在。 sendMail.ts html文件用handlebar读取,将相关变量放入内容,发送

import * as nodemailer from 'nodemailer';
import * as handlebars from 'handlebars';
import * as fs from 'fs';
import * as path from 'path';

export async function sendEmail(email: string, subject: string, url: string) {
  const filePath = path.join(__dirname, '../emails/password-reset.html');
  const source = fs.readFileSync(filePath, 'utf-8').toString();
  const template = handlebars.compile(source);
  const replacements = {
    username: "Umut YEREBAKMAZ"
  };
  const htmlToSend = template(replacements);
  const transporter = nodemailer.createTransport({
    host: "smtp.mailtrap.io",
    port: 2525, // 587
    secure: false,
    auth: {
      user: "fg7f6g7g67",
      pass: "asds7ds7d6"
    }
  });
  const mailOptions = {
    from: '"noreply@yourdomain.com" <noreply@yourdomain.com>',
    to: email,
    subject: subject,
    text: url,
    html: htmlToSend
  };
  const info = await transporter.sendMail(mailOptions);
  console.log("Message sent: %s", info.messageId);
  console.log("Preview URL: %s", "https://mailtrap.io/inboxes/test/messages/");

}

String replace 不是一个好主意,因为您必须恢复旧字符串或创建备份文件以便下次更改它们,而且它不会'不是异步的,它会在各个方面引起问题! 你可以做到 更容易并且更清洁

只需转到您的邮件选项并添加上下文和您的变量:

var mailOptions = {
  from: 'nginx-iwnl@gmail.com',
  to: 'username@gmail.com',
  subject: 'Sending email',
  template: 'yourTemplate',
  context: {                  // <=
    username: username,
    whatever: variable
  }
};

接下来 要做的是打开您的 html 文件并调用您的变量,例如:

{{用户名}}

有一种简单的方法可以在 nodemailer 的 html 中插入变量。

    html:"<p>Your message "+variable1+".Message continueous "+variable 2+"</p>"

创建一个文件emailTemplates.js在那里你可以将每个模板存储为一个函数

emailTemplates.js

const newsLetterEmail = (clientName) => `<p>Hi ${clientName}, here you have today news.</p>`
const welcomeEmail = (clientName, username) => `<p>Welcome ${clientName}, your username is ${username}.</p>`

export {newsLetterEmail, welcomeEmail}

然后在控制器中调用任何 templateFunction 并存储在输出变量中

controller.js

import {welcomeEmail} from './emailTeamplates.js'

const registerUser = async(req, res) => {
    const {name, usename, email} = req.body
    // User register code....
    const output = welcomeEmail(name, username)

    let mailOptions = {
        from: '"Welcome" <welcome@welcome.com>',
        to: 'client@gmail.com',
        subject: 'Welcome email!',
        text: 'Hello World',
        html: output,
    }