简体   繁体   English

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

[英]Pass variable to html template in nodemailer

I want to send email with nodemailer using html template.我想使用 html 模板通过 nodemailer 发送电子邮件。 In that template I need to inject some dynamically some variables and I really can't do that.在那个模板中,我需要动态注入一些变量,但我真的做不到。 My code:我的代码:

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);
    }
});

Let's say I want in emailWithPDF.html something like this:假设我想要在 emailWithPDF.html 中是这样的:

Hello {{username}}!

I've found some examples, where was smth like this:我找到了一些例子,像这样的smth:

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

but I want it in separate html file.但我希望它在单独的 html 文件中。 Is it possible?可能吗?

What you can do is read the HTML file using fs module in node and then replace the elements that you want changed in the html string using handlebars您可以做的是使用节点中的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);
        }
    });
});

I use it in all my projects.我在所有项目中都使用它。 more clean and up to date and understandable.更干净,最新且易于理解。 callback hell doesn't exist.回调地狱不存在。 sendMail.ts The html file reads with handlebar, puts the relevant variables into the contents, and sends. 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 isn't a good idea because you'll have to restore old strings or create a backup file to be able to change them another time, also it won't be asynchrone and it will cause a problem in every way!字符串替换不是一个好主意,因为您必须恢复旧字符串或创建备份文件才能再次更改它们,而且它不会是异步的,它会在各个方面造成问题! you can do it much easier and more cleaner :您可以更轻松更清洁地进行操作:

just go to your mail options and add context with your variables:只需转到您的邮件选项并使用您的变量添加上下文

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

next thing to do is openning your html file and call your variables like:接下来要做的是打开您的 html 文件并调用您的变量,例如:

{{username}} {{用户名}}

If you're using Nodemailer 2.0.0 or higher, check this documentation: https://community.nodemailer.com/2-0-0-beta/templating/ There they explain how to make use of external rendering with templates like that:如果您使用的是 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'));

They also give this example:他们还举了这个例子:

// 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',
});

where you see how to pass variables.您可以在其中看到如何传递变量。

You will need the email-templates module: https://github.com/crocodilejs/node-email-templates and a template engine of your choice.您将需要email-templates模块: https ://github.com/crocodilejs/node-email-templates 和您选择的模板引擎。

Also in the documentation of email-templates you'll find how to make your file structure in order that your templates can be found:此外,在email-templates的文档中,您将找到如何制作文件结构以便可以找到您的模板:

html.{{ext}} (required) - for html format of email html.{{ext}}(必需)- 用于电子邮件的 html 格式

text.{{ext}} (optional) - for text format of email style. text.{{ext}}(可选)- 用于电子邮件样式的文本格式。

{{ext}}(optional) - styles for html format subject. {{ext}}(可选)- html 格式主题的样式。

{{ext}}(optional) - for subject of email {{ext}}(可选)- 用于电子邮件主题

See supported template engines for possible template engine extensions (eg .ejs, .jade, .nunjucks) to use for the value of {{ext}} above.请参阅支持的模板引擎以了解可能的模板引擎扩展(例如 .ejs、.jade、.nunjucks)以用于上述 {{ext}} 的值。

You may prefix any file name with anything you like to help you identify the files more easily in your IDE.您可以在任何文件名前加上您喜欢的任何内容,以帮助您在 IDE 中更轻松地识别文件。 The only requirement is that the filename contains html., text., style., and subject.唯一的要求是文件名包含 html.、text.、style. 和主题。 respectively.分别。

For those using pug as templating engine对于那些使用 pug 作为模板引擎的人

Just a quick way to render a template in a separate file using pug's render function:使用 pug 的 render 函数在单独的文件中渲染模板的快速方法:

// 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}

See https://pugjs.org/api/getting-started.html for further details.有关详细信息,请参阅https://pugjs.org/api/getting-started.html Note that this will cause template re-compilation every time a message is sent.请注意,这将导致每次发送消息时重新编译模板。 That is fine for occasional e-mail deliveries.这对于偶尔发送的电子邮件来说很好。 If you send tons of e-mails, you can cache the compiled template to work around that.如果您发送大量电子邮件,您可以缓存已编译的模板来解决这个问题。 Check out pug docs for that set up if you need it.如果需要,请查看该设置的哈巴狗文档。

Create one file emailTemplates.js there yo can store each template as a function创建一个文件emailTemplates.js在那里你可以将每个模板存储为一个函数

emailTemplates.js电子邮件模板.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}

Then in the controllers call any templateFunction and store in output varaible然后在控制器中调用任何模板函数并存储在输出变量中

controller.js控制器.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,
    }
 

You can use a Web Request to build an html template using handlebars or any other engine.您可以使用Web 请求使用handlebars或任何其他引擎构建 html 模板。

Create a template创建模板

First you must create an html template for the email body.首先,您必须为电子邮件正文创建一个 html 模板。 In this example I used a handlebars hbs file.在此示例中,我使用了车把hbs文件。

在此处输入图像描述

Do your design stuff with html and add the variables that you will need in the message:使用 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>

Create a template request创建模板请求

You must create the access to this view.您必须创建对此视图的访问权。 Then a request is created where we can send the template name as an url parameter to make the request parameterizable for other templates.然后创建一个请求,我们可以将模板名称作为 url 参数发送,以使请求可参数化其他模板。

const web = express.Router()

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

Mail function邮件功能

Finally you can send the email after making the request to the template.最后,您可以在向模板提出请求后发送电子邮件。 You can use a function like the following:您可以使用如下函数:

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)
        })
    })
}

This can be done without templates.这可以在没有模板的情况下完成。

Try changing it to this:尝试将其更改为:

`Hello ${username}!`

Make sure that these are not inverted commas but back ticks.确保这些不是引号而是反引号。

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

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

You can also use async/await syntax or promises and avoid using callbacks, like I did here, using async/await:您还可以使用 async/await 语法或承诺,并避免使用回调,就像我在这里所做的那样,使用 async/await:

const fs = require("fs").promises;
const path = require("path");
const handlebars = require("handlebars");
const relativeTemplatePath = "../../html/reset-pw-email-template.html";

function sendEmail(){
    const templatePath = path.join(__dirname, relativeTemplatePath);
    const templateFile = await fs.readFile(templatePath, 'utf-8');
    const template = handlebars.compile(templateFile);
    const replacements = {
        username:""
    };
    const finalHtml = template(replacements);
    const mailOptions = {
       from: "",
       to: "",
       subject: "",
       html: finalHtml,
    };
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM