如何使用 Node.js 发送电子邮件全解和相关工具推荐

news2024/12/23 7:14:30

大多数Web应用程序都需要发送电子邮件。它可能用于注册、密码重置、状态报告,甚至是完整的市场营销活动,如新闻和促销。本教程解释了如何在Node.js中发送电子邮件,但其概念和挑战适用于您正在使用的任何系统。

你会在 npm 上找到大量与电子邮件相关的模块,其中最流行的是 NodeMailer,每周的下载量超过 300 万次。

要使用它,您需要一个可以发送电子邮件的 SMTP 服务器。您可以使用自己的电子邮件提供程序,但是出于演示的目的,我使用免费的 WPOven Test SMTP 服务器。

创建一个新的项目文件夹:

mkdir emailtest
cd emailtest

然后创建一个新的 package.json 文件,内容如下:

{
  "name": "emailtest",
  "type": "module",
  "main": "index.js",
  "dependencies": {
    "nodemailer": "^6.0.0"
  }
}

安装模块(NodeMailer):

npm install

并创建以下 index.js 代码:

import nodemailer from 'nodemailer';

const transporter = nodemailer.createTransport({
  host: 'smtp.freesmtpservers.com',
  port: 25
});

try {
  const send = await transporter.sendMail({
    from: '"Test Email" <test@email.com>',  // sender address
    to: 'someone@example.com',              // list of receivers
    subject: 'Hello!',                      // subject line
    text: 'Hello world!',                   // plain text body
    html: '<p>Hello world!</p>',            // HTML body
  });

  console.dir(send, { depth: null, color: true });

}
catch(e) {
  console.dir(e, { depth: null, color: true });
}

运行代码。您应该看到包含 250 OK 响应和 messageId 的结果:

$ node index.js
{
  accepted: [ 'someone@example.com' ],
  rejected: [],
  ehlo: [ 'SIZE 33554432', '8BITMIME', 'SMTPUTF8', 'HELP' ],
  envelopeTime: 486,
  messageTime: 289,
  messageSize: 595,
  response: '250 OK',
  envelope: {
    from: 'test@email.com',
    to: [ 'someone@example.com' ]
  },
  messageId: '<4673597e-a9e4-e422-85f7-4422edf31774@email.com>'
}

检查 to: 地址的收件箱,在 WPOven Test SMTP Server 页面输入该地址并单击 Access Inbox。单击“Hello!” 消息检查内容。

NodeMailer 基础知识

要发送电子邮件,你必须创建一个NodeMailer传输器(transporter)对象来定义服务类型。SMTP是最常见的,但其他服务也可以使用。通常需要一个身份验证用户ID和密码:

import nodemailer from 'nodemailer';

const transporter = nodemailer.createTransport({
  host: 'smtp.yourserver.com',
  port: 587,
  auth: {
    user: 'myid@yourserver.com',
    pass: 'my-password'
  },
});

你可以使用传输器的 sendMail() 方法发送电子邮件给一个或多个收件人:

const send = await transporter.sendMail({
  from: '"Test Email" <test@email.com>',          // sender address
  to: 'someone@example.com, sometwo@example.com', // list of receivers
  cc: 'somethree@example.com',
  bcc: 'somefour@example.com',
  subject: 'Hello!',                              // subject line
  text: 'Plain text version of the message',      // plain text body
  html: '<p>HTML version of the message</p>',     // HTML body
});

所有的邮件客户端都支持纯文本消息,当邮件客户端支持HTML时,你也可以发送相同消息的富格式版本(更多内容见下文)。

NodeMailer 提供了许多其他的消息选项,但最常见的是附件。

const send = await transporter.sendMail({
  // ...
  attachments: [
    { // get file content from disk
      filename: 'text1.txt',
      path: '/path/to/file1.txt'
    },
    {  // get file content from a URL
      filename: 'text2.txt',
      path: 'https://myserver.com/text2.txt'
    },
    { // create file from UTF-8 string
      filename: 'text3.txt',
      content: 'This is the file content!'
    },
    { // create file from data URI
      filename: 'text4.txt',
      path: 'data:text/plain;base64,SGVsbG8gd29ybGQh'
    }
  ]
});

发送服务

发送简单的一次性电子邮件很容易,但请不要低估随着需求变化的挑战。

  • 你可能没有SMTP服务器。不是所有的电子邮件服务提供SMTP(谷歌正在收回Gmail的基本SMTP支持)。
  • 大多数服务都会限制外发电子邮件。如果您发送大量电子邮件,则可能会达到提供商的限制。那时,通过同一服务的所有电子邮件都将失败。
  • 你可能成为垃圾邮件发送者。收件人很容易把你的邮件标记为“垃圾邮件”——即使它不是垃圾邮件。当足够多的人这样做时,你会发现来自你域名的所有电子邮件都被拦截了。

最好使用专用的电子邮件服务,而不是自己的邮件服务器。以下服务可以减少潜在的问题,有些服务还为那些使用要求较低的用户提供免费计划:

  • https://aws.amazon.com/ses/
  • https://www.brevo.com/
  • clicksend.com
  • https://mailchimp.com/
  • https://www.mailersend.com/
  • https://www.mailgun.com/
  • https://www.mailjet.com/
  • https://mailtrap.io/
  • https://postmarkapp.com/
  • https://www.sender.net/
  • https://sendgrid.com/

异步应用程序架构

发送单个电子邮件通常很快,但是:

  • SMTP服务器可能已经关闭,所以重试是必要的,或者
  • 消息可能会在大量新闻邮件中被截获。

通常,最好将数据发送到任务队列,而不是直接在 Node.js 应用程序中发送电子邮件。最终用户无需等待响应,可以继续使用该应用程序。

另一个进程可以监视电子邮件队列,发送下一条消息,并在发生故障时重新排队。

制作HTML邮件

HTML5和CSS3在现代浏览器中一直运行良好。电子邮件客户端则是另一回事,它把我们带回了令人沮丧的20世纪90年代末的表格和内联样式。

这些是你将面临的一些问题:

  • 有几十种本地和基于Web的电子邮件客户端,包括Gmail、雅虎邮件、苹果邮件、iOS邮件、Android邮件、Windows邮件、Outlook、Outlook.com、(新)Outlook、雷鸟、AOL、Claws、RoundCube等。
  • 所有这些浏览器都使用各自奇怪又奇妙的渲染引擎,这些引擎都有各自的问题和漏洞。 有些奇怪的是,Outlook从2007年起就使用微软Word来渲染HTML(尽管新的预览版是基于浏览器的)。
  • 大多数客户端会阻止或限制字体、图像、追踪器、媒体查询、iframe、视频、音频、表单和脚本。
  • 即使是基于浏览器的电子邮件客户端也必须删除HTML、CSS和JavaScript,这些代码是危险的,或者会影响UI布局。 例如,电子邮件不应该自动点击自己的链接,或者绝对将一个元素定位在删除按钮上。
  • 电子邮件客户端可以重新格式化你的HTML,以确保它是单一的列或遵循用户的明/暗模式偏好。

手工编写HTML邮件是可能的,但除非你的布局很简单,否则这会是一个困难、令人沮丧且容易出错的过程。下面几节建议一些工具和资源,可能会让你的生活变得更容易。

预先构建的电子邮件模板

以下站点提供免费且强大的商业电子邮件模板,您可以轻松预览、下载和使用:

  • codedmails.com
  • 活动监控模板
  • Litmus邮件模板
  • Stripo模板

邮件模板设计工具

以下无代码设计工具允许您使用更简单的 WYSWYG 编辑器创建自己的 HTML 电子邮件模板:

  • Beefree
  • Blocks Edit
  • Campaign Monitor
  • chamaileon
  • fly-brid
  • GrapesJS
  • knak
  • Mail Developer
  • Maily
  • Postcards
  • Psd2Newsletters
  • Stensul
  • Stripo
  • Topol
  • Unlayer

其中一些服务还提供代码验证和测试工具。

电子邮件模板转换

Premailer 是一个web工具,它可以将页面URL或粘贴的源代码转换为兼容电子邮件的HTML和纯文本模板。

类似的工具包括:

  • alter.email
  • email-comb
  • Postdrop

邮件模板标记工具

Cerberus、Email Framework、Email Skeleton,和 Good Email Code 提供HTML组件片段,你可以复制并调整到你自己的模板中。

HEML 和 MJML 是电子邮件标记语言。它们类似于HTML,但避免了典型的兼容性问题。Maizzle 使用了类似的方法,使用了Tailwind CSS。

Parcel 是一个代码编辑器,它可以理解邮件格式并显示预览。你也可以找到大量的VS Code的邮件扩展。

caniemail.com 是相当于网页版 caniuse.com 的电子邮件,报告特定 HTML 或 CSS 功能是否可在多个客户端上使用。最后,Accessible Email 提供了相关的资源和链接。

邮件测试工具

虽然HTML邮件可能在你自己的邮件应用程序中工作,但你能确定它在其他应用程序中工作吗?下面的工具将有所帮助,但没有什么可以替代测试一系列真实的设备、操作系统和电子邮件客户端。

HTML Email Check 和 MailTrap 验证您的源代码,并报告您在特定客户机中可能遇到的问题。

emailpreview, Mailosaur 和 Email Preview Services 提供布局预览工具,这样你就可以检查你的设计在各种客户机上的效果。

最后,Litmus和 Email on Acid 有一系列工具来验证代码、检查可访问性、跨客户端预览、记录分析和运行完整的营销活动。

读取收到的电子邮件

大多数应用只需要发送邮件,但有时你可能需要检查接收到的邮件 - 比如服务注册、退订处理、自动化支持等等。虽然这超出了本教程的范围,但 Node.js 模块,如 ImapFlow,允许应用连接到 IMAP 收件箱,获取消息并处理响应:

import ImapFlow from 'imapflow';

const client = new ImapFlow({
    host: 'imap.email',
    port: 993,
    secure: true,
    auth: {
        user: 'account@imap.email',
        pass: 'mypassword'
    }
});

try {

  // connect
  await client.connect();

  // select and lock inbox
  const lock = await client.getMailboxLock('INBOX');

  // get latest message
  const msg = await client.fetchOne(client.mailbox.exists, { source: true });
  console.log( msg.source.toString() );

  // release lock
  lock.release();

  // log out
  await client.logout();

}
catch (e) {
  console.log(e);
}

使用 Node.js 发送电子邮件的常见问题

我如何使用 Node.js 将文件附加到我的电子邮件中?

使用 Node.js 在邮件中附加文件非常简单,你可以在邮件选项中使用 attachments 属性,这个属性接受一个附件选项数组,每个附件选项是一个对象,包含文件名和路径属性,文件名属性是文件名,它将出现在邮件中,路径属性是文件在系统中的位置。

这里有一个例子:

let mailOptions = {
    from: 'sender@example.com',
    to: 'receiver@example.com',
    subject: 'Hello',
    text: 'Hello world',
    attachments: [
        {
            filename: 'file.txt',
            path: '/path/to/file.txt'
        }
    ]
};

我可以使用 Node.js 发送 HTML 电子邮件吗?

是的,你可以使用 Node.js 发送 HTML 邮件。在邮件选项中,你使用的是 html 属性,而不是 text 属性。这个属性的值是邮件的 HTML 内容。

这里有一个例子:

let mailOptions = {
    from: 'sender@example.com',
    to: 'receiver@example.com',
    subject: 'Hello',
    html: '<h1>Hello world</h1>'
};

我怎么能把电子邮件发送给多个收件人?

要向多个收件人发送电子邮件,您可以在邮件选项的 to 属性中提供一个以逗号分隔的电子邮件地址列表。

let mailOptions = {
    from: 'sender@example.com',
    to: 'receiver1@example.com, receiver2@example.com',
    subject: 'Hello',
    text: 'Hello world'
    };

我如何处理发送电子邮件时出现的错误?

你可以使用回调函数来处理发送电子邮件时的错误。该函数作为 sendMail方法的第二个参数传递。回调函数接受两个参数:一个 error 对象和一个info 对象。如果发送电子邮件时发生错误,error 对象将包含有关错误的信息。

transporter.sendMail(mailOptions, function(error, info){
    if (error) {
        console.log(error);
    } else {
        console.log('Email sent: ' + info.response);
    }
});

我可以用Gmail账户发邮件吗?

是的,你可以使用Gmail账户发送电子邮件。但是,你需要在Gmail账户设置中启用“(Less secure apps)不安全的应用程序”。此外,你需要在传输选项中使用 smtp.gmail.com 作为主机和587作为端口。

let transporter = nodemailer.createTransport({
    host: 'smtp.gmail.com',
    port: 587,
    auth: {
        user: 'your-email@gmail.com',
        pass: 'your-password'
    }
});

我怎么异步发送电子邮件?

你可以使用 Promise异步发送邮件。 sendMail 方法返回一个 Promise,当邮件发送时,它会解析为一个info对象。

transporter.sendMail(mailOptions)
.then(info => console.log('Email sent: ' + info.response))
.catch(error => console.log(error));

我可以使用自定义的SMTP服务器发送电子邮件吗?

是的,您可以使用自定义的 SMTP 服务器发送电子邮件。您需要在传输器选项中提供 SMTP 服务器的主机、端口和身份验证详细信息。

let transporter = nodemailer.createTransport({
    host: 'smtp.example.com',
    port: 587,
    auth: {
        user: 'username',
        pass: 'password'
    }
});

我如何发送带有特定字符集的电子邮件?

您可以使用邮件选项中的 charset 属性发送具有特定字符集的电子邮件。该属性设置了电子邮件的字符集。

let mailOptions = {
    from: 'sender@example.com',
    to: 'receiver@example.com',
    subject: 'Hello',
    text: 'Hello world',
    charset: 'UTF-8'
};

我可以发送带有特定内容类型的电子邮件吗?

是的,你可以发送带有特定内容类型的邮件。你可以在邮件选项中使用contentType 属性。这个属性设置了邮件的内容类型。

let mailOptions = {
    from: 'sender@example.com',
    to: 'receiver@example.com',
    subject: 'Hello',
    text: 'Hello world'
    contentType: 'text/plain'
};

我如何发送带有特定编码的电子邮件?

你可以使用邮件选项中的 encoding 属性来发送带有特定编码的邮件。这个属性设置了邮件的编码。

let mailOptions = {
    from: 'sender@example.com',
    to: 'receiver@example.com',
    subject: 'Hello',
    text: 'Hello world',
    encoding: 'base64'
};

结论

通过 Node.js Web 应用程序发送电子邮件很简单。但要发送外观漂亮、在所有电子邮件客户端都能可靠运行、不会让用户停机、不会引起垃圾邮件问题的电子邮件,则要困难得多。

我建议你保持邮件的简洁,也许可以选择不常用的纯文本信息。当然,您的客户和营销部门很快就会想要精美的颜色和动画,但您明天就可以交付!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1613509.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度图转点云

一、理论分析 二、其他分析 1、相机内参 相机内参主要是四个参数fx,fy,u0,v0。要明白相机内参就是相机内部参数&#xff0c;是参考像素坐标系而言&#xff0c;有了这个前提&#xff0c;这四个参数也就很好理解了。 &#xff08;1&#xff09;首先&#xff0c;。其中F是相机的…

内存管理下及模板初阶

嗨喽&#xff0c;今天阿鑫给大家带来内存管理下以及模板初阶的博客&#xff0c;下面让我们开始今天的学习吧&#xff01; 内存管理下及模板初阶 new和delete的实现原理定位new表达式(placement-new)常见面试题泛型编程函数模板类模板 1. new和delete的实现原理 1.1 内置类型…

上位机工作感想-从C#到Qt的转变-1

0.前言 接触Qt开发也有一年多的时间了&#xff0c;还记得去年初从杭州回合肥时&#xff0c;刚来公司面临的几个问题&#xff1a; 1.C#转上位机的迷茫2.新公司管理模式的差异3.试用期的各种紧急任务。 当时也是加班加点学习C和Qt的基础知识&#xff0c;做了两个考核项目后&am…

Hadoop——Yarn 生产环境核心参数

1. ResourceManager 相关参数&#xff1a; yarn.resourcemanager.hostname&#xff1a;ResourceManager 的主机名。yarn.resourcemanager.webapp.address&#xff1a;ResourceManager 的 Web 应用程序地址。yarn.resourcemanager.scheduler.address&#xff1a;ResourceManage…

MB21屏幕增强

MB21 增强 一、屏幕抬头增强 需要在屏幕的抬头添加两个字段&#xff0c;并将字段保存至自建表 二、增强步骤 首先屏幕中的收货字段找到对应的屏幕为0521。 在对应的屏幕添加增强的字段&#xff1a;命名需要和对应的表名一样 根据需求&#xff0c;增强只针对预留中的异动…

华为机考入门python3--(16)牛客16-购物单最大满意度

分类&#xff1a;动态规划&#xff0c;组合&#xff0c;最大值&#xff0c;装箱问题 知识点&#xff1a; 生成递减数 100, 90, 80, ..., 0 range(100, -1, -10) 访问列表的下标key for key, value in enumerate(my_list): 动态规划-捆绑装箱问题 a. 把有捆绑约束的物…

SpringMvc的核心组件和执行流程

一、 springmvc的核心组件及作用 1.DispatcherServlet:前置控制器&#xff0c;是整个流程控制的核心&#xff0c;用来控制其他组件的执行&#xff0c;降低了其他组件的耦合性 2.Handler:控制器&#xff0c;完成具体的业务逻辑&#xff0c;当DispatcherServlet接收到请求后&am…

力扣70:爬楼梯(经典动态规划)

题目 解题思路 考虑动态规划&#xff0c;dp[i]表示爬到第i层的方法种数&#xff0c;对于第i层&#xff0c;可以从第i-2层爬两个台阶到达&#xff0c;也可以从i-1层爬一个台阶到达&#xff0c;故dp[i]dp[i-1]dp[i-2]&#xff0c;输出dp[n]即为答案 代码 #include<iostream…

CSS——高级选择器

层次的选择器&#xff1a; <1> 后代选择器&#xff1a; 格式&#xff1a; 标签1 标签2{} 解释&#xff1a; 标签1 不生效&#xff0c;被标签1 嵌套中的 标签2才生效 举例&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charse…

利用fft算法理解频率和像素变化率的关系

算法我就不贴了。算法就是算法导论的内容。 我直接写推导过程。 假设变化率为f(n1)-f(n) 首先计算二进制数&#xff0c;这里我假设为3位二进制。 例如:f(5)-f(4)&#xff0c; 5和4的二进制为101,100。所以逆序数为101&#xff0c;001 101对应的频率为5, 001对应的频率为1…

go | defer、panic、recover

刷一道题&#xff0c; 将当函数触发panic 之后&#xff0c;函数是怎么执行的 然后我去找相关博客&#xff0c;发现这篇讲的蛮好的 接下来我直接上demo &#xff0c;然后通过demo 来逐个分析 package mainimport ("fmt" )func f() {defer func() {if r : recover();…

【 AIGC 研究最新方向(上)】面向平面、视觉、时尚设计的高可用 AIGC 研究方向总结

目前面向平面、视觉、时尚等设计领域的高可用 AIGC 方向有以下 4 种&#xff1a; 透明图层生成可控生成图像定制化SVG 生成 本篇&#xff08;上篇&#xff09;介绍 1、2&#xff0c;而下篇将介绍 3、4。 透明图层生成 LayerDiffuse 代表性论文&#xff1a;Transparent Imag…

23种设计模式之抽象工厂

简单工厂和工厂方法 关注 产品等级 抽象工厂 关注 产品族 对于比较稳定的产品&#xff0c;抽象工厂更有效率&#xff08;一个工厂生产很多产品族&#xff09; 抽象工厂代码例子加深理解

数组的删除与插入优化思路

数据结构&#xff1a;线性表、非线性表 线性表&#xff1a; 数组&#xff0c;链表、队列、栈等。 线性表就是数据排成像一条线一样的结构&#xff0c;每个线性表上的数据最多只有前和后两个方向。 非线性表&#xff1a; 二叉树、堆、图等。 在非线性表中&#xff0c;数据之间并…

09 JavaScript学习:对象

对象的概念 在计算机科学中&#xff0c;对象是一种数据结构&#xff0c;用于存储数据和方法&#xff08;也称为函数&#xff09;。对象可以包含属性&#xff08;也称为成员变量&#xff09;和方法&#xff08;也称为成员函数&#xff09;&#xff0c;通过这些属性和方法可以描述…

SpringMVC--RESTful

1. RESTful 1.1. RESTful简介 REST&#xff1a;Representational State Transfer&#xff0c;表现层资源状态转移。 RESTful是一种网络架构风格&#xff0c;它定义了如何通过网络进行数据的交互。这种风格基于HTTP协议&#xff0c;使得网络应用之间的通信变得更加简洁和高效。…

每天五分钟机器学习:神经网络模型参数的选择

本文重点 在深度学习和人工智能的浪潮中,神经网络作为其中的核心力量,发挥着举足轻重的作用。然而,神经网络的性能并非一蹴而就,而是需要经过精心的参数选择和调优。 神经网络由大量的神经元组成,每个神经元之间通过权重进行连接。这些权重,以及神经元的偏置、激活函数…

CSS基础:position定位的5个类型详解!

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合…

《R语言与农业数据统计分析及建模》学习——数据框的统计处理

1、数据框的透视 aggregate()函数用于对数据框进行聚合操作&#xff0c;可以按照指定的条件对数据进行分组&#xff0c;并计算每组的汇总统计量。函数如下&#xff1a; aggregate(formula,data,FUN,...) formula&#xff1a;定义聚合的公式&#xff0c;指定需要聚合的变量和分…

【精】Devops实战学习CI/CD落地方案#CI篇#

目录 先有个大概了解 基本概念 CI/CD Devops 阿里云效 devops产品 K8s jenkins docker git maven 知行合一&#xff0c;上手操作 实操记录 安装VMware 安装并配置虚拟机 安装并配置docker docker安装 修改镜像源&#xff08;关键且易出错&#xff09; CentOS…