Skip to content

Commit bcab236

Browse files
committed
deps: remove nodemailer from koru
Clients need to integrate their own email solutuions. The interface is directly compatible with nodemailer.
1 parent 5359e79 commit bcab236

File tree

6 files changed

+168
-209
lines changed

6 files changed

+168
-209
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ See [Getting started](doc/getting-started.md) and [Koru API documentation](https
99

1010
The MIT License (MIT)
1111

12-
Copyright (c) 2014-2025 Geoff Jacobsen <geoffjacobsen@gmail.com>
12+
Copyright (c) 2014-2026 Geoff Jacobsen <geoffjacobsen@gmail.com>
1313

1414
Permission is hereby granted, free of charge, to any person obtaining a copy
1515
of this software and associated documentation files (the "Software"), to deal

app/koru/email-test.js

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ isServer && define((require, exports, module) => {
22
'use strict';
33
const TH = require('koru/test-helper');
44
const util = require('koru/util');
5-
const NodeMailer = requirejs.nodeRequire('nodemailer');
6-
const SmtpStub = requirejs.nodeRequire('nodemailer-stub-transport');
75
const stream = require('stream');
86
const nodeUtil = requirejs.nodeRequire('util');
97

@@ -23,49 +21,33 @@ isServer && define((require, exports, module) => {
2321
});
2422

2523
test('send', async () => {
26-
Email._transport = {
24+
Email.initPool({
2725
sendMail(options, callback) {
2826
v.sendOpts = options;
2927
callback();
3028
},
31-
};
29+
});
3230
await Email.send(v.options = {from: 'foo@vimaly.com'});
3331

3432
assert.same(v.sendOpts, v.options);
3533
});
3634

37-
test('initPool to stub', async () => {
38-
const stub = SmtpStub();
39-
let logCount = 0;
40-
stub.on('log', function (info) {
41-
++logCount;
42-
if (info.type === 'envelope') v.info = info;
43-
});
35+
test('stubPool', async () => {
36+
stub(console, 'log');
4437

45-
Email.initPool(stub);
46-
await Email.send(v.options = {
38+
Email.stubPool();
39+
await Email.send({
4740
from: 'foo@vimaly.com',
4841
to: 'bar@vimaly.com',
4942
subject: 'The subject',
5043
text: 'The text body',
5144
});
5245

53-
assert.same(logCount, 5);
54-
assert.equals(JSON.parse(v.info.message), {
55-
from: 'foo@vimaly.com', to: ['bar@vimaly.com']});
56-
});
57-
58-
test('initPool to url', () => {
59-
stub(NodeMailer, 'createTransport');
60-
61-
Email.initPool('smtp://foo:bar@vimaly.com:465');
62-
63-
assert.calledOnceWith(NodeMailer.createTransport, {
64-
pool: true,
65-
port: 465, host: 'vimaly.com',
66-
auth: {user: 'foo', pass: 'bar'},
67-
secure: false, requireTLS: true,
68-
});
46+
assert.calledOnce(console.log);
47+
assert.equals(
48+
console.log.firstCall.args[0],
49+
'Email Stub:\nTo: bar@vimaly.com\nFrom: foo@vimaly.com\nSubject: The subject\n======== Text ===========\nThe text body\n======== HTML ===========\nundefined\n======== EOM ============',
50+
);
6951
});
7052
});
7153
});

app/koru/email.js

Lines changed: 26 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,34 @@
11
define((require) => {
22
'use strict';
3-
const Future = require('koru/future');
4-
const NodeMailer = requirejs.nodeRequire('nodemailer');
5-
const SmtpStub = requirejs.nodeRequire('nodemailer-stub-transport');
6-
const urlModule = requirejs.nodeRequire('url');
7-
83
const Email = {
9-
send: (options) => new Promise((resolve) => {Email._transport.sendMail(options, resolve)}),
10-
11-
initPool(urlOrTransport) {
12-
if (typeof urlOrTransport === 'string') {
13-
const mailUrl = urlModule.parse(urlOrTransport);
14-
if (mailUrl.protocol !== 'smtp:') {
15-
throw new Error("Email protocol must be 'smtp'");
16-
}
17-
18-
const port = +(mailUrl.port);
19-
let auth = false;
20-
if (mailUrl.auth) {
21-
const parts = mailUrl.auth.split(':', 2);
22-
auth = {user: parts[0] && decodeURIComponent(parts[0]),
23-
pass: parts[1] && decodeURIComponent(parts[1])};
24-
}
4+
send: (options) =>
5+
new Promise((resolve) => {
6+
Email._transport.sendMail(options, resolve);
7+
}),
8+
9+
initPool(transport) {
10+
if (typeof transport.sendMail !== 'function') {
11+
throw new Error('Invalid email transport');
12+
}
2513

26-
Email._transport = NodeMailer.createTransport({
27-
pool: true,
28-
port: port || 25,
29-
host: mailUrl.hostname || 'localhost',
30-
secure: false,
31-
requireTLS: port == 465,
32-
auth,
33-
});
34-
} else {
35-
if (urlOrTransport === undefined) {
36-
urlOrTransport = SmtpStub();
14+
Email._transport = transport;
15+
},
3716

38-
urlOrTransport.on('log', (info) => {
39-
switch (info.type) {
40-
case 'message':
41-
console.log(info.message
42-
.replace(/=([A-F0-9]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
43-
.replace(/=\r\n/g, '').replace(/\r\n/g, '\n'));
44-
break;
45-
default:
46-
console.log('====== Email ======');
47-
}
48-
});
49-
}
50-
Email._transport = NodeMailer.createTransport(urlOrTransport);
51-
}
17+
stubPool() {
18+
Email.initPool({
19+
sendMail(options, callback) {
20+
console.log(`Email Stub:
21+
To: ${options.to}
22+
From: ${options.from}
23+
Subject: ${options.subject}
24+
======== Text ===========
25+
${options.text}
26+
======== HTML ===========
27+
${options.html}
28+
======== EOM ============`);
29+
callback();
30+
},
31+
});
5232
},
5333

5434
/** private */

0 commit comments

Comments
 (0)