@nocobase/plugin-workflow-mailer 2.3.0-beta.13 → 2.3.0-beta.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/externalVersion.js +6 -6
- package/dist/node_modules/joi/package.json +1 -1
- package/dist/node_modules/nodemailer/dist/cjs/addressparser/index.d.ts +59 -0
- package/dist/node_modules/nodemailer/dist/cjs/addressparser/index.js +790 -0
- package/dist/node_modules/nodemailer/dist/cjs/base64/index.d.ts +36 -0
- package/dist/node_modules/nodemailer/dist/cjs/base64/index.js +119 -0
- package/dist/node_modules/nodemailer/dist/cjs/dkim/index.d.ts +52 -0
- package/dist/node_modules/nodemailer/dist/cjs/dkim/index.js +228 -0
- package/dist/node_modules/nodemailer/dist/cjs/dkim/message-parser.d.ts +48 -0
- package/dist/node_modules/nodemailer/dist/cjs/dkim/message-parser.js +180 -0
- package/dist/node_modules/nodemailer/dist/cjs/dkim/relaxed-body.d.ts +36 -0
- package/dist/node_modules/nodemailer/dist/cjs/dkim/relaxed-body.js +148 -0
- package/dist/node_modules/nodemailer/dist/cjs/dkim/sign.d.ts +52 -0
- package/dist/node_modules/nodemailer/dist/cjs/dkim/sign.js +165 -0
- package/dist/node_modules/nodemailer/dist/cjs/errors.d.ts +96 -0
- package/dist/node_modules/nodemailer/dist/cjs/errors.js +70 -0
- package/dist/node_modules/nodemailer/dist/cjs/fetch/cookies.d.ts +107 -0
- package/dist/node_modules/nodemailer/dist/cjs/fetch/cookies.js +282 -0
- package/dist/node_modules/nodemailer/dist/cjs/fetch/index.d.ts +65 -0
- package/dist/node_modules/nodemailer/dist/cjs/fetch/index.js +384 -0
- package/dist/node_modules/nodemailer/dist/cjs/json-transport/index.d.ts +64 -0
- package/dist/node_modules/nodemailer/dist/cjs/json-transport/index.js +99 -0
- package/dist/node_modules/nodemailer/dist/cjs/mail-composer/index.d.ts +174 -0
- package/dist/node_modules/nodemailer/dist/cjs/mail-composer/index.js +613 -0
- package/dist/node_modules/nodemailer/dist/cjs/mailer/index.d.ts +237 -0
- package/dist/node_modules/nodemailer/dist/cjs/mailer/index.js +415 -0
- package/dist/node_modules/nodemailer/dist/cjs/mailer/mail-message.d.ts +97 -0
- package/dist/node_modules/nodemailer/dist/cjs/mailer/mail-message.js +342 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-funcs/index.d.ts +161 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-funcs/index.js +787 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-funcs/mime-types.d.ts +2 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-funcs/mime-types.js +2103 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-node/index.d.ts +333 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-node/index.js +1493 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-node/last-newline.d.ts +5 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-node/last-newline.js +32 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-node/le-unix.d.ts +9 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-node/le-unix.js +40 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-node/le-windows.d.ts +10 -0
- package/dist/node_modules/nodemailer/dist/cjs/mime-node/le-windows.js +47 -0
- package/dist/node_modules/nodemailer/dist/cjs/nodemailer.d.ts +124 -0
- package/dist/node_modules/nodemailer/dist/cjs/nodemailer.js +1 -0
- package/dist/node_modules/nodemailer/dist/cjs/package-info.d.ts +3 -0
- package/dist/node_modules/nodemailer/dist/cjs/package-info.js +7 -0
- package/dist/node_modules/nodemailer/dist/cjs/package.json +3 -0
- package/dist/node_modules/nodemailer/dist/cjs/punycode/index.d.ts +73 -0
- package/dist/node_modules/nodemailer/{lib → dist/cjs}/punycode/index.js +62 -111
- package/dist/node_modules/nodemailer/dist/cjs/qp/index.d.ts +32 -0
- package/dist/node_modules/nodemailer/dist/cjs/qp/index.js +207 -0
- package/dist/node_modules/nodemailer/dist/cjs/sendmail-transport/index.d.ts +69 -0
- package/dist/node_modules/nodemailer/dist/cjs/sendmail-transport/index.js +210 -0
- package/dist/node_modules/nodemailer/dist/cjs/ses-transport/index.d.ts +112 -0
- package/dist/node_modules/nodemailer/dist/cjs/ses-transport/index.js +252 -0
- package/dist/node_modules/nodemailer/dist/cjs/shared/index.d.ts +260 -0
- package/dist/node_modules/nodemailer/dist/cjs/shared/index.js +680 -0
- package/dist/node_modules/nodemailer/dist/cjs/shared/objects.d.ts +23 -0
- package/dist/node_modules/nodemailer/dist/cjs/shared/objects.js +43 -0
- package/dist/node_modules/nodemailer/dist/cjs/shared/url.d.ts +21 -0
- package/dist/node_modules/nodemailer/dist/cjs/shared/url.js +255 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/data-stream.d.ts +15 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/data-stream.js +108 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.d.ts +47 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.js +189 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/index.d.ts +416 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/index.js +1837 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-pool/index.d.ts +133 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-pool/index.js +569 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-pool/pool-resource.d.ts +62 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-pool/pool-resource.js +257 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-transport/index.d.ts +156 -0
- package/dist/node_modules/nodemailer/dist/cjs/smtp-transport/index.js +371 -0
- package/dist/node_modules/nodemailer/dist/cjs/stream-transport/index.d.ts +65 -0
- package/dist/node_modules/nodemailer/dist/cjs/stream-transport/index.js +146 -0
- package/dist/node_modules/nodemailer/dist/cjs/well-known/index.d.ts +35 -0
- package/dist/node_modules/nodemailer/dist/cjs/well-known/index.js +41 -0
- package/dist/node_modules/nodemailer/dist/cjs/well-known/services.d.ts +2 -0
- package/dist/node_modules/nodemailer/dist/cjs/well-known/services.js +674 -0
- package/dist/node_modules/nodemailer/dist/cjs/xoauth2/index.d.ts +201 -0
- package/dist/node_modules/nodemailer/dist/cjs/xoauth2/index.js +426 -0
- package/dist/node_modules/nodemailer/dist/esm/addressparser/index.d.ts +59 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/addressparser/index.js +361 -131
- package/dist/node_modules/nodemailer/dist/esm/base64/index.d.ts +36 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/base64/index.js +31 -56
- package/dist/node_modules/nodemailer/dist/esm/dkim/index.d.ts +52 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/dkim/index.js +49 -78
- package/dist/node_modules/nodemailer/dist/esm/dkim/message-parser.d.ts +48 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/dkim/message-parser.js +64 -42
- package/dist/node_modules/nodemailer/dist/esm/dkim/relaxed-body.d.ts +36 -0
- package/dist/node_modules/nodemailer/dist/esm/dkim/relaxed-body.js +141 -0
- package/dist/node_modules/nodemailer/dist/esm/dkim/sign.d.ts +52 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/dkim/sign.js +50 -46
- package/dist/node_modules/nodemailer/dist/esm/errors.d.ts +96 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/errors.js +26 -18
- package/dist/node_modules/nodemailer/dist/esm/fetch/cookies.d.ts +107 -0
- package/dist/node_modules/nodemailer/dist/esm/fetch/cookies.js +242 -0
- package/dist/node_modules/nodemailer/dist/esm/fetch/index.d.ts +65 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/fetch/index.js +80 -147
- package/dist/node_modules/nodemailer/dist/esm/json-transport/index.d.ts +64 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/json-transport/index.js +19 -39
- package/dist/node_modules/nodemailer/dist/esm/mail-composer/index.d.ts +174 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/mail-composer/index.js +199 -265
- package/dist/node_modules/nodemailer/dist/esm/mailer/index.d.ts +237 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/mailer/index.js +128 -234
- package/dist/node_modules/nodemailer/dist/esm/mailer/mail-message.d.ts +97 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/mailer/mail-message.js +62 -114
- package/dist/node_modules/nodemailer/dist/esm/mime-funcs/index.d.ts +161 -0
- package/dist/node_modules/nodemailer/dist/esm/mime-funcs/index.js +738 -0
- package/dist/node_modules/nodemailer/dist/esm/mime-funcs/mime-types.d.ts +2 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/mime-funcs/mime-types.js +29 -42
- package/dist/node_modules/nodemailer/dist/esm/mime-node/index.d.ts +333 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/mime-node/index.js +259 -372
- package/dist/node_modules/nodemailer/dist/esm/mime-node/last-newline.d.ts +5 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/mime-node/last-newline.js +4 -10
- package/dist/node_modules/nodemailer/dist/esm/mime-node/le-unix.d.ts +9 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/mime-node/le-unix.js +6 -11
- package/dist/node_modules/nodemailer/dist/esm/mime-node/le-windows.d.ts +10 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/mime-node/le-windows.js +6 -13
- package/dist/node_modules/nodemailer/dist/esm/nodemailer.d.ts +124 -0
- package/dist/node_modules/nodemailer/dist/esm/nodemailer.js +166 -0
- package/dist/node_modules/nodemailer/dist/esm/package-info.d.ts +3 -0
- package/dist/node_modules/nodemailer/dist/esm/package-info.js +4 -0
- package/dist/node_modules/nodemailer/dist/esm/package.json +3 -0
- package/dist/node_modules/nodemailer/dist/esm/punycode/index.d.ts +73 -0
- package/dist/node_modules/nodemailer/dist/esm/punycode/index.js +405 -0
- package/dist/node_modules/nodemailer/dist/esm/qp/index.d.ts +32 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/qp/index.js +38 -67
- package/dist/node_modules/nodemailer/dist/esm/sendmail-transport/index.d.ts +69 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/sendmail-transport/index.js +51 -101
- package/dist/node_modules/nodemailer/dist/esm/ses-transport/index.d.ts +112 -0
- package/dist/node_modules/nodemailer/dist/esm/ses-transport/index.js +212 -0
- package/dist/node_modules/nodemailer/dist/esm/shared/index.d.ts +260 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/shared/index.js +156 -272
- package/dist/node_modules/nodemailer/dist/esm/shared/objects.d.ts +23 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/shared/objects.js +13 -17
- package/dist/node_modules/nodemailer/dist/esm/shared/url.d.ts +21 -0
- package/dist/node_modules/nodemailer/dist/esm/shared/url.js +214 -0
- package/dist/node_modules/nodemailer/dist/esm/smtp-connection/data-stream.d.ts +15 -0
- package/dist/node_modules/nodemailer/dist/esm/smtp-connection/data-stream.js +103 -0
- package/dist/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.d.ts +47 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/smtp-connection/http-proxy-client.js +49 -74
- package/dist/node_modules/nodemailer/dist/esm/smtp-connection/index.d.ts +416 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/smtp-connection/index.js +574 -794
- package/dist/node_modules/nodemailer/dist/esm/smtp-pool/index.d.ts +133 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/smtp-pool/index.js +172 -284
- package/dist/node_modules/nodemailer/dist/esm/smtp-pool/pool-resource.d.ts +62 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/smtp-pool/pool-resource.js +57 -97
- package/dist/node_modules/nodemailer/dist/esm/smtp-transport/index.d.ts +156 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/smtp-transport/index.js +81 -179
- package/dist/node_modules/nodemailer/dist/esm/stream-transport/index.d.ts +65 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/stream-transport/index.js +36 -74
- package/dist/node_modules/nodemailer/dist/esm/well-known/index.d.ts +35 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/well-known/index.js +5 -16
- package/dist/node_modules/nodemailer/dist/esm/well-known/services.d.ts +2 -0
- package/dist/node_modules/nodemailer/dist/esm/well-known/services.js +671 -0
- package/dist/node_modules/nodemailer/dist/esm/xoauth2/index.d.ts +201 -0
- package/dist/node_modules/nodemailer/{lib → dist/esm}/xoauth2/index.js +125 -187
- package/dist/node_modules/nodemailer/{lib → dist}/well-known/services.json +9 -2
- package/dist/node_modules/nodemailer/package.json +1 -1
- package/package.json +3 -3
- package/dist/node_modules/nodemailer/.gitattributes +0 -6
- package/dist/node_modules/nodemailer/.ncurc.js +0 -9
- package/dist/node_modules/nodemailer/.prettierignore +0 -8
- package/dist/node_modules/nodemailer/.prettierrc +0 -12
- package/dist/node_modules/nodemailer/.prettierrc.js +0 -10
- package/dist/node_modules/nodemailer/.release-please-config.json +0 -9
- package/dist/node_modules/nodemailer/eslint.config.js +0 -88
- package/dist/node_modules/nodemailer/lib/dkim/relaxed-body.js +0 -154
- package/dist/node_modules/nodemailer/lib/fetch/cookies.js +0 -276
- package/dist/node_modules/nodemailer/lib/mime-funcs/index.js +0 -671
- package/dist/node_modules/nodemailer/lib/nodemailer.js +0 -1
- package/dist/node_modules/nodemailer/lib/ses-transport/index.js +0 -266
- package/dist/node_modules/nodemailer/lib/shared/url.js +0 -151
- package/dist/node_modules/nodemailer/lib/smtp-connection/data-stream.js +0 -105
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Transform } from 'node:stream';
|
|
2
|
+
/**
|
|
3
|
+
* Encodes a Buffer into a base64 encoded string
|
|
4
|
+
*
|
|
5
|
+
* @param buffer Buffer to convert
|
|
6
|
+
* @returns base64 encoded string
|
|
7
|
+
*/
|
|
8
|
+
export declare function encode(buffer: Buffer | string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Adds soft line breaks to a base64 string
|
|
11
|
+
*
|
|
12
|
+
* @param str base64 encoded string that might need line wrapping
|
|
13
|
+
* @param [lineLength=76] Maximum allowed length for a line
|
|
14
|
+
* @returns Soft-wrapped base64 encoded string
|
|
15
|
+
*/
|
|
16
|
+
export declare function wrap(str: string, lineLength?: number | false): string;
|
|
17
|
+
/**
|
|
18
|
+
* Options for the base64 encoder stream
|
|
19
|
+
*/
|
|
20
|
+
export interface EncoderOptions {
|
|
21
|
+
/** Maximum length for lines, set to false to disable wrapping */
|
|
22
|
+
lineLength?: number | false | undefined;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Creates a transform stream for encoding data to base64 encoding
|
|
26
|
+
*
|
|
27
|
+
* @constructor
|
|
28
|
+
* @param options Stream options
|
|
29
|
+
* @param [options.lineLength=76] Maximum length for lines, set to false to disable wrapping
|
|
30
|
+
*/
|
|
31
|
+
export declare class Encoder extends Transform {
|
|
32
|
+
options: EncoderOptions;
|
|
33
|
+
inputBytes: number;
|
|
34
|
+
outputBytes: number;
|
|
35
|
+
constructor(options?: EncoderOptions);
|
|
36
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Encoder = void 0;
|
|
4
|
+
exports.encode = encode;
|
|
5
|
+
exports.wrap = wrap;
|
|
6
|
+
const node_stream_1 = require("node:stream");
|
|
7
|
+
/**
|
|
8
|
+
* Encodes a Buffer into a base64 encoded string
|
|
9
|
+
*
|
|
10
|
+
* @param buffer Buffer to convert
|
|
11
|
+
* @returns base64 encoded string
|
|
12
|
+
*/
|
|
13
|
+
function encode(buffer) {
|
|
14
|
+
if (typeof buffer === 'string') {
|
|
15
|
+
buffer = Buffer.from(buffer, 'utf-8');
|
|
16
|
+
}
|
|
17
|
+
return buffer.toString('base64');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Adds soft line breaks to a base64 string
|
|
21
|
+
*
|
|
22
|
+
* @param str base64 encoded string that might need line wrapping
|
|
23
|
+
* @param [lineLength=76] Maximum allowed length for a line
|
|
24
|
+
* @returns Soft-wrapped base64 encoded string
|
|
25
|
+
*/
|
|
26
|
+
function wrap(str, lineLength) {
|
|
27
|
+
str = (str || '').toString();
|
|
28
|
+
// a negative length would step backwards through the input and never finish
|
|
29
|
+
lineLength = Math.max(Number(lineLength) || 76, 1);
|
|
30
|
+
if (str.length <= lineLength) {
|
|
31
|
+
return str;
|
|
32
|
+
}
|
|
33
|
+
const result = [];
|
|
34
|
+
let pos = 0;
|
|
35
|
+
const chunkLength = lineLength * 1024;
|
|
36
|
+
const wrapRegex = new RegExp('.{' + lineLength + '}', 'g');
|
|
37
|
+
while (pos < str.length) {
|
|
38
|
+
const wrappedLines = str.substr(pos, chunkLength).replace(wrapRegex, '$&\r\n').trim();
|
|
39
|
+
result.push(wrappedLines);
|
|
40
|
+
pos += chunkLength;
|
|
41
|
+
}
|
|
42
|
+
return result.join('\r\n').trim();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Creates a transform stream for encoding data to base64 encoding
|
|
46
|
+
*
|
|
47
|
+
* @constructor
|
|
48
|
+
* @param options Stream options
|
|
49
|
+
* @param [options.lineLength=76] Maximum length for lines, set to false to disable wrapping
|
|
50
|
+
*/
|
|
51
|
+
class Encoder extends node_stream_1.Transform {
|
|
52
|
+
constructor(options) {
|
|
53
|
+
super();
|
|
54
|
+
this.options = options || {};
|
|
55
|
+
if (this.options.lineLength !== false) {
|
|
56
|
+
this.options.lineLength = this.options.lineLength || 76;
|
|
57
|
+
}
|
|
58
|
+
this._curLine = '';
|
|
59
|
+
this._remainingBytes = false;
|
|
60
|
+
this.inputBytes = 0;
|
|
61
|
+
this.outputBytes = 0;
|
|
62
|
+
}
|
|
63
|
+
/** @internal */
|
|
64
|
+
_transform(chunk, encoding, done) {
|
|
65
|
+
let buf = encoding !== 'buffer' ? Buffer.from(chunk, encoding) : chunk;
|
|
66
|
+
if (!buf || !buf.length) {
|
|
67
|
+
setImmediate(done);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
this.inputBytes += buf.length;
|
|
71
|
+
if (this._remainingBytes && this._remainingBytes.length) {
|
|
72
|
+
buf = Buffer.concat([this._remainingBytes, buf], this._remainingBytes.length + buf.length);
|
|
73
|
+
this._remainingBytes = false;
|
|
74
|
+
}
|
|
75
|
+
if (buf.length % 3) {
|
|
76
|
+
this._remainingBytes = buf.slice(buf.length - (buf.length % 3));
|
|
77
|
+
buf = buf.slice(0, buf.length - (buf.length % 3));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this._remainingBytes = false;
|
|
81
|
+
}
|
|
82
|
+
let b64 = this._curLine + encode(buf);
|
|
83
|
+
if (this.options.lineLength) {
|
|
84
|
+
b64 = wrap(b64, this.options.lineLength);
|
|
85
|
+
// remove last line as it is still most probably incomplete
|
|
86
|
+
const lastLF = b64.lastIndexOf('\n');
|
|
87
|
+
if (lastLF < 0) {
|
|
88
|
+
this._curLine = b64;
|
|
89
|
+
b64 = '';
|
|
90
|
+
}
|
|
91
|
+
else if (lastLF === b64.length - 1) {
|
|
92
|
+
this._curLine = '';
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
this._curLine = b64.substring(lastLF + 1);
|
|
96
|
+
b64 = b64.substring(0, lastLF + 1);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (b64) {
|
|
100
|
+
this.outputBytes += b64.length;
|
|
101
|
+
this.push(Buffer.from(b64, 'ascii'));
|
|
102
|
+
}
|
|
103
|
+
setImmediate(done);
|
|
104
|
+
}
|
|
105
|
+
/** @internal */
|
|
106
|
+
_flush(done) {
|
|
107
|
+
if (this._remainingBytes && this._remainingBytes.length) {
|
|
108
|
+
this._curLine += encode(this._remainingBytes);
|
|
109
|
+
}
|
|
110
|
+
if (this._curLine) {
|
|
111
|
+
this._curLine = wrap(this._curLine, this.options.lineLength);
|
|
112
|
+
this.outputBytes += this._curLine.length;
|
|
113
|
+
this.push(Buffer.from(this._curLine, 'ascii'));
|
|
114
|
+
this._curLine = '';
|
|
115
|
+
}
|
|
116
|
+
done();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
exports.Encoder = Encoder;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type DKIMKey, type DKIMPrivateKey, type DKIMSignOptions } from './sign.js';
|
|
2
|
+
import { PassThrough, type Readable } from 'node:stream';
|
|
3
|
+
/**
|
|
4
|
+
* A single DKIM signing key
|
|
5
|
+
*/
|
|
6
|
+
export type { DKIMKey, DKIMPrivateKey, DKIMSignOptions };
|
|
7
|
+
/**
|
|
8
|
+
* Options for the DKIM signer
|
|
9
|
+
*/
|
|
10
|
+
export interface DKIMOptions extends DKIMSignOptions {
|
|
11
|
+
/** One or more signing keys, used instead of the domainName, keySelector and privateKey options */
|
|
12
|
+
keys?: DKIMKey | DKIMKey[] | undefined;
|
|
13
|
+
/** Directory for buffering large message bodies to disk, no buffering when not set */
|
|
14
|
+
cacheDir?: string | false | undefined;
|
|
15
|
+
/** Body size in bytes from which the body is buffered to cacheDir, defaults to 10 MB */
|
|
16
|
+
cacheTreshold?: number | undefined;
|
|
17
|
+
/** Hash algorithm for the body hash and the signature, defaults to sha256 */
|
|
18
|
+
hashAlgo?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The signed message as returned by DKIM#sign
|
|
22
|
+
*/
|
|
23
|
+
export interface DKIMSignedStream extends PassThrough {
|
|
24
|
+
/** true if the message body was buffered to cacheDir while signing */
|
|
25
|
+
usingCache: boolean;
|
|
26
|
+
}
|
|
27
|
+
declare class DKIM {
|
|
28
|
+
options: DKIMOptions;
|
|
29
|
+
keys: DKIMKey[];
|
|
30
|
+
constructor(options: DKIMOptions);
|
|
31
|
+
sign(input: Readable | Buffer | string, extraOptions?: DKIMOptions): DKIMSignedStream;
|
|
32
|
+
}
|
|
33
|
+
/** The signer options without any key material */
|
|
34
|
+
export type DKIMOptionalOptions = Omit<DKIMOptions, 'keys' | 'domainName' | 'keySelector' | 'privateKey'>;
|
|
35
|
+
/** The signer options for a single key given as domainName, keySelector and privateKey */
|
|
36
|
+
export type DKIMSingleKeyOptions = Omit<DKIMOptions, 'keys'>;
|
|
37
|
+
/** The signer options for one or more keys given through `keys` */
|
|
38
|
+
export type DKIMMultipleKeysOptions = DKIMOptionalOptions & {
|
|
39
|
+
keys: DKIMKey | DKIMKey[];
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Type aliases in the layout of @types/nodemailer, so `DKIM.Options` style references keep working
|
|
43
|
+
*/
|
|
44
|
+
declare namespace DKIM {
|
|
45
|
+
type Options = DKIMOptions;
|
|
46
|
+
type OptionalOptions = DKIMOptionalOptions;
|
|
47
|
+
type SingleKeyOptions = DKIMSingleKeyOptions;
|
|
48
|
+
type MultipleKeysOptions = DKIMMultipleKeysOptions;
|
|
49
|
+
}
|
|
50
|
+
/** The same aliases as module level exports, for `import * as DKIM` and `import DKIM = require()` */
|
|
51
|
+
export type { DKIMOptions as Options, DKIMOptionalOptions as OptionalOptions, DKIMSingleKeyOptions as SingleKeyOptions, DKIMMultipleKeysOptions as MultipleKeysOptions };
|
|
52
|
+
export default DKIM;
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// FIXME:
|
|
3
|
+
// replace this Transform mess with a method that pipes input argument to output argument
|
|
4
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const message_parser_js_1 = __importDefault(require("./message-parser.js"));
|
|
9
|
+
const relaxed_body_js_1 = __importDefault(require("./relaxed-body.js"));
|
|
10
|
+
const sign_js_1 = __importDefault(require("./sign.js"));
|
|
11
|
+
const node_stream_1 = require("node:stream");
|
|
12
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
15
|
+
const objects_js_1 = require("../shared/objects.js");
|
|
16
|
+
const DKIM_ALGO = 'sha256';
|
|
17
|
+
const MAX_MESSAGE_SIZE = 10 * 1024 * 1024; // buffer messages larger than this to disk
|
|
18
|
+
class DKIMSigner {
|
|
19
|
+
constructor(options, keys, input, output) {
|
|
20
|
+
this.options = options || {};
|
|
21
|
+
this.keys = keys;
|
|
22
|
+
this.cacheTreshold = Number(this.options.cacheTreshold) || MAX_MESSAGE_SIZE;
|
|
23
|
+
this.hashAlgo = this.options.hashAlgo || DKIM_ALGO;
|
|
24
|
+
this.cacheDir = this.options.cacheDir || false;
|
|
25
|
+
this.chunks = [];
|
|
26
|
+
this.chunklen = 0;
|
|
27
|
+
this.readPos = 0;
|
|
28
|
+
this.cachePath = this.cacheDir
|
|
29
|
+
? node_path_1.default.join(this.cacheDir, 'message.' + Date.now() + '-' + node_crypto_1.default.randomBytes(14).toString('hex'))
|
|
30
|
+
: false;
|
|
31
|
+
this.cache = false;
|
|
32
|
+
this.headers = false;
|
|
33
|
+
this.bodyHash = false;
|
|
34
|
+
this.parser = false;
|
|
35
|
+
this.relaxedBody = false;
|
|
36
|
+
this.input = input;
|
|
37
|
+
this.output = output;
|
|
38
|
+
this.output.usingCache = false;
|
|
39
|
+
this.hasErrored = false;
|
|
40
|
+
this.input.on('error', err => {
|
|
41
|
+
this.hasErrored = true;
|
|
42
|
+
this.cleanup();
|
|
43
|
+
output.emit('error', err);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
cleanup() {
|
|
47
|
+
if (!this.cache || !this.cachePath) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
node_fs_1.default.unlink(this.cachePath, () => false);
|
|
51
|
+
}
|
|
52
|
+
createReadCache() {
|
|
53
|
+
// pipe remainings to cache file
|
|
54
|
+
this.cache = node_fs_1.default.createReadStream(this.cachePath);
|
|
55
|
+
this.cache.once('error', err => {
|
|
56
|
+
this.cleanup();
|
|
57
|
+
this.output.emit('error', err);
|
|
58
|
+
});
|
|
59
|
+
this.cache.once('close', () => {
|
|
60
|
+
this.cleanup();
|
|
61
|
+
});
|
|
62
|
+
this.cache.pipe(this.output);
|
|
63
|
+
}
|
|
64
|
+
sendNextChunk() {
|
|
65
|
+
if (this.hasErrored) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (this.readPos >= this.chunks.length) {
|
|
69
|
+
if (!this.cache) {
|
|
70
|
+
this.output.end();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
return this.createReadCache();
|
|
74
|
+
}
|
|
75
|
+
const chunk = this.chunks[this.readPos++];
|
|
76
|
+
if (this.output.write(chunk) === false) {
|
|
77
|
+
this.output.once('drain', () => {
|
|
78
|
+
this.sendNextChunk();
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
setImmediate(() => this.sendNextChunk());
|
|
83
|
+
}
|
|
84
|
+
sendSignedOutput() {
|
|
85
|
+
let keyPos = 0;
|
|
86
|
+
const signNextKey = () => {
|
|
87
|
+
if (keyPos >= this.keys.length) {
|
|
88
|
+
this.output.write(this.parser.rawHeaders);
|
|
89
|
+
setImmediate(() => this.sendNextChunk());
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const key = this.keys[keyPos++];
|
|
93
|
+
let dkimField;
|
|
94
|
+
try {
|
|
95
|
+
dkimField = (0, sign_js_1.default)(this.headers, this.hashAlgo, this.bodyHash, {
|
|
96
|
+
domainName: key.domainName,
|
|
97
|
+
keySelector: key.keySelector,
|
|
98
|
+
privateKey: key.privateKey,
|
|
99
|
+
headerFieldNames: this.options.headerFieldNames,
|
|
100
|
+
skipFields: this.options.skipFields
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
this.hasErrored = true;
|
|
105
|
+
this.cleanup();
|
|
106
|
+
this.output.emit('error', err);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (dkimField) {
|
|
110
|
+
this.output.write(Buffer.from(dkimField + '\r\n'));
|
|
111
|
+
}
|
|
112
|
+
setImmediate(signNextKey);
|
|
113
|
+
};
|
|
114
|
+
if (this.bodyHash && this.headers) {
|
|
115
|
+
return signNextKey();
|
|
116
|
+
}
|
|
117
|
+
this.output.write(this.parser.rawHeaders);
|
|
118
|
+
this.sendNextChunk();
|
|
119
|
+
}
|
|
120
|
+
createWriteCache() {
|
|
121
|
+
this.output.usingCache = true;
|
|
122
|
+
// pipe remainings to cache file
|
|
123
|
+
this.cache = node_fs_1.default.createWriteStream(this.cachePath);
|
|
124
|
+
this.cache.once('error', err => {
|
|
125
|
+
this.cleanup();
|
|
126
|
+
// drain input
|
|
127
|
+
this.relaxedBody.unpipe(this.cache);
|
|
128
|
+
this.relaxedBody.on('readable', () => {
|
|
129
|
+
while (this.relaxedBody.read() !== null) {
|
|
130
|
+
// do nothing
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
this.hasErrored = true;
|
|
134
|
+
// emit error
|
|
135
|
+
this.output.emit('error', err);
|
|
136
|
+
});
|
|
137
|
+
this.cache.once('close', () => {
|
|
138
|
+
this.sendSignedOutput();
|
|
139
|
+
});
|
|
140
|
+
this.relaxedBody.removeAllListeners('readable');
|
|
141
|
+
this.relaxedBody.pipe(this.cache);
|
|
142
|
+
}
|
|
143
|
+
signStream() {
|
|
144
|
+
this.parser = new message_parser_js_1.default();
|
|
145
|
+
this.relaxedBody = new relaxed_body_js_1.default({
|
|
146
|
+
hashAlgo: this.hashAlgo
|
|
147
|
+
});
|
|
148
|
+
this.parser.on('headers', value => {
|
|
149
|
+
this.headers = value;
|
|
150
|
+
});
|
|
151
|
+
this.relaxedBody.on('hash', value => {
|
|
152
|
+
this.bodyHash = value;
|
|
153
|
+
});
|
|
154
|
+
this.relaxedBody.on('readable', () => {
|
|
155
|
+
let chunk;
|
|
156
|
+
if (this.cache) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
while ((chunk = this.relaxedBody.read()) !== null) {
|
|
160
|
+
this.chunks.push(chunk);
|
|
161
|
+
this.chunklen += chunk.length;
|
|
162
|
+
if (this.chunklen >= this.cacheTreshold && this.cachePath) {
|
|
163
|
+
return this.createWriteCache();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
this.relaxedBody.on('end', () => {
|
|
168
|
+
if (this.cache) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
this.sendSignedOutput();
|
|
172
|
+
});
|
|
173
|
+
this.parser.pipe(this.relaxedBody);
|
|
174
|
+
setImmediate(() => this.input.pipe(this.parser));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
class DKIM {
|
|
178
|
+
constructor(options) {
|
|
179
|
+
this.options = options || {};
|
|
180
|
+
this.keys = [].concat(this.options.keys || {
|
|
181
|
+
domainName: options.domainName,
|
|
182
|
+
keySelector: options.keySelector,
|
|
183
|
+
privateKey: options.privateKey
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
sign(input, extraOptions) {
|
|
187
|
+
const output = new node_stream_1.PassThrough();
|
|
188
|
+
let inputStream = input;
|
|
189
|
+
let writeValue = false;
|
|
190
|
+
if (Buffer.isBuffer(input)) {
|
|
191
|
+
writeValue = input;
|
|
192
|
+
inputStream = new node_stream_1.PassThrough();
|
|
193
|
+
}
|
|
194
|
+
else if (typeof input === 'string') {
|
|
195
|
+
writeValue = Buffer.from(input);
|
|
196
|
+
inputStream = new node_stream_1.PassThrough();
|
|
197
|
+
}
|
|
198
|
+
let options = this.options;
|
|
199
|
+
if (extraOptions && Object.keys(extraOptions).length) {
|
|
200
|
+
// extraOptions is mail.data._dkim, caller supplied message data. An own
|
|
201
|
+
// "__proto__" key there would let every option this signer reads and the
|
|
202
|
+
// transport did not set, such as skipFields, answer from the caller
|
|
203
|
+
options = (0, objects_js_1.copyOwnKeys)({}, extraOptions);
|
|
204
|
+
(0, objects_js_1.copyOwnKeys)(options, this.options);
|
|
205
|
+
}
|
|
206
|
+
const signer = new DKIMSigner(options, this.keys, inputStream, output);
|
|
207
|
+
setImmediate(() => {
|
|
208
|
+
try {
|
|
209
|
+
signer.signStream();
|
|
210
|
+
}
|
|
211
|
+
catch (_E) {
|
|
212
|
+
// the body hash is created here, an unknown hashAlgo throws inside this timer
|
|
213
|
+
// where nothing else could catch it
|
|
214
|
+
output.emit('error', sign_js_1.default.unsupportedHashAlgoError(signer.hashAlgo));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (writeValue) {
|
|
218
|
+
setImmediate(() => {
|
|
219
|
+
inputStream.end(writeValue);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
return output;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
exports.default = DKIM;
|
|
227
|
+
module.exports = exports.default;
|
|
228
|
+
Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Transform, type TransformOptions } from 'node:stream';
|
|
2
|
+
/**
|
|
3
|
+
* A header line as emitted with the 'headers' event
|
|
4
|
+
*/
|
|
5
|
+
export interface MessageParserHeaderLine {
|
|
6
|
+
/** Lowercase header field name */
|
|
7
|
+
key: string;
|
|
8
|
+
/** Full header line, folded continuation lines included, one character per byte ('binary' encoding) */
|
|
9
|
+
line: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* MessageParser instance is a transform stream that separates message headers
|
|
13
|
+
* from the rest of the body. Headers are emitted with the 'headers' event. Message
|
|
14
|
+
* body is passed on as the resulting stream.
|
|
15
|
+
*/
|
|
16
|
+
declare class MessageParser extends Transform {
|
|
17
|
+
lastBytes: Buffer;
|
|
18
|
+
headersParsed: boolean;
|
|
19
|
+
headerBytes: number;
|
|
20
|
+
headerChunks: Buffer[] | null;
|
|
21
|
+
rawHeaders: Buffer | false;
|
|
22
|
+
bodySize: number;
|
|
23
|
+
constructor(options?: TransformOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Keeps count of the last 4 bytes in order to detect line breaks on chunk boundaries
|
|
26
|
+
*
|
|
27
|
+
* @param data Next data chunk from the stream
|
|
28
|
+
*/
|
|
29
|
+
updateLastBytes(data: Buffer): void;
|
|
30
|
+
/**
|
|
31
|
+
* Finds and removes message headers from the remaining body. We want to keep
|
|
32
|
+
* headers separated until final delivery to be able to modify these
|
|
33
|
+
*
|
|
34
|
+
* @param data Next chunk of data
|
|
35
|
+
* @return Returns true if headers are already found or false otherwise
|
|
36
|
+
*/
|
|
37
|
+
checkHeaders(data: Buffer): boolean;
|
|
38
|
+
parseHeaders(): MessageParserHeaderLine[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Type aliases in the layout of @types/nodemailer, so `MessageParser.Header` style references keep working
|
|
42
|
+
*/
|
|
43
|
+
declare namespace MessageParser {
|
|
44
|
+
type Header = MessageParserHeaderLine;
|
|
45
|
+
}
|
|
46
|
+
/** The same alias as a module level export, for `import * as MessageParser` and `import MessageParser = require()` */
|
|
47
|
+
export type { MessageParserHeaderLine as Header };
|
|
48
|
+
export default MessageParser;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const node_stream_1 = require("node:stream");
|
|
4
|
+
/**
|
|
5
|
+
* Drops the SP and HTAB from both ends of a field name.
|
|
6
|
+
*
|
|
7
|
+
* An index scan rather than `/^[ \t]+|[ \t]+$/g`, which retries the trailing branch at
|
|
8
|
+
* every offset of a blank run that is followed by other text: the run is consumed greedily,
|
|
9
|
+
* `$` fails, and the engine gives the characters back one at a time before moving on to
|
|
10
|
+
* start the same walk one offset further in. A field name carrying a 128 KiB run of spaces
|
|
11
|
+
* between two atoms took about 6.7 seconds to trim, and the cost grows with its square.
|
|
12
|
+
*
|
|
13
|
+
* Not `.trim()`, which takes the other Unicode spaces along: an NBSP in front of a field
|
|
14
|
+
* name would come off and select the name into the signed set, where the relaxed
|
|
15
|
+
* canonicalization in sign.ts deliberately leaves everything but SP and HTAB alone.
|
|
16
|
+
*
|
|
17
|
+
* @param str Field name to trim
|
|
18
|
+
* @return The field name without the surrounding SP and HTAB
|
|
19
|
+
*/
|
|
20
|
+
function _trimFieldName(str) {
|
|
21
|
+
let start = 0;
|
|
22
|
+
let end = str.length;
|
|
23
|
+
while (start < end && (str.charCodeAt(start) === 0x20 || str.charCodeAt(start) === 0x09)) {
|
|
24
|
+
start++;
|
|
25
|
+
}
|
|
26
|
+
while (end > start && (str.charCodeAt(end - 1) === 0x20 || str.charCodeAt(end - 1) === 0x09)) {
|
|
27
|
+
end--;
|
|
28
|
+
}
|
|
29
|
+
return str.slice(start, end);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* MessageParser instance is a transform stream that separates message headers
|
|
33
|
+
* from the rest of the body. Headers are emitted with the 'headers' event. Message
|
|
34
|
+
* body is passed on as the resulting stream.
|
|
35
|
+
*/
|
|
36
|
+
class MessageParser extends node_stream_1.Transform {
|
|
37
|
+
constructor(options) {
|
|
38
|
+
super(options);
|
|
39
|
+
this.lastBytes = Buffer.alloc(4);
|
|
40
|
+
this.headersParsed = false;
|
|
41
|
+
this.headerBytes = 0;
|
|
42
|
+
this.headerChunks = [];
|
|
43
|
+
this.rawHeaders = false;
|
|
44
|
+
this.bodySize = 0;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Keeps count of the last 4 bytes in order to detect line breaks on chunk boundaries
|
|
48
|
+
*
|
|
49
|
+
* @param data Next data chunk from the stream
|
|
50
|
+
*/
|
|
51
|
+
updateLastBytes(data) {
|
|
52
|
+
const lblen = this.lastBytes.length;
|
|
53
|
+
const nblen = Math.min(data.length, lblen);
|
|
54
|
+
// shift existing bytes
|
|
55
|
+
for (let i = 0, len = lblen - nblen; i < len; i++) {
|
|
56
|
+
this.lastBytes[i] = this.lastBytes[i + nblen];
|
|
57
|
+
}
|
|
58
|
+
// add new bytes
|
|
59
|
+
for (let i = 1; i <= nblen; i++) {
|
|
60
|
+
this.lastBytes[lblen - i] = data[data.length - i];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Finds and removes message headers from the remaining body. We want to keep
|
|
65
|
+
* headers separated until final delivery to be able to modify these
|
|
66
|
+
*
|
|
67
|
+
* @param data Next chunk of data
|
|
68
|
+
* @return Returns true if headers are already found or false otherwise
|
|
69
|
+
*/
|
|
70
|
+
checkHeaders(data) {
|
|
71
|
+
if (this.headersParsed) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
const lblen = this.lastBytes.length;
|
|
75
|
+
let headerPos = 0;
|
|
76
|
+
for (let i = 0, len = this.lastBytes.length + data.length; i < len; i++) {
|
|
77
|
+
let chr;
|
|
78
|
+
if (i < lblen) {
|
|
79
|
+
chr = this.lastBytes[i];
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
chr = data[i - lblen];
|
|
83
|
+
}
|
|
84
|
+
if (chr === 0x0a && i) {
|
|
85
|
+
const pr1 = i - 1 < lblen ? this.lastBytes[i - 1] : data[i - 1 - lblen];
|
|
86
|
+
const pr2 = i > 1 ? (i - 2 < lblen ? this.lastBytes[i - 2] : data[i - 2 - lblen]) : false;
|
|
87
|
+
if (pr1 === 0x0a) {
|
|
88
|
+
this.headersParsed = true;
|
|
89
|
+
headerPos = i - lblen + 1;
|
|
90
|
+
this.headerBytes += headerPos;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
else if (pr1 === 0x0d && pr2 === 0x0a) {
|
|
94
|
+
this.headersParsed = true;
|
|
95
|
+
headerPos = i - lblen + 1;
|
|
96
|
+
this.headerBytes += headerPos;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (this.headersParsed) {
|
|
102
|
+
this.headerChunks.push(data.slice(0, headerPos));
|
|
103
|
+
this.rawHeaders = Buffer.concat(this.headerChunks, this.headerBytes);
|
|
104
|
+
this.headerChunks = null;
|
|
105
|
+
this.emit('headers', this.parseHeaders());
|
|
106
|
+
if (data.length > headerPos) {
|
|
107
|
+
const chunk = data.slice(headerPos);
|
|
108
|
+
this.bodySize += chunk.length;
|
|
109
|
+
// this would be the first chunk of data sent downstream
|
|
110
|
+
setImmediate(() => this.push(chunk));
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
this.headerBytes += data.length;
|
|
115
|
+
this.headerChunks.push(data);
|
|
116
|
+
// store last 4 bytes to catch header break
|
|
117
|
+
this.updateLastBytes(data);
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
/** @internal */
|
|
121
|
+
_transform(chunk, encoding, callback) {
|
|
122
|
+
if (!chunk || !chunk.length) {
|
|
123
|
+
return callback();
|
|
124
|
+
}
|
|
125
|
+
if (typeof chunk === 'string') {
|
|
126
|
+
chunk = Buffer.from(chunk, encoding);
|
|
127
|
+
}
|
|
128
|
+
let headersFound;
|
|
129
|
+
try {
|
|
130
|
+
headersFound = this.checkHeaders(chunk);
|
|
131
|
+
}
|
|
132
|
+
catch (E) {
|
|
133
|
+
return callback(E);
|
|
134
|
+
}
|
|
135
|
+
if (headersFound) {
|
|
136
|
+
this.bodySize += chunk.length;
|
|
137
|
+
this.push(chunk);
|
|
138
|
+
}
|
|
139
|
+
setImmediate(callback);
|
|
140
|
+
}
|
|
141
|
+
/** @internal */
|
|
142
|
+
_flush(callback) {
|
|
143
|
+
if (this.headerChunks) {
|
|
144
|
+
// no empty line was seen, so the message consists of headers only
|
|
145
|
+
this.rawHeaders = Buffer.concat(this.headerChunks, this.headerBytes);
|
|
146
|
+
this.headerChunks = null;
|
|
147
|
+
this.emit('headers', this.parseHeaders());
|
|
148
|
+
}
|
|
149
|
+
callback();
|
|
150
|
+
}
|
|
151
|
+
parseHeaders() {
|
|
152
|
+
// the header bytes are kept as they are, one character per byte, so the
|
|
153
|
+
// signature covers exactly the bytes the receiving side canonicalizes
|
|
154
|
+
// Only SP and HTAB fold a line, and only they are trimmed from the field name, the
|
|
155
|
+
// same whitespace the relaxed canonicalization in sign.ts works with
|
|
156
|
+
const rawLines = (this.rawHeaders || Buffer.alloc(0)).toString('binary').split(/\r?\n/);
|
|
157
|
+
// Unfold in a single forward pass and only ever test a freshly split line for the
|
|
158
|
+
// continuation prefix. Testing an already merged line instead would rescan a string
|
|
159
|
+
// that grows with every continuation line, so a header folded into many continuation
|
|
160
|
+
// lines (a large recipient list, for example) would take quadratic time to unfold
|
|
161
|
+
const lines = [];
|
|
162
|
+
for (const rawLine of rawLines) {
|
|
163
|
+
if (lines.length && /^[ \t]/.test(rawLine)) {
|
|
164
|
+
lines[lines.length - 1] += '\n' + rawLine;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
lines.push(rawLine);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return lines
|
|
171
|
+
.filter(line => /[^ \t\r]/.test(line))
|
|
172
|
+
.map(line => ({
|
|
173
|
+
key: _trimFieldName(line.substr(0, line.indexOf(':'))).toLowerCase(),
|
|
174
|
+
line
|
|
175
|
+
}));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.default = MessageParser;
|
|
179
|
+
module.exports = exports.default;
|
|
180
|
+
Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
|