test-smtp-server 0.9.0

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Chris. Webster
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Test SMTP Server
2
+
3
+ Test SMTP Server is a lightweight wrapper for
4
+ [smtp-server](<https://nodemailer.com/extras/smtp-server/>).
5
+ It is primarily intended for development and testing. The test code can start the server, run email tests and then validate the email contents. It can replace the use of external fake SMTP services which may have availablility issues.
6
+
7
+ All received emails are stored in an array. The emails may be viewed as raw data or a parsed object that is easily examined.
8
+
9
+ ## Getting Started
10
+
11
+ ### Prerequisites
12
+
13
+ Tested on Node v16 with npm v7.
14
+
15
+ ### Installation
16
+
17
+ ```sh
18
+ npm install test-smtp-server --save-dev
19
+ ```
20
+
21
+ ### Usage
22
+
23
+ See [test code](https://github.com/webstech/test-smtp-server/test/index.ts) for an example.
24
+
25
+ ```js
26
+ import { testSmtpServer } from "test-smtp-server";
27
+
28
+ (async (): Promise<void> => {
29
+ const smtpserver = new testSmtpServer();
30
+ await smtpserver.startServer(); // start listening
31
+
32
+ // send some emails capturing ids ..
33
+ messageId.unshift( await sendMail(email, smtpOptions));
34
+
35
+ const mails = smtpserver.getEmails();
36
+
37
+ // validate/dump emails
38
+
39
+ if (mails.length) {
40
+ let entry = 0;
41
+ for (const mail of mails) {
42
+ console.log(`Checking mail entry <${entry}>`);
43
+ console.log(mail.envelope);
44
+ const parsed = await mail.getParsed();
45
+ if (parsed.messageId !== messageId[entry]) {
46
+ throw new Error(`Messageids do not match for email ${
47
+ entry} <${parsed.messageId}> <${messageId[entry]}>`);
48
+ }
49
+
50
+ console.log(parsed);
51
+ entry++;
52
+ }
53
+ } else {
54
+ throw new Error("No emails captured when expected");
55
+ }
56
+
57
+ await smtpserver.stopServer(); // terminate server
58
+ ```
59
+
60
+ ### Security
61
+
62
+ The server is started as secure but that may not be possibly in the tesing
63
+ environment. If the server does not have a valid certificate, the connection
64
+ will fail from the client side. Some clients (e.g. nodemailer/SMTP-Transport options)
65
+ allow connections to non-secure servers. Node allows connections through an
66
+ environment variable that turns off certificate authorization chaecking. See
67
+ [node_tls_reject_unauthorizedvalue](https://nodejs.org/api/cli.html#node_tls_reject_unauthorizedvalue)
68
+ for more information. This may be insecure if other ports are used.
69
+
70
+ ## License
71
+
72
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
@@ -0,0 +1,66 @@
1
+ /// <reference types="node" />
2
+ import { SMTPServerEnvelope } from "smtp-server";
3
+ import { ParsedMail } from "mailparser";
4
+ /**
5
+ * Class to describe an email. The `envelope` contains the SMTP routing
6
+ * information. This may not match the `to/cc/bcc` information in the
7
+ * email contaents. The buffer contains the raw email content. To easily
8
+ * access parts of the email, `getParsed` should be used.
9
+ */
10
+ export declare class eMail {
11
+ envelope: SMTPServerEnvelope;
12
+ buffer: Buffer | null;
13
+ length: number;
14
+ constructor(envelope: SMTPServerEnvelope, buffer: Buffer);
15
+ /**
16
+ * Return a parsed email as formatted by `simpleParser`.
17
+ *
18
+ * @returns Promise<ParsedMail> See
19
+ * https://nodemailer.com/extras/mailparser/ for the structure.
20
+ */
21
+ getParsed(): Promise<ParsedMail>;
22
+ }
23
+ /**
24
+ * testSmtpServer optional parameters
25
+ */
26
+ export declare type testSmtpServerOptions = {
27
+ /** the port number to use (default: 1025) */
28
+ smtpPort?: number;
29
+ /** logging function like console.log() */
30
+ debug?: (message?: unknown, ...optionalParams: any[]) => void;
31
+ };
32
+ /**
33
+ * Create a testSmtpServer. This provides a wrapper to SMTPServer that
34
+ * can be used for testing. The emails are stored in an array that
35
+ * can be examined to validate the content.
36
+ */
37
+ export declare class testSmtpServer {
38
+ private debug;
39
+ private emails;
40
+ private isDebugging;
41
+ private port;
42
+ private server;
43
+ constructor(options?: testSmtpServerOptions | undefined);
44
+ /**
45
+ * Clear the set of emails.
46
+ *
47
+ * @returns number of emails deleted
48
+ */
49
+ clearEmails(): number;
50
+ /**
51
+ * Retrieve the set of emails in order from latest to oldest.
52
+ *
53
+ * @returns array of eMail objects
54
+ */
55
+ getEmails(): eMail[];
56
+ /**
57
+ * Query for the port number used by the server.
58
+ *
59
+ * @returns the port number being used
60
+ */
61
+ getPort(): number;
62
+ /** Start the server */
63
+ startServer(): void;
64
+ /** Stop the server */
65
+ stopServer(): void;
66
+ }
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.testSmtpServer = exports.eMail = void 0;
4
+ const smtp_server_1 = require("smtp-server");
5
+ const mailparser_1 = require("mailparser");
6
+ const stream_1 = require("stream");
7
+ /**
8
+ * Class to describe an email. The `envelope` contains the SMTP routing
9
+ * information. This may not match the `to/cc/bcc` information in the
10
+ * email contaents. The buffer contains the raw email content. To easily
11
+ * access parts of the email, `getParsed` should be used.
12
+ */
13
+ class eMail {
14
+ constructor(envelope, buffer) {
15
+ this.buffer = null;
16
+ this.length = 0;
17
+ this.envelope = envelope;
18
+ this.buffer = buffer;
19
+ }
20
+ /**
21
+ * Return a parsed email as formatted by `simpleParser`.
22
+ *
23
+ * @returns Promise<ParsedMail> See
24
+ * https://nodemailer.com/extras/mailparser/ for the structure.
25
+ */
26
+ async getParsed() {
27
+ if (this.buffer) {
28
+ const stream = stream_1.Readable.from(this.buffer);
29
+ const options = {
30
+ skipHtmlToText: true,
31
+ skipTextLinks: true,
32
+ skipTextToHtml: true
33
+ };
34
+ return (0, mailparser_1.simpleParser)(stream, options);
35
+ }
36
+ else {
37
+ throw new Error("Empty email buffer");
38
+ }
39
+ }
40
+ }
41
+ exports.eMail = eMail;
42
+ /**
43
+ * Create a testSmtpServer. This provides a wrapper to SMTPServer that
44
+ * can be used for testing. The emails are stored in an array that
45
+ * can be examined to validate the content.
46
+ */
47
+ class testSmtpServer {
48
+ constructor(options) {
49
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
50
+ this.debug = (_message, ..._optionalParams) => { };
51
+ this.emails = [];
52
+ this.isDebugging = false;
53
+ this.port = 1025;
54
+ if (options) {
55
+ if (options.smtpPort) {
56
+ this.port = options.smtpPort;
57
+ }
58
+ if (options.debug) {
59
+ this.debug = options.debug;
60
+ }
61
+ }
62
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
63
+ const that = this; // preserve for use in other objects
64
+ this.server = new smtp_server_1.SMTPServer({
65
+ authOptional: true,
66
+ onConnect(session, callback) {
67
+ if (session.remoteAddress !== "127.0.0.1") {
68
+ return callback(new Error("Only connections from localhost allowed"));
69
+ }
70
+ return callback(); // Accept the connection
71
+ },
72
+ onAuth(auth, _session, callback) {
73
+ that.debug(`SMTP login for user: ${auth.username}`);
74
+ callback(null, { user: auth.username });
75
+ },
76
+ onData(stream, session, callback) {
77
+ const buffers = [];
78
+ const writer = new stream_1.Writable({
79
+ write(data, _encoding, writerCallback) {
80
+ buffers.push(data);
81
+ writerCallback();
82
+ },
83
+ });
84
+ stream.pipe(writer);
85
+ stream.on("end", () => {
86
+ const buffer = Buffer.concat(buffers);
87
+ const email = new eMail(session.envelope, buffer);
88
+ that.emails.unshift(email);
89
+ if (that.isDebugging) {
90
+ that.debug(JSON.stringify(email, (key, value) => {
91
+ if ("buffer" === key) {
92
+ return buffer.toString();
93
+ }
94
+ else {
95
+ return value;
96
+ }
97
+ }, 2));
98
+ }
99
+ callback();
100
+ });
101
+ },
102
+ secure: true,
103
+ });
104
+ }
105
+ /**
106
+ * Clear the set of emails.
107
+ *
108
+ * @returns number of emails deleted
109
+ */
110
+ clearEmails() {
111
+ const count = this.emails.length;
112
+ this.emails.length = 0;
113
+ return count;
114
+ }
115
+ /**
116
+ * Retrieve the set of emails in order from latest to oldest.
117
+ *
118
+ * @returns array of eMail objects
119
+ */
120
+ getEmails() {
121
+ return this.emails;
122
+ }
123
+ /**
124
+ * Query for the port number used by the server.
125
+ *
126
+ * @returns the port number being used
127
+ */
128
+ getPort() {
129
+ return this.port;
130
+ }
131
+ /** Start the server */
132
+ startServer() {
133
+ this.server.listen(this.port);
134
+ }
135
+ /** Stop the server */
136
+ stopServer() {
137
+ this.server.close();
138
+ }
139
+ }
140
+ exports.testSmtpServer = testSmtpServer;
141
+ //# sourceMappingURL=test-smtp-server.js.map
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "test-smtp-server",
3
+ "version": "0.9.0",
4
+ "description": "The test-smtp-server package allows internal testing of projects needing an SMTP server.",
5
+ "main": "./build/lib/test-smtp-server.js",
6
+ "xtype": "module",
7
+ "types": "./build/lib/test-smtp-server.d.ts",
8
+ "directories": {
9
+ "lib": "lib",
10
+ "test": "test"
11
+ },
12
+ "files": [
13
+ "/build/lib/test-smtp-server.js",
14
+ "/build/lib/test-smtp-server.d.ts"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "lint": "eslint --ignore-path .gitignore -c .eslintrc.js --ext .ts,.js \"{lib,test}/**/*.{ts,tsx,mjs,js}\"",
19
+ "test": "npm run test:ts && npm run test:js",
20
+ "test:ts": "node build/test/index.js",
21
+ "test:js": "node test/jstest.mjs"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/webstech/test-smtp-server/issues"
25
+ },
26
+ "homepage": "https://github.com/webstech/test-smtp-server#readme",
27
+ "keywords": [
28
+ "smtp",
29
+ "development",
30
+ "test",
31
+ "fake",
32
+ "dummy",
33
+ "mock",
34
+ "faux",
35
+ "email",
36
+ "e-mail",
37
+ "automated",
38
+ "integration",
39
+ "ci"
40
+ ],
41
+ "author": "Chris. Webster <chris@webstech.net> (https://www.webstech.com/)",
42
+ "license": "MIT",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/webstech/test-smtp-server"
46
+ },
47
+ "devDependencies": {
48
+ "@types/nodemailer": "^6.4.4",
49
+ "@types/smtp-server": "^3.5.7",
50
+ "@typescript-eslint/eslint-plugin": "^5.1.0",
51
+ "@typescript-eslint/parser": "^5.1.0",
52
+ "commander": "^8.3.0",
53
+ "eslint": "^8.2.0",
54
+ "eslint-config-prettier": "^8.3.0",
55
+ "eslint-plugin-jsdoc": "^37.0.0",
56
+ "nodemailer": "^6.7.0",
57
+ "typescript": "^4.4.4"
58
+ },
59
+ "dependencies": {
60
+ "@types/mailparser": "^3.4.0",
61
+ "mailparser": "^3.4.0",
62
+ "smtp-server": "^3.9.0"
63
+ },
64
+ "engines": {
65
+ "node": ">= 16.0.0"
66
+ }
67
+ }