@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.
Files changed (76) hide show
  1. package/LICENSE +16 -0
  2. package/README.md +287 -0
  3. package/bin/maildev +13 -0
  4. package/dist/app/components/angular/angular.js +20282 -0
  5. package/dist/app/components/angular/angular.min.js +201 -0
  6. package/dist/app/components/angular/angular.min.js.map +8 -0
  7. package/dist/app/components/angular-cookies/angular-cookies.js +202 -0
  8. package/dist/app/components/angular-cookies/angular-cookies.min.js +8 -0
  9. package/dist/app/components/angular-cookies/angular-cookies.min.js.map +8 -0
  10. package/dist/app/components/angular-resource/angular-resource.js +546 -0
  11. package/dist/app/components/angular-resource/angular-resource.min.js +12 -0
  12. package/dist/app/components/angular-resource/angular-resource.min.js.map +8 -0
  13. package/dist/app/components/angular-route/angular-route.js +891 -0
  14. package/dist/app/components/angular-route/angular-route.min.js +14 -0
  15. package/dist/app/components/angular-route/angular-route.min.js.map +8 -0
  16. package/dist/app/components/angular-sanitize/angular-sanitize.js +615 -0
  17. package/dist/app/components/angular-sanitize/angular-sanitize.min.js +14 -0
  18. package/dist/app/components/angular-sanitize/angular-sanitize.min.js.map +8 -0
  19. package/dist/app/components/socket.io/socket.io.min.js +7 -0
  20. package/dist/app/favicon.ico +0 -0
  21. package/dist/app/index.html +176 -0
  22. package/dist/app/scripts/app.js +68 -0
  23. package/dist/app/scripts/components/address.js +15 -0
  24. package/dist/app/scripts/controllers/item.js +191 -0
  25. package/dist/app/scripts/controllers/main.js +259 -0
  26. package/dist/app/scripts/services.js +84 -0
  27. package/dist/app/styles/style.css +37 -0
  28. package/dist/app/views/address.html +3 -0
  29. package/dist/app/views/item.html +310 -0
  30. package/dist/app/views/main.html +18 -0
  31. package/dist/app/webfonts/fa-brands-400.eot +0 -0
  32. package/dist/app/webfonts/fa-brands-400.svg +3717 -0
  33. package/dist/app/webfonts/fa-brands-400.ttf +0 -0
  34. package/dist/app/webfonts/fa-brands-400.woff +0 -0
  35. package/dist/app/webfonts/fa-brands-400.woff2 +0 -0
  36. package/dist/app/webfonts/fa-regular-400.eot +0 -0
  37. package/dist/app/webfonts/fa-regular-400.svg +801 -0
  38. package/dist/app/webfonts/fa-regular-400.ttf +0 -0
  39. package/dist/app/webfonts/fa-regular-400.woff +0 -0
  40. package/dist/app/webfonts/fa-regular-400.woff2 +0 -0
  41. package/dist/app/webfonts/fa-solid-900.eot +0 -0
  42. package/dist/app/webfonts/fa-solid-900.svg +5028 -0
  43. package/dist/app/webfonts/fa-solid-900.ttf +0 -0
  44. package/dist/app/webfonts/fa-solid-900.woff +0 -0
  45. package/dist/app/webfonts/fa-solid-900.woff2 +0 -0
  46. package/dist/index.d.ts +26 -0
  47. package/dist/index.js +50 -0
  48. package/dist/lib/auth.d.ts +4 -0
  49. package/dist/lib/auth.js +26 -0
  50. package/dist/lib/helpers/bcc.d.ts +5 -0
  51. package/dist/lib/helpers/bcc.js +16 -0
  52. package/dist/lib/helpers/smtp.d.ts +4 -0
  53. package/dist/lib/helpers/smtp.js +16 -0
  54. package/dist/lib/helpers/strtotime.d.ts +2 -0
  55. package/dist/lib/helpers/strtotime.js +1301 -0
  56. package/dist/lib/logger.d.ts +2 -0
  57. package/dist/lib/logger.js +30 -0
  58. package/dist/lib/mailbuffer.d.ts +21 -0
  59. package/dist/lib/mailbuffer.js +102 -0
  60. package/dist/lib/mailparser.d.ts +2 -0
  61. package/dist/lib/mailparser.js +253 -0
  62. package/dist/lib/mailserver.d.ts +115 -0
  63. package/dist/lib/mailserver.js +497 -0
  64. package/dist/lib/options.d.ts +3 -0
  65. package/dist/lib/options.js +150 -0
  66. package/dist/lib/outgoing.d.ts +40 -0
  67. package/dist/lib/outgoing.js +162 -0
  68. package/dist/lib/routes.d.ts +2 -0
  69. package/dist/lib/routes.js +139 -0
  70. package/dist/lib/type.d.ts +228 -0
  71. package/dist/lib/type.js +2 -0
  72. package/dist/lib/utils.d.ts +4 -0
  73. package/dist/lib/utils.js +65 -0
  74. package/dist/lib/web.d.ts +32 -0
  75. package/dist/lib/web.js +90 -0
  76. package/package.json +109 -0
@@ -0,0 +1,40 @@
1
+ export interface OutgoingOptions {
2
+ host?: string;
3
+ port?: number;
4
+ secure?: boolean;
5
+ auth?: {
6
+ user: string;
7
+ pass: string;
8
+ };
9
+ autoRelayAddress?: string;
10
+ autoRelayRules?: string | {
11
+ allow?: string;
12
+ deny?: string;
13
+ }[];
14
+ }
15
+ export declare class Outgoing {
16
+ port: number;
17
+ host: string;
18
+ secure: boolean;
19
+ autoRelay: boolean;
20
+ autoRelayAddress: string | undefined;
21
+ autoRelayRules: {
22
+ allow?: string;
23
+ deny?: string;
24
+ }[] | undefined;
25
+ auth: {
26
+ user: string;
27
+ pass: string;
28
+ } | undefined;
29
+ client: any;
30
+ emailQueue: any;
31
+ constructor(options?: OutgoingOptions);
32
+ getOutgoingHost(): string;
33
+ close(): void;
34
+ setAutoRelayMode(enabled: boolean, emailAddress: string | undefined, rules: {
35
+ allow?: string;
36
+ deny?: string;
37
+ }[] | string | undefined): void;
38
+ isAutoRelayEnabled(): boolean;
39
+ relayMail(emailObject: any, emailStream: any, isAutoRelay: any, callback: any): void;
40
+ }
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Outgoing = void 0;
4
+ /**
5
+ * MailDev - outgoing
6
+ */
7
+ const SMTPConnection = require("nodemailer/lib/smtp-connection");
8
+ const async = require("async");
9
+ const fs = require("fs");
10
+ const logger = require("./logger");
11
+ const wildstring = require("wildstring");
12
+ class Outgoing {
13
+ constructor(options) {
14
+ var _a, _b, _c;
15
+ this.autoRelay = false;
16
+ wildstring.caseSensitive = false;
17
+ this.secure = (_a = options === null || options === void 0 ? void 0 : options.secure) !== null && _a !== void 0 ? _a : false;
18
+ this.host = (_b = options === null || options === void 0 ? void 0 : options.host) !== null && _b !== void 0 ? _b : "localhost";
19
+ this.port = (_c = options === null || options === void 0 ? void 0 : options.port) !== null && _c !== void 0 ? _c : (this.secure ? 465 : 25);
20
+ this.auth = options === null || options === void 0 ? void 0 : options.auth;
21
+ createClient(this);
22
+ // Create a queue to sent out the emails
23
+ // We use a queue so we don't run into concurrency issues
24
+ this.emailQueue = async.queue((task, callback) => {
25
+ const relayCallback = function (err, result) {
26
+ task.callback && task.callback(err, result);
27
+ callback(err, result);
28
+ };
29
+ relayMail(this, task.emailObject, task.emailStream, task.isAutoRelay, relayCallback);
30
+ }, 1);
31
+ if ((options === null || options === void 0 ? void 0 : options.autoRelayAddress) || (options === null || options === void 0 ? void 0 : options.autoRelayRules)) {
32
+ this.setAutoRelayMode(true, options === null || options === void 0 ? void 0 : options.autoRelayAddress, options === null || options === void 0 ? void 0 : options.autoRelayRules);
33
+ }
34
+ }
35
+ getOutgoingHost() {
36
+ return this.host;
37
+ }
38
+ close() {
39
+ if (this.client) {
40
+ this.client.close();
41
+ }
42
+ }
43
+ setAutoRelayMode(enabled, emailAddress, rules) {
44
+ this.autoRelay = enabled;
45
+ this.autoRelayAddress = emailAddress;
46
+ if (rules) {
47
+ if (typeof rules === "string") {
48
+ try {
49
+ rules = JSON.parse(fs.readFileSync(rules, "utf8"));
50
+ }
51
+ catch (err) {
52
+ logger.error(`Error reading rules file at ${rules}: ${err}`);
53
+ throw err;
54
+ }
55
+ }
56
+ if (Array.isArray(rules)) {
57
+ this.autoRelayRules = rules;
58
+ }
59
+ }
60
+ if (this.autoRelay) {
61
+ const msg = ["Auto-Relay mode on"];
62
+ if (this.autoRelayAddress) {
63
+ msg.push(`Relaying all emails to ${this.autoRelayAddress}`);
64
+ }
65
+ if (this.autoRelayRules) {
66
+ msg.push(`Relay rules: ${JSON.stringify(this.autoRelayRules)}`);
67
+ }
68
+ logger.info(msg.join(", "));
69
+ }
70
+ }
71
+ isAutoRelayEnabled() {
72
+ return this.autoRelay;
73
+ }
74
+ relayMail(emailObject, emailStream, isAutoRelay, callback) {
75
+ this.emailQueue.push({ emailObject, emailStream, isAutoRelay, callback });
76
+ }
77
+ }
78
+ exports.Outgoing = Outgoing;
79
+ function createClient(outgoing) {
80
+ var _a, _b;
81
+ try {
82
+ outgoing.client = new SMTPConnection({
83
+ port: outgoing.port,
84
+ host: outgoing.host,
85
+ secure: outgoing.secure,
86
+ auth: outgoing.auth || false,
87
+ tls: { rejectUnauthorized: false },
88
+ debug: true,
89
+ });
90
+ outgoing.client.on("error", function (err) {
91
+ logger.error("SMTP Connection error for outgoing email: ", err);
92
+ });
93
+ logger.info("MailDev outgoing SMTP Server %s:%d (user:%s, pass:%s, secure:%s)", outgoing.host, outgoing.port, (_a = outgoing === null || outgoing === void 0 ? void 0 : outgoing.auth) === null || _a === void 0 ? void 0 : _a.user, ((_b = outgoing === null || outgoing === void 0 ? void 0 : outgoing.auth) === null || _b === void 0 ? void 0 : _b.pass) ? "####" : undefined, outgoing.secure ? "yes" : "no");
94
+ }
95
+ catch (err) {
96
+ logger.error("Error during configuration of SMTP Server for outgoing email", err);
97
+ }
98
+ }
99
+ function relayMail(outgoing, emailObject, emailStream, isAutoRelay, done) {
100
+ if (isAutoRelay && outgoing.autoRelayAddress) {
101
+ emailObject.to = [{ address: outgoing.autoRelayAddress }];
102
+ emailObject.envelope.to = [{ address: outgoing.autoRelayAddress, args: false }];
103
+ }
104
+ let recipients = emailObject.envelope.to.map(getAddressFromAddressObject);
105
+ if (isAutoRelay && outgoing.autoRelayRules) {
106
+ recipients = getAutoRelayableRecipients(recipients, outgoing.autoRelayRules);
107
+ }
108
+ // Fail silently with auth relay mode on
109
+ if (recipients.length === 0) {
110
+ return done("Email had no recipients");
111
+ }
112
+ const mailSendCallback = function (err) {
113
+ if (err) {
114
+ logger.error("Outgoing client login error: ", err);
115
+ return done(err);
116
+ }
117
+ const sender = getAddressFromAddressObject(emailObject.envelope.from);
118
+ outgoing.client.send({
119
+ from: sender,
120
+ to: recipients,
121
+ }, emailStream, function (err) {
122
+ outgoing.client.quit();
123
+ createClient(outgoing);
124
+ if (err) {
125
+ logger.error("Mail Delivery Error: ", err);
126
+ return done(err);
127
+ }
128
+ logger.log("Mail Delivered: ", emailObject.subject);
129
+ return done();
130
+ });
131
+ };
132
+ const mailConnectCallback = function (err) {
133
+ if (err) {
134
+ logger.error("Outgoing connection error: ", err);
135
+ return done(err);
136
+ }
137
+ if (outgoing.auth) {
138
+ outgoing.client.login(outgoing.auth, mailSendCallback);
139
+ }
140
+ else {
141
+ mailSendCallback(err);
142
+ }
143
+ };
144
+ outgoing.client.connect(mailConnectCallback);
145
+ }
146
+ // Fallback to the object if the address key isn't defined
147
+ function getAddressFromAddressObject(addressObj) {
148
+ return typeof addressObj.address !== "undefined" ? addressObj.address : addressObj;
149
+ }
150
+ function getAutoRelayableRecipients(recipients, rules) {
151
+ return recipients.filter(function (email) {
152
+ return validateAutoRelayRules(email, rules);
153
+ });
154
+ }
155
+ function validateAutoRelayRules(email, rules) {
156
+ return rules.reduce(function (result, rule) {
157
+ const toMatch = rule.allow || rule.deny || "";
158
+ const isMatch = wildstring.match(toMatch, email);
159
+ // Override previous rule if it matches
160
+ return isMatch ? !!rule.allow : result;
161
+ }, true);
162
+ }
@@ -0,0 +1,2 @@
1
+ import { MailServer } from "./mailserver";
2
+ export declare function routes(app: any, mailserver: MailServer, basePathname: string): void;
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.routes = routes;
4
+ /**
5
+ * MailDev - routes
6
+ */
7
+ const express = require("express");
8
+ const compression = require("compression");
9
+ const pkg = require("../../package.json");
10
+ const { filterEmails } = require("./utils");
11
+ const emailRegexp = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
12
+ function routes(app, mailserver, basePathname) {
13
+ const router = express.Router();
14
+ // Get all emails Enveloppe
15
+ router.get("/envelope", compression(), function (req, res) {
16
+ res.json(mailserver.getAllEnvelope());
17
+ });
18
+ // Get all emails
19
+ router.get("/email", compression(), function (req, res) {
20
+ mailserver
21
+ .getAllEmail()
22
+ .then((mails) => res.json(req.query ? filterEmails(mails, req.query) : mails))
23
+ .catch((err) => res.status(500).json({ error: err.message }));
24
+ });
25
+ // Get single email
26
+ router.get("/email/:id", function (req, res) {
27
+ mailserver
28
+ .getEmail(req.params.id)
29
+ .then((mail) => {
30
+ mail.envelope.isRead = true; // Mark the email as 'read'
31
+ res.json(mail);
32
+ })
33
+ .catch((err) => res.status(404).json({ error: err.message }));
34
+ });
35
+ // Read email
36
+ // router.patch('/email/:id/read', function (req, res) {
37
+ // mailserver.readEmail(req.params.id, function (err, email) {
38
+ // if (err) return res.status(500).json({ error: err.message })
39
+ // res.json(true)
40
+ // })
41
+ // })
42
+ // Read all emails
43
+ router.patch("/email/read-all", function (req, res) {
44
+ const count = mailserver.readAllEmail();
45
+ res.json(count);
46
+ });
47
+ // Delete all emails
48
+ router.delete("/email/all", function (req, res) {
49
+ mailserver
50
+ .deleteAllEmail()
51
+ .then((count) => res.json(count))
52
+ .catch((err) => res.status(500).json({ error: err.message }));
53
+ });
54
+ // Delete email by id
55
+ router.delete("/email/:id", function (req, res) {
56
+ mailserver
57
+ .deleteEmail(req.params.id)
58
+ .then((deleted) => res.json(deleted))
59
+ .catch((err) => res.status(500).json({ error: err.message }));
60
+ });
61
+ // Get Email HTML
62
+ router.get("/email/:id/html", function (req, res) {
63
+ // Use the headers over hostname to include any port
64
+ const baseUrl = req.headers.host + (req.baseUrl || "");
65
+ mailserver
66
+ .getEmailHTML(req.params.id, baseUrl)
67
+ .then((html) => res.send(html))
68
+ .catch((err) => res.status(404).json({ error: err.message }));
69
+ });
70
+ // Serve Attachments
71
+ router.get("/email/:id/attachment/:filename", function (req, res) {
72
+ mailserver
73
+ .getEmailAttachment(req.params.id, req.params.filename)
74
+ .then((attachement) => {
75
+ res.contentType(attachement.contentType);
76
+ res.send(attachement.content);
77
+ })
78
+ .catch((err) => res.status(404).json({ error: err.message }));
79
+ });
80
+ // Serve email.eml
81
+ router.get("/email/:id/download", function (req, res) {
82
+ mailserver
83
+ .getEmailEml(req.params.id)
84
+ .then(([contentType, filename, stream]) => {
85
+ res.setHeader("Content-disposition", "attachment; filename=" + filename);
86
+ res.contentType(contentType);
87
+ stream.pipe(res);
88
+ })
89
+ .catch((err) => res.status(404).json({ error: err.message }));
90
+ });
91
+ // Get email source from .eml file
92
+ router.get("/email/:id/source", function (req, res) {
93
+ mailserver
94
+ .getRawEmail(req.params.id)
95
+ .then((stream) => stream.pipe(res))
96
+ .catch((err) => res.status(404).json({ error: err.message }));
97
+ });
98
+ // Get any config settings for display
99
+ router.get("/config", function (req, res) {
100
+ res.json({
101
+ version: pkg.version,
102
+ smtpPort: mailserver.port,
103
+ isOutgoingEnabled: mailserver.isOutgoingEnabled(),
104
+ outgoingHost: mailserver.getOutgoingHost(),
105
+ });
106
+ });
107
+ // Relay the email
108
+ router.post("/email/:id/relay/:relayTo?", function (req, res) {
109
+ mailserver
110
+ .getEmail(req.params.id)
111
+ .then((mail) => {
112
+ if (req.params.relayTo) {
113
+ if (emailRegexp.test(req.params.relayTo)) {
114
+ mail.to = [{ address: req.params.relayTo, name: "" }];
115
+ mail.envelope.to = [{ address: req.params.relayTo, name: "" }];
116
+ }
117
+ else {
118
+ return res.status(400).json({
119
+ error: "Incorrect email address provided :" + req.params.relayTo,
120
+ });
121
+ }
122
+ }
123
+ return mailserver
124
+ .relayMail(mail, false)
125
+ .then(() => res.json(true))
126
+ .catch((err) => res.status(500).json({ error: err.message }));
127
+ })
128
+ .catch((err) => res.status(404).json({ error: err.message }));
129
+ });
130
+ // Health check
131
+ router.get("/healthz", function (req, res) {
132
+ res.json(true);
133
+ });
134
+ router.get("/reloadMailsFromDirectory", function (req, res) {
135
+ mailserver.loadMailsFromDirectory();
136
+ res.json(true);
137
+ });
138
+ app.use(basePathname, router);
139
+ }
@@ -0,0 +1,228 @@
1
+ import type * as MailParser from "mailparser";
2
+ /**
3
+ * Structured object for headers with arguments.
4
+ *
5
+ * `content-type: text/plain; CHARSET="UTF-8"` =>
6
+ * ```
7
+ * {
8
+ * "value": "text/plain",
9
+ * "params": {
10
+ * "charset": "UTF-8"
11
+ * }
12
+ * }
13
+ * ```
14
+ */
15
+ export interface StructuredHeader extends MailParser.StructuredHeader {
16
+ /**
17
+ * The main value.
18
+ */
19
+ value: string;
20
+ /**
21
+ * Additional arguments.
22
+ */
23
+ params: {
24
+ [key: string]: string;
25
+ };
26
+ }
27
+ /**
28
+ * Possible types of a header value.
29
+ */
30
+ export type HeaderValue = string[];
31
+ /**
32
+ * A Map object with lowercase header keys.
33
+ */
34
+ export type HeadersMap = Map<string, HeaderValue>;
35
+ /**
36
+ * Address object.
37
+ */
38
+ export interface AddressObject {
39
+ /**
40
+ * An array with address details.
41
+ */
42
+ value: EmailAddress[];
43
+ /**
44
+ * A formatted address string for HTML context.
45
+ */
46
+ html: string;
47
+ /**
48
+ * A formatted address string for plaintext context.
49
+ */
50
+ text: string;
51
+ }
52
+ /**
53
+ * Address details.
54
+ */
55
+ export interface EmailAddress {
56
+ /**
57
+ * The email address.
58
+ */
59
+ address: string;
60
+ /**
61
+ * The name part of the email/group.
62
+ */
63
+ name: string;
64
+ }
65
+ /**
66
+ * A Map object with lowercase header keys.
67
+ */
68
+ export type Headers = {
69
+ date: Date | undefined;
70
+ contentType: StructuredHeader | undefined;
71
+ contentDisposition: StructuredHeader | undefined;
72
+ dkimSignature: StructuredHeader[];
73
+ from: AddressObject | undefined;
74
+ to: AddressObject | undefined;
75
+ cc: AddressObject | undefined;
76
+ bcc: AddressObject | undefined;
77
+ sender: AddressObject | undefined;
78
+ replyTo: AddressObject | undefined;
79
+ deliveredTo: AddressObject | undefined;
80
+ dispositionNotificationTo: AddressObject | undefined;
81
+ received: string[];
82
+ priority: string | undefined;
83
+ headers: HeadersMap;
84
+ };
85
+ /**
86
+ * An array of raw header lines
87
+ */
88
+ export type HeaderLines = ReadonlyArray<{
89
+ key: string;
90
+ line: string;
91
+ }>;
92
+ /**
93
+ * COmmon part of the Attachment object.
94
+ */
95
+ export interface Attachment extends MailParser.Attachment {
96
+ /**
97
+ * Message type.
98
+ */
99
+ type: "attachment";
100
+ /**
101
+ * If true then this attachment should not be offered for download
102
+ * (at least not in the main attachments list).
103
+ */
104
+ related: boolean;
105
+ /**
106
+ * Attachment contents.
107
+ */
108
+ content: Buffer;
109
+ /**
110
+ * MIME type of the message.
111
+ */
112
+ contentType: string;
113
+ /**
114
+ * Content disposition type for the attachment,
115
+ * most probably `'attachment'`.
116
+ */
117
+ contentDisposition: string;
118
+ /**
119
+ * File name of the attachment.
120
+ */
121
+ filename?: string | undefined;
122
+ /**
123
+ * A Map value that holds MIME headers for the attachment node.
124
+ */
125
+ headers: HeadersMap;
126
+ /**
127
+ * An array of raw header lines for the attachment node.
128
+ */
129
+ headerLines: HeaderLines;
130
+ /**
131
+ * A MD5 hash of the message content.
132
+ */
133
+ checksum: string;
134
+ /**
135
+ * Message size in bytes.
136
+ */
137
+ size: number;
138
+ /**
139
+ * The header value from `Content-ID`.
140
+ */
141
+ contentId?: string | undefined;
142
+ /**
143
+ * `contentId` without `<` and `>`.
144
+ */
145
+ cid?: string | undefined;
146
+ generatedFileName: string;
147
+ }
148
+ export interface ParsedMail {
149
+ /**
150
+ * An array of attachments.
151
+ */
152
+ attachments: Attachment[];
153
+ /**
154
+ * A Map object with lowercase header keys.
155
+ *
156
+ * - All address headers are converted into address objects.
157
+ * - `references` is a string if only a single reference-id exists or an
158
+ * array if multiple ids exist.
159
+ * - `date` value is a Date object.
160
+ */
161
+ headers: Headers;
162
+ /**
163
+ * An array of raw header lines
164
+ */
165
+ headerLines: HeaderLines;
166
+ /**
167
+ * The HTML body of the message.
168
+ *
169
+ * Sets to `false` when there is no HTML body.
170
+ *
171
+ * If the message included embedded images as cid: urls then these are all
172
+ * replaced with base64 formatted data: URIs.
173
+ */
174
+ html: string | false;
175
+ /**
176
+ * The plaintext body of the message.
177
+ */
178
+ text?: string | undefined;
179
+ /**
180
+ * The plaintext body of the message formatted as HTML.
181
+ */
182
+ textAsHtml?: string | undefined;
183
+ /**
184
+ * The subject line.
185
+ */
186
+ subject?: string | undefined;
187
+ /**
188
+ * An array of referenced Message-ID values.
189
+ */
190
+ references: string[];
191
+ /**
192
+ * A Date object for the `Date:` header.
193
+ */
194
+ date: Date;
195
+ to: EmailAddress[];
196
+ from: EmailAddress[];
197
+ cc: EmailAddress[];
198
+ bcc: EmailAddress[];
199
+ replyTo: EmailAddress[];
200
+ /**
201
+ * The In-Reply-To value string.
202
+ */
203
+ inReplyTo: string[];
204
+ /**
205
+ * The Message-ID value string.
206
+ */
207
+ messageId?: string | undefined;
208
+ /**
209
+ * Priority of the e-mail.
210
+ */
211
+ priority: "normal" | "low" | "high";
212
+ }
213
+ export interface Envelope {
214
+ id: string;
215
+ from: EmailAddress[];
216
+ to: EmailAddress[];
217
+ date: Date;
218
+ subject?: string | undefined;
219
+ hasAttachment: boolean;
220
+ isRead: boolean;
221
+ }
222
+ export interface Mail extends ParsedMail {
223
+ id: string;
224
+ calculatedBcc: EmailAddress[];
225
+ size: number;
226
+ sizeHuman: string;
227
+ envelope: Envelope;
228
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export declare function makeId(): string;
2
+ export declare function formatBytes(bytes: number, decimals?: number): string;
3
+ export declare function filterEmails(emails: string[], query: any): string[];
4
+ export declare function delay(ms: any): Promise<void>;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeId = makeId;
4
+ exports.formatBytes = formatBytes;
5
+ exports.filterEmails = filterEmails;
6
+ exports.delay = delay;
7
+ // Create an unique id, length 8 characters
8
+ function makeId() {
9
+ let text = "";
10
+ const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
11
+ for (let i = 0; i < 8; i++) {
12
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
13
+ }
14
+ return text;
15
+ }
16
+ // Format bytes
17
+ // Source: https://stackoverflow.com/a/18650828/3143704
18
+ function formatBytes(bytes, decimals = 2) {
19
+ if (bytes === 0)
20
+ return "0 bytes";
21
+ const k = 1024;
22
+ const dm = decimals < 0 ? 0 : decimals;
23
+ const sizes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
24
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
25
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
26
+ }
27
+ function lookup(obj, path) {
28
+ const parts = path.split(".");
29
+ const base = obj[parts[0]];
30
+ if (!base)
31
+ return;
32
+ if (parts.length === 1) {
33
+ return base;
34
+ }
35
+ const next = parts.slice(1).join(".");
36
+ if (Array.isArray(base)) {
37
+ return base.map((el) => {
38
+ return lookup(el, next);
39
+ });
40
+ }
41
+ else {
42
+ return lookup(base, next);
43
+ }
44
+ }
45
+ function filterEmails(emails, query) {
46
+ return emails.filter((email) => {
47
+ const hits = [];
48
+ for (const key in query) {
49
+ if (Object.hasOwnProperty.call(query, key)) {
50
+ const element = query[key];
51
+ const value = lookup(email, key);
52
+ if (Array.isArray(value)) {
53
+ hits.push(value.includes(element));
54
+ }
55
+ else {
56
+ hits.push(value === element);
57
+ }
58
+ }
59
+ }
60
+ return !hits.includes(false);
61
+ });
62
+ }
63
+ function delay(ms) {
64
+ return new Promise((resolve) => setTimeout(resolve, ms));
65
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * MailDev - web
3
+ */
4
+ import { MailServer } from "./mailserver";
5
+ export interface WebOptions {
6
+ port?: number;
7
+ host?: string;
8
+ basePathname?: string;
9
+ auth?: {
10
+ user: string;
11
+ pass: string;
12
+ };
13
+ ssl?: {
14
+ cert: string;
15
+ key: string;
16
+ };
17
+ }
18
+ export declare class Web {
19
+ protocol: string;
20
+ port: number;
21
+ host: string;
22
+ basePathname: string;
23
+ /**
24
+ * Keep record of all connections to close them on shutdown
25
+ */
26
+ connections: {};
27
+ server: any;
28
+ io: any;
29
+ constructor(mailserver: MailServer, options?: WebOptions);
30
+ listen(): Promise<void>;
31
+ close(): Promise<void>;
32
+ }