@timshel_npm/maildev 3.1.1
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/LICENSE +16 -0
- package/README.md +287 -0
- package/bin/maildev +13 -0
- package/dist/app/components/angular/angular.js +20282 -0
- package/dist/app/components/angular/angular.min.js +201 -0
- package/dist/app/components/angular/angular.min.js.map +8 -0
- package/dist/app/components/angular-cookies/angular-cookies.js +202 -0
- package/dist/app/components/angular-cookies/angular-cookies.min.js +8 -0
- package/dist/app/components/angular-cookies/angular-cookies.min.js.map +8 -0
- package/dist/app/components/angular-resource/angular-resource.js +546 -0
- package/dist/app/components/angular-resource/angular-resource.min.js +12 -0
- package/dist/app/components/angular-resource/angular-resource.min.js.map +8 -0
- package/dist/app/components/angular-route/angular-route.js +891 -0
- package/dist/app/components/angular-route/angular-route.min.js +14 -0
- package/dist/app/components/angular-route/angular-route.min.js.map +8 -0
- package/dist/app/components/angular-sanitize/angular-sanitize.js +615 -0
- package/dist/app/components/angular-sanitize/angular-sanitize.min.js +14 -0
- package/dist/app/components/angular-sanitize/angular-sanitize.min.js.map +8 -0
- package/dist/app/components/socket.io/socket.io.min.js +7 -0
- package/dist/app/favicon.ico +0 -0
- package/dist/app/index.html +176 -0
- package/dist/app/scripts/app.js +68 -0
- package/dist/app/scripts/components/address.js +15 -0
- package/dist/app/scripts/controllers/item.js +191 -0
- package/dist/app/scripts/controllers/main.js +259 -0
- package/dist/app/scripts/services.js +84 -0
- package/dist/app/styles/style.css +37 -0
- package/dist/app/views/address.html +3 -0
- package/dist/app/views/item.html +310 -0
- package/dist/app/views/main.html +18 -0
- package/dist/app/webfonts/fa-brands-400.eot +0 -0
- package/dist/app/webfonts/fa-brands-400.svg +3717 -0
- package/dist/app/webfonts/fa-brands-400.ttf +0 -0
- package/dist/app/webfonts/fa-brands-400.woff +0 -0
- package/dist/app/webfonts/fa-brands-400.woff2 +0 -0
- package/dist/app/webfonts/fa-regular-400.eot +0 -0
- package/dist/app/webfonts/fa-regular-400.svg +801 -0
- package/dist/app/webfonts/fa-regular-400.ttf +0 -0
- package/dist/app/webfonts/fa-regular-400.woff +0 -0
- package/dist/app/webfonts/fa-regular-400.woff2 +0 -0
- package/dist/app/webfonts/fa-solid-900.eot +0 -0
- package/dist/app/webfonts/fa-solid-900.svg +5028 -0
- package/dist/app/webfonts/fa-solid-900.ttf +0 -0
- package/dist/app/webfonts/fa-solid-900.woff +0 -0
- package/dist/app/webfonts/fa-solid-900.woff2 +0 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +50 -0
- package/dist/lib/auth.d.ts +4 -0
- package/dist/lib/auth.js +26 -0
- package/dist/lib/helpers/bcc.d.ts +5 -0
- package/dist/lib/helpers/bcc.js +16 -0
- package/dist/lib/helpers/smtp.d.ts +4 -0
- package/dist/lib/helpers/smtp.js +16 -0
- package/dist/lib/helpers/strtotime.d.ts +2 -0
- package/dist/lib/helpers/strtotime.js +1301 -0
- package/dist/lib/logger.d.ts +2 -0
- package/dist/lib/logger.js +30 -0
- package/dist/lib/mailbuffer.d.ts +21 -0
- package/dist/lib/mailbuffer.js +102 -0
- package/dist/lib/mailparser.d.ts +2 -0
- package/dist/lib/mailparser.js +253 -0
- package/dist/lib/mailserver.d.ts +115 -0
- package/dist/lib/mailserver.js +497 -0
- package/dist/lib/options.d.ts +3 -0
- package/dist/lib/options.js +150 -0
- package/dist/lib/outgoing.d.ts +40 -0
- package/dist/lib/outgoing.js +162 -0
- package/dist/lib/routes.d.ts +2 -0
- package/dist/lib/routes.js +139 -0
- package/dist/lib/type.d.ts +228 -0
- package/dist/lib/type.js +2 -0
- package/dist/lib/utils.d.ts +4 -0
- package/dist/lib/utils.js +65 -0
- package/dist/lib/web.d.ts +32 -0
- package/dist/lib/web.js +90 -0
- package/package.json +109 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MailDev - logger.js
|
|
4
|
+
*/
|
|
5
|
+
let logLevel = 1;
|
|
6
|
+
module.exports = {};
|
|
7
|
+
/**
|
|
8
|
+
* Initialize the logger
|
|
9
|
+
*/
|
|
10
|
+
module.exports.setLevel = function (level) {
|
|
11
|
+
logLevel = level;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* The info method will always log to the console
|
|
15
|
+
*/
|
|
16
|
+
module.exports.info = function () {
|
|
17
|
+
if (logLevel > 0) {
|
|
18
|
+
console.info.apply(console, arguments);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Extend the basic console.x functions, checking if the logging is on
|
|
23
|
+
*/
|
|
24
|
+
["log", "dir", "warn", "error"].forEach(function (fn) {
|
|
25
|
+
module.exports[fn] = function () {
|
|
26
|
+
if (logLevel > 1) {
|
|
27
|
+
console[fn].apply(console, arguments);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Mail } from "./type";
|
|
2
|
+
import type { MailServer } from "./mailserver";
|
|
3
|
+
interface Next {
|
|
4
|
+
filter: (Mail: any) => boolean;
|
|
5
|
+
resolve: (Mail: any) => any;
|
|
6
|
+
reject: (Error: any) => any;
|
|
7
|
+
consume: boolean;
|
|
8
|
+
timeout?: NodeJS.Timeout | undefined;
|
|
9
|
+
}
|
|
10
|
+
export declare class MailBuffer {
|
|
11
|
+
mails: Mail[];
|
|
12
|
+
nexts: Next[];
|
|
13
|
+
defaultTimeout: number;
|
|
14
|
+
close: () => any;
|
|
15
|
+
_receive: (Mail: any) => any;
|
|
16
|
+
constructor(mailServer: MailServer, subject: String, defaultTimeout: number);
|
|
17
|
+
find(filter: (Mail: any) => boolean, consume: boolean): Mail | undefined;
|
|
18
|
+
next(filter: (Mail: any) => boolean, consume?: boolean): Promise<Mail>;
|
|
19
|
+
expect(filter: (Mail: any) => boolean, consume?: boolean, timeout?: number): Promise<Mail>;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.MailBuffer = void 0;
|
|
15
|
+
class MailBuffer {
|
|
16
|
+
constructor(mailServer, subject, defaultTimeout) {
|
|
17
|
+
this.mails = [];
|
|
18
|
+
this.nexts = [];
|
|
19
|
+
this.defaultTimeout = defaultTimeout;
|
|
20
|
+
this._receive = (mail) => {
|
|
21
|
+
let consumed = false;
|
|
22
|
+
let index = -1;
|
|
23
|
+
do {
|
|
24
|
+
index = this.nexts.findIndex((n) => n.filter(mail));
|
|
25
|
+
if (index > -1) {
|
|
26
|
+
const n = this.nexts[index];
|
|
27
|
+
consumed = n.consume;
|
|
28
|
+
this.nexts.splice(index, 1);
|
|
29
|
+
n.resolve(mail);
|
|
30
|
+
if (n.timeout !== undefined) {
|
|
31
|
+
clearTimeout(n.timeout);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
} while (index > -1 && !consumed);
|
|
35
|
+
if (!consumed) {
|
|
36
|
+
this.mails.push(mail);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
this.close = () => {
|
|
40
|
+
mailServer.removeListener("close", this.close);
|
|
41
|
+
mailServer.removeListener(subject, this._receive);
|
|
42
|
+
const error = new Error("Closing buffer");
|
|
43
|
+
for (let _a of this.nexts) {
|
|
44
|
+
const { reject } = _a, _ = __rest(_a, ["reject"]);
|
|
45
|
+
reject(error);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
mailServer.on(subject, this._receive);
|
|
49
|
+
mailServer.once("close", this.close);
|
|
50
|
+
}
|
|
51
|
+
find(filter, consume) {
|
|
52
|
+
const index = this.mails.findIndex(filter);
|
|
53
|
+
if (index > -1) {
|
|
54
|
+
const mail = this.mails[index];
|
|
55
|
+
if (consume) {
|
|
56
|
+
this.mails.splice(index, 1);
|
|
57
|
+
}
|
|
58
|
+
return mail;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
next(filter, consume = true) {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
const mail = this.find(filter, consume);
|
|
64
|
+
if (mail !== undefined) {
|
|
65
|
+
resolve(mail);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this.nexts.push({
|
|
69
|
+
filter,
|
|
70
|
+
resolve,
|
|
71
|
+
reject,
|
|
72
|
+
consume,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
expect(filter, consume = true, timeout) {
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
const mail = this.find(filter, consume);
|
|
80
|
+
if (mail !== undefined) {
|
|
81
|
+
resolve(mail);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
let next = {
|
|
85
|
+
filter,
|
|
86
|
+
resolve,
|
|
87
|
+
reject,
|
|
88
|
+
consume,
|
|
89
|
+
};
|
|
90
|
+
this.nexts.push(next);
|
|
91
|
+
next.timeout = setTimeout(() => {
|
|
92
|
+
let index = this.nexts.findIndex((n) => n === next);
|
|
93
|
+
if (index > -1) {
|
|
94
|
+
this.nexts.splice(index, 1);
|
|
95
|
+
reject(new Error("Timeout while waiting for Mail"));
|
|
96
|
+
}
|
|
97
|
+
}, timeout || this.defaultTimeout);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.MailBuffer = MailBuffer;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.parse = parse;
|
|
13
|
+
const mime = require("mime");
|
|
14
|
+
const simpleParser = require("mailparser").simpleParser;
|
|
15
|
+
const strtotime = require("./helpers/strtotime");
|
|
16
|
+
const logger = require("./logger");
|
|
17
|
+
function parse(input) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
return simpleParser(input, {}).then((parsed) => {
|
|
20
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
21
|
+
const headers = {
|
|
22
|
+
date: getDate(parsed.headers, "date"),
|
|
23
|
+
contentType: single(getSructured(parsed.headers, "content-type")),
|
|
24
|
+
contentDisposition: single(getSructured(parsed.headers, "content-disposition")),
|
|
25
|
+
dkimSignature: getSructured(parsed.headers, "dkim-signature"),
|
|
26
|
+
from: getAddress(parsed.headers, "from"),
|
|
27
|
+
to: getAddress(parsed.headers, "to"),
|
|
28
|
+
cc: getAddress(parsed.headers, "cc"),
|
|
29
|
+
bcc: getAddress(parsed.headers, "bcc"),
|
|
30
|
+
sender: getAddress(parsed.headers, "sender"),
|
|
31
|
+
replyTo: getAddress(parsed.headers, "reply-to"),
|
|
32
|
+
deliveredTo: getAddress(parsed.headers, "delivered-to"),
|
|
33
|
+
dispositionNotificationTo: getAddress(parsed.headers, "disposition-notification-to"),
|
|
34
|
+
priority: getSring(parsed.headers, "priority"),
|
|
35
|
+
received: getSringArray(parsed.headers, "received"),
|
|
36
|
+
headers: new Map(Array.from(parsed.headers, ([key, value]) => {
|
|
37
|
+
const cast = value;
|
|
38
|
+
return [key, typeof cast === "string" ? [cast] : cast];
|
|
39
|
+
})),
|
|
40
|
+
};
|
|
41
|
+
const references = (typeof parsed.references === "string" ? [parsed.references] : ((_a = parsed.references) !== null && _a !== void 0 ? _a : [])).map((ref) => {
|
|
42
|
+
return ref.replace(/^<(.*)>$/, "$1");
|
|
43
|
+
});
|
|
44
|
+
const inReplyTo = (typeof parsed.inReplyTo === "string" ? ((_b = parsed.inReplyTo.match(/<([^<>]*)>/g)) !== null && _b !== void 0 ? _b : []) : []).map((ref) => {
|
|
45
|
+
return ref.replace(/^<(.*)>$/, "$1");
|
|
46
|
+
});
|
|
47
|
+
const fileNames = [];
|
|
48
|
+
const attachments = ((_c = parsed.attachments) !== null && _c !== void 0 ? _c : []).map((attachment) => {
|
|
49
|
+
const generatedFileName = generateFileNames(fileNames, attachment.filename, attachment.contentType);
|
|
50
|
+
return Object.assign(Object.assign({}, attachment), { generatedFileName });
|
|
51
|
+
});
|
|
52
|
+
return Object.assign(Object.assign({}, parsed), { headers, replyTo: (_e = (_d = headers === null || headers === void 0 ? void 0 : headers.replyTo) === null || _d === void 0 ? void 0 : _d.value) !== null && _e !== void 0 ? _e : [], from: (_g = (_f = headers === null || headers === void 0 ? void 0 : headers.from) === null || _f === void 0 ? void 0 : _f.value) !== null && _g !== void 0 ? _g : [], to: (_j = (_h = headers === null || headers === void 0 ? void 0 : headers.to) === null || _h === void 0 ? void 0 : _h.value) !== null && _j !== void 0 ? _j : [], cc: (_l = (_k = headers === null || headers === void 0 ? void 0 : headers.cc) === null || _k === void 0 ? void 0 : _k.value) !== null && _l !== void 0 ? _l : [], bcc: (_o = (_m = headers === null || headers === void 0 ? void 0 : headers.bcc) === null || _m === void 0 ? void 0 : _m.value) !== null && _o !== void 0 ? _o : [], date: (_p = parsed.date) !== null && _p !== void 0 ? _p : new Date(), priority: (_q = headers.priority) !== null && _q !== void 0 ? _q : "normal", receivedDate: parseReceived(parsed.date, headers.received, parsed.headers.get("x-received")), references,
|
|
53
|
+
inReplyTo,
|
|
54
|
+
attachments });
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function single(array) {
|
|
59
|
+
return array.length > 0 ? array[0] : undefined;
|
|
60
|
+
}
|
|
61
|
+
function getDate(headers, key) {
|
|
62
|
+
const value = headers.get(key);
|
|
63
|
+
headers.delete(key);
|
|
64
|
+
if (value instanceof Date || value === undefined) {
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
logger.error("Invalid header value for %s, expected date got %s", key, value);
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
function getSring(headers, key) {
|
|
73
|
+
const value = headers.get(key);
|
|
74
|
+
headers.delete(key);
|
|
75
|
+
if (typeof value === "string" || value === undefined) {
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
logger.error("Invalid header value for %s, expected string got %s", key, value);
|
|
80
|
+
}
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
function getSringArray(headers, key) {
|
|
84
|
+
var _a;
|
|
85
|
+
const value = (_a = headers.get(key)) !== null && _a !== void 0 ? _a : [];
|
|
86
|
+
headers.delete(key);
|
|
87
|
+
if (typeof value === "string") {
|
|
88
|
+
return [value];
|
|
89
|
+
}
|
|
90
|
+
else if (Array.isArray(value)) {
|
|
91
|
+
return value.filter((elt) => {
|
|
92
|
+
const isString = typeof elt === "string";
|
|
93
|
+
if (!isString) {
|
|
94
|
+
logger.error("Invalid header value for %s, expected string[] got a %s", key, value);
|
|
95
|
+
}
|
|
96
|
+
return isString;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
logger.error("Invalid header value for %s, expected string or string[] got %s", key, value);
|
|
101
|
+
}
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
function getAddress(headers, key) {
|
|
105
|
+
var _a;
|
|
106
|
+
const headerValue = headers.get(key);
|
|
107
|
+
headers.delete(key);
|
|
108
|
+
function flatten(acc, addr) {
|
|
109
|
+
if (addr.group) {
|
|
110
|
+
addr.group.forEach((e) => flatten(acc, e));
|
|
111
|
+
}
|
|
112
|
+
if (addr.address) {
|
|
113
|
+
acc.push({ address: addr.address, name: addr.name });
|
|
114
|
+
}
|
|
115
|
+
return acc;
|
|
116
|
+
}
|
|
117
|
+
return headerValue
|
|
118
|
+
? {
|
|
119
|
+
value: (_a = headerValue.value.reduce(flatten, [])) !== null && _a !== void 0 ? _a : [],
|
|
120
|
+
html: headerValue.html,
|
|
121
|
+
text: headerValue.text,
|
|
122
|
+
}
|
|
123
|
+
: undefined;
|
|
124
|
+
}
|
|
125
|
+
function getSructured(headers, key) {
|
|
126
|
+
const value = headers.get(key);
|
|
127
|
+
headers.delete(key);
|
|
128
|
+
if (typeof value === "string") {
|
|
129
|
+
return [{ value, params: {} }];
|
|
130
|
+
}
|
|
131
|
+
else if (Array.isArray(value)) {
|
|
132
|
+
return value.map((n) => {
|
|
133
|
+
return { value: n, params: {} };
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
else if (typeof value === "object") {
|
|
137
|
+
return [value];
|
|
138
|
+
}
|
|
139
|
+
else if (value) {
|
|
140
|
+
logger.error("Invalid header value for %s, expected StructuredHeader or [] got %s", key, value);
|
|
141
|
+
}
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* <p>Generates a context unique filename for an attachment</p>
|
|
146
|
+
*
|
|
147
|
+
* <p>If a filename already exists, append a number to it</p>
|
|
148
|
+
*
|
|
149
|
+
* <ul>
|
|
150
|
+
* <li>file.txt</li>
|
|
151
|
+
* <li>file-1.txt</li>
|
|
152
|
+
* <li>file-2.txt</li>
|
|
153
|
+
* </ul>
|
|
154
|
+
*
|
|
155
|
+
* @param {String} fileName source filename
|
|
156
|
+
* @param {String} contentType source content type
|
|
157
|
+
* @returns {String} generated filename
|
|
158
|
+
*/
|
|
159
|
+
function generateFileNames(fileNames, fileName, contentType) {
|
|
160
|
+
let ext;
|
|
161
|
+
let defaultExt = "";
|
|
162
|
+
if (contentType) {
|
|
163
|
+
const ext = mime.extension(contentType); // renamed as getExtension in > 2.0
|
|
164
|
+
defaultExt = ext ? "." + ext : "";
|
|
165
|
+
}
|
|
166
|
+
fileName = fileName || "attachment" + defaultExt;
|
|
167
|
+
// remove path if it is included in the filename
|
|
168
|
+
fileName =
|
|
169
|
+
fileName
|
|
170
|
+
.toString()
|
|
171
|
+
.split(/[/\\]+/)
|
|
172
|
+
.pop()
|
|
173
|
+
.replace(/^\.+/, "") || "attachment";
|
|
174
|
+
const fileRootName = fileName.replace(/(?:-\d+)+(\.[^.]*)$/, "$1") || "attachment";
|
|
175
|
+
if (fileRootName in fileNames) {
|
|
176
|
+
fileNames[fileRootName]++;
|
|
177
|
+
ext = fileName.substr((fileName.lastIndexOf(".") || 0) + 1);
|
|
178
|
+
if (ext === fileName) {
|
|
179
|
+
fileName += "-" + fileNames[fileRootName];
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
fileName =
|
|
183
|
+
fileName.substr(0, fileName.length - ext.length - 1) +
|
|
184
|
+
"-" +
|
|
185
|
+
fileNames[fileRootName] +
|
|
186
|
+
"." +
|
|
187
|
+
ext;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
fileNames[fileRootName] = 0;
|
|
192
|
+
}
|
|
193
|
+
return fileName;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* <p>Parses Received and X-Received header field value</p>
|
|
197
|
+
*
|
|
198
|
+
* <p>Pulls received date from the received and x-received header fields and
|
|
199
|
+
* update current node meta object with this date as long as it's later as the
|
|
200
|
+
* existing date of the meta object</p>
|
|
201
|
+
*
|
|
202
|
+
* <p>Example: <code>by 10.25.25.72 with SMTP id 69csp2404548lfz; Fri, 6 Feb 2015 15:15:32 -0800 (PST)</code>
|
|
203
|
+
* will become:
|
|
204
|
+
* </p>
|
|
205
|
+
*
|
|
206
|
+
* <pre>new Date('2015-02-06T23:15:32.000Z')</pre>
|
|
207
|
+
*
|
|
208
|
+
* @param {String} value Received string
|
|
209
|
+
* @returns {Date|Boolean} parsed received date
|
|
210
|
+
*/
|
|
211
|
+
function parseReceived(date, received, xReceived) {
|
|
212
|
+
let receivedDate;
|
|
213
|
+
function parse(value) {
|
|
214
|
+
const splitString = value.split(";");
|
|
215
|
+
return parseDateString(splitString[splitString.length - 1]);
|
|
216
|
+
}
|
|
217
|
+
if (received && received.length > 0) {
|
|
218
|
+
receivedDate = parse(received[0]);
|
|
219
|
+
}
|
|
220
|
+
if (!receivedDate && xReceived) {
|
|
221
|
+
receivedDate = parse(xReceived);
|
|
222
|
+
}
|
|
223
|
+
return !receivedDate || date > receivedDate ? date : receivedDate;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* <p>Parses date string</o>
|
|
227
|
+
*
|
|
228
|
+
* <p>Receives possible date string in different formats and
|
|
229
|
+
* transforms it into a JS Date object</p>
|
|
230
|
+
*
|
|
231
|
+
* @param {String} value possible date string
|
|
232
|
+
* @returns {Date|Boolean} date object
|
|
233
|
+
*/
|
|
234
|
+
function parseDateString(value) {
|
|
235
|
+
let date;
|
|
236
|
+
date = new Date(value);
|
|
237
|
+
if (Object.prototype.toString.call(date) !== "[object Date]" ||
|
|
238
|
+
date.toString() === "Invalid Date") {
|
|
239
|
+
try {
|
|
240
|
+
date = strtotime(value);
|
|
241
|
+
}
|
|
242
|
+
catch (E) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
if (date) {
|
|
246
|
+
date = new Date(date * 1000);
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return date;
|
|
253
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MailDev - mailserver
|
|
3
|
+
*/
|
|
4
|
+
import type { Attachment, Envelope, Mail } from "./type";
|
|
5
|
+
import type { OutgoingOptions } from "./outgoing";
|
|
6
|
+
import type { ReadStream } from "fs";
|
|
7
|
+
import { MailBuffer } from "./mailbuffer";
|
|
8
|
+
import { Outgoing } from "./outgoing";
|
|
9
|
+
import { SMTPServer } from "smtp-server";
|
|
10
|
+
export interface MailServerOptions {
|
|
11
|
+
port?: number;
|
|
12
|
+
host?: string;
|
|
13
|
+
mailDir?: string;
|
|
14
|
+
hideExtensions?: string[];
|
|
15
|
+
isSecure?: boolean;
|
|
16
|
+
auth?: {
|
|
17
|
+
user: string;
|
|
18
|
+
pass: string;
|
|
19
|
+
};
|
|
20
|
+
ssl?: {
|
|
21
|
+
certPath: string;
|
|
22
|
+
keyPath: string;
|
|
23
|
+
};
|
|
24
|
+
hide8BITMIME?: boolean;
|
|
25
|
+
hidePIPELINING?: boolean;
|
|
26
|
+
hideSMTPUTF8?: boolean;
|
|
27
|
+
outgoing?: OutgoingOptions;
|
|
28
|
+
}
|
|
29
|
+
export declare class MailServer {
|
|
30
|
+
port: number;
|
|
31
|
+
host: string;
|
|
32
|
+
mailDir: string;
|
|
33
|
+
store: Envelope[];
|
|
34
|
+
eventEmitter: any;
|
|
35
|
+
mailEventSubjectMapper: (Mail: any) => string | undefined;
|
|
36
|
+
smtp: typeof SMTPServer;
|
|
37
|
+
outgoing: Outgoing | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Extend Event Emitter methods
|
|
40
|
+
* events:
|
|
41
|
+
* 'new' - emitted when new email has arrived
|
|
42
|
+
*/
|
|
43
|
+
emit: any;
|
|
44
|
+
on: any;
|
|
45
|
+
off: any;
|
|
46
|
+
once: any;
|
|
47
|
+
prependListener: any;
|
|
48
|
+
prependOnceListener: any;
|
|
49
|
+
removeListener: any;
|
|
50
|
+
removeAllListeners: any;
|
|
51
|
+
next(subject: string): Promise<Mail>;
|
|
52
|
+
/**
|
|
53
|
+
* Use an internal array to store received email even if not consummed
|
|
54
|
+
* Use `.return()` to close it
|
|
55
|
+
**/
|
|
56
|
+
iterator(subject: string): AsyncIterator<Mail>;
|
|
57
|
+
/**
|
|
58
|
+
* Return a struct which store received emails.
|
|
59
|
+
* Then allow to obtain a `Promise<Mail>` dependant on a predicate `(Mail) => boolean`.
|
|
60
|
+
* Allow to wait for `Mail` independant of their order of arrival.
|
|
61
|
+
*/
|
|
62
|
+
buffer(subject: string, defaultTimeout?: number): MailBuffer;
|
|
63
|
+
constructor(options?: MailServerOptions, mailEventSubjectMapper?: (Mail: any) => string | undefined);
|
|
64
|
+
/**
|
|
65
|
+
* Start the mailServer
|
|
66
|
+
*/
|
|
67
|
+
listen(): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Stop the mailserver
|
|
70
|
+
*/
|
|
71
|
+
close(): Promise<void>;
|
|
72
|
+
isOutgoingEnabled(): boolean;
|
|
73
|
+
getOutgoingHost(): string | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Set Auto Relay Mode, automatic send email to recipient
|
|
76
|
+
*/
|
|
77
|
+
setAutoRelayMode(enabled: boolean, emailAddress: string | undefined, rules: {
|
|
78
|
+
allow?: string;
|
|
79
|
+
deny?: string;
|
|
80
|
+
}[] | string | undefined): void;
|
|
81
|
+
relayMail(mail: Mail, isAutoRelay?: boolean): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Get an email by id
|
|
84
|
+
*/
|
|
85
|
+
getEmail(id: string): Promise<Mail>;
|
|
86
|
+
/**
|
|
87
|
+
* Returns a readable stream of the raw email
|
|
88
|
+
*/
|
|
89
|
+
getRawEmail(id: string): Promise<ReadStream>;
|
|
90
|
+
/**
|
|
91
|
+
* Returns the html of a given email
|
|
92
|
+
*/
|
|
93
|
+
getEmailHTML(id: string, baseUrl?: string): Promise<string>;
|
|
94
|
+
/**
|
|
95
|
+
* Set all emails to read
|
|
96
|
+
*/
|
|
97
|
+
readAllEmail(): number;
|
|
98
|
+
getAllEnvelope(): Envelope[];
|
|
99
|
+
getAllEmail(): Promise<Mail[]>;
|
|
100
|
+
deleteEmail(id: string): Promise<boolean>;
|
|
101
|
+
deleteAllEmail(): Promise<boolean>;
|
|
102
|
+
/**
|
|
103
|
+
* Delete everything in the mail directory
|
|
104
|
+
*/
|
|
105
|
+
clearMailDir(): Promise<void[]>;
|
|
106
|
+
/**
|
|
107
|
+
* Returns the content type and a readable stream of the file
|
|
108
|
+
*/
|
|
109
|
+
getEmailAttachment(id: string, filename: string): Promise<Attachment>;
|
|
110
|
+
/**
|
|
111
|
+
* Download a given email
|
|
112
|
+
*/
|
|
113
|
+
getEmailEml(id: any): Promise<[string, string, ReadStream]>;
|
|
114
|
+
loadMailsFromDirectory(): Promise<void[]>;
|
|
115
|
+
}
|