mirror of https://github.com/eleith/emailjs.git
Compare commits
6 Commits
c1c4d0b81b
...
99bdf2fb14
Author | SHA1 | Date |
---|---|---|
Zack Schuster | 99bdf2fb14 | |
Zack Schuster | 3403819397 | |
eleith | ad2e355286 | |
eleith | bc1fcf1f8e | |
Zack Schuster | afe2105919 | |
Zack Schuster | f8a691f80a |
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [3.4.0] - 2020-12-01
|
||||||
|
### Added
|
||||||
|
- `SMTPClient#sendAsync` API [#267](https://github.com/eleith/emailjs/issues/267)
|
||||||
|
- `isRFC2822Date` API
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- use `WeakSet` instead of `WeakMap` for greylist tracking
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- use camelCase style for internal function names
|
||||||
|
- use correct types in jsdoc comments
|
||||||
|
|
||||||
## [3.3.0] - 2020-08-08
|
## [3.3.0] - 2020-08-08
|
||||||
### Added
|
### Added
|
||||||
- greylist support [#202](https://github.com/eleith/emailjs/issues/202)
|
- greylist support [#202](https://github.com/eleith/emailjs/issues/202)
|
||||||
|
|
27
README.md
27
README.md
|
@ -50,6 +50,33 @@ client.send(
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## EXAMPLE USAGE - using async/await
|
||||||
|
|
||||||
|
```js
|
||||||
|
// assuming top-level await for brevity
|
||||||
|
import { SMTPClient } from 'emailjs';
|
||||||
|
|
||||||
|
const client = new SMTPClient({
|
||||||
|
user: 'user',
|
||||||
|
password: 'password',
|
||||||
|
host: 'smtp.your-email.com',
|
||||||
|
ssl: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const message = await client.sendAsync({
|
||||||
|
text: 'i hope this works',
|
||||||
|
from: 'you <username@your-email.com>',
|
||||||
|
to: 'someone <someone@your-email.com>, another <another@your-email.com>',
|
||||||
|
cc: 'else <else@your-email.com>',
|
||||||
|
subject: 'testing emailjs',
|
||||||
|
});
|
||||||
|
console.log(message);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## EXAMPLE USAGE - html emails and attachments
|
## EXAMPLE USAGE - html emails and attachments
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "emailjs",
|
"name": "emailjs",
|
||||||
"description": "send text/html emails and attachments (files, streams and strings) from node.js to any smtp server",
|
"description": "send text/html emails and attachments (files, streams and strings) from node.js to any smtp server",
|
||||||
"version": "3.3.0",
|
"version": "3.4.0",
|
||||||
"author": "eleith",
|
"author": "eleith",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"izuzak",
|
"izuzak",
|
||||||
|
|
197
rollup/email.cjs
197
rollup/email.cjs
|
@ -256,6 +256,19 @@ function getRFC2822DateUTC(date = new Date()) {
|
||||||
dates.push('+0000');
|
dates.push('+0000');
|
||||||
return dates.join(' ');
|
return dates.join(' ');
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* RFC 2822 regex
|
||||||
|
* @see https://tools.ietf.org/html/rfc2822#section-3.3
|
||||||
|
* @see https://github.com/moment/moment/blob/a831fc7e2694281ce31e4f090bbcf90a690f0277/src/lib/create/from-string.js#L101
|
||||||
|
*/
|
||||||
|
const rfc2822re = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/.compile();
|
||||||
|
/**
|
||||||
|
* @param {string} [date] a string to check for conformance to the [rfc2822](https://tools.ietf.org/html/rfc2822#section-3.3) standard
|
||||||
|
* @returns {boolean} the result of the conformance check
|
||||||
|
*/
|
||||||
|
function isRFC2822Date(date) {
|
||||||
|
return rfc2822re.test(date);
|
||||||
|
}
|
||||||
|
|
||||||
// adapted from https://github.com/emailjs/emailjs-mime-codec/blob/6909c706b9f09bc0e5c3faf48f723cca53e5b352/src/mimecodec.js
|
// adapted from https://github.com/emailjs/emailjs-mime-codec/blob/6909c706b9f09bc0e5c3faf48f723cca53e5b352/src/mimecodec.js
|
||||||
const encoder = new util.TextEncoder();
|
const encoder = new util.TextEncoder();
|
||||||
|
@ -458,7 +471,7 @@ const MIME64CHUNK = (MIMECHUNK * 6);
|
||||||
*/
|
*/
|
||||||
const BUFFERSIZE = (MIMECHUNK * 24 * 7);
|
const BUFFERSIZE = (MIMECHUNK * 24 * 7);
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
function generate_boundary() {
|
function generateBoundary() {
|
||||||
let text = '';
|
let text = '';
|
||||||
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+_,-./:=?";
|
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+_,-./:=?";
|
||||||
for (let i = 0; i < 69; i++) {
|
for (let i = 0; i < 69; i++) {
|
||||||
|
@ -597,7 +610,7 @@ class Message {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @returns {*} a stream of the current message
|
* @returns {MessageStream} a stream of the current message
|
||||||
*/
|
*/
|
||||||
stream() {
|
stream() {
|
||||||
return new MessageStream(this);
|
return new MessageStream(this);
|
||||||
|
@ -617,7 +630,7 @@ class Message {
|
||||||
}
|
}
|
||||||
class MessageStream extends stream.Stream {
|
class MessageStream extends stream.Stream {
|
||||||
/**
|
/**
|
||||||
* @param {*} message the message to stream
|
* @param {Message} message the message to stream
|
||||||
*/
|
*/
|
||||||
constructor(message) {
|
constructor(message) {
|
||||||
super();
|
super();
|
||||||
|
@ -670,7 +683,7 @@ class MessageStream extends stream.Stream {
|
||||||
* @param {MessageAttachment} [attachment] the attachment whose headers you would like to output
|
* @param {MessageAttachment} [attachment] the attachment whose headers you would like to output
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_attachment_headers = (attachment) => {
|
const outputAttachmentHeaders = (attachment) => {
|
||||||
let data = [];
|
let data = [];
|
||||||
const headers = {
|
const headers = {
|
||||||
'content-type': attachment.type +
|
'content-type': attachment.type +
|
||||||
|
@ -702,7 +715,7 @@ class MessageStream extends stream.Stream {
|
||||||
* @param {function(): void} [callback] the function to call after output is finished
|
* @param {function(): void} [callback] the function to call after output is finished
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_base64 = (data, callback) => {
|
const outputBase64 = (data, callback) => {
|
||||||
const loops = Math.ceil(data.length / MIMECHUNK);
|
const loops = Math.ceil(data.length / MIMECHUNK);
|
||||||
let loop = 0;
|
let loop = 0;
|
||||||
while (loop < loops) {
|
while (loop < loops) {
|
||||||
|
@ -713,7 +726,7 @@ class MessageStream extends stream.Stream {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const output_file = (attachment, next) => {
|
const outputFile = (attachment, next) => {
|
||||||
const chunk = MIME64CHUNK * 16;
|
const chunk = MIME64CHUNK * 16;
|
||||||
const buffer = Buffer.alloc(chunk);
|
const buffer = Buffer.alloc(chunk);
|
||||||
const closed = (fd) => fs.closeSync(fd);
|
const closed = (fd) => fs.closeSync(fd);
|
||||||
|
@ -739,7 +752,7 @@ class MessageStream extends stream.Stream {
|
||||||
encoding = 'base64';
|
encoding = 'base64';
|
||||||
}
|
}
|
||||||
// guaranteed to be encoded without padding unless it is our last read
|
// guaranteed to be encoded without padding unless it is our last read
|
||||||
output_base64(buffer.toString(encoding, 0, bytes), () => {
|
outputBase64(buffer.toString(encoding, 0, bytes), () => {
|
||||||
if (bytes == chunk) {
|
if (bytes == chunk) {
|
||||||
// we read a full chunk, there might be more
|
// we read a full chunk, there might be more
|
||||||
fs.read(fd, buffer, 0, chunk, null, read);
|
fs.read(fd, buffer, 0, chunk, null, read);
|
||||||
|
@ -768,13 +781,13 @@ class MessageStream extends stream.Stream {
|
||||||
* @param {function(): void} callback the function to call after output is finished
|
* @param {function(): void} callback the function to call after output is finished
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_stream = (attachment, callback) => {
|
const outputStream = (attachment, callback) => {
|
||||||
const { stream } = attachment;
|
const { stream } = attachment;
|
||||||
if (stream === null || stream === void 0 ? void 0 : stream.readable) {
|
if (stream === null || stream === void 0 ? void 0 : stream.readable) {
|
||||||
let previous = Buffer.alloc(0);
|
let previous = Buffer.alloc(0);
|
||||||
stream.resume();
|
stream.resume();
|
||||||
stream.on('end', () => {
|
stream.on('end', () => {
|
||||||
output_base64(previous.toString('base64'), callback);
|
outputBase64(previous.toString('base64'), callback);
|
||||||
this.removeListener('pause', stream.pause);
|
this.removeListener('pause', stream.pause);
|
||||||
this.removeListener('resume', stream.resume);
|
this.removeListener('resume', stream.resume);
|
||||||
this.removeListener('error', stream.resume);
|
this.removeListener('error', stream.resume);
|
||||||
|
@ -792,7 +805,7 @@ class MessageStream extends stream.Stream {
|
||||||
// copy dangling bytes into previous buffer
|
// copy dangling bytes into previous buffer
|
||||||
buffer.copy(previous, 0, buffer.length - padded);
|
buffer.copy(previous, 0, buffer.length - padded);
|
||||||
}
|
}
|
||||||
output_base64(buffer.toString('base64', 0, buffer.length - padded));
|
outputBase64(buffer.toString('base64', 0, buffer.length - padded));
|
||||||
});
|
});
|
||||||
this.on('pause', stream.pause);
|
this.on('pause', stream.pause);
|
||||||
this.on('resume', stream.resume);
|
this.on('resume', stream.resume);
|
||||||
|
@ -802,13 +815,13 @@ class MessageStream extends stream.Stream {
|
||||||
this.emit('error', { message: 'stream not readable' });
|
this.emit('error', { message: 'stream not readable' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const output_attachment = (attachment, callback) => {
|
const outputAttachment = (attachment, callback) => {
|
||||||
const build = attachment.path
|
const build = attachment.path
|
||||||
? output_file
|
? outputFile
|
||||||
: attachment.stream
|
: attachment.stream
|
||||||
? output_stream
|
? outputStream
|
||||||
: output_data;
|
: outputData;
|
||||||
output_attachment_headers(attachment);
|
outputAttachmentHeaders(attachment);
|
||||||
build(attachment, callback);
|
build(attachment, callback);
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -818,14 +831,14 @@ class MessageStream extends stream.Stream {
|
||||||
* @param {function(): void} callback the function to call if index is greater than upper bound
|
* @param {function(): void} callback the function to call if index is greater than upper bound
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_message = (boundary, list, index, callback) => {
|
const outputMessage = (boundary, list, index, callback) => {
|
||||||
if (index < list.length) {
|
if (index < list.length) {
|
||||||
output(`--${boundary}${CRLF}`);
|
output(`--${boundary}${CRLF}`);
|
||||||
if (list[index].related) {
|
if (list[index].related) {
|
||||||
output_related(list[index], () => output_message(boundary, list, index + 1, callback));
|
outputRelated(list[index], () => outputMessage(boundary, list, index + 1, callback));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
output_attachment(list[index], () => output_message(boundary, list, index + 1, callback));
|
outputAttachment(list[index], () => outputMessage(boundary, list, index + 1, callback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -833,17 +846,17 @@ class MessageStream extends stream.Stream {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const output_mixed = () => {
|
const outputMixed = () => {
|
||||||
const boundary = generate_boundary();
|
const boundary = generateBoundary();
|
||||||
output(`Content-Type: multipart/mixed; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
output(`Content-Type: multipart/mixed; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
||||||
if (this.message.alternative == null) {
|
if (this.message.alternative == null) {
|
||||||
output_text(this.message);
|
outputText(this.message);
|
||||||
output_message(boundary, this.message.attachments, 0, close);
|
outputMessage(boundary, this.message.attachments, 0, close);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
output_alternative(
|
outputAlternative(
|
||||||
// typescript bug; should narrow to { alternative: MessageAttachment }
|
// typescript bug; should narrow to { alternative: MessageAttachment }
|
||||||
this.message, () => output_message(boundary, this.message.attachments, 0, close));
|
this.message, () => outputMessage(boundary, this.message.attachments, 0, close));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -851,16 +864,16 @@ class MessageStream extends stream.Stream {
|
||||||
* @param {function(): void} callback the function to call after output is finished
|
* @param {function(): void} callback the function to call after output is finished
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_data = (attachment, callback) => {
|
const outputData = (attachment, callback) => {
|
||||||
var _a, _b;
|
var _a, _b;
|
||||||
output_base64(attachment.encoded
|
outputBase64(attachment.encoded
|
||||||
? (_a = attachment.data) !== null && _a !== void 0 ? _a : '' : Buffer.from((_b = attachment.data) !== null && _b !== void 0 ? _b : '').toString('base64'), callback);
|
? (_a = attachment.data) !== null && _a !== void 0 ? _a : '' : Buffer.from((_b = attachment.data) !== null && _b !== void 0 ? _b : '').toString('base64'), callback);
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @param {Message} message the message to output
|
* @param {Message} message the message to output
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_text = (message) => {
|
const outputText = (message) => {
|
||||||
let data = [];
|
let data = [];
|
||||||
data = data.concat([
|
data = data.concat([
|
||||||
'Content-Type:',
|
'Content-Type:',
|
||||||
|
@ -878,12 +891,12 @@ class MessageStream extends stream.Stream {
|
||||||
* @param {function(): void} callback the function to call after output is finished
|
* @param {function(): void} callback the function to call after output is finished
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_related = (message, callback) => {
|
const outputRelated = (message, callback) => {
|
||||||
const boundary = generate_boundary();
|
const boundary = generateBoundary();
|
||||||
output(`Content-Type: multipart/related; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
output(`Content-Type: multipart/related; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
||||||
output_attachment(message, () => {
|
outputAttachment(message, () => {
|
||||||
var _a;
|
var _a;
|
||||||
output_message(boundary, (_a = message.related) !== null && _a !== void 0 ? _a : [], 0, () => {
|
outputMessage(boundary, (_a = message.related) !== null && _a !== void 0 ? _a : [], 0, () => {
|
||||||
output(`${CRLF}--${boundary}--${CRLF}${CRLF}`);
|
output(`${CRLF}--${boundary}--${CRLF}${CRLF}`);
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
@ -894,10 +907,10 @@ class MessageStream extends stream.Stream {
|
||||||
* @param {function(): void} callback the function to call after output is finished
|
* @param {function(): void} callback the function to call after output is finished
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_alternative = (message, callback) => {
|
const outputAlternative = (message, callback) => {
|
||||||
const boundary = generate_boundary();
|
const boundary = generateBoundary();
|
||||||
output(`Content-Type: multipart/alternative; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
output(`Content-Type: multipart/alternative; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
||||||
output_text(message);
|
outputText(message);
|
||||||
output(`--${boundary}${CRLF}`);
|
output(`--${boundary}${CRLF}`);
|
||||||
/**
|
/**
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
|
@ -907,10 +920,10 @@ class MessageStream extends stream.Stream {
|
||||||
callback();
|
callback();
|
||||||
};
|
};
|
||||||
if (message.alternative.related) {
|
if (message.alternative.related) {
|
||||||
output_related(message.alternative, finish);
|
outputRelated(message.alternative, finish);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
output_attachment(message.alternative, finish);
|
outputAttachment(message.alternative, finish);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const close = (err) => {
|
const close = (err) => {
|
||||||
|
@ -934,20 +947,20 @@ class MessageStream extends stream.Stream {
|
||||||
/**
|
/**
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_header_data = () => {
|
const outputHeaderData = () => {
|
||||||
if (this.message.attachments.length || this.message.alternative) {
|
if (this.message.attachments.length || this.message.alternative) {
|
||||||
output(`MIME-Version: 1.0${CRLF}`);
|
output(`MIME-Version: 1.0${CRLF}`);
|
||||||
output_mixed();
|
outputMixed();
|
||||||
} // you only have a text message!
|
} // you only have a text message!
|
||||||
else {
|
else {
|
||||||
output_text(this.message);
|
outputText(this.message);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_header = () => {
|
const outputHeader = () => {
|
||||||
let data = [];
|
let data = [];
|
||||||
for (const header in this.message.header) {
|
for (const header in this.message.header) {
|
||||||
// do not output BCC in the headers (regex) nor custom Object.prototype functions...
|
// do not output BCC in the headers (regex) nor custom Object.prototype functions...
|
||||||
|
@ -962,10 +975,10 @@ class MessageStream extends stream.Stream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output(data.join(''));
|
output(data.join(''));
|
||||||
output_header_data();
|
outputHeaderData();
|
||||||
};
|
};
|
||||||
this.once('destroy', close);
|
this.once('destroy', close);
|
||||||
process.nextTick(output_header);
|
process.nextTick(outputHeader);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
|
@ -1136,7 +1149,7 @@ const CRLF$1 = '\r\n';
|
||||||
const GREYLIST_DELAY = 300;
|
const GREYLIST_DELAY = 300;
|
||||||
let DEBUG = 0;
|
let DEBUG = 0;
|
||||||
/**
|
/**
|
||||||
* @param {...any} args the message(s) to log
|
* @param {...any[]} args the message(s) to log
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const log = (...args) => {
|
const log = (...args) => {
|
||||||
|
@ -1149,8 +1162,8 @@ const log = (...args) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @param {function(...*): void} callback the function to call
|
* @param {function(...any[]): void} callback the function to call
|
||||||
* @param {...*} args the arguments to apply to the function
|
* @param {...any[]} args the arguments to apply to the function
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const caller = (callback, ...args) => {
|
const caller = (callback, ...args) => {
|
||||||
|
@ -1187,7 +1200,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
this.host = 'localhost';
|
this.host = 'localhost';
|
||||||
this.ssl = false;
|
this.ssl = false;
|
||||||
this.tls = false;
|
this.tls = false;
|
||||||
this.greylistResponseTracker = new WeakMap();
|
this.greylistResponseTracker = new WeakSet();
|
||||||
if (Array.isArray(authentication)) {
|
if (Array.isArray(authentication)) {
|
||||||
this.authentication = authentication;
|
this.authentication = authentication;
|
||||||
}
|
}
|
||||||
|
@ -1250,7 +1263,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
* NOTE: `host` is trimmed before being used to establish a connection; however, the original untrimmed value will still be visible in configuration.
|
* NOTE: `host` is trimmed before being used to establish a connection; however, the original untrimmed value will still be visible in configuration.
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {number} [port] the port to use for the connection
|
* @param {number} [port] the port to use for the connection
|
||||||
* @param {string} [host] the hostname to use for the connection
|
* @param {string} [host] the hostname to use for the connection
|
||||||
* @param {ConnectOptions} [options={}] the options
|
* @param {ConnectOptions} [options={}] the options
|
||||||
|
@ -1332,7 +1345,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {string} str the string to send
|
* @param {string} str the string to send
|
||||||
* @param {*} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
send(str, callback) {
|
send(str, callback) {
|
||||||
|
@ -1359,7 +1372,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {string} cmd command to issue
|
* @param {string} cmd command to issue
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {(number[] | number)} [codes=[250]] array codes
|
* @param {(number[] | number)} [codes=[250]] array codes
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1380,8 +1393,8 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
else if ((code === 450 || code === 451) &&
|
else if ((code === 450 || code === 451) &&
|
||||||
msg.message.toLowerCase().includes('greylist') &&
|
msg.message.toLowerCase().includes('greylist') &&
|
||||||
this.greylistResponseTracker.get(response) === false) {
|
this.greylistResponseTracker.has(response) === false) {
|
||||||
this.greylistResponseTracker.set(response, true);
|
this.greylistResponseTracker.add(response);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.send(cmd + CRLF$1, response);
|
this.send(cmd + CRLF$1, response);
|
||||||
}, GREYLIST_DELAY);
|
}, GREYLIST_DELAY);
|
||||||
|
@ -1393,7 +1406,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.greylistResponseTracker.set(response, false);
|
this.greylistResponseTracker.delete(response);
|
||||||
this.send(cmd + CRLF$1, response);
|
this.send(cmd + CRLF$1, response);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1406,7 +1419,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
* As this command was deprecated by rfc2821, it should only be used for compatibility with non-compliant servers.
|
* As this command was deprecated by rfc2821, it should only be used for compatibility with non-compliant servers.
|
||||||
* @see https://tools.ietf.org/html/rfc2821#appendix-F.3
|
* @see https://tools.ietf.org/html/rfc2821#appendix-F.3
|
||||||
*
|
*
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} domain the domain to associate with the 'helo' request
|
* @param {string} domain the domain to associate with the 'helo' request
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1423,7 +1436,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
starttls(callback) {
|
starttls(callback) {
|
||||||
|
@ -1478,7 +1491,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} domain the domain to associate with the 'ehlo' request
|
* @param {string} domain the domain to associate with the 'ehlo' request
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1511,7 +1524,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @description SMTP 'help' command, returns text from the server
|
* @description SMTP 'help' command, returns text from the server
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} domain the domain to associate with the 'help' request
|
* @param {string} domain the domain to associate with the 'help' request
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1520,7 +1533,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
rset(callback) {
|
rset(callback) {
|
||||||
|
@ -1528,7 +1541,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
noop(callback) {
|
noop(callback) {
|
||||||
|
@ -1536,7 +1549,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} from the sender
|
* @param {string} from the sender
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1545,7 +1558,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} to the receiver
|
* @param {string} to the receiver
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1554,7 +1567,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
data(callback) {
|
data(callback) {
|
||||||
|
@ -1562,7 +1575,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
data_end(callback) {
|
data_end(callback) {
|
||||||
|
@ -1582,7 +1595,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
* @public
|
* @public
|
||||||
* @description SMTP 'verify' command -- checks for address validity.
|
* @description SMTP 'verify' command -- checks for address validity.
|
||||||
* @param {string} address the address to validate
|
* @param {string} address the address to validate
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
verify(address, callback) {
|
verify(address, callback) {
|
||||||
|
@ -1592,7 +1605,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
* @public
|
* @public
|
||||||
* @description SMTP 'expn' command -- expands a mailing list.
|
* @description SMTP 'expn' command -- expands a mailing list.
|
||||||
* @param {string} address the mailing list to expand
|
* @param {string} address the mailing list to expand
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
expn(address, callback) {
|
expn(address, callback) {
|
||||||
|
@ -1605,7 +1618,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
* If there has been no previous EHLO or HELO command self session, self
|
* If there has been no previous EHLO or HELO command self session, self
|
||||||
* method tries ESMTP EHLO first.
|
* method tries ESMTP EHLO first.
|
||||||
*
|
*
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} [domain] the domain to associate with the command
|
* @param {string} [domain] the domain to associate with the command
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1633,7 +1646,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
*
|
*
|
||||||
* This method will return normally if the authentication was successful.
|
* This method will return normally if the authentication was successful.
|
||||||
*
|
*
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} [user] the username to authenticate with
|
* @param {string} [user] the username to authenticate with
|
||||||
* @param {string} [password] the password for the authentication
|
* @param {string} [password] the password for the authentication
|
||||||
* @param {{ method: string, domain: string }} [options] login options
|
* @param {{ method: string, domain: string }} [options] login options
|
||||||
|
@ -1658,7 +1671,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
* @param {string} challenge challenge
|
* @param {string} challenge challenge
|
||||||
* @returns {string} base64 cram hash
|
* @returns {string} base64 cram hash
|
||||||
*/
|
*/
|
||||||
const encode_cram_md5 = (challenge) => {
|
const encodeCramMd5 = (challenge) => {
|
||||||
const hmac = crypto.createHmac('md5', login.password());
|
const hmac = crypto.createHmac('md5', login.password());
|
||||||
hmac.update(Buffer.from(challenge, 'base64').toString('ascii'));
|
hmac.update(Buffer.from(challenge, 'base64').toString('ascii'));
|
||||||
return Buffer.from(`${login.user()} ${hmac.digest('hex')}`).toString('base64');
|
return Buffer.from(`${login.user()} ${hmac.digest('hex')}`).toString('base64');
|
||||||
|
@ -1666,12 +1679,12 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @returns {string} base64 login/password
|
* @returns {string} base64 login/password
|
||||||
*/
|
*/
|
||||||
const encode_plain = () => Buffer.from(`\u0000${login.user()}\u0000${login.password()}`).toString('base64');
|
const encodePlain = () => Buffer.from(`\u0000${login.user()}\u0000${login.password()}`).toString('base64');
|
||||||
/**
|
/**
|
||||||
* @see https://developers.google.com/gmail/xoauth2_protocol
|
* @see https://developers.google.com/gmail/xoauth2_protocol
|
||||||
* @returns {string} base64 xoauth2 auth token
|
* @returns {string} base64 xoauth2 auth token
|
||||||
*/
|
*/
|
||||||
const encode_xoauth2 = () => Buffer.from(`user=${login.user()}\u0001auth=Bearer ${login.password()}\u0001\u0001`).toString('base64');
|
const encodeXoauth2 = () => Buffer.from(`user=${login.user()}\u0001auth=Bearer ${login.password()}\u0001\u0001`).toString('base64');
|
||||||
// List of authentication methods we support: from preferred to
|
// List of authentication methods we support: from preferred to
|
||||||
// less preferred methods.
|
// less preferred methods.
|
||||||
if (!method) {
|
if (!method) {
|
||||||
|
@ -1690,7 +1703,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
/**
|
/**
|
||||||
* handle bad responses from command differently
|
* handle bad responses from command differently
|
||||||
* @param {Error} err err
|
* @param {Error} err err
|
||||||
* @param {*} data data
|
* @param {unknown} data data
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const failed = (err, data) => {
|
const failed = (err, data) => {
|
||||||
|
@ -1700,7 +1713,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @param {Error} err err
|
* @param {Error} err err
|
||||||
* @param {*} data data
|
* @param {unknown} data data
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const response = (err, data) => {
|
const response = (err, data) => {
|
||||||
|
@ -1714,7 +1727,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @param {Error} err err
|
* @param {Error} err err
|
||||||
* @param {*} data data
|
* @param {unknown} data data
|
||||||
* @param {string} msg msg
|
* @param {string} msg msg
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1724,7 +1737,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (method === AUTH_METHODS['CRAM-MD5']) {
|
if (method === AUTH_METHODS['CRAM-MD5']) {
|
||||||
this.command(encode_cram_md5(msg), response, [235, 503]);
|
this.command(encodeCramMd5(msg), response, [235, 503]);
|
||||||
}
|
}
|
||||||
else if (method === AUTH_METHODS.LOGIN) {
|
else if (method === AUTH_METHODS.LOGIN) {
|
||||||
this.command(Buffer.from(login.password()).toString('base64'), response, [235, 503]);
|
this.command(Buffer.from(login.password()).toString('base64'), response, [235, 503]);
|
||||||
|
@ -1733,11 +1746,11 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @param {Error} err err
|
* @param {Error} err err
|
||||||
* @param {*} data data
|
* @param {unknown} data data
|
||||||
* @param {string} msg msg
|
* @param {string} msg msg
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const attempt_user = (err, data) => {
|
const attemptUser = (err, data) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
failed(err, data);
|
failed(err, data);
|
||||||
}
|
}
|
||||||
|
@ -1752,18 +1765,16 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
this.command(`AUTH ${AUTH_METHODS['CRAM-MD5']}`, attempt, [334]);
|
this.command(`AUTH ${AUTH_METHODS['CRAM-MD5']}`, attempt, [334]);
|
||||||
break;
|
break;
|
||||||
case AUTH_METHODS.LOGIN:
|
case AUTH_METHODS.LOGIN:
|
||||||
this.command(`AUTH ${AUTH_METHODS.LOGIN}`, attempt_user, [334]);
|
this.command(`AUTH ${AUTH_METHODS.LOGIN}`, attemptUser, [334]);
|
||||||
break;
|
break;
|
||||||
case AUTH_METHODS.PLAIN:
|
case AUTH_METHODS.PLAIN:
|
||||||
this.command(`AUTH ${AUTH_METHODS.PLAIN} ${encode_plain()}`, response, [235, 503]);
|
this.command(`AUTH ${AUTH_METHODS.PLAIN} ${encodePlain()}`, response, [235, 503]);
|
||||||
break;
|
break;
|
||||||
case AUTH_METHODS.XOAUTH2:
|
case AUTH_METHODS.XOAUTH2:
|
||||||
this.command(`AUTH ${AUTH_METHODS.XOAUTH2} ${encode_xoauth2()}`, response, [235, 503]);
|
this.command(`AUTH ${AUTH_METHODS.XOAUTH2} ${encodeXoauth2()}`, response, [235, 503]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
const msg = 'no form of authorization supported';
|
caller(callback, SMTPError.create('no form of authorization supported', SMTPErrorStates.AUTHNOTSUPPORTED, null, data));
|
||||||
const err = SMTPError.create(msg, SMTPErrorStates.AUTHNOTSUPPORTED, null, data);
|
|
||||||
caller(callback, err);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1797,7 +1808,7 @@ class SMTPConnection extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} [callback] function to call after response
|
* @param {function(...any[]): void} [callback] function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
quit(callback) {
|
quit(callback) {
|
||||||
|
@ -1853,6 +1864,23 @@ class SMTPClient {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
* @param {Message} msg the message to send
|
||||||
|
* @returns {Promise<Message>} a promise that resolves to the fully processed message
|
||||||
|
*/
|
||||||
|
sendAsync(msg) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.send(msg, (err, msg) => {
|
||||||
|
if (err != null) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @description Converts a message to the raw object used by the internal stack.
|
* @description Converts a message to the raw object used by the internal stack.
|
||||||
|
@ -1966,8 +1994,8 @@ class SMTPClient {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @param {*} attachment attachment
|
* @param {MessageAttachment | MessageAttachment[]} attachment attachment
|
||||||
* @returns {*} whether the attachment contains inlined html
|
* @returns {boolean} whether the attachment contains inlined html
|
||||||
*/
|
*/
|
||||||
_containsInlinedHtml(attachment) {
|
_containsInlinedHtml(attachment) {
|
||||||
if (Array.isArray(attachment)) {
|
if (Array.isArray(attachment)) {
|
||||||
|
@ -2088,6 +2116,7 @@ exports.SMTPState = SMTPState;
|
||||||
exports.addressparser = addressparser;
|
exports.addressparser = addressparser;
|
||||||
exports.getRFC2822Date = getRFC2822Date;
|
exports.getRFC2822Date = getRFC2822Date;
|
||||||
exports.getRFC2822DateUTC = getRFC2822DateUTC;
|
exports.getRFC2822DateUTC = getRFC2822DateUTC;
|
||||||
|
exports.isRFC2822Date = isRFC2822Date;
|
||||||
exports.mimeEncode = mimeEncode;
|
exports.mimeEncode = mimeEncode;
|
||||||
exports.mimeWordEncode = mimeWordEncode;
|
exports.mimeWordEncode = mimeWordEncode;
|
||||||
//# sourceMappingURL=email.cjs.map
|
//# sourceMappingURL=email.cjs.map
|
||||||
|
|
File diff suppressed because one or more lines are too long
198
rollup/email.mjs
198
rollup/email.mjs
|
@ -252,6 +252,19 @@ function getRFC2822DateUTC(date = new Date()) {
|
||||||
dates.push('+0000');
|
dates.push('+0000');
|
||||||
return dates.join(' ');
|
return dates.join(' ');
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* RFC 2822 regex
|
||||||
|
* @see https://tools.ietf.org/html/rfc2822#section-3.3
|
||||||
|
* @see https://github.com/moment/moment/blob/a831fc7e2694281ce31e4f090bbcf90a690f0277/src/lib/create/from-string.js#L101
|
||||||
|
*/
|
||||||
|
const rfc2822re = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/.compile();
|
||||||
|
/**
|
||||||
|
* @param {string} [date] a string to check for conformance to the [rfc2822](https://tools.ietf.org/html/rfc2822#section-3.3) standard
|
||||||
|
* @returns {boolean} the result of the conformance check
|
||||||
|
*/
|
||||||
|
function isRFC2822Date(date) {
|
||||||
|
return rfc2822re.test(date);
|
||||||
|
}
|
||||||
|
|
||||||
// adapted from https://github.com/emailjs/emailjs-mime-codec/blob/6909c706b9f09bc0e5c3faf48f723cca53e5b352/src/mimecodec.js
|
// adapted from https://github.com/emailjs/emailjs-mime-codec/blob/6909c706b9f09bc0e5c3faf48f723cca53e5b352/src/mimecodec.js
|
||||||
const encoder = new TextEncoder();
|
const encoder = new TextEncoder();
|
||||||
|
@ -454,7 +467,7 @@ const MIME64CHUNK = (MIMECHUNK * 6);
|
||||||
*/
|
*/
|
||||||
const BUFFERSIZE = (MIMECHUNK * 24 * 7);
|
const BUFFERSIZE = (MIMECHUNK * 24 * 7);
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
function generate_boundary() {
|
function generateBoundary() {
|
||||||
let text = '';
|
let text = '';
|
||||||
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+_,-./:=?";
|
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+_,-./:=?";
|
||||||
for (let i = 0; i < 69; i++) {
|
for (let i = 0; i < 69; i++) {
|
||||||
|
@ -593,7 +606,7 @@ class Message {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @returns {*} a stream of the current message
|
* @returns {MessageStream} a stream of the current message
|
||||||
*/
|
*/
|
||||||
stream() {
|
stream() {
|
||||||
return new MessageStream(this);
|
return new MessageStream(this);
|
||||||
|
@ -613,7 +626,7 @@ class Message {
|
||||||
}
|
}
|
||||||
class MessageStream extends Stream {
|
class MessageStream extends Stream {
|
||||||
/**
|
/**
|
||||||
* @param {*} message the message to stream
|
* @param {Message} message the message to stream
|
||||||
*/
|
*/
|
||||||
constructor(message) {
|
constructor(message) {
|
||||||
super();
|
super();
|
||||||
|
@ -666,7 +679,7 @@ class MessageStream extends Stream {
|
||||||
* @param {MessageAttachment} [attachment] the attachment whose headers you would like to output
|
* @param {MessageAttachment} [attachment] the attachment whose headers you would like to output
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_attachment_headers = (attachment) => {
|
const outputAttachmentHeaders = (attachment) => {
|
||||||
let data = [];
|
let data = [];
|
||||||
const headers = {
|
const headers = {
|
||||||
'content-type': attachment.type +
|
'content-type': attachment.type +
|
||||||
|
@ -698,7 +711,7 @@ class MessageStream extends Stream {
|
||||||
* @param {function(): void} [callback] the function to call after output is finished
|
* @param {function(): void} [callback] the function to call after output is finished
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_base64 = (data, callback) => {
|
const outputBase64 = (data, callback) => {
|
||||||
const loops = Math.ceil(data.length / MIMECHUNK);
|
const loops = Math.ceil(data.length / MIMECHUNK);
|
||||||
let loop = 0;
|
let loop = 0;
|
||||||
while (loop < loops) {
|
while (loop < loops) {
|
||||||
|
@ -709,7 +722,7 @@ class MessageStream extends Stream {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const output_file = (attachment, next) => {
|
const outputFile = (attachment, next) => {
|
||||||
const chunk = MIME64CHUNK * 16;
|
const chunk = MIME64CHUNK * 16;
|
||||||
const buffer = Buffer.alloc(chunk);
|
const buffer = Buffer.alloc(chunk);
|
||||||
const closed = (fd) => fs.closeSync(fd);
|
const closed = (fd) => fs.closeSync(fd);
|
||||||
|
@ -735,7 +748,7 @@ class MessageStream extends Stream {
|
||||||
encoding = 'base64';
|
encoding = 'base64';
|
||||||
}
|
}
|
||||||
// guaranteed to be encoded without padding unless it is our last read
|
// guaranteed to be encoded without padding unless it is our last read
|
||||||
output_base64(buffer.toString(encoding, 0, bytes), () => {
|
outputBase64(buffer.toString(encoding, 0, bytes), () => {
|
||||||
if (bytes == chunk) {
|
if (bytes == chunk) {
|
||||||
// we read a full chunk, there might be more
|
// we read a full chunk, there might be more
|
||||||
fs.read(fd, buffer, 0, chunk, null, read);
|
fs.read(fd, buffer, 0, chunk, null, read);
|
||||||
|
@ -764,13 +777,13 @@ class MessageStream extends Stream {
|
||||||
* @param {function(): void} callback the function to call after output is finished
|
* @param {function(): void} callback the function to call after output is finished
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_stream = (attachment, callback) => {
|
const outputStream = (attachment, callback) => {
|
||||||
const { stream } = attachment;
|
const { stream } = attachment;
|
||||||
if (stream === null || stream === void 0 ? void 0 : stream.readable) {
|
if (stream === null || stream === void 0 ? void 0 : stream.readable) {
|
||||||
let previous = Buffer.alloc(0);
|
let previous = Buffer.alloc(0);
|
||||||
stream.resume();
|
stream.resume();
|
||||||
stream.on('end', () => {
|
stream.on('end', () => {
|
||||||
output_base64(previous.toString('base64'), callback);
|
outputBase64(previous.toString('base64'), callback);
|
||||||
this.removeListener('pause', stream.pause);
|
this.removeListener('pause', stream.pause);
|
||||||
this.removeListener('resume', stream.resume);
|
this.removeListener('resume', stream.resume);
|
||||||
this.removeListener('error', stream.resume);
|
this.removeListener('error', stream.resume);
|
||||||
|
@ -788,7 +801,7 @@ class MessageStream extends Stream {
|
||||||
// copy dangling bytes into previous buffer
|
// copy dangling bytes into previous buffer
|
||||||
buffer.copy(previous, 0, buffer.length - padded);
|
buffer.copy(previous, 0, buffer.length - padded);
|
||||||
}
|
}
|
||||||
output_base64(buffer.toString('base64', 0, buffer.length - padded));
|
outputBase64(buffer.toString('base64', 0, buffer.length - padded));
|
||||||
});
|
});
|
||||||
this.on('pause', stream.pause);
|
this.on('pause', stream.pause);
|
||||||
this.on('resume', stream.resume);
|
this.on('resume', stream.resume);
|
||||||
|
@ -798,13 +811,13 @@ class MessageStream extends Stream {
|
||||||
this.emit('error', { message: 'stream not readable' });
|
this.emit('error', { message: 'stream not readable' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const output_attachment = (attachment, callback) => {
|
const outputAttachment = (attachment, callback) => {
|
||||||
const build = attachment.path
|
const build = attachment.path
|
||||||
? output_file
|
? outputFile
|
||||||
: attachment.stream
|
: attachment.stream
|
||||||
? output_stream
|
? outputStream
|
||||||
: output_data;
|
: outputData;
|
||||||
output_attachment_headers(attachment);
|
outputAttachmentHeaders(attachment);
|
||||||
build(attachment, callback);
|
build(attachment, callback);
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -814,14 +827,14 @@ class MessageStream extends Stream {
|
||||||
* @param {function(): void} callback the function to call if index is greater than upper bound
|
* @param {function(): void} callback the function to call if index is greater than upper bound
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_message = (boundary, list, index, callback) => {
|
const outputMessage = (boundary, list, index, callback) => {
|
||||||
if (index < list.length) {
|
if (index < list.length) {
|
||||||
output(`--${boundary}${CRLF}`);
|
output(`--${boundary}${CRLF}`);
|
||||||
if (list[index].related) {
|
if (list[index].related) {
|
||||||
output_related(list[index], () => output_message(boundary, list, index + 1, callback));
|
outputRelated(list[index], () => outputMessage(boundary, list, index + 1, callback));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
output_attachment(list[index], () => output_message(boundary, list, index + 1, callback));
|
outputAttachment(list[index], () => outputMessage(boundary, list, index + 1, callback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -829,17 +842,17 @@ class MessageStream extends Stream {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const output_mixed = () => {
|
const outputMixed = () => {
|
||||||
const boundary = generate_boundary();
|
const boundary = generateBoundary();
|
||||||
output(`Content-Type: multipart/mixed; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
output(`Content-Type: multipart/mixed; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
||||||
if (this.message.alternative == null) {
|
if (this.message.alternative == null) {
|
||||||
output_text(this.message);
|
outputText(this.message);
|
||||||
output_message(boundary, this.message.attachments, 0, close);
|
outputMessage(boundary, this.message.attachments, 0, close);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
output_alternative(
|
outputAlternative(
|
||||||
// typescript bug; should narrow to { alternative: MessageAttachment }
|
// typescript bug; should narrow to { alternative: MessageAttachment }
|
||||||
this.message, () => output_message(boundary, this.message.attachments, 0, close));
|
this.message, () => outputMessage(boundary, this.message.attachments, 0, close));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -847,16 +860,16 @@ class MessageStream extends Stream {
|
||||||
* @param {function(): void} callback the function to call after output is finished
|
* @param {function(): void} callback the function to call after output is finished
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_data = (attachment, callback) => {
|
const outputData = (attachment, callback) => {
|
||||||
var _a, _b;
|
var _a, _b;
|
||||||
output_base64(attachment.encoded
|
outputBase64(attachment.encoded
|
||||||
? (_a = attachment.data) !== null && _a !== void 0 ? _a : '' : Buffer.from((_b = attachment.data) !== null && _b !== void 0 ? _b : '').toString('base64'), callback);
|
? (_a = attachment.data) !== null && _a !== void 0 ? _a : '' : Buffer.from((_b = attachment.data) !== null && _b !== void 0 ? _b : '').toString('base64'), callback);
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @param {Message} message the message to output
|
* @param {Message} message the message to output
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_text = (message) => {
|
const outputText = (message) => {
|
||||||
let data = [];
|
let data = [];
|
||||||
data = data.concat([
|
data = data.concat([
|
||||||
'Content-Type:',
|
'Content-Type:',
|
||||||
|
@ -874,12 +887,12 @@ class MessageStream extends Stream {
|
||||||
* @param {function(): void} callback the function to call after output is finished
|
* @param {function(): void} callback the function to call after output is finished
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_related = (message, callback) => {
|
const outputRelated = (message, callback) => {
|
||||||
const boundary = generate_boundary();
|
const boundary = generateBoundary();
|
||||||
output(`Content-Type: multipart/related; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
output(`Content-Type: multipart/related; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
||||||
output_attachment(message, () => {
|
outputAttachment(message, () => {
|
||||||
var _a;
|
var _a;
|
||||||
output_message(boundary, (_a = message.related) !== null && _a !== void 0 ? _a : [], 0, () => {
|
outputMessage(boundary, (_a = message.related) !== null && _a !== void 0 ? _a : [], 0, () => {
|
||||||
output(`${CRLF}--${boundary}--${CRLF}${CRLF}`);
|
output(`${CRLF}--${boundary}--${CRLF}${CRLF}`);
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
@ -890,10 +903,10 @@ class MessageStream extends Stream {
|
||||||
* @param {function(): void} callback the function to call after output is finished
|
* @param {function(): void} callback the function to call after output is finished
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_alternative = (message, callback) => {
|
const outputAlternative = (message, callback) => {
|
||||||
const boundary = generate_boundary();
|
const boundary = generateBoundary();
|
||||||
output(`Content-Type: multipart/alternative; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
output(`Content-Type: multipart/alternative; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}`);
|
||||||
output_text(message);
|
outputText(message);
|
||||||
output(`--${boundary}${CRLF}`);
|
output(`--${boundary}${CRLF}`);
|
||||||
/**
|
/**
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
|
@ -903,10 +916,10 @@ class MessageStream extends Stream {
|
||||||
callback();
|
callback();
|
||||||
};
|
};
|
||||||
if (message.alternative.related) {
|
if (message.alternative.related) {
|
||||||
output_related(message.alternative, finish);
|
outputRelated(message.alternative, finish);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
output_attachment(message.alternative, finish);
|
outputAttachment(message.alternative, finish);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const close = (err) => {
|
const close = (err) => {
|
||||||
|
@ -930,20 +943,20 @@ class MessageStream extends Stream {
|
||||||
/**
|
/**
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_header_data = () => {
|
const outputHeaderData = () => {
|
||||||
if (this.message.attachments.length || this.message.alternative) {
|
if (this.message.attachments.length || this.message.alternative) {
|
||||||
output(`MIME-Version: 1.0${CRLF}`);
|
output(`MIME-Version: 1.0${CRLF}`);
|
||||||
output_mixed();
|
outputMixed();
|
||||||
} // you only have a text message!
|
} // you only have a text message!
|
||||||
else {
|
else {
|
||||||
output_text(this.message);
|
outputText(this.message);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output_header = () => {
|
const outputHeader = () => {
|
||||||
let data = [];
|
let data = [];
|
||||||
for (const header in this.message.header) {
|
for (const header in this.message.header) {
|
||||||
// do not output BCC in the headers (regex) nor custom Object.prototype functions...
|
// do not output BCC in the headers (regex) nor custom Object.prototype functions...
|
||||||
|
@ -958,10 +971,10 @@ class MessageStream extends Stream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output(data.join(''));
|
output(data.join(''));
|
||||||
output_header_data();
|
outputHeaderData();
|
||||||
};
|
};
|
||||||
this.once('destroy', close);
|
this.once('destroy', close);
|
||||||
process.nextTick(output_header);
|
process.nextTick(outputHeader);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
|
@ -1132,7 +1145,7 @@ const CRLF$1 = '\r\n';
|
||||||
const GREYLIST_DELAY = 300;
|
const GREYLIST_DELAY = 300;
|
||||||
let DEBUG = 0;
|
let DEBUG = 0;
|
||||||
/**
|
/**
|
||||||
* @param {...any} args the message(s) to log
|
* @param {...any[]} args the message(s) to log
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const log = (...args) => {
|
const log = (...args) => {
|
||||||
|
@ -1145,8 +1158,8 @@ const log = (...args) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @param {function(...*): void} callback the function to call
|
* @param {function(...any[]): void} callback the function to call
|
||||||
* @param {...*} args the arguments to apply to the function
|
* @param {...any[]} args the arguments to apply to the function
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const caller = (callback, ...args) => {
|
const caller = (callback, ...args) => {
|
||||||
|
@ -1183,7 +1196,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
this.host = 'localhost';
|
this.host = 'localhost';
|
||||||
this.ssl = false;
|
this.ssl = false;
|
||||||
this.tls = false;
|
this.tls = false;
|
||||||
this.greylistResponseTracker = new WeakMap();
|
this.greylistResponseTracker = new WeakSet();
|
||||||
if (Array.isArray(authentication)) {
|
if (Array.isArray(authentication)) {
|
||||||
this.authentication = authentication;
|
this.authentication = authentication;
|
||||||
}
|
}
|
||||||
|
@ -1246,7 +1259,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
* NOTE: `host` is trimmed before being used to establish a connection; however, the original untrimmed value will still be visible in configuration.
|
* NOTE: `host` is trimmed before being used to establish a connection; however, the original untrimmed value will still be visible in configuration.
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {number} [port] the port to use for the connection
|
* @param {number} [port] the port to use for the connection
|
||||||
* @param {string} [host] the hostname to use for the connection
|
* @param {string} [host] the hostname to use for the connection
|
||||||
* @param {ConnectOptions} [options={}] the options
|
* @param {ConnectOptions} [options={}] the options
|
||||||
|
@ -1328,7 +1341,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {string} str the string to send
|
* @param {string} str the string to send
|
||||||
* @param {*} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
send(str, callback) {
|
send(str, callback) {
|
||||||
|
@ -1355,7 +1368,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {string} cmd command to issue
|
* @param {string} cmd command to issue
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {(number[] | number)} [codes=[250]] array codes
|
* @param {(number[] | number)} [codes=[250]] array codes
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1376,8 +1389,8 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
else if ((code === 450 || code === 451) &&
|
else if ((code === 450 || code === 451) &&
|
||||||
msg.message.toLowerCase().includes('greylist') &&
|
msg.message.toLowerCase().includes('greylist') &&
|
||||||
this.greylistResponseTracker.get(response) === false) {
|
this.greylistResponseTracker.has(response) === false) {
|
||||||
this.greylistResponseTracker.set(response, true);
|
this.greylistResponseTracker.add(response);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.send(cmd + CRLF$1, response);
|
this.send(cmd + CRLF$1, response);
|
||||||
}, GREYLIST_DELAY);
|
}, GREYLIST_DELAY);
|
||||||
|
@ -1389,7 +1402,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.greylistResponseTracker.set(response, false);
|
this.greylistResponseTracker.delete(response);
|
||||||
this.send(cmd + CRLF$1, response);
|
this.send(cmd + CRLF$1, response);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1402,7 +1415,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
* As this command was deprecated by rfc2821, it should only be used for compatibility with non-compliant servers.
|
* As this command was deprecated by rfc2821, it should only be used for compatibility with non-compliant servers.
|
||||||
* @see https://tools.ietf.org/html/rfc2821#appendix-F.3
|
* @see https://tools.ietf.org/html/rfc2821#appendix-F.3
|
||||||
*
|
*
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} domain the domain to associate with the 'helo' request
|
* @param {string} domain the domain to associate with the 'helo' request
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1419,7 +1432,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
starttls(callback) {
|
starttls(callback) {
|
||||||
|
@ -1474,7 +1487,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} domain the domain to associate with the 'ehlo' request
|
* @param {string} domain the domain to associate with the 'ehlo' request
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1507,7 +1520,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @description SMTP 'help' command, returns text from the server
|
* @description SMTP 'help' command, returns text from the server
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} domain the domain to associate with the 'help' request
|
* @param {string} domain the domain to associate with the 'help' request
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1516,7 +1529,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
rset(callback) {
|
rset(callback) {
|
||||||
|
@ -1524,7 +1537,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
noop(callback) {
|
noop(callback) {
|
||||||
|
@ -1532,7 +1545,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} from the sender
|
* @param {string} from the sender
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1541,7 +1554,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} to the receiver
|
* @param {string} to the receiver
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1550,7 +1563,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
data(callback) {
|
data(callback) {
|
||||||
|
@ -1558,7 +1571,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
data_end(callback) {
|
data_end(callback) {
|
||||||
|
@ -1578,7 +1591,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
* @public
|
* @public
|
||||||
* @description SMTP 'verify' command -- checks for address validity.
|
* @description SMTP 'verify' command -- checks for address validity.
|
||||||
* @param {string} address the address to validate
|
* @param {string} address the address to validate
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
verify(address, callback) {
|
verify(address, callback) {
|
||||||
|
@ -1588,7 +1601,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
* @public
|
* @public
|
||||||
* @description SMTP 'expn' command -- expands a mailing list.
|
* @description SMTP 'expn' command -- expands a mailing list.
|
||||||
* @param {string} address the mailing list to expand
|
* @param {string} address the mailing list to expand
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
expn(address, callback) {
|
expn(address, callback) {
|
||||||
|
@ -1601,7 +1614,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
* If there has been no previous EHLO or HELO command self session, self
|
* If there has been no previous EHLO or HELO command self session, self
|
||||||
* method tries ESMTP EHLO first.
|
* method tries ESMTP EHLO first.
|
||||||
*
|
*
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} [domain] the domain to associate with the command
|
* @param {string} [domain] the domain to associate with the command
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1629,7 +1642,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
*
|
*
|
||||||
* This method will return normally if the authentication was successful.
|
* This method will return normally if the authentication was successful.
|
||||||
*
|
*
|
||||||
* @param {function(...*): void} callback function to call after response
|
* @param {function(...any[]): void} callback function to call after response
|
||||||
* @param {string} [user] the username to authenticate with
|
* @param {string} [user] the username to authenticate with
|
||||||
* @param {string} [password] the password for the authentication
|
* @param {string} [password] the password for the authentication
|
||||||
* @param {{ method: string, domain: string }} [options] login options
|
* @param {{ method: string, domain: string }} [options] login options
|
||||||
|
@ -1654,7 +1667,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
* @param {string} challenge challenge
|
* @param {string} challenge challenge
|
||||||
* @returns {string} base64 cram hash
|
* @returns {string} base64 cram hash
|
||||||
*/
|
*/
|
||||||
const encode_cram_md5 = (challenge) => {
|
const encodeCramMd5 = (challenge) => {
|
||||||
const hmac = createHmac('md5', login.password());
|
const hmac = createHmac('md5', login.password());
|
||||||
hmac.update(Buffer.from(challenge, 'base64').toString('ascii'));
|
hmac.update(Buffer.from(challenge, 'base64').toString('ascii'));
|
||||||
return Buffer.from(`${login.user()} ${hmac.digest('hex')}`).toString('base64');
|
return Buffer.from(`${login.user()} ${hmac.digest('hex')}`).toString('base64');
|
||||||
|
@ -1662,12 +1675,12 @@ class SMTPConnection extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @returns {string} base64 login/password
|
* @returns {string} base64 login/password
|
||||||
*/
|
*/
|
||||||
const encode_plain = () => Buffer.from(`\u0000${login.user()}\u0000${login.password()}`).toString('base64');
|
const encodePlain = () => Buffer.from(`\u0000${login.user()}\u0000${login.password()}`).toString('base64');
|
||||||
/**
|
/**
|
||||||
* @see https://developers.google.com/gmail/xoauth2_protocol
|
* @see https://developers.google.com/gmail/xoauth2_protocol
|
||||||
* @returns {string} base64 xoauth2 auth token
|
* @returns {string} base64 xoauth2 auth token
|
||||||
*/
|
*/
|
||||||
const encode_xoauth2 = () => Buffer.from(`user=${login.user()}\u0001auth=Bearer ${login.password()}\u0001\u0001`).toString('base64');
|
const encodeXoauth2 = () => Buffer.from(`user=${login.user()}\u0001auth=Bearer ${login.password()}\u0001\u0001`).toString('base64');
|
||||||
// List of authentication methods we support: from preferred to
|
// List of authentication methods we support: from preferred to
|
||||||
// less preferred methods.
|
// less preferred methods.
|
||||||
if (!method) {
|
if (!method) {
|
||||||
|
@ -1686,7 +1699,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* handle bad responses from command differently
|
* handle bad responses from command differently
|
||||||
* @param {Error} err err
|
* @param {Error} err err
|
||||||
* @param {*} data data
|
* @param {unknown} data data
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const failed = (err, data) => {
|
const failed = (err, data) => {
|
||||||
|
@ -1696,7 +1709,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @param {Error} err err
|
* @param {Error} err err
|
||||||
* @param {*} data data
|
* @param {unknown} data data
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const response = (err, data) => {
|
const response = (err, data) => {
|
||||||
|
@ -1710,7 +1723,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @param {Error} err err
|
* @param {Error} err err
|
||||||
* @param {*} data data
|
* @param {unknown} data data
|
||||||
* @param {string} msg msg
|
* @param {string} msg msg
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -1720,7 +1733,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (method === AUTH_METHODS['CRAM-MD5']) {
|
if (method === AUTH_METHODS['CRAM-MD5']) {
|
||||||
this.command(encode_cram_md5(msg), response, [235, 503]);
|
this.command(encodeCramMd5(msg), response, [235, 503]);
|
||||||
}
|
}
|
||||||
else if (method === AUTH_METHODS.LOGIN) {
|
else if (method === AUTH_METHODS.LOGIN) {
|
||||||
this.command(Buffer.from(login.password()).toString('base64'), response, [235, 503]);
|
this.command(Buffer.from(login.password()).toString('base64'), response, [235, 503]);
|
||||||
|
@ -1729,11 +1742,11 @@ class SMTPConnection extends EventEmitter {
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @param {Error} err err
|
* @param {Error} err err
|
||||||
* @param {*} data data
|
* @param {unknown} data data
|
||||||
* @param {string} msg msg
|
* @param {string} msg msg
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const attempt_user = (err, data) => {
|
const attemptUser = (err, data) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
failed(err, data);
|
failed(err, data);
|
||||||
}
|
}
|
||||||
|
@ -1748,18 +1761,16 @@ class SMTPConnection extends EventEmitter {
|
||||||
this.command(`AUTH ${AUTH_METHODS['CRAM-MD5']}`, attempt, [334]);
|
this.command(`AUTH ${AUTH_METHODS['CRAM-MD5']}`, attempt, [334]);
|
||||||
break;
|
break;
|
||||||
case AUTH_METHODS.LOGIN:
|
case AUTH_METHODS.LOGIN:
|
||||||
this.command(`AUTH ${AUTH_METHODS.LOGIN}`, attempt_user, [334]);
|
this.command(`AUTH ${AUTH_METHODS.LOGIN}`, attemptUser, [334]);
|
||||||
break;
|
break;
|
||||||
case AUTH_METHODS.PLAIN:
|
case AUTH_METHODS.PLAIN:
|
||||||
this.command(`AUTH ${AUTH_METHODS.PLAIN} ${encode_plain()}`, response, [235, 503]);
|
this.command(`AUTH ${AUTH_METHODS.PLAIN} ${encodePlain()}`, response, [235, 503]);
|
||||||
break;
|
break;
|
||||||
case AUTH_METHODS.XOAUTH2:
|
case AUTH_METHODS.XOAUTH2:
|
||||||
this.command(`AUTH ${AUTH_METHODS.XOAUTH2} ${encode_xoauth2()}`, response, [235, 503]);
|
this.command(`AUTH ${AUTH_METHODS.XOAUTH2} ${encodeXoauth2()}`, response, [235, 503]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
const msg = 'no form of authorization supported';
|
caller(callback, SMTPError.create('no form of authorization supported', SMTPErrorStates.AUTHNOTSUPPORTED, null, data));
|
||||||
const err = SMTPError.create(msg, SMTPErrorStates.AUTHNOTSUPPORTED, null, data);
|
|
||||||
caller(callback, err);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1793,7 +1804,7 @@ class SMTPConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {function(...*): void} [callback] function to call after response
|
* @param {function(...any[]): void} [callback] function to call after response
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
quit(callback) {
|
quit(callback) {
|
||||||
|
@ -1849,6 +1860,23 @@ class SMTPClient {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
* @param {Message} msg the message to send
|
||||||
|
* @returns {Promise<Message>} a promise that resolves to the fully processed message
|
||||||
|
*/
|
||||||
|
sendAsync(msg) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.send(msg, (err, msg) => {
|
||||||
|
if (err != null) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @description Converts a message to the raw object used by the internal stack.
|
* @description Converts a message to the raw object used by the internal stack.
|
||||||
|
@ -1962,8 +1990,8 @@ class SMTPClient {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @param {*} attachment attachment
|
* @param {MessageAttachment | MessageAttachment[]} attachment attachment
|
||||||
* @returns {*} whether the attachment contains inlined html
|
* @returns {boolean} whether the attachment contains inlined html
|
||||||
*/
|
*/
|
||||||
_containsInlinedHtml(attachment) {
|
_containsInlinedHtml(attachment) {
|
||||||
if (Array.isArray(attachment)) {
|
if (Array.isArray(attachment)) {
|
||||||
|
@ -2069,5 +2097,5 @@ class SMTPClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { AUTH_METHODS, BUFFERSIZE, DEFAULT_TIMEOUT, MIME64CHUNK, MIMECHUNK, Message, SMTPClient, SMTPConnection, SMTPError, SMTPErrorStates, SMTPResponseMonitor, SMTPState, addressparser, getRFC2822Date, getRFC2822DateUTC, mimeEncode, mimeWordEncode };
|
export { AUTH_METHODS, BUFFERSIZE, DEFAULT_TIMEOUT, MIME64CHUNK, MIMECHUNK, Message, SMTPClient, SMTPConnection, SMTPError, SMTPErrorStates, SMTPResponseMonitor, SMTPState, addressparser, getRFC2822Date, getRFC2822DateUTC, isRFC2822Date, mimeEncode, mimeWordEncode };
|
||||||
//# sourceMappingURL=email.mjs.map
|
//# sourceMappingURL=email.mjs.map
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue