Node.js sends emails based on STMP protocol and EWS protocol

Node.js sends emails based on STMP protocol and EWS protocol

This article mainly introduces the method of using node.js to send emails based on STMP protocol and MS Exchange Web Service(EWS) protocol. All reference codes in this article are coded in TypeScript.

1 Node.js method of sending emails based on STMP protocol

When talking about using node.js to send emails, the famous Nodemailer module will basically be mentioned. It is currently the first choice for sending emails using STMP.
There are many articles on the Internet about sending STMP protocol emails based on NodeMailer , and the official documentation is also quite detailed. Here we only list the sample code for comparison and reference:
Encapsulate a sendMail email sending method:

/**
 * Use Nodemailer to send STMP emails * @param {Object} opts email sending configuration * @param {Object} smtpCfg smtp server configuration */
async function sendMail(opts, smtpCfg) {
 const resultInfo = { code: 0, msg: '', result: null };
 if (!smtpCfg) {
 resultInfo.msg = 'Email sending information is not configured';
 resultInfo.code = -1009;
 return resultInfo;
 }

 // Create a mail object const mailOpts = Object.assign(
 {
 // Sender from: `Notify <${smtpCfg.auth.user}>`,
 // Subject subject: 'Notify',
 // text: opts.content,
 //html: opts.content,
 // Attachment 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 = 'The email recipient is not configured';
 resultInfo.code = -1010;
 return resultInfo;
 }

 const mailToList = mailOpts.to;
 const transporter = nodemailer.createTransport(smtpCfg);

 // to list to send separately 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;
}

Use the sendMail method to send mail:

const opts = {
 subject: 'subject for test',
 /** HTML format email content*/
 html: `email content for test: <a href="https://lzw.me" rel="external nofollow" rel="external nofollow" >https://lzw.me</a>`,
 /** TEXT text format email content*/
 text: '',
 to: '[email protected]',
 //Attachments list//attachments: [],
};
const smtpConfig = {
 host: 'smtp.qq.com', //QQ: smtp.qq.com; NetEase: smtp.163.com
 port: 465, //Port number. QQ mailbox 465, NetEase mailbox 25
 secure: true,
 auth:
 user: '[email protected]', //Email account pass: '', //Email authorization code},
};
sendMail(opts, smtpConfig).then(result => console.log(result));

2 Node.js method for sending emails based on MS Exchange mail server

Nodemailer is powerless for email services built using Microsoft's Microsoft Exchange Server. Exchange Web Service (EWS) provides an interface for accessing Exchange resources, and there is a detailed interface definition document in Microsoft's official documentation. Popular third-party libraries for Exchange mail services include node-ews and ews-javascript-api.

2.1 Sending MS Exchange emails using node-ews

The following uses the node-ews module as an example to introduce how to send emails using the Exchange mail service.

2.1.1 Encapsulate a method for sending emails based on node-ews

Encapsulate a sendMailByNodeEws method:

import EWS from 'node-ews';

export interface IEwsSendOptions {
 auth:
 user: string;
 pass?: string;
 /** The encrypted password key (NTLMAuth.nt_password). When it is a string, it should be the hex encoding result*/
 nt_password?: string | Buffer;
 /** Password encrypted key (NTLMAuth.lm_password). When it is a string, it should be the hex encoding result*/
 lm_password?: string | Buffer;
 };
 /** Exchange address*/
 host?: string;
 /** Email subject */
 subject?: string;
 /** HTML format email content*/
 html?: string;
 /** TEXT text format email body content (lower priority than html parameter) */
 text?: string;
 to?: string;
}

/**
 * Send email using 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;
}

Use the sendMailByNodeEws method to send email:

sendMailByNodeEws({
 auth:
 user: '[email protected]',
 pass: '123456',
 /** The encrypted password key (NTLMAuth.nt_password). When it is a string, it should be the hex encoding result*/
 nt_password: '',
 /** Password encrypted key (NTLMAuth.lm_password). When it is a string, it should be the hex encoding result*/
 lm_password: '',
 },
 /** Exchange address*/
 host: 'https://ews.xxx.com',
 /** Email subject */
 subject: 'subject for test',
 /** HTML format email content*/
 html: `email content for test: <a href="https://lzw.me" rel="external nofollow" rel="external nofollow" >https://lzw.me</a>`,
 /** TEXT text format email body content (lower priority than html parameter) */
 text: '',
 to: '[email protected]',
})

2.1.2 Authentication configuration based on NTLMAuth

Directly configuring the pass password may lead to the disclosure of the plain text password. We can leave the pass field blank, configure the nt_password and lm_password fields, and use the NTLMAuth authentication mode. These two fields are generated based on the pass plain text. The nodejs generation method can be completed with the help of the httpntlm module. The specific reference is as follows:

import { ntlm as NTLMAuth } from 'httpntlm';

/** Convert the input email account password into NTLMAuth key (hex) format and output*/
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 Sending MS Exchange emails using ews-javascript-api

Based on the way of sending emails by ews-javascript-api, there are relevant examples in its official wiki, but I failed in the test process, specifically because I could not obtain server authentication, and I could not verify the specific reason, so the following code is only for reference:

/**
 * Use `ews-javascript-api` to send (MS Exchange) emails */
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;

 // Send attachment // 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 Extended reference

nodemailer.com/about/
github.com/CumberlandG…
github.com/gautamsi/ew…
github.com/lzwme/node-…

The above is the details of node.js sending emails based on STMP protocol and EWS protocol. For more information about node.js sending emails, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • In-depth analysis of Node.js single-threaded model
  • Understanding what Node.js is is so easy
  • Specific use of node.js global variables
  • The whole process of node.js using express to automatically build the project
  • Detailed explanation of node.js installation and HbuilderX configuration
  • Node.js file copying, folder creation and other related operations
  • Detailed explanation of asynchronous generators and asynchronous iterations in Node.js
  • Detailed explanation of the steps to create a web server with node.js
  • How to collect and parse command line arguments in Node.js
  • Detailed explanation of Alibaba Node.js technical documentation process module learning guide
  • Complete steps to develop cli using node.js
  • How to connect MySQL to Node.js through Sequelize
  • How to install the latest version of Node.js on CentOS 8.2 server
  • How to remove the BOM header of Node.js text file
  • Appium+python automated configuration (adk, jdk, node.js)
  • How to convert a callback in Node.js to a Promise
  • Node.js path module, get the file suffix operation
  • First experience with node.js crawler framework node-crawler
  • Nodejs Exploration: In-depth understanding of the principle of single-threaded high concurrency

<<:  MySql login password forgotten and password forgotten solution

>>:  Compile CPP files using G++ in Ubuntu

Recommend

Parsing MySQL binlog

Table of contents 1. Introduction to binlog 2. Bi...

Two practical ways to enable proxy in React

Two ways to enable proxy React does not have enca...

Steps to create a Vite project

Table of contents Preface What does yarn create d...

Example of usage of keep-alive component in Vue

Problem description (what is keep-alive) keep-ali...

Teach you how to implement a react from html

What is React React is a simple javascript UI lib...

Solution to Docker pull timeout

Recently, Docker image pull is very unstable. It ...

Analysis of the Linux input subsystem framework principle

Input subsystem framework The linux input subsyst...

Example of how to adapt the Vue project to the large screen

A brief analysis of rem First of all, rem is a CS...

HTML drawing user registration page

This article shares the specific implementation c...

Professional and non-professional web design

First of all, the formation of web page style main...

How to use cursor triggers in MySQL

cursor The set of rows returned by the select que...

What are the advantages of MySQL MGR?

MGR (MySQL Group Replication) is a new feature ad...

Five solutions to cross-browser problems (summary)

Brief review: Browser compatibility issues are of...

How to add a column to a large MySQL table

The question is referenced from: https://www.zhih...

JS Asynchronous Stack Tracing: Why await is better than Promise

Overview The fundamental difference between async...