node.js 基于 STMP 协议和 EWS 协议发送邮件

 更新时间:2021年2月15日 14:28  点击:2308

本文主要介绍 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 <${smtpCfg.auth.user}>`,
 // 主题
 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: <a href="https://lzw.me" rel="external nofollow" rel="external nofollow" >https://lzw.me</a>`,
 /** TEXT 文本格式邮件正文内容 */
 text: '',
 to: 'xxx@lzw.me',
 // 附件列表
 // attachments: [],
};
const smtpConfig = {
 host: 'smtp.qq.com', //QQ: smtp.qq.com; 网易: smtp.163.com
 port: 465, //端口号。QQ邮箱 465,网易邮箱 25
 secure: true,
 auth: {
 user: 'xxx@qq.com', //邮箱账号
 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: 'abc@xxx.com',
 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: <a href="https://lzw.me" rel="external nofollow" rel="external nofollow" >https://lzw.me</a>`,
 /** TEXT 文本格式邮件正文内容(优先级低于 html 参数) */
 text: '',
 to: 'xxx@lzw.me',
})

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 发送邮件的资料请关注猪先飞其它相关文章!

[!--infotagslink--]

相关文章

  • NodeJS实现阿里大鱼短信通知发送

    本文给大家介绍的是nodejs实现使用阿里大鱼短信API发送消息的方法和代码,有需要的小伙伴可以参考下。...2016-01-20
  • PHP测试成功的邮件发送案例

    mail()函数的作用:连接到邮件服务器,利用smtp协议,与该服务器交互并投邮件。注意:1、mail函数不支持esmtp协议,---即,只能直投,不能登陆2、由上条,我们只能直投至最终的收件服务器地址.而该地址,又是在PHP.ini中指定的,所...2015-10-30
  • node.JS md5加密中文与php结果不一致怎么办

    这次文章要给大家介绍的是node.JS md5加密中文与php结果不一致怎么办,不知道具体解决办法的下面跟小编一起来看看。 因项目需要,需要Node.js与PHP做接口调用,发现nod...2017-07-06
  • NODE.JS加密模块CRYPTO常用方法介绍

    使用require('crypto')调用加密模块。加密模块需要底层系统提供OpenSSL的支持。它提供了一种安全凭证的封装方式,可以用于HTTPS安全网络以及普通HTTP连接。该模块还提供了一套针对OpenSSL的hash(哈希),hmac(密钥哈希),cipher...2014-06-07
  • php邮件发送的两种方式

    这篇文章研究的主要内容就是使用PHP来发送电子邮件,总结为以下两种方法:一、使用PHP内置的mail()函数<&#63;php $to = "test@163.com"; //收件人 $subject = "Test"; //主题 $message = "This is a test mail!"; //正文...2015-10-30
  • c# 实现发送邮件的功能

    这篇文章主要介绍了c# 如何实现发送邮件的功能,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-07
  • 安装使用Mongoose配合Node.js操作MongoDB的基础教程

    这篇文章主要介绍了安装使用Mongoose来让Node.js操作MongoDB的基础教程,前端js+后端node+js操作MongoDB正是所谓最流行的一种JavaScript全栈开发方案,需要的朋友可以参考下...2016-03-03
  • 浅谈node.js中async异步编程

    1.什么是异步编程? 异步编程是指由于异步I/O等因素,无法同步获得执行结果时, 在回调函数中进行下一步操作的代码编写风格,常见的如setTimeout函数、ajax请求等等。示例: for (var i = 1; i <= 3; i++) {setTimeout(functi...2015-10-23
  • node.js+express留言板功能实现示例

    本文介绍基于nodejs+express+art-template的留言板功能。包含列表界面、添加界面和发送留言功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-21
  • php邮件发送的两种方式

    这篇文章研究的主要内容就是使用PHP来发送电子邮件,总结为以下两种方法:一、使用PHP内置的mail()函数<&#63;php $to = "test@163.com"; //收件人 $subject = "Test"; //主题 $message = "This is a test mail!"; //正文...2015-10-30
  • 利用Node.js获取项目根目录的小技巧

    这篇文章介绍的是一个小技巧来获取node.js项目根目录,这个技巧非常实用。有需要的朋友们可以参考借鉴,下面来一起看看吧。...2016-10-02
  • node.js从数据库获取数据

    这篇文章主要为大家详细介绍了node.js从数据库获取数据的具体代码,nodejs可以获取具体某张数据表信息,感兴趣的朋友可以参考一下...2016-05-09
  • Node.js之http模块的用法

    这篇文章主要介绍了Node.js之http模块的用法,对Node.js感兴趣的同学,可以参考下...2021-04-25
  • python实现企业微信定时发送文本消息的实例代码

    这篇文章主要介绍了python实现企业微信定时发送文本消息的实例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-11-25
  • c#使用netmail方式发送邮件示例

    这篇文章主要介绍了c#使用netmail方式发送邮件的示例,大家参考使用吧...2020-06-25
  • 比较node.js和Deno

    这篇文章主要介绍了node.js和Deno的区别,对deno感兴趣的同学,可以参考下...2021-04-27
  • node.js [superAgent] 请求使用示例

    post请求:复制代码 代码如下: request.post('/api/pet') .end(function(resp,err){ if (resp.body.status===200) { alert('yay got ' + JSON.stringify(res.body)); } else { return nex...2015-03-15
  • node.js 全局变量的具体使用

    这篇文章主要介绍了node.js 全局变量的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-04-15
  • Webpack 实现 Node.js 代码热替换

    这两天为了这个问题, Gitter 上问, Twitter 上问, GitHub 上问, 两天没反应 原来写博客的 jlongster 不理我, 我也不知道 Webpack 作者的联系方式 最后在 Gitter 上发的消息他似乎看到了, 就粗略地解释了一遍, 醍醐灌...2015-10-23
  • PHPMailer在SAE上无法发送邮件的解决方法

    PHPMailer在SAE上无法发送邮件怎么回事呢,我们以前在php5.2.7版本中使用了PHPMailer是可以发,但移到sae中发现无法发邮件了,那么此问题如何解决 在SAE上直接用5.2.7...2016-11-25