mirror of https://github.com/eleith/emailjs.git
Compare commits
4 Commits
d8980abc86
...
615de80130
Author | SHA1 | Date |
---|---|---|
Zack Schuster | 615de80130 | |
Zack Schuster | 5841918d7d | |
Zack Schuster | 8706678fbc | |
Zack Schuster | 8503c7f63a |
|
@ -0,0 +1 @@
|
|||
*.ts text eol=lf
|
|
@ -31,7 +31,7 @@ const OPERATORS = new Map([
|
|||
/**
|
||||
* Tokenizes the original input string
|
||||
*
|
||||
* @param {string | string[] | undefined} address string(s) to tokenize
|
||||
* @param {string | string[]} [address=''] string(s) to tokenize
|
||||
* @return {AddressToken[]} An array of operator & text tokens
|
||||
*/
|
||||
function tokenizeAddress(address: string | string[] = '') {
|
||||
|
@ -208,7 +208,7 @@ function convertAddressTokens(tokens: AddressToken[]) {
|
|||
*
|
||||
* [{name: "Name", address: "address@domain"}]
|
||||
*
|
||||
* @param {string | string[] | undefined} address
|
||||
* @param {string | string[] | undefined} [address]
|
||||
* @return {AddressObject[]}
|
||||
*/
|
||||
export function addressparser(address?: string | string[]) {
|
||||
|
|
|
@ -35,7 +35,7 @@ export class SMTPClient {
|
|||
*
|
||||
* NOTE: `host` is trimmed before being used to establish a connection; however, the original untrimmed value will still be visible in configuration.
|
||||
*
|
||||
* @param {SMTPConnectionOptions} server smtp options
|
||||
* @param {Partial<SMTPConnectionOptions>} server smtp options
|
||||
*/
|
||||
constructor(server: Partial<SMTPConnectionOptions>) {
|
||||
this.smtp = new SMTPConnection(server);
|
||||
|
@ -223,7 +223,7 @@ export class SMTPClient {
|
|||
|
||||
/**
|
||||
* @protected
|
||||
* @param {MessageAttachment | MessageAttachment[]} attachment
|
||||
* @param {MessageAttachment | MessageAttachment[]} [attachment]
|
||||
* @returns {boolean}
|
||||
*/
|
||||
protected _containsInlinedHtml(
|
||||
|
@ -240,7 +240,7 @@ export class SMTPClient {
|
|||
|
||||
/**
|
||||
* @protected
|
||||
* @param {MessageAttachment} attachment
|
||||
* @param {MessageAttachment} [attachment]
|
||||
* @returns {boolean}
|
||||
*/
|
||||
protected _isAttachmentInlinedHtml(attachment?: MessageAttachment) {
|
||||
|
|
|
@ -785,11 +785,15 @@ export class SMTPConnection extends EventEmitter {
|
|||
|
||||
/**
|
||||
* handle bad responses from command differently
|
||||
* @param {Error} err
|
||||
* @param {unknown} data
|
||||
* @param {Error | SMTPError | null} err
|
||||
* @param {(
|
||||
* string |
|
||||
* { code: (string | number), data: string, message: string } |
|
||||
* null
|
||||
* )} [data]
|
||||
* @returns {void}
|
||||
*/
|
||||
const failed = (err: Error, data: unknown) => {
|
||||
const failed: SMTPCommandCallback = (err, data) => {
|
||||
this.loggedin = false;
|
||||
this.close(); // if auth is bad, close the connection, it won't get better by itself
|
||||
callback(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* @param {Date} [date] an optional date to convert to RFC2822 format
|
||||
* @param {boolean} [useUtc] whether to parse the date as UTC (default: false)
|
||||
* @param {Date} [date=new Date()] an optional date to convert to RFC2822 format
|
||||
* @param {boolean} [useUtc=false] whether to parse the date as UTC (default: false)
|
||||
* @returns {string} the converted date
|
||||
*/
|
||||
export function getRFC2822Date(date = new Date(), useUtc = false) {
|
||||
|
@ -24,7 +24,7 @@ export function getRFC2822Date(date = new Date(), useUtc = false) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {Date} [date] an optional date to convert to RFC2822 format (UTC)
|
||||
* @param {Date} [date=new Date()] an optional date to convert to RFC2822 format (UTC)
|
||||
* @returns {string} the converted date
|
||||
*/
|
||||
export function getRFC2822DateUTC(date = new Date()) {
|
||||
|
|
|
@ -163,7 +163,7 @@ export class Message {
|
|||
this.header.subject = mimeWordEncode(headers.subject as string);
|
||||
} else if (/^(cc|bcc|to|from)/i.test(header)) {
|
||||
this.header[header.toLowerCase()] = convertPersonToAddress(
|
||||
headers[header] as string | string[]
|
||||
headers[header as 'cc' | 'bcc' | 'to' | 'from'] ?? ''
|
||||
);
|
||||
} else {
|
||||
// allow any headers the user wants to set??
|
||||
|
|
20
smtp/mime.ts
20
smtp/mime.ts
|
@ -71,7 +71,7 @@ function encodeBase64(data: Uint8Array) {
|
|||
* Splits a mime encoded string. Needed for dividing mime words into smaller chunks
|
||||
*
|
||||
* @param {string} str Mime encoded string to be split up
|
||||
* @param {number} maxlen Maximum length of characters for one part (minimum 12)
|
||||
* @param {number} [maxlen=12] Maximum length of characters for one part (minimum 12)
|
||||
* @return {string[]} lines
|
||||
*/
|
||||
function splitMimeEncodedString(str: string, maxlen = 12) {
|
||||
|
@ -127,17 +127,17 @@ function checkRanges(nr: number) {
|
|||
|
||||
/**
|
||||
* Encodes all non printable and non ascii bytes to =XX form, where XX is the
|
||||
* byte value in hex. This function does not convert linebreaks etc. it
|
||||
* only escapes character sequences
|
||||
* byte value in hex. This function only escapes character sequences; it does not
|
||||
* convert linebreaks etc.
|
||||
*
|
||||
* NOTE: Encoding support depends on util.TextDecoder, which is severely limited
|
||||
* NOTE: Encoding support depends on `util.TextDecoder`, which lacks full ICU support
|
||||
* prior to Node.js 13.
|
||||
*
|
||||
* @see https://nodejs.org/api/util.html#util_whatwg_supported_encodings
|
||||
* @see https://github.com/nodejs/node/issues/19214
|
||||
*
|
||||
* @param {string|Uint8Array} data Either a string or an Uint8Array
|
||||
* @param {string} encoding WHATWG supported encoding
|
||||
* @param {string | Uint8Array} [data='']
|
||||
* @param {string} [encoding='utf-8'] WHATWG supported encoding
|
||||
* @return {string} Mime encoded string
|
||||
*/
|
||||
export function mimeEncode(data: string | Uint8Array = '', encoding = 'utf-8') {
|
||||
|
@ -168,16 +168,16 @@ export function mimeEncode(data: string | Uint8Array = '', encoding = 'utf-8') {
|
|||
/**
|
||||
* Encodes a string or an Uint8Array to an UTF-8 MIME Word
|
||||
*
|
||||
* NOTE: Encoding support depends on util.TextDecoder, which is severely limited
|
||||
* NOTE: Encoding support depends on `util.TextDecoder`, which lacks full ICU support
|
||||
* prior to Node.js 13.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc2047
|
||||
* @see https://nodejs.org/api/util.html#util_whatwg_supported_encodings
|
||||
* @see https://github.com/nodejs/node/issues/19214
|
||||
*
|
||||
* @param {string|Uint8Array} data String to be encoded
|
||||
* @param {'Q' | 'B'} mimeWordEncoding='Q' Encoding for the mime word, either Q or B
|
||||
* @param {string} encoding WHATWG supported encoding
|
||||
* @param {string | Uint8Array} data
|
||||
* @param {'Q' | 'B'} [mimeWordEncoding='Q']
|
||||
* @param {string} [encoding='utf-8'] WHATWG supported encoding
|
||||
* @return {string} Single or several mime words joined together
|
||||
*/
|
||||
export function mimeWordEncode(
|
||||
|
|
|
@ -5,6 +5,11 @@ import type { TLSSocket } from 'tls';
|
|||
export class SMTPResponseMonitor {
|
||||
public readonly stop: (err?: Error) => void;
|
||||
|
||||
/**
|
||||
* @param {Socket | TLSSocket} stream
|
||||
* @param {number} timeout
|
||||
* @param {function(Error): void} onerror
|
||||
*/
|
||||
constructor(
|
||||
stream: Socket | TLSSocket,
|
||||
timeout: number,
|
||||
|
|
|
@ -17,7 +17,7 @@ function connect({
|
|||
return new Promise<void>((resolve, reject) => {
|
||||
const server = new SMTPServer({
|
||||
authMethods,
|
||||
secure: secure,
|
||||
secure,
|
||||
onAuth(auth, _session, callback) {
|
||||
const { accessToken, method, username, password } = auth;
|
||||
if (
|
||||
|
|
|
@ -122,8 +122,12 @@ test('client accepts array sender', async (t) => {
|
|||
});
|
||||
msg.header.from = [msg.header.from as string];
|
||||
|
||||
const { isValid } = msg.checkValidity();
|
||||
t.true(isValid);
|
||||
const message = await client.sendAsync(msg);
|
||||
t.is(message.text, msg.text);
|
||||
t.deepEqual(message.header.from, ['zelda@gmail.com']);
|
||||
t.is(message.header.to, 'gannon1@gmail.com');
|
||||
t.is(message.header.cc, undefined);
|
||||
t.is(message.header.bcc, undefined);
|
||||
});
|
||||
|
||||
test('client rejects message without `from` header', async (t) => {
|
||||
|
|
|
@ -380,6 +380,21 @@ test('text + two attachments message (streams)', async (t) => {
|
|||
t.is(mail.to?.text, msg.to);
|
||||
});
|
||||
|
||||
test('message validation succeeds when `from` header is an array', async (t) => {
|
||||
const msg = new Message({
|
||||
from: ['zelda@gmail.com'],
|
||||
to: 'gannon1@gmail.com',
|
||||
});
|
||||
|
||||
t.false(Array.isArray(msg.header.from));
|
||||
|
||||
msg.header.from = [msg.header.from as string];
|
||||
const { isValid } = msg.checkValidity();
|
||||
|
||||
t.true(Array.isArray(msg.header.from));
|
||||
t.true(isValid);
|
||||
});
|
||||
|
||||
test('message validation fails without `from` header', async (t) => {
|
||||
const msg = new Message({});
|
||||
const { isValid, validationError } = msg.checkValidity();
|
||||
|
|
|
@ -84,23 +84,18 @@ test('synchronous queue failures are handled gracefully by client', async (t) =>
|
|||
})
|
||||
);
|
||||
|
||||
// @ts-expect-error need to check protected prop
|
||||
const { ready, sending, smtp } = tlsClient;
|
||||
const state = smtp.state();
|
||||
|
||||
t.log(
|
||||
`SMTPClient ${JSON.stringify(
|
||||
{
|
||||
// @ts-expect-error need to check protected prop
|
||||
ready: tlsClient.ready,
|
||||
// @ts-expect-error need to check protected prop
|
||||
sending: tlsClient.sending,
|
||||
state: tlsClient.smtp.state(),
|
||||
},
|
||||
null,
|
||||
'\t'
|
||||
).replace(/"/g, '')}`
|
||||
`SMTPClient ${JSON.stringify({ ready, sending, state }, null, '\t').replace(
|
||||
/"/g,
|
||||
''
|
||||
)}`
|
||||
);
|
||||
|
||||
// @ts-expect-error need to check protected prop
|
||||
t.false(tlsClient.ready);
|
||||
// @ts-expect-error need to check protected prop
|
||||
t.false(tlsClient.sending);
|
||||
t.is(tlsClient.smtp.state(), 0);
|
||||
t.false(ready);
|
||||
t.false(sending);
|
||||
t.is(state, 0);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue