如何使用Nodemailer发邮件并在Pug渲染的HTML中设置背景图片
核心问题原因
- 模板渲染逻辑错误:你当前调用
pug.renderFile时传入了空的img、img2参数,此时模板里的#{img}、#{img2}已经被替换为空值,后续再对渲染结果执行pug.compile根本不会生效,cid地址没有被正确填入背景图的url中。 - 附件未明确标记为内联资源:背景图附件没有设置
contentDisposition: 'inline',Gmail会默认将其识别为普通附件,不会嵌入到邮件内容里。 - 邮件客户端兼容性问题:Gmail对div元素的CSS
background-image属性支持度较差,优先使用table标签的background属性兼容性更好。
修复后的代码
Node.js 代码修改
const nodemailer = require("nodemailer"); const pug = require('pug'); const path = require('path'); const excel = require('../../public/scripts/readExcel'); const image_path = path.join(__dirname, '../../../img/', 'logo.png'); const image_ground_path = path.join(__dirname, '../../../img/', 'backGround.png'); const path_Excel = path.join(__dirname, '../../../config/BD/emails.xlsx'); let dateObj = new Date(); let year = dateObj.getUTCFullYear(); exports.sendEmail = () => { try { return new Promise((resolve, reject) => { let dataExcel = excel.readExcel(path_Excel); if (dataExcel.length <= 0) return resolve("No emails sent"); const transporter = nodemailer.createTransport({ service: 'gmail', host: "smtp.gmail.com", port: 587, secure: false, auth: { user: "mygmail@gmail.com", pass: "*****" }, }); // 批量发送处理,避免异步提前resolve const sendPromises = dataExcel.map(user => { return new Promise((res, rej) => { // 直接在renderFile时传入所有参数,无需二次compile const html = pug.renderFile(path.join(__dirname, "../../../views/index.pug"), { name: user.name, img: "cid:logo", img2: "cid:backGroundImg", year, area: user.area }); const mainOptions = { from: "mygmail@gmail.com", to: user.email, // 替换为你Excel中实际的收件人字段 subject: "Hello", html: html, attachments: [ { filename: 'logo-U.png', path: image_path, cid: 'logo', contentDisposition: 'inline', contentType: 'image/png' }, { filename: 'backGround.png', path: image_ground_path, cid: 'backGroundImg', contentDisposition: 'inline', // 明确标记为内联资源 contentType: 'image/png' } ] }; transporter.sendMail(mainOptions, (err, info) => { if (err) return rej(err); res(info); }); }); }); Promise.all(sendPromises) .then(() => resolve("Email(s) sent")) .catch(err => reject(err.message)); }); } catch (error) { return Promise.reject(error); } }
Pug 模板修改
优先用table的background属性实现背景,兼容Gmail:
tr td div(style='background-color:#082CAF;color:white;padding:10px;border-radius:10px 10px 0 0') table(width='100%' align='center' cellpadding='0') tbody tr td(width='10%' height='70') img(src=img) td(width='80%' height='70' style='color:white;text-align:center;font-size:25px') strong General Directorate of Services tr td div(style='background-color:#ecf0f5;padding:10px;') table(width='100%' cellpadding='0' style='margin-top:20px;margin-bottom:40px') tbody tr td(width='10%') td(width='60%') // 用table嵌套实现背景,兼容性更好 table(width='100%' cellpadding='40' background=img2 style='border:0.5px solid #e5e5e5;border-radius:2px;background-repeat: no-repeat;background-position:center;background-size: 100% 100%;') tr td p(style='font-size:20px;text-align:center;margin:0') strong Dear #{name}.
补充注意事项
- 不要在style属性里用
#{}插值,Pug中动态属性直接写src=img、background=img2即可,避免转义错误 - 背景图不要超过100KB,尺寸建议控制在1920px宽度以内,避免Gmail拦截
- 批量发送邮件时不要在for循环里直接resolve Promise,会导致第一个邮件发送成功就直接返回,其余邮件还未发送完成
内容的提问来源于stack exchange,提问作者Jorge Rojas C.
相关产品推荐
相关产品推荐

