mirror of https://github.com/eleith/emailjs.git
Compare commits
4 Commits
1e28b13f21
...
1ab1da4cda
Author | SHA1 | Date |
---|---|---|
Zack Schuster | 1ab1da4cda | |
Zack Schuster | f6bd3bb6a0 | |
Zack Schuster | dace0f0a6b | |
Zack Schuster | 17e2b7a7df |
|
@ -7,6 +7,25 @@ export default {
|
||||||
file: 'email.js',
|
file: 'email.js',
|
||||||
format: 'es',
|
format: 'es',
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
|
banner: '/* eslint-disable no-undef */',
|
||||||
|
footer: `
|
||||||
|
/**
|
||||||
|
* @typedef {{ [index: string]: any }} AddressObject
|
||||||
|
* @typedef {{ [index: string]: any }} AddressToken
|
||||||
|
* @typedef {{ [index: string]: any }} ConnectOptions
|
||||||
|
* @typedef {{ [index: string]: any }} MessageAttachment
|
||||||
|
* @typedef {{ [index: string]: any }} MessageHeaders
|
||||||
|
* @typedef {{ [index: string]: any }} MessageStack
|
||||||
|
* @typedef {{ [index: string]: any }} SMTPConnectionOptions
|
||||||
|
* @typedef {Function} SMTPCommandCallback
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @template {Message | MessageHeaders} T
|
||||||
|
* @typedef {<T>(err: Error, msg: T) => void} MessageCallback
|
||||||
|
*/
|
||||||
|
`
|
||||||
|
.trim()
|
||||||
|
.replace(/\t/g, ''),
|
||||||
},
|
},
|
||||||
external: builtinModules,
|
external: builtinModules,
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|
|
@ -94,7 +94,7 @@ export class SMTPClient {
|
||||||
* @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.
|
||||||
* @param {Message} message message to convert
|
* @param {Message} message message to convert
|
||||||
* @param {MessageCallback} callback errback
|
* @param {MessageCallback<Message>} callback errback
|
||||||
* @returns {MessageStack} raw message object
|
* @returns {MessageStack} raw message object
|
||||||
*/
|
*/
|
||||||
public createMessageStack(
|
public createMessageStack(
|
||||||
|
@ -322,7 +322,7 @@ export class SMTPClient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
* @param {Error} err err
|
* @param {Error | null} err err
|
||||||
* @param {MessageStack} stack stack
|
* @param {MessageStack} stack stack
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,8 +9,8 @@ import { SMTPError, SMTPErrorStates } from './error.js';
|
||||||
import { SMTPResponseMonitor } from './response.js';
|
import { SMTPResponseMonitor } from './response.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @readonly
|
* @constant
|
||||||
* @enum
|
* @enum {string}
|
||||||
*/
|
*/
|
||||||
export const AUTH_METHODS = {
|
export const AUTH_METHODS = {
|
||||||
PLAIN: 'PLAIN',
|
PLAIN: 'PLAIN',
|
||||||
|
@ -20,8 +20,8 @@ export const AUTH_METHODS = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @readonly
|
* @constant
|
||||||
* @enum
|
* @enum {number}
|
||||||
*/
|
*/
|
||||||
export const SMTPState = {
|
export const SMTPState = {
|
||||||
NOTCONNECTED: 0,
|
NOTCONNECTED: 0,
|
||||||
|
@ -122,6 +122,8 @@ export class SMTPConnection extends EventEmitter {
|
||||||
* To target a Message Transfer Agent (MTA), omit all options.
|
* To target a Message Transfer Agent (MTA), omit all options.
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
|
*
|
||||||
|
* @param {Partial<SMTPConnectionOptions>} options options
|
||||||
*/
|
*/
|
||||||
constructor({
|
constructor({
|
||||||
timeout,
|
timeout,
|
||||||
|
@ -443,7 +445,7 @@ export class SMTPConnection extends EventEmitter {
|
||||||
* @see https://tools.ietf.org/html/rfc2821#appendix-F.3
|
* @see https://tools.ietf.org/html/rfc2821#appendix-F.3
|
||||||
*
|
*
|
||||||
* @param {SMTPCommandCallback} callback function to call after response
|
* @param {SMTPCommandCallback} 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}
|
||||||
*/
|
*/
|
||||||
public helo(callback: SMTPCommandCallback, domain?: string) {
|
public helo(callback: SMTPCommandCallback, domain?: string) {
|
||||||
|
@ -528,7 +530,7 @@ export class SMTPConnection extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @param {SMTPCommandCallback} callback function to call after response
|
* @param {SMTPCommandCallback} 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}
|
||||||
*/
|
*/
|
||||||
public ehlo(callback: SMTPCommandCallback, domain?: string) {
|
public ehlo(callback: SMTPCommandCallback, domain?: string) {
|
||||||
|
@ -695,7 +697,9 @@ export class SMTPConnection extends EventEmitter {
|
||||||
* @param {SMTPCommandCallback} callback function to call after response
|
* @param {SMTPCommandCallback} 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 {Object} [options] login options
|
||||||
|
* @param {string} [options.method] login method
|
||||||
|
* @param {string} [options.domain] login domain
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
public login(
|
public login(
|
||||||
|
@ -755,7 +759,10 @@ export class SMTPConnection extends EventEmitter {
|
||||||
const preferred = this.authentication;
|
const preferred = this.authentication;
|
||||||
let auth = '';
|
let auth = '';
|
||||||
|
|
||||||
if (typeof this.features?.['auth'] === 'string') {
|
if (
|
||||||
|
this.features != null &&
|
||||||
|
typeof this.features['auth'] === 'string'
|
||||||
|
) {
|
||||||
auth = this.features['auth'];
|
auth = this.features['auth'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ 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}))$/;
|
/^(?:(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}))$/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} [date] a string to check for conformance to the [rfc2822](https://tools.ietf.org/html/rfc2822#section-3.3) standard
|
* @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
|
* @returns {boolean} the result of the conformance check
|
||||||
*/
|
*/
|
||||||
export function isRFC2822Date(date: string) {
|
export function isRFC2822Date(date: string) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @readonly
|
* @constant
|
||||||
* @enum
|
* @enum {number}
|
||||||
*/
|
*/
|
||||||
export const SMTPErrorStates = {
|
export const SMTPErrorStates = {
|
||||||
COULDNOTCONNECT: 1,
|
COULDNOTCONNECT: 1,
|
||||||
|
@ -32,8 +32,8 @@ export class SMTPError extends Error {
|
||||||
*
|
*
|
||||||
* @param {string} message error message
|
* @param {string} message error message
|
||||||
* @param {number} code smtp error state
|
* @param {number} code smtp error state
|
||||||
* @param {Error | null} error previous error
|
* @param {Error | null} [error] previous error
|
||||||
* @param {unknown} smtp arbitrary data
|
* @param {unknown} [smtp] arbitrary data
|
||||||
* @returns {SMTPError} error
|
* @returns {SMTPError} error
|
||||||
*/
|
*/
|
||||||
public static create(
|
public static create(
|
||||||
|
@ -42,7 +42,8 @@ export class SMTPError extends Error {
|
||||||
error?: Error | null,
|
error?: Error | null,
|
||||||
smtp?: unknown
|
smtp?: unknown
|
||||||
) {
|
) {
|
||||||
const msg = error?.message ? `${message} (${error.message})` : message;
|
const { message: errorMsg } = error ?? { message: undefined };
|
||||||
|
const msg = errorMsg ? `${message} (${errorMsg})` : message;
|
||||||
const err = new SMTPError(msg);
|
const err = new SMTPError(msg);
|
||||||
|
|
||||||
err.code = code;
|
err.code = code;
|
||||||
|
|
|
@ -247,17 +247,6 @@ export class Message {
|
||||||
return { isValid: true, validationError: undefined };
|
return { isValid: true, validationError: undefined };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
* @deprecated does not conform to the `errback` style followed by the rest of the library, and will be removed in the next major version. use `checkValidity` instead.
|
|
||||||
* @param {function(isValid: boolean, invalidReason: (string | undefined)): void} callback .
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
public valid(callback: (isValid: boolean, invalidReason?: string) => void) {
|
|
||||||
const { isValid, validationError } = this.checkValidity();
|
|
||||||
callback(isValid, validationError);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
* @returns {MessageStream} a stream of the current message
|
* @returns {MessageStream} a stream of the current message
|
||||||
|
@ -305,9 +294,7 @@ class MessageStream extends Stream {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} [data] the data to output
|
* @param {string} data the data to output
|
||||||
* @param {Function} [callback] the function
|
|
||||||
* @param {any[]} [args] array of arguments to pass to the callback
|
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const output = (data: string) => {
|
const output = (data: string) => {
|
||||||
|
@ -359,7 +346,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 outputAttachmentHeaders = (attachment: MessageAttachment) => {
|
const outputAttachmentHeaders = (attachment: MessageAttachment) => {
|
||||||
|
@ -430,7 +417,7 @@ class MessageStream extends Stream {
|
||||||
: inputEncoding;
|
: inputEncoding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Error} err the error to emit
|
* @param {NodeJS.ErrnoException | null} err the error to emit
|
||||||
* @param {number} fd the file descriptor
|
* @param {number} fd the file descriptor
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
@ -572,7 +559,7 @@ class MessageStream extends Stream {
|
||||||
outputMessage(boundary, this.message.attachments, 0, close);
|
outputMessage(boundary, this.message.attachments, 0, close);
|
||||||
} else {
|
} else {
|
||||||
outputAlternative(
|
outputAlternative(
|
||||||
// typescript bug; should narrow to { alternative: MessageAttachment }
|
// typescript bug; should narrow to Message & { alternative: MessageAttachment }
|
||||||
this.message as Parameters<typeof outputAlternative>[0],
|
this.message as Parameters<typeof outputAlternative>[0],
|
||||||
() => outputMessage(boundary, this.message.attachments, 0, close)
|
() => outputMessage(boundary, this.message.attachments, 0, close)
|
||||||
);
|
);
|
||||||
|
@ -661,10 +648,11 @@ class MessageStream extends Stream {
|
||||||
callback();
|
callback();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (message.alternative.related) {
|
const { alternative } = message;
|
||||||
outputRelated(message.alternative, finish);
|
if (alternative.related) {
|
||||||
|
outputRelated(alternative, finish);
|
||||||
} else {
|
} else {
|
||||||
outputAttachment(message.alternative, finish);
|
outputAttachment(alternative, finish);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ function splitMimeEncodedString(str: string, maxlen = 12) {
|
||||||
*/
|
*/
|
||||||
function checkRanges(nr: number) {
|
function checkRanges(nr: number) {
|
||||||
return RANGES.reduce(
|
return RANGES.reduce(
|
||||||
(val, range) =>
|
(/** @type {boolean} */ val, range) =>
|
||||||
val ||
|
val ||
|
||||||
(range.length === 1 && nr === range[0]) ||
|
(range.length === 1 && nr === range[0]) ||
|
||||||
(range.length === 2 && nr >= range[0] && nr <= range[1]),
|
(range.length === 2 && nr >= range[0] && nr <= range[1]),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
|
|
||||||
import test from 'ava';
|
import test from 'ava';
|
||||||
import { SMTPServer } from 'smtp-server';
|
import { SMTPServer, SMTPServerOptions } from 'smtp-server';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DEFAULT_TIMEOUT,
|
DEFAULT_TIMEOUT,
|
||||||
|
@ -13,22 +13,11 @@ import {
|
||||||
const port = 3333;
|
const port = 3333;
|
||||||
let greylistPort = 4444;
|
let greylistPort = 4444;
|
||||||
|
|
||||||
const client = new SMTPClient({
|
const client = new SMTPClient({ port });
|
||||||
port,
|
|
||||||
user: 'pooh',
|
|
||||||
password: 'honey',
|
|
||||||
ssl: true,
|
|
||||||
});
|
|
||||||
const server = new SMTPServer({
|
const server = new SMTPServer({
|
||||||
secure: true,
|
authOptional: true,
|
||||||
onAuth(auth, _session, callback) {
|
maxAllowedUnauthenticatedCommands: Infinity,
|
||||||
if (auth.username === 'pooh' && auth.password === 'honey') {
|
} as unknown as SMTPServerOptions);
|
||||||
callback(null, { user: 'pooh' });
|
|
||||||
} else {
|
|
||||||
return callback(new Error('invalid user / pass'));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
test.before(async (t) => {
|
test.before(async (t) => {
|
||||||
server.listen(port, t.pass);
|
server.listen(port, t.pass);
|
||||||
|
|
|
@ -10,8 +10,8 @@ let counter = 0;
|
||||||
function testConnection(options: Partial<SMTPConnectionOptions> = {}) {
|
function testConnection(options: Partial<SMTPConnectionOptions> = {}) {
|
||||||
const increment = counter++;
|
const increment = counter++;
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
const { ssl } = options;
|
const server = new SMTPServer({ secure: options.ssl as boolean });
|
||||||
const server = new SMTPServer(ssl ? { secure: true } : undefined);
|
server.on('error', (err) => reject(err));
|
||||||
server.listen(port + increment, () => {
|
server.listen(port + increment, () => {
|
||||||
const connection = new SMTPConnection(options);
|
const connection = new SMTPConnection(options);
|
||||||
connection.connect((err) => {
|
connection.connect((err) => {
|
||||||
|
|
Loading…
Reference in New Issue