@timshel_npm/maildev 3.1.4 → 3.2.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/README.md CHANGED
@@ -30,8 +30,8 @@ Or can be installed using [Github](https://docs.npmjs.com/cli/v10/configuring-np
30
30
  Ex:
31
31
  ```json
32
32
  "devDependencies": {
33
- "maildev": "github:timshel/maildev#3.1.4",
34
- "maildev": "npm:@timshel_npm/maildev@^3.1.4"
33
+ "maildev": "github:timshel/maildev#3.2.1",
34
+ "maildev": "npm:@timshel_npm/maildev@^3.2.1"
35
35
  }
36
36
  ```
37
37
 
package/dist/index.js CHANGED
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MailDev = void 0;
4
4
  const mailserver_1 = require("./lib/mailserver");
5
5
  const web_1 = require("./lib/web");
6
- const async = require("async");
7
6
  const logger = require("./lib/logger");
8
7
  class MailDev extends mailserver_1.MailServer {
9
8
  constructor(config, mailEventSubjectMapper) {
@@ -160,7 +160,7 @@ function generateFileNames(fileNames, fileName, contentType) {
160
160
  let ext;
161
161
  let defaultExt = "";
162
162
  if (contentType) {
163
- const ext = mime.extension(contentType); // renamed as getExtension in > 2.0
163
+ const ext = mime.getExtension(contentType);
164
164
  defaultExt = ext ? "." + ext : "";
165
165
  }
166
166
  fileName = fileName || "attachment" + defaultExt;
@@ -226,7 +226,7 @@ class MailServer {
226
226
  return elt.id === id;
227
227
  });
228
228
  if (envelope) {
229
- return getDiskEmail(this.mailDir, envelope.id, envelope).then((mail) => {
229
+ return getDiskEmail(this.mailDir, envelope.id).then((mail) => {
230
230
  if (mail.html) {
231
231
  // sanitize html
232
232
  const window = new JSDOM("").window;
@@ -390,7 +390,7 @@ class MailServer {
390
390
  const saved = files.map(function (file) {
391
391
  return __awaiter(this, void 0, void 0, function* () {
392
392
  const id = path.parse(file).name;
393
- const email = yield getDiskEmail(self.mailDir, id, undefined);
393
+ const email = yield getDiskEmail(self.mailDir, id);
394
394
  return saveEmailToStore(self, email);
395
395
  });
396
396
  });
@@ -417,29 +417,27 @@ function createMailDir(mailDir) {
417
417
  fs.mkdirSync(mailDir, { recursive: true });
418
418
  logger.info("MailDev using directory %s", mailDir);
419
419
  }
420
- function getDiskEmail(mailDir, id, envelope) {
420
+ function getDiskEmail(mailDir, id) {
421
421
  return __awaiter(this, void 0, void 0, function* () {
422
422
  const emlPath = path.join(mailDir, id + ".eml");
423
423
  const data = yield fs_1.promises.readFile(emlPath, "utf8");
424
424
  const parsedMail = yield (0, mailparser_1.parse)(data);
425
- if (envelope === undefined) {
426
- envelope = {
427
- id: id,
428
- from: parsedMail.from,
429
- to: parsedMail.to,
430
- date: parsedMail.date,
431
- subject: parsedMail.subject,
432
- hasAttachment: parsedMail.attachments.length > 0,
433
- isRead: false,
434
- };
435
- }
436
- return buildMail(mailDir, envelope, parsedMail);
425
+ return buildMail(mailDir, id, parsedMail);
437
426
  });
438
427
  }
439
- function buildMail(mailDir, envelope, parsedMail) {
428
+ function buildMail(mailDir, id, parsedMail) {
440
429
  return __awaiter(this, void 0, void 0, function* () {
441
- const emlPath = path.join(mailDir, envelope.id + ".eml");
430
+ const emlPath = path.join(mailDir, id + ".eml");
442
431
  const stat = yield fs_1.promises.stat(emlPath);
432
+ const envelope = {
433
+ id: id,
434
+ from: parsedMail.from,
435
+ to: parsedMail.to,
436
+ date: parsedMail.date,
437
+ subject: parsedMail.subject,
438
+ hasAttachment: parsedMail.attachments.length > 0,
439
+ isRead: false,
440
+ };
443
441
  return Object.assign({ id: envelope.id, envelope, calculatedBcc: (0, bcc_1.calculateBcc)(envelope.to, parsedMail.to, parsedMail.cc), size: stat.size, sizeHuman: utils.formatBytes(stat.size) }, parsedMail);
444
442
  });
445
443
  }
@@ -482,16 +480,7 @@ function handleDataStream(mailServer, stream, session, callback) {
482
480
  });
483
481
  stream.pipe(emlStream);
484
482
  const parsed = yield (0, mailparser_1.parse)(stream);
485
- const envelope = {
486
- id: id,
487
- from: session.envelope.mailFrom,
488
- to: session.envelope.rcptTo,
489
- date: parsed.date,
490
- subject: parsed.subject,
491
- hasAttachment: parsed.attachments.length > 0,
492
- isRead: false,
493
- };
494
- const mail = yield buildMail(mailServer.mailDir, envelope, parsed);
483
+ const mail = yield buildMail(mailServer.mailDir, id, parsed);
495
484
  return saveEmailToStore(mailServer, mail);
496
485
  });
497
486
  }
@@ -58,7 +58,11 @@ const options = [
58
58
  ],
59
59
  ["--web-user <user>", "MAILDEV_WEB_USER", "HTTP user for GUI"],
60
60
  ["--web-pass <password>", "MAILDEV_WEB_PASS", "HTTP password for GUI"],
61
- ["--web-domain <path>", "MAILDEV_WEB_DOMAIN", "External domain name (used for socket CORS, \"*\" otherwise)"],
61
+ [
62
+ "--web-domain <path>",
63
+ "MAILDEV_WEB_DOMAIN",
64
+ 'External domain name (used for socket CORS, "*" otherwise)',
65
+ ],
62
66
  ["--base-pathname <path>", "MAILDEV_BASE_PATHNAME", "Base path for URLs"],
63
67
  ["--https", "MAILDEV_HTTPS", "Switch from http to https protocol", false],
64
68
  ["--https-key <file>", "MAILDEV_HTTPS_KEY", "The file path to the ssl private key"],
@@ -135,7 +139,7 @@ function cliOptions() {
135
139
  hide8BITMIME: ((_a = config === null || config === void 0 ? void 0 : config.hideExtensions) !== null && _a !== void 0 ? _a : []).includes("8BITMIME"),
136
140
  hidePIPELINING: ((_b = config === null || config === void 0 ? void 0 : config.hideExtensions) !== null && _b !== void 0 ? _b : []).includes("PIPELINING"),
137
141
  hideSMTPUTF8: ((_c = config === null || config === void 0 ? void 0 : config.hideExtensions) !== null && _c !== void 0 ? _c : []).includes("SMTPUTF8"),
138
- outgoing: (config === null || config === void 0 ? void 0 : config.autoRelay) || (config === null || config === void 0 ? void 0 : config.autoRelayRules)
142
+ outgoing: (config === null || config === void 0 ? void 0 : config.autoRelay) || (config === null || config === void 0 ? void 0 : config.autoRelayRules) || (config === null || config === void 0 ? void 0 : config.outgoingHost)
139
143
  ? {
140
144
  host: config === null || config === void 0 ? void 0 : config.outgoingHost,
141
145
  port: config === null || config === void 0 ? void 0 : config.outgoingPort,
@@ -1,9 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Outgoing = void 0;
4
- /**
5
- * MailDev - outgoing
6
- */
7
4
  const SMTPConnection = require("nodemailer/lib/smtp-connection");
8
5
  const async = require("async");
9
6
  const fs = require("fs");
@@ -98,17 +95,19 @@ function createClient(outgoing) {
98
95
  }
99
96
  function relayMail(outgoing, emailObject, emailStream, isAutoRelay, done) {
100
97
  if (isAutoRelay && outgoing.autoRelayAddress) {
101
- emailObject.to = [{ address: outgoing.autoRelayAddress }];
102
- emailObject.envelope.to = [{ address: outgoing.autoRelayAddress, args: false }];
98
+ emailObject.to = [{ address: outgoing.autoRelayAddress, name: "Auto-Relay" }];
99
+ emailObject.envelope.to = [{ address: outgoing.autoRelayAddress, name: "Auto-Relay" }];
103
100
  }
104
101
  let recipients = emailObject.envelope.to.map(getAddressFromAddressObject);
105
102
  if (isAutoRelay && outgoing.autoRelayRules) {
106
103
  recipients = getAutoRelayableRecipients(recipients, outgoing.autoRelayRules);
107
104
  }
108
- // Fail silently with auth relay mode on
109
105
  if (recipients.length === 0) {
110
106
  return done("Email had no recipients");
111
107
  }
108
+ if (emailObject.envelope.from.length === 0) {
109
+ return done("Email had no sender");
110
+ }
112
111
  const mailSendCallback = function (err) {
113
112
  if (err) {
114
113
  logger.error("Outgoing client login error: ", err);
@@ -116,13 +115,13 @@ function relayMail(outgoing, emailObject, emailStream, isAutoRelay, done) {
116
115
  }
117
116
  const sender = getAddressFromAddressObject(emailObject.envelope.from);
118
117
  outgoing.client.send({
119
- from: sender,
118
+ from: emailObject.envelope.from[0].address,
120
119
  to: recipients,
121
120
  }, emailStream, function (err) {
122
121
  outgoing.client.quit();
123
122
  createClient(outgoing);
124
123
  if (err) {
125
- logger.error("Mail Delivery Error: ", err);
124
+ logger.error("Mail Delivery Error: ", err, { sender, recipients });
126
125
  return done(err);
127
126
  }
128
127
  logger.log("Mail Delivered: ", emailObject.subject);
@@ -13,13 +13,13 @@ function routes(app, mailserver, basePathname) {
13
13
  const router = express.Router();
14
14
  // Get all emails Enveloppe
15
15
  router.get("/envelope", compression(), function (req, res) {
16
- res.json(mailserver.getAllEnvelope());
16
+ res.status(200).json(mailserver.getAllEnvelope());
17
17
  });
18
18
  // Get all emails
19
19
  router.get("/email", compression(), function (req, res) {
20
20
  mailserver
21
21
  .getAllEmail()
22
- .then((mails) => res.json(req.query ? filterEmails(mails, req.query) : mails))
22
+ .then((mails) => res.status(200).json(req.query ? filterEmails(mails, req.query) : mails))
23
23
  .catch((err) => res.status(500).json({ error: err.message }));
24
24
  });
25
25
  // Get single email
@@ -28,7 +28,7 @@ function routes(app, mailserver, basePathname) {
28
28
  .getEmail(req.params.id)
29
29
  .then((mail) => {
30
30
  mail.envelope.isRead = true; // Mark the email as 'read'
31
- res.json(mail);
31
+ res.status(200).json(mail);
32
32
  })
33
33
  .catch((err) => res.status(404).json({ error: err.message }));
34
34
  });
@@ -42,20 +42,20 @@ function routes(app, mailserver, basePathname) {
42
42
  // Read all emails
43
43
  router.patch("/email/read-all", function (req, res) {
44
44
  const count = mailserver.readAllEmail();
45
- res.json(count);
45
+ res.status(200).json(count);
46
46
  });
47
47
  // Delete all emails
48
48
  router.delete("/email/all", function (req, res) {
49
49
  mailserver
50
50
  .deleteAllEmail()
51
- .then((count) => res.json(count))
51
+ .then((count) => res.status(200).json(count))
52
52
  .catch((err) => res.status(500).json({ error: err.message }));
53
53
  });
54
54
  // Delete email by id
55
55
  router.delete("/email/:id", function (req, res) {
56
56
  mailserver
57
57
  .deleteEmail(req.params.id)
58
- .then((deleted) => res.json(deleted))
58
+ .then((deleted) => res.status(200).json(deleted))
59
59
  .catch((err) => res.status(500).json({ error: err.message }));
60
60
  });
61
61
  // Get Email HTML
@@ -64,7 +64,7 @@ function routes(app, mailserver, basePathname) {
64
64
  const baseUrl = req.headers.host + (req.baseUrl || "");
65
65
  mailserver
66
66
  .getEmailHTML(req.params.id, baseUrl)
67
- .then((html) => res.send(html))
67
+ .then((html) => res.status(200).send(html))
68
68
  .catch((err) => res.status(404).json({ error: err.message }));
69
69
  });
70
70
  // Serve Attachments
@@ -73,7 +73,7 @@ function routes(app, mailserver, basePathname) {
73
73
  .getEmailAttachment(req.params.id, req.params.filename)
74
74
  .then((attachement) => {
75
75
  res.contentType(attachement.contentType);
76
- res.send(attachement.content);
76
+ res.status(200).send(attachement.content);
77
77
  })
78
78
  .catch((err) => res.status(404).json({ error: err.message }));
79
79
  });
@@ -97,7 +97,7 @@ function routes(app, mailserver, basePathname) {
97
97
  });
98
98
  // Get any config settings for display
99
99
  router.get("/config", function (req, res) {
100
- res.json({
100
+ res.status(200).json({
101
101
  version: pkg.version,
102
102
  smtpPort: mailserver.port,
103
103
  isOutgoingEnabled: mailserver.isOutgoingEnabled(),
@@ -105,7 +105,7 @@ function routes(app, mailserver, basePathname) {
105
105
  });
106
106
  });
107
107
  // Relay the email
108
- router.post("/email/:id/relay/:relayTo?", function (req, res) {
108
+ router.post("/email/:id/relay{/:relayTo}", function (req, res) {
109
109
  mailserver
110
110
  .getEmail(req.params.id)
111
111
  .then((mail) => {
@@ -122,18 +122,18 @@ function routes(app, mailserver, basePathname) {
122
122
  }
123
123
  return mailserver
124
124
  .relayMail(mail, false)
125
- .then(() => res.json(true))
125
+ .then(() => res.status(200).json(true))
126
126
  .catch((err) => res.status(500).json({ error: err.message }));
127
127
  })
128
128
  .catch((err) => res.status(404).json({ error: err.message }));
129
129
  });
130
130
  // Health check
131
131
  router.get("/healthz", function (req, res) {
132
- res.json(true);
132
+ res.status(200).json(true);
133
133
  });
134
134
  router.get("/reloadMailsFromDirectory", function (req, res) {
135
135
  mailserver.loadMailsFromDirectory();
136
- res.json(true);
136
+ res.status(200).json(true);
137
137
  });
138
138
  app.use(basePathname, router);
139
139
  }
package/dist/lib/web.js CHANGED
@@ -33,11 +33,11 @@ class Web {
33
33
  app.use(auth((_d = options === null || options === void 0 ? void 0 : options.auth) === null || _d === void 0 ? void 0 : _d.user, (_e = options === null || options === void 0 ? void 0 : options.auth) === null || _e === void 0 ? void 0 : _e.pass));
34
34
  }
35
35
  this.io = socketio({
36
- path: path.posix.join(this.basePathname, '/socket.io'),
36
+ path: path.posix.join(this.basePathname, "/socket.io"),
37
37
  cors: {
38
- origin: (_f = options === null || options === void 0 ? void 0 : options.domain) !== null && _f !== void 0 ? _f : '*',
39
- methods: ["GET", "POST"]
40
- }
38
+ origin: (_f = options === null || options === void 0 ? void 0 : options.domain) !== null && _f !== void 0 ? _f : "*",
39
+ methods: ["GET", "POST"],
40
+ },
41
41
  });
42
42
  app.use(this.basePathname, express.static(path.join(__dirname, "../app")));
43
43
  app.use(cors());
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@timshel_npm/maildev",
3
3
  "description": "SMTP Server with async API and Web Interface for viewing and testing emails during development",
4
- "version": "3.1.4",
4
+ "version": "3.2.1",
5
5
  "keywords": [
6
6
  "email",
7
7
  "e-mail",
@@ -15,7 +15,7 @@
15
15
  "playwright"
16
16
  ],
17
17
  "author": "Timshel",
18
- "homepage": "https://github.com/timshel/maildev",
18
+ "homepage": "https://github.com/Timshel/maildev",
19
19
  "maintainers": [
20
20
  {
21
21
  "name": "Timshel",
@@ -24,7 +24,7 @@
24
24
  ],
25
25
  "repository": {
26
26
  "type": "git",
27
- "url": "https://github.com/timshel/maildev.git"
27
+ "url": "https://github.com/Timshel/maildev"
28
28
  },
29
29
  "scripts": {
30
30
  "clean": "rm -rf dist coverage tsconfig.tsbuildinfo",
@@ -58,16 +58,16 @@
58
58
  "@types/mailparser": "^3.4.6",
59
59
  "addressparser": "1.0.1",
60
60
  "async": "^3.2.6",
61
- "commander": "^12.1.0",
62
- "compression": "^1.8.0",
61
+ "commander": "^13.1.0",
62
+ "compression": "^1.8.1",
63
63
  "cors": "^2.8.5",
64
64
  "dompurify": "^3.2.6",
65
- "express": "^4.21.2",
66
- "jsdom": "^24.1.3",
67
- "mailparser": "^3.7.3",
68
- "mime": "1.6.0",
69
- "nodemailer": "^6.10.1",
70
- "smtp-server": "^3.13.8",
65
+ "express": "^5.1.0",
66
+ "jsdom": "^26.1.0",
67
+ "mailparser": "^3.7.4",
68
+ "mime": "^3.0.0",
69
+ "nodemailer": "^7.0.5",
70
+ "smtp-server": "^3.14.0",
71
71
  "socket.io": "^4.8.1",
72
72
  "wildstring": "1.0.9"
73
73
  },
@@ -76,19 +76,19 @@
76
76
  },
77
77
  "devDependencies": {
78
78
  "@types/express": "^4.17.23",
79
- "@types/node": "^18.19.112",
80
- "expect": "^29.7.0",
79
+ "@types/node": "^18.19.122",
80
+ "expect": "^30.0.3",
81
81
  "http-proxy-middleware": "^3.0.5",
82
- "jest": "^29.7.0",
83
- "jest-mock": "^29.7.0",
84
- "mocha": "^10.8.2",
82
+ "jest": "^30.0.5",
83
+ "jest-mock": "^30.0.2",
84
+ "mocha": "^11.7.1",
85
85
  "nodemon": "^3.1.10",
86
86
  "nyc": "^17.1.0",
87
87
  "prettier": "^3.6.2",
88
- "sass": "^1.89.2",
88
+ "sass": "^1.90.0",
89
89
  "ts-node": "^10.9.2",
90
90
  "ts-node-dev": "^2.0.0",
91
- "typescript": "^5.8.3"
91
+ "typescript": "^5.9.2"
92
92
  },
93
93
  "engines": {
94
94
  "node": ">=18.0.0"