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

Posted

技术标签:

【中文标题】将变量传递给nodemailer中的html模板【英文标题】:Pass variable to html template in nodemailer 【发布时间】:2017-01-22 04:31:16 【问题描述】:

我想使用 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 文件中。有可能吗?

【问题讨论】:

【参考方案1】:

如果您使用的是 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(必需)- 用于电子邮件的 html 格式

text.ext(可选)- 用于电子邮件样式的文本格式。

ext(可选)- html 格式主题的样式。

ext(可选)- 用于电子邮件主题

查看支持的模板引擎,了解可能的模板引擎扩展(例如 .ejs、.jade、.nunjucks)以用于上述 ext 的值。

您可以在任何文件名前加上您喜欢的任何内容,以帮助您在 IDE 中更轻松地识别文件。唯一的要求是文件名包含 html.、text.、style. 和主题。分别。

【讨论】:

有没有其他方法可以像我们在 .pug 文件的情况下一样,我们只是将对象传递给映射变量【参考方案2】:

您可以做的是使用节点中的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);
        
    );
);

【讨论】:

有没有其他方法可以像我们在.pug文件的情况下一样,我们只是将对象传递给映射变量 这是否支持内联 CSS 样式? 是的,您可以将css样式添加到您的html页面 谢谢@AnanthPai,发布的答案真的很有帮助。最初,我对带有把手、快速把手等的动态电子邮件模板感到非常困惑。现在有了清晰的东西。 如何在视图文件中使用或打印变量?【参考方案3】:

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

尝试将其更改为:

`Hello $username!`

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

【讨论】:

这将显示为文本现在 html。 这可能很危险,因为文本不会被 HTML 编码【参考方案4】:

您可以使用 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)
        )
    )

【讨论】:

&lt;!DOCTYPE html&gt; 用于电子邮件?...比这长一点。 任何示例都链接到此实现代码箱或代码笔,以查看完整的操作流程。【参考方案5】:

对于那些使用 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。请注意,这将导致每次发送消息时重新编译模板。这对于偶尔发送的电子邮件来说很好。如果您发送大量电子邮件,您可以缓存已编译的模板来解决这个问题。如果需要,请查看该设置的哈巴狗文档。

【讨论】:

【参考方案6】:

我在所有项目中都使用它。更干净,最新且易于理解。回调地狱不存在。 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/");


【讨论】:

这样可以在HTML模板中使用本地图片吗?尝试使用一个,但它不会加载。当然,使用 URL 确实有效。 如果您提供服务器上文件的绝对路径,您可以使用它。例如:yourdomain.com/images/logo.png 你可以像传统的 html 一样使用它。他们在官方网站上的文档中解释了不同的方式。 community.nodemailer.com/using-embedded-images 我仍然觉得我的方式更简单、更灵活。我先准备好我的 html 模板,然后将其包含在工作中。 我也是这样做的。但是我的 CSS 没有与 html 链接。可能是什么原因? 如果您打算使用 css 处理电子邮件,请确保使用内联样式。【参考方案7】:

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

只需转到您的 邮件选项 并使用您的变量添加 context

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

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

用户名

【讨论】:

试过但对我不起作用,还有其他设置吗? @larachiwnl【参考方案8】:

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

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

【讨论】:

确保中间没有空格。【参考方案9】:

创建一个文件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,
    
 

【讨论】:

以上是关于将变量传递给nodemailer中的html模板的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法将变量传递给 Django 中的“扩展”模板?

Django 3:创建 CRUD 表模板(将上下文变量传递给 HTML)

如何使用 EJS 模板引擎将变量传递给内联 javascript?

Flask / WTF表单将变量传递给模板会产生500错误,表单未定义

如何将不同的模板变量传递给angular2中的一个按钮?

将模板中的按钮中的 id 传递给 Django 视图