本文主要介绍 node.js 发送基于 STMP 协议和 MS Exchange Web Service(EWS) 协议的邮件的方法。文中所有参考代码均以 TypeScript 编码示例。

1 基于 STMP 协议的 node.js 发送邮件方法

提到使用 node.js 发送邮件,基本都会提到大名鼎鼎的 Nodemailer 模块,它是当前使用 STMP 方式发送邮件的首选。

基于 NodeMailer 发送 STMP 协议邮件的文章网上已非常多,官方文档介绍也比较详细,在此仅列举示例代码以供对比参考:

封装一个 sendMail 邮件发送方法:

/**

* 使用 Nodemailer 发送 STMP 邮件

* @param {Object} opts 邮件发送配置

* @param {Object} smtpCfg smtp 服务器配置

*/

async function sendMail(opts, smtpCfg) {

const resultInfo = { code: 0, msg: '', result: null };

if (!smtpCfg) {

resultInfo.msg = '未配置邮件发送信息';

resultInfo.code = - 1009;

return resultInfo;

}

// 创建一个邮件对象

const mailOpts = Object.assign(

{

// 发件人

from: `Notify `,

// 主题

subject: 'Notify',

// text: opts.content,

// html: opts.content,

// 附件内容

// /*attachments: [{

// filename: 'data1.json',

// path: path.resolve(__dirname, 'data1.json')

// }, {

// filename: 'pic01.jpg',

// path: path.resolve(__dirname, 'pic01.jpg')

// }, {

// filename: 'test.txt',

// path: path.resolve(__dirname, 'test.txt')

// }],*/

},

opts

);

if (!mailOpts.to) mailOpts.to = [];

if (!Array.isArray(mailOpts.to)) mailOpts.to = String(mailOpts.to).split(',');

mailOpts.to = mailOpts.to.map(m => String(m).trim()).filter(m => m.includes('@'));

if (!mailOpts.to.length) {

resultInfo.msg = '未配置邮件接收者';

resultInfo.code = - 1010;

return resultInfo;

}

const mailToList = mailOpts.to;

const transporter = nodemailer.createTransport(smtpCfg);

// to 列表分开发送

for (const to of mailToList) {

mailOpts.to = to.trim();

try {

const info = await transporter.sendMail(mailOpts);

console.log('mail sent to:', mailOpts.to, ' response:', info.response);

resultInfo.msg = info.response;

} catch (error) {

console.log(error);

resultInfo.code = -1001;

resultInfo.msg = error;

}

}

return resultInfo;

}

使用 sendMail 方法发送邮件:

const opts = {

subject: 'subject for test',

/** HTML 格式邮件正文内容 */

html: `email content for test: https://lzw.me`,

/** TEXT 文本格式邮件正文内容 */

text: '',

to: [email protected]',

// 附件列表

// attachments: [],

};

const smtpConfig = {

host: 'smtp.qq.com', //QQ: smtp.qq.com; 网易: smtp.163.com

port: 465, //端口号。QQ邮箱 465,网易邮箱 25

secure: true,

auth: {

user: [email protected]', //邮箱账号

pass: '', //邮箱的授权码

},

};

sendMail(opts, smtpConfig).then(result => console.log(result));

2 基于 MS Exchange 邮件服务器的 node.js 发送邮件方法

对于使用微软的 Microsoft Exchange Server 搭建的邮件服务,Nodemailer 就无能为力了。Exchange Web Service(EWS)提供了访问 Exchange 资源的接口,在微软官方文档中对其有详细的接口定义文档。针对 Exchange 邮件服务的流行第三方库主要有 node-ews 和 ews-javascript-api。

2.1 使用 node-ews 发送 MS Exchange 邮件

下面以 node-ews 模块为例,介绍使用 Exchange 邮件服务发送邮件的方法。

2.1.1 封装一个基于 node-ews 发送邮件的方法

封装一个 sendMailByNodeEws 方法:

import EWS from 'node-ews';

export interface IEwsSendOptions {

auth: {

user: string;

pass?: string;

/** 密码加密后的秘钥(NTLMAuth.nt_password)。为字符串时,应为 hex 编码结果 */

nt_password?: string | Buffer;

/** 密码加密后的秘钥(NTLMAuth.lm_password)。为字符串时,应为 hex 编码结果 */

lm_password?: string | Buffer;

};

/** Exchange 地址 */

host?: string;

/** 邮件主题 */

subject?: string;

/** HTML 格式邮件正文内容 */

html?: string;

/** TEXT 文本格式邮件正文内容(优先级低于 html 参数) */

text?: string;

to?: string;

}

/**

* 使用 Exchange(EWS) 发送邮件

*/

export async function sendMailByNodeEws(options: IEwsSendOptions) {

const resultInfo = { code: 0, msg: '', result: null };

if (!options) {

resultInfo.code = -1001;

resultInfo.msg = 'Options can not be null';

} else if (!options.auth) {

resultInfo.code = -1002;

resultInfo.msg = 'Options.auth{user,pass} can not be null';

} else if (!options.auth.user || (!options.auth.pass && !options.auth.lm_password)) {

resultInfo.code = -1003;

resultInfo.msg = 'Options.auth.user or Options.auth.password can not be null';

}

if (resultInfo.code) return resultInfo;

const ewsConfig = {

username: options.auth.user,

password: options.auth.pass,

nt_password: options.auth.nt_password,

lm_password: options.auth.lm_password,

host: options.host,

// auth: 'basic',

};

if (ewsConfig.nt_password && typeof ewsConfig.nt_password === 'string') {

ewsConfig.nt_password = Buffer.from(ewsConfig.nt_password, 'hex');

}

if (ewsConfig.lm_password && typeof ewsConfig.lm_password === 'string') {

ewsConfig.lm_password = Buffer.from(ewsConfig.lm_password, 'hex');

}

Object.keys(ewsConfig).forEach(key => {

if (!ewsConfig[key]) delete ewsConfig[key];

});

// initialize node-ews

const ews = new EWS(ewsConfig);

// define ews api function

const ewsFunction = 'CreateItem';

// define ews api function args

const ewsArgs = {

attributes: {

MessageDisposition: 'SendAndSaveCopy',

},

SavedItemFolderId: {

DistinguishedFolderId: {

attributes: {

Id: 'sentitems',

},

},

},

Items: {

Message: {

ItemClass: 'IPM.Note',

Subject: options.subject,

Body: {

attributes: {

BodyType: options.html ? 'HTML' : 'Text',

},

$value: options.html || options.text,

},

ToRecipients: {

Mailbox: {

EmailAddress: options.to,

},

},

IsRead: 'false',

},

},

};

try {

const result = await ews.run(ewsFunction, ewsArgs);

// console.log('mail sent to:', options.to, ' response:', result);

resultInfo.result = result;

if (result.ResponseMessages.MessageText) resultInfo.msg = result.ResponseMessages.MessageText;

} catch (err) {

console.log(err.stack);

resultInfo.code = 1001;

resultInfo.msg = err.stack;

}

return resultInfo;

}

使用 sendMailByNodeEws 方法发送邮件:

sendMailByNodeEws({

auth: {

user: [email protected]',

pass: '123456',

/** 密码加密后的秘钥(NTLMAuth.nt_password)。为字符串时,应为 hex 编码结果 */

nt_password: '',

/** 密码加密后的秘钥(NTLMAuth.lm_password)。为字符串时,应为 hex 编码结果 */

lm_password: '',

},

/** Exchange 地址 */

host: 'https://ews.xxx.com',

/** 邮件主题 */

subject: 'subject for test',

/** HTML 格式邮件正文内容 */

html: `email content for test: https://lzw.me`,

/** TEXT 文本格式邮件正文内容(优先级低于 html 参数) */

text: '',

to: [email protected]',

})

2.1.2 基于 NTLMAuth 的认证配置方式

直接配置 pass 密码可能会导致明文密码泄露,我们可以将 pass 字段留空,配置 nt_password 和 lm_password 字段,使用 NTLMAuth 认证模式。此二字段基于 pass 明文生成,其 nodejs 生成方式可借助 httpntlm 模块完成,具体参考如下:

import { ntlm as NTLMAuth } from 'httpntlm';

/** 将输入的邮箱账号密码转换为 NTLMAuth 秘钥(hex)格式并输出 */

const getHashedPwd = () => {

const passwordPlainText = process.argv.slice(2)[0];

if (!passwordPlainText) {

console.log('USEAGE: \n\tnode get-hashed-pwd.js [password]');

return;

}

const nt_password = NTLMAuth.create_NT_hashed_password(passwordPlainText.trim());

const lm_password = NTLMAuth.create_LM_hashed_password(passwordPlainText.trim());

// console.log('\n password:', passwordPlainText);

console.log(` nt_password:`, nt_password.toString('hex'));

console.log(` lm_password:`, lm_password.toString('hex'));

return {

nt_password,

lm_password,

};

};

getHashedPwd();

2.2 使用 ews-javascript-api 发送 MS Exchange 邮件

基于 ews-javascript-api 发送邮件的方式,在其官方 wiki 有相关示例,但本人在测试过程中未能成功,具体为无法取得服务器认证,也未能查证具体原因,故以下代码仅作参考:

/**

* 使用 `ews-javascript-api` 发送(MS Exchange)邮件

*/

export async function sendMailByEwsJApi(options: IEwsSendOptions) {

const resultInfo = { code: 0, msg: '', result: null };

if (!options) {

resultInfo.code = -1001;

resultInfo.msg = 'Options can not be null';

} else if (!options.auth) {

resultInfo.code = -1002;

resultInfo.msg = 'Options.auth{user,pass} can not be null';

} else if (!options.auth.user || (!options.auth.pass && !options.auth.lm_password)) {

resultInfo.code = -1003;

resultInfo.msg = 'Options.auth.user or Options.auth.password can not be null';

}

const ews = require('ews-javascript-api');

const exch = new ews.ExchangeService(ews.ExchangeVersion.Exchange2010);

exch.Credentials = new ews.WebCredentials(options.auth.user, options.auth.pass);

exch.Url = new ews.Uri(options.host);

ews.EwsLogging.DebugLogEnabled = true; // false to turnoff debugging.

const msgattach = new ews.EmailMessage(exch);

msgattach.Subject = options.subject;

msgattach.Body = new ews.MessageBody(ews.BodyType.HTML, escape(options.html || options.text));

if (!Array.isArray(options.to)) options.to = [options.to];

options.to.forEach(to => msgattach.ToRecipients.Add(to));

// msgattach.Importance = ews.Importance.High;

// 发送附件

// msgattach.Attachments.AddFileAttachment('filename to attach.txt', 'c29tZSB0ZXh0');

try {

const result = await msgattach.SendAndSaveCopy(); // .Send();

console.log('DONE!', result);

resultInfo.result = result;

} catch (err) {

console.log('ERROR:', err);

resultInfo.code = 1001;

resultInfo.msg = err;

}

return resultInfo;

}

3 扩展参考

nodemailer.com/about/

github.com/CumberlandG…

github.com/gautamsi/ew…

github.com/lzwme/node-…

以上就是node.js 基于 STMP 协议和 EWS 协议发送邮件的详细内容,更多关于node.js 发送邮件的资料请关注猪先飞其它相关文章!

php-ews发送邮件,node.js 基于 STMP 协议和 EWS 协议发送邮件相关推荐

  1. 基于SMTP协议和POP3协议实现的邮件收发客户端

    一.概要设计 1.1 抽象数据类型定义 主要定义了三个抽象数据类型: Base64 功能:用于发送邮件时进行编码,以及接收邮件时进行解码 数据部分:无 操作部分:编码(encode).解码(decod ...

  2. 邮件系统(基于SMTP协议和POP3协议-C语言实现)

    前些天发现了十分不错的人工智能学习网站,通俗易懂,风趣幽默,没有广告,分享给大家,大家可以自行看看.(点击跳转人工智能学习资料) 微信公众号:创享日记 发送关键词:邮件系统 获取邮件发送端和接收端C语 ...

  3. php node 目录,node.js基于fs模块对系统文件及目录进行读写操作的方法详解

    本文主要介绍了node.js基于fs模块对系统文件及目录进行读写操作的方法,结合实例形式分析了nodejs使用fs模块针对文件与目录的读写.创建.删除等相关操作技巧,需要的朋友可以参考下. 如果要用这 ...

  4. node.js基于微信小程序的外卖订餐系统 uniapp 小程序

    美食是人类永恒的话题,无论是在古代还是现代人们对美食都有一种非常的热爱在里面,但是随着时代的发展,人们可能没有更多的时间去研究美食,很多时候人们在下班或者放学之后更希望通过网络来进行订餐,为此我开发了 ...

  5. node.js基于JavaScript语言新兴框架

    node.js基于JavaScript语言,不在单用学习一门新的语言,从而降低了陌生语言的门槛,同时js语言在web前端开发至关重要,特别HTML5必须使用,前后台语言统一,不仅可以实现程序员全栈开发 ...

  6. 计算机网络实验(华为eNSP模拟器)——第十四章 RIP协议和OSPF协议

    目录 一.RIP协议和OSPF协议 (一)自治系统AS (二)内部.外部网关协议 (三)RIP协议 (四)OSPF路由协议 二.实验目的 三.实验内容 四.实验结果 结语 一.RIP协议和OSPF协议 ...

  7. Java爬虫技术—入门秘籍之HTTP协议和robtos协议(一)

    文章目录: 入门秘籍-Http协议与robots协议 内功修炼-深入理解网络爬虫概念,作用,原理和爬取方式及流程 山中奇遇-得授页面解析技术之Xpath 入驻兵器阁-获取爬虫神器之Jsoup 入驻兵器 ...

  8. doraemon的python tcp协议和udp协议

    ### 8.9 tcp协议和udp协议#### 8.9.1 tcp协议 -------打电话 特点:- ​ 可靠 慢 全双工通信 - ​ 建立连接的时候:三次握手 - ​ 断开连接的时候:四次挥手 - ...

  9. Bytom BIP-32协议和BIP-44协议解读

    我们知道HD(分层确定性)钱包,基于 BIP-32:多币种和多帐户钱包,基于 BIP-44:最近比原社区的钱包开发者对比原的BIP-32和BIP-44协议有疑问,所以我今天就专门整理了一下该协议的内容 ...

最新文章

  1. ACL-文件访问控制列表
  2. Python中的eval(),exec()以及其相关函数
  3. ad服务器修改域名,ad服务器改域名
  4. 英特尔西安团队将被裁撤 波及约200人?回应...
  5. oracle级联赋权,Oracle 级联with admin option 和 with grant option
  6. 搭建Demo验证在一次Socket请求中有借助缓冲区处理数据
  7. 华南理工大学控制工程考研经验分享
  8. 关于composer安装插件时候提示找不到fxp插件时候的解决办法
  9. linux 模拟误码率,基于System View的比特误码率测试的仿真研究
  10. Linux网络编程1之什么是什么是网路通信?
  11. 计算机英语课外知识竞赛,英语知识竞赛活动方案
  12. 年终盘点 | 用Python分析了上千个基金,终于发现了赚钱的秘密!
  13. 美团html页面代码,html+css+js制作美团官网
  14. openlayers 实现风场效果图
  15. Java技术之AQS详解
  16. java生成随机密码,包含大小写字母,数字,特殊字符等
  17. 没有对象的进来找个对象吧
  18. 一文读懂CAN总线/LIN总线/FlexRay/以太网
  19. linux网络管理工具net-tools 对决 iproute2
  20. 【测绘程序设计】——坐标正算和反算

热门文章

  1. 关于#ifndef以及#ifndef WIN32
  2. 云产研见客户的行为分析
  3. python 制作 二维码
  4. python插入排序实现及详解
  5. 利用华为短信包开发短信功能中中文转码和msgId获取经验
  6. 计算机领域职业简介-PM,RD,FE,UE,UI,QA,OP,DBA,BRD,MRD,PRD,FSD等缩写的全称解析
  7. 云主机和物理机的区别
  8. LeNet实现手写数字识别
  9. 服务器cpu占用率高怎么解决,线上服务器CPU占用率高怎么办?
  10. 几分钟黑掉阿里,被马云500万年薪收编的黑客,现在混得咋样了?