mail-time 1.3.4 → 3.0.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 +1 -1
- package/README.md +520 -145
- package/adapters/blank-example.js +230 -0
- package/adapters/mongo.js +310 -0
- package/adapters/redis.js +302 -0
- package/helpers.js +11 -0
- package/index.cjs +1285 -0
- package/index.js +428 -383
- package/package.json +30 -11
- package/CHANGELOG.md +0 -1
- package/HISTORY.md +0 -1
package/README.md
CHANGED
|
@@ -1,39 +1,54 @@
|
|
|
1
1
|
[](https://github.com/sponsors/dr-dimitru)
|
|
2
2
|
[](https://paypal.me/veliovgroup)
|
|
3
|
-
<a href="https://ostr.io/info/built-by-developers-for-developers">
|
|
4
|
-
|
|
5
|
-
</a>
|
|
3
|
+
<a href="https://ostr.io/info/built-by-developers-for-developers?ref=github-mail-time-repo-top"><img src="https://ostr.io/apple-touch-icon-60x60.png" height="20"></a>
|
|
4
|
+
<a href="https://meteor-files.com/?ref=github-mail-time-repo-top"><img src="https://meteor-files.com/apple-touch-icon-60x60.png" height="20"></a>
|
|
6
5
|
|
|
7
6
|
# MailTime
|
|
8
7
|
|
|
9
|
-
"Mail-Time" is
|
|
8
|
+
"Mail-Time" is NPM package for mail queue management. Build on top of the [`nodemailer`](https://github.com/nodemailer/nodemailer) package. Mail-Time made for single-server and horizontally scaled multi-server setups in mind.
|
|
10
9
|
|
|
11
|
-
Every `MailTime` instance can
|
|
10
|
+
Every `MailTime` instance can have `type` configured as *Server* or *Client*. *Server* type of `MailTime` is great for creating an emailing micro-service app.
|
|
12
11
|
|
|
13
12
|
The main difference between *Server* and *Client* `type` is that the *Server* handles the queue and __sends__ email. While the *Client* only __adds__ emails into the queue.
|
|
14
13
|
|
|
15
14
|
## ToC
|
|
16
15
|
|
|
17
|
-
- [How it works?](https://github.com/veliovgroup/mail-time#how-it-works)
|
|
18
|
-
- [With single SMTP](https://github.com/veliovgroup/mail-time#single-point-of-failure)
|
|
19
|
-
- [With multiple SMTP](https://github.com/veliovgroup/mail-time#multiple-smtp-providers)
|
|
20
|
-
- [
|
|
21
|
-
- [Features](https://github.com/veliovgroup/mail-time#features)
|
|
22
|
-
- [Installation](https://github.com/veliovgroup/mail-time#installation)
|
|
16
|
+
- [How it works?](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#how-it-works)
|
|
17
|
+
- [With single SMTP](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#single-point-of-failure)
|
|
18
|
+
- [With multiple SMTP](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#multiple-smtp-providers)
|
|
19
|
+
- [For horizontally-scaled apps](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#sending-emails-from-cluster-of-servers)
|
|
20
|
+
- [Features](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#features)
|
|
21
|
+
- [Installation](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#installation)
|
|
23
22
|
- [Meteor.js usage](https://github.com/veliovgroup/mail-time/blob/master/docs/meteor.md)
|
|
24
|
-
- [Usage
|
|
25
|
-
- [
|
|
26
|
-
- [
|
|
27
|
-
- [
|
|
28
|
-
|
|
29
|
-
- [
|
|
30
|
-
- [
|
|
23
|
+
- [Usage examples](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#basic-usage)
|
|
24
|
+
- [Require/Import `mail-time`](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#1-require-package)
|
|
25
|
+
- [Create NodeMailer's transports](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#2-create-nodemailers-transports)
|
|
26
|
+
- [Initiate `mail-time`](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#3-initiate-mail-time)
|
|
27
|
+
- [Connect to Redis](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#3a-initiate-and-connect-to-redis)
|
|
28
|
+
- [Connect to MongoDB](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#3b-initiate-and-connect-to-mongodb)
|
|
29
|
+
- [Initiate as *Client* instance](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#3c-optionally-create-client-type-of-mailtime)
|
|
30
|
+
- [Initiate two `MailTime` instances within the single app](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#two-mailtime-instances-usage-example)
|
|
31
|
+
- [Use templates](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#passing-variables-to-the-template)
|
|
32
|
+
- Different storage configurations:
|
|
33
|
+
- [Use MongoDB for queue and scheduler](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#using-mongodb-for-queue-and-scheduler)
|
|
34
|
+
- [Use MongoDB for queue and Redis for scheduler](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#using-mongodb-for-queue-and-redis-for-scheduler)
|
|
35
|
+
- [Use Redis for queue and MongoDB for scheduler](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#using-redis-for-queue-and-mongodb-for-scheduler)
|
|
36
|
+
- [Use Redis for queue and scheduler](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#using-redis-for-queue-and-scheduler)
|
|
37
|
+
- [API](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#api)
|
|
38
|
+
- [`new MailTime` *Constructor*](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#new-mailtimeopts-constructor)
|
|
39
|
+
- [`new RedisQueue` *Constructor*](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#new-redisqueueopts-constructor)
|
|
40
|
+
- [`new MongoQueue` *Constructor*](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#new-mongoqueueopts-constructor)
|
|
41
|
+
- [`.sendMail()`](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#sendmailopts)
|
|
42
|
+
- [`.cancelMail()`](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#cancelmailuuid)
|
|
43
|
+
- [Default Template](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#static-mailtimetemplate)
|
|
44
|
+
- [Custom Templates](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#template-example)
|
|
45
|
+
- [Running tests](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#testing)
|
|
31
46
|
|
|
32
47
|
## Main features:
|
|
33
48
|
|
|
34
|
-
- 👨🔬 ~
|
|
49
|
+
- 👨🔬 ~94% tests coverage;
|
|
35
50
|
- 📦 Two simple dependencies, written from scratch for top performance;
|
|
36
|
-
- 🏢 Synchronize email queue across multiple servers;
|
|
51
|
+
- 🏢 Synchronize email queue across multiple (horizontally scaled) servers;
|
|
37
52
|
- 💪 Bulletproof design, built-in retries.
|
|
38
53
|
|
|
39
54
|
## How does it work?
|
|
@@ -42,7 +57,7 @@ Redundant solution for email transmission.
|
|
|
42
57
|
|
|
43
58
|
### Single point of failure
|
|
44
59
|
|
|
45
|
-
Issue -
|
|
60
|
+
Issue - mitigate a single point of failure via persistent queue and re-send attempts
|
|
46
61
|
|
|
47
62
|
```ascii
|
|
48
63
|
|----------------| |------| |------------------|
|
|
@@ -72,7 +87,7 @@ it will keep the letter in the queue and retry to send it again
|
|
|
72
87
|
|
|
73
88
|
### Multiple SMTP providers
|
|
74
89
|
|
|
75
|
-
|
|
90
|
+
Rotate email transports by using multiple SMTP providers. *MailTime* support two strategies `backup` (*rotate when failed*) and `balancer` (*round-robin rotation*)
|
|
76
91
|
|
|
77
92
|
```ascii
|
|
78
93
|
|--------|
|
|
@@ -88,43 +103,60 @@ Backup scheme with multiple SMTP providers
|
|
|
88
103
|
|--------|
|
|
89
104
|
```
|
|
90
105
|
|
|
91
|
-
###
|
|
106
|
+
### Sending emails from cluster of servers
|
|
92
107
|
|
|
93
|
-
It is common to
|
|
108
|
+
It is common to have horizontally scaled "Cluster" of servers for load-balancing and for durability.
|
|
94
109
|
|
|
95
|
-
Most modern application has scheduled or recurring emails. For example, once a day — with recent news and updates. It won't be an issue with a single server setup — the server would send emails at a daily interval via timer or CRON.
|
|
110
|
+
Most modern application has scheduled or recurring emails. For example, once a day — with recent news and updates. It won't be an issue with a single server setup — the server would send emails at a daily interval via timer or CRON. But in "Cluster" implementation — each server will attempt to send the same email. *MailTime* built to avoid sending the same email multiple times to a user from horizontally scaled applications.
|
|
96
111
|
|
|
97
|
-
|
|
112
|
+
For the maximum durability and agility each Application Server can run *MailTime* in the "Server" mode:
|
|
113
|
+
|
|
114
|
+
```ascii
|
|
115
|
+
|===================THE=CLUSTER===================| |=QUEUE=|
|
|
116
|
+
| |----------| |----------| |----------| | | | |--------|
|
|
117
|
+
| | App | | App | | App | | | |-->| SMTP 1 |------\
|
|
118
|
+
| | Server 1 | | Server 2 | | Server 3 | | | | |--------| \
|
|
119
|
+
| |-----\----| |----\-----| |----\-----| | | | |-------------|
|
|
120
|
+
| \---------------\----------------\----------> | |--------| | ^_^ |
|
|
121
|
+
| | | |-->| SMTP 2 |-->| Happy users |
|
|
122
|
+
| Each "App Server" | | | |--------| |-------------|
|
|
123
|
+
| runs MailTime as a "Server" | | | /
|
|
124
|
+
| for the maximum durability | | | |--------| /
|
|
125
|
+
| | | |-->| SMTP 3 |-----/
|
|
126
|
+
| | | | |--------|
|
|
127
|
+
|=================================================| |=======|
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
To split roles *MailTime* can run on a dedicated machine as micro-service. This case is great for private email servers with implemented authentication via rDNS and PTR records:
|
|
98
131
|
|
|
99
132
|
```ascii
|
|
100
133
|
|===================THE=CLUSTER===================| |=QUEUE=| |===Mail=Time===|
|
|
101
|
-
| |----------| |----------| |----------| | | |
|
|
102
|
-
| | App | | App | | App | | | | |
|
|
103
|
-
| | Server 1 | | Server 2 | | Server 3 | | |
|
|
104
|
-
| |-----\----| |----\-----| |----\-----| | |
|
|
105
|
-
| \---------------\----------------\----------> | |
|
|
106
|
-
|
|
|
107
|
-
|
|
|
108
|
-
|
|
|
109
|
-
|
|
|
110
|
-
|
|
|
111
|
-
|
|
|
134
|
+
| |----------| |----------| |----------| | | | | | |--------|
|
|
135
|
+
| | App | | App | | App | | | | | Micro-service |-->| SMTP 1 |------\
|
|
136
|
+
| | Server 1 | | Server 2 | | Server 3 | | | | | running | |--------| \
|
|
137
|
+
| |-----\----| |----\-----| |----\-----| | | | | MailTime as | |-------------|
|
|
138
|
+
| \---------------\----------------\----------> | | "Server" only | |--------| | ^_^ |
|
|
139
|
+
| | | | | sending |-->| SMTP 2 |-->| Happy users |
|
|
140
|
+
| Each "App Server" runs MailTime as | | | | emails | |--------| |-------------|
|
|
141
|
+
| a "Client" only placing emails to the queue. | | <-------- | /
|
|
142
|
+
| | | --------> | |--------| /
|
|
143
|
+
| | | | | |-->| SMTP 3 |-----/
|
|
144
|
+
| | | | | | |--------|
|
|
112
145
|
|=================================================| |=======| |===============|
|
|
113
146
|
```
|
|
114
147
|
|
|
115
148
|
## Features
|
|
116
149
|
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
123
|
-
- Templating support with [Mustache](https://mustache.github.io/)-like placeholders
|
|
150
|
+
- __Email Queue__ - Managed via MongoDB, Redis, or [Custom Queue](https://github.com/veliovgroup/mail-time/blob/master/docs/queue-api.md). Storage-based queue will survive server reboots and failures
|
|
151
|
+
- __Made for horizontally scaled multi-server setups__ - *MailTime* is made to run in multi-server environments, like "Clusters", multiple app instances, load balanced solutions, and replications. *MailTime* is the perfect fit for applications scaled on a single machine, multiple virtual servers, multiple "bare metal" servers, within single or multiple data centers
|
|
152
|
+
- __Email concatenation__ - Reduce amount of sent emails to a single user with concatenation, and avoid mistakenly duplicated emails. When "email concatenation" is enabled the same emails (*checked by addressee and content*) won't be sent twice. If emails are sent multiple times, due to issues in logic or application failures, - enable "email concatenation" to solve this behavior
|
|
153
|
+
- __Multiple NodeMailer/SMTP transports__ — Support for multiple SMPT transports implemented in two modes - `backup` and `balancing`. Use this feature to reduce the cost of SMTP services and add extra layer of durability. When one of the transports is failing to send an email — `mail-time` will switch to the next one
|
|
154
|
+
- __Sending retries__ — Built-in retries for failed to send emails due to network or other failures
|
|
155
|
+
- __Templating__ — Built with support of [Mustache](https://mustache.github.io/)-like placeholders, see [templating docs](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#passing-variables-to-the-template)
|
|
124
156
|
|
|
125
157
|
## Installation
|
|
126
158
|
|
|
127
|
-
To implement Server functionality —
|
|
159
|
+
To implement Server functionality — begin with installing `nodemailer`, although this package meant to be used with `nodemailer`, it's not added as the dependency, as `nodemailer` not needed by Client, and to give freedom to choose `nodemailer`'s version to fit every project needs:
|
|
128
160
|
|
|
129
161
|
```shell
|
|
130
162
|
npm install --save nodemailer
|
|
@@ -133,31 +165,57 @@ npm install --save nodemailer
|
|
|
133
165
|
Install *MailTime* package:
|
|
134
166
|
|
|
135
167
|
```shell
|
|
136
|
-
# for node@>=
|
|
168
|
+
# for node@>=14.20.0
|
|
137
169
|
npm install --save mail-time
|
|
138
170
|
|
|
171
|
+
# for node@<14.20.0
|
|
172
|
+
npm install --save mail-time@=1.3.4
|
|
173
|
+
|
|
139
174
|
# for node@<8.9.0
|
|
140
175
|
npm install --save mail-time@=0.1.7
|
|
141
176
|
```
|
|
142
177
|
|
|
143
178
|
## Basic usage
|
|
144
179
|
|
|
145
|
-
|
|
180
|
+
Setup Nodemailer's transports, Queue storage, and *MailTime* instance
|
|
181
|
+
|
|
182
|
+
### Steps to get started
|
|
183
|
+
|
|
184
|
+
See steps 1-4 below to learn about different parts of *MailTime* library and how it can get used. From configuration options to sending email
|
|
185
|
+
|
|
186
|
+
1. [Require `mail-time` package](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#1-require-package)
|
|
187
|
+
2. [Create NodeMailer's transports](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#2-create-nodemailers-transports)
|
|
188
|
+
3. [Initiate `mail-time` *server*](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#3-initiate-mail-time)
|
|
189
|
+
- a. [Connect to Redis](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#3a-initiate-and-connect-to-redis); Or
|
|
190
|
+
- b. [Connect to MongoDB](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#3b-initiate-and-connect-to-mongodb); And
|
|
191
|
+
- c. [*optionally*] [initiate `mail-time` as *client*](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#3c-optionally-create-client-type-of-mailtime)
|
|
192
|
+
4. [Start sending emails](https://github.com/veliovgroup/mail-time?tab=readme-ov-file#4-send-email)
|
|
193
|
+
|
|
194
|
+
#### 1. Require package
|
|
146
195
|
|
|
147
196
|
```js
|
|
148
|
-
|
|
197
|
+
// import as ES Module
|
|
198
|
+
import { MailTime, MongoQueue, RedisQueue } from 'mail-time';
|
|
199
|
+
|
|
200
|
+
// require as CommonJS
|
|
201
|
+
const { MailTime, MongoQueue, RedisQueue } = require('mail-time');
|
|
149
202
|
```
|
|
150
203
|
|
|
151
|
-
Create
|
|
204
|
+
#### 2. Create NodeMailer's transports
|
|
152
205
|
|
|
153
|
-
|
|
154
|
-
const transports = [];
|
|
155
|
-
const nodemailer = require('nodemailer');
|
|
206
|
+
For compatibility and flexibility *MailTime* has no dependency on `nodemailer` it should be installed and imported manually. Create one or more "SMTP transports" before initializing new *MailTime* instance.
|
|
156
207
|
|
|
208
|
+
For details and full list of options available in `.createTransport()` see [`nodemailer` docs](https://nodemailer.com/smtp/)
|
|
209
|
+
|
|
210
|
+
```js
|
|
211
|
+
// transports.js
|
|
212
|
+
import nodemailer from 'nodemailer';
|
|
157
213
|
// Use DIRECT transport
|
|
158
214
|
// and enable sending email from localhost
|
|
159
215
|
// install "nodemailer-direct-transport" NPM package:
|
|
160
|
-
|
|
216
|
+
import directTransport from 'nodemailer-direct-transport';
|
|
217
|
+
|
|
218
|
+
const transports = [];
|
|
161
219
|
const directTransportOpts = {
|
|
162
220
|
pool: false,
|
|
163
221
|
direct: true,
|
|
@@ -199,62 +257,123 @@ transports.push(nodemailer.createTransport({
|
|
|
199
257
|
pass: 'xxx'
|
|
200
258
|
},
|
|
201
259
|
}));
|
|
260
|
+
|
|
261
|
+
export { transports };
|
|
202
262
|
```
|
|
203
263
|
|
|
204
|
-
|
|
264
|
+
#### 3. Initiate `mail-time`
|
|
265
|
+
|
|
266
|
+
Create new instance of *MailTime* in the *Server* mode, — it will be able to __send__ and __add__ emails to the queue.
|
|
267
|
+
|
|
268
|
+
#### 3a. Initiate and connect to Redis
|
|
269
|
+
|
|
270
|
+
Connecting to Redis before initiating `new MailTime` instance:
|
|
205
271
|
|
|
206
272
|
```js
|
|
207
|
-
|
|
208
|
-
|
|
273
|
+
// mail-queue.js
|
|
274
|
+
import { MailTime, RedisQueue } from 'mail-time';
|
|
275
|
+
import { createClient } from 'redis';
|
|
276
|
+
import { transports } from './transports.js';
|
|
277
|
+
|
|
278
|
+
// Use REDIS_URL environment variable to store connection string to MongoDB
|
|
279
|
+
// example: "REDIS_URL=redis://127.0.0.1:6379/myapp node mail-micro-service.js"
|
|
280
|
+
const redisClient = await createClient({ url: process.env.REDIS_URL }).connect();
|
|
281
|
+
const mailQueue = new MailTime({
|
|
282
|
+
transports,
|
|
283
|
+
queue: new MongoQueue({
|
|
284
|
+
client: redisClient,
|
|
285
|
+
}),
|
|
286
|
+
josk: {
|
|
287
|
+
adapter: {
|
|
288
|
+
type: 'redis',
|
|
289
|
+
client: redisClient,
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
template: MailTime.Template // Use default template
|
|
293
|
+
from(transport) {
|
|
294
|
+
// To pass spam-filters `from` field should be correctly set
|
|
295
|
+
// for each transport, check `transport` object for more options
|
|
296
|
+
return `"Awesome App" <${transport.options.from}>`;
|
|
297
|
+
},
|
|
298
|
+
onError(error, email, details) {
|
|
299
|
+
console.log(`Email "${email.mailOptions.subject}" wasn't sent to ${email.mailOptions.to}`, error, details);
|
|
300
|
+
},
|
|
301
|
+
onSent(email, details) {
|
|
302
|
+
console.log(`Email "${email.mailOptions.subject}" successfully sent to ${email.mailOptions.to}`, details);
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
export { mailQueue };
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
#### 3b. Initiate and connect to MongoDB
|
|
209
310
|
|
|
210
|
-
|
|
311
|
+
Connecting to MongoDB before initiating `new MailTime` instance:
|
|
312
|
+
|
|
313
|
+
```js
|
|
314
|
+
// mail-queue.js
|
|
315
|
+
import { MailTime, MongoQueue } from 'mail-time';
|
|
316
|
+
import { MongoClient } from 'mongodb';
|
|
317
|
+
import { transports } from './transports.js';
|
|
211
318
|
|
|
212
319
|
// Use MONGO_URL environment variable to store connection string to MongoDB
|
|
213
320
|
// example: "MONGO_URL=mongodb://127.0.0.1:27017/myapp node mail-micro-service.js"
|
|
214
|
-
MongoClient.connect(process.env.MONGO_URL
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
db,
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
321
|
+
const mongodb = (await MongoClient.connect(process.env.MONGO_URL)).db('database');
|
|
322
|
+
const mailQueue = new MailTime({
|
|
323
|
+
transports,
|
|
324
|
+
queue: new MongoQueue({
|
|
325
|
+
db: mongodb,
|
|
326
|
+
}),
|
|
327
|
+
josk: {
|
|
328
|
+
adapter: {
|
|
329
|
+
type: 'mongo',
|
|
330
|
+
db: mongodb,
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
template: MailTime.Template // Use default template
|
|
334
|
+
from(transport) {
|
|
335
|
+
// To pass spam-filters `from` field should be correctly set
|
|
336
|
+
// for each transport, check `transport` object for more options
|
|
337
|
+
return `"Awesome App" <${transport.options.from}>`;
|
|
338
|
+
},
|
|
339
|
+
onError(error, email, details) {
|
|
340
|
+
console.log(`Email "${email.mailOptions.subject}" wasn't sent to ${email.mailOptions.to}`, error, details);
|
|
341
|
+
},
|
|
342
|
+
onSent(email, details) {
|
|
343
|
+
console.log(`Email "${email.mailOptions.subject}" successfully sent to ${email.mailOptions.to}`, details);
|
|
344
|
+
},
|
|
231
345
|
});
|
|
346
|
+
|
|
347
|
+
export { mailQueue };
|
|
232
348
|
```
|
|
233
349
|
|
|
234
|
-
|
|
350
|
+
#### 3c. Optionally create *Client* type of *MailTime*
|
|
235
351
|
|
|
236
|
-
|
|
237
|
-
const MailTime = require('mail-time');
|
|
238
|
-
const MongoClient = require('mongodb').MongoClient;
|
|
352
|
+
Only __one__ `MailTime` *Server* instance required to send email. In the other parts of an app (like UI units or in sub-apps) use `mail-time` in the *Client* mode to __add__ emails to queue
|
|
239
353
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
354
|
+
```js
|
|
355
|
+
// mail-queue.js
|
|
356
|
+
import { MailTime, RedisQueue } from 'mail-time';
|
|
357
|
+
import { createClient } from 'redis';
|
|
244
358
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
});
|
|
359
|
+
const mailQueue = new MailTime({
|
|
360
|
+
type: 'client',
|
|
361
|
+
queue: new RedisQueue({
|
|
362
|
+
client: await createClient({ url: 'redis://url' }).connect()
|
|
363
|
+
}),
|
|
251
364
|
});
|
|
365
|
+
|
|
366
|
+
export { mailQueue };
|
|
252
367
|
```
|
|
253
368
|
|
|
254
|
-
Send email
|
|
369
|
+
#### 4. Send email
|
|
370
|
+
|
|
371
|
+
Import created `mailQueue` where needed and call `.sendMail()` method. See [NodeMailer's message configuration documentation](https://nodemailer.com/message/) for details
|
|
255
372
|
|
|
256
373
|
```js
|
|
257
|
-
mailQueue.
|
|
374
|
+
import { mailQueue } from './mail-queue.js';
|
|
375
|
+
|
|
376
|
+
await mailQueue.sendMail({
|
|
258
377
|
to: 'user@gmail.com',
|
|
259
378
|
subject: 'You\'ve got an email!',
|
|
260
379
|
text: 'Plain text message',
|
|
@@ -262,41 +381,174 @@ mailQueue.sendMail({
|
|
|
262
381
|
});
|
|
263
382
|
```
|
|
264
383
|
|
|
384
|
+
### Using MongoDB for queue and scheduler
|
|
385
|
+
|
|
386
|
+
*MailTime* uses separate storage for Queue management and Scheduler. In the example below MongoDB is used for both
|
|
387
|
+
|
|
388
|
+
```js
|
|
389
|
+
import { MailTime, MongoQueue } from 'mail-time';
|
|
390
|
+
import { MongoClient } from 'mongodb';
|
|
391
|
+
import { transports } from './transports.js';
|
|
392
|
+
|
|
393
|
+
const db = (await MongoClient.connect('mongodb://url')).db('database');
|
|
394
|
+
const mailQueue = new MailTime({
|
|
395
|
+
queue: new MongoQueue({
|
|
396
|
+
db: db,
|
|
397
|
+
}),
|
|
398
|
+
josk: {
|
|
399
|
+
adapter: {
|
|
400
|
+
type: 'mongo',
|
|
401
|
+
db: db,
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
transports,
|
|
405
|
+
from(transport) {
|
|
406
|
+
// To pass spam-filters `from` field should be correctly set
|
|
407
|
+
// for each transport, check `transport` object for more options
|
|
408
|
+
return `"Awesome App" <${transport.options.from}>`;
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Using MongoDB for queue and Redis for scheduler
|
|
414
|
+
|
|
415
|
+
*MailTime* uses separate storage for Queue management and Scheduler. In the example below MongoDB is used for queue and Redis is used for scheduler
|
|
416
|
+
|
|
417
|
+
```js
|
|
418
|
+
import { MailTime, MongoQueue } from 'mail-time';
|
|
419
|
+
import { MongoClient } from 'mongodb';
|
|
420
|
+
import { createClient } from 'redis';
|
|
421
|
+
import { transports } from './transports.js';
|
|
422
|
+
|
|
423
|
+
const mailQueue = new MailTime({
|
|
424
|
+
queue: new MongoQueue({
|
|
425
|
+
db: (await MongoClient.connect('mongodb://url')).db('database'),
|
|
426
|
+
}),
|
|
427
|
+
josk: {
|
|
428
|
+
adapter: {
|
|
429
|
+
type: 'redis',
|
|
430
|
+
client: await createClient({ url: 'redis://url' }).connect(),
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
transports,
|
|
434
|
+
from(transport) {
|
|
435
|
+
return `"Awesome App" <${transport.options.from}>`;
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Using Redis for queue and MongoDB for scheduler
|
|
441
|
+
|
|
442
|
+
*MailTime* uses separate storage for Queue management and Scheduler. In the example below Redis is used for queue and MongoDB is used for scheduler
|
|
443
|
+
|
|
444
|
+
```js
|
|
445
|
+
import { MailTime, RedisQueue } from 'mail-time';
|
|
446
|
+
import { MongoClient } from 'mongodb';
|
|
447
|
+
import { createClient } from 'redis';
|
|
448
|
+
import { transports } from './transports.js';
|
|
449
|
+
|
|
450
|
+
const mailQueue = new MailTime({
|
|
451
|
+
queue: new RedisQueue({
|
|
452
|
+
client: await createClient({ url: 'redis://url' }).connect(),
|
|
453
|
+
}),
|
|
454
|
+
josk: {
|
|
455
|
+
adapter: {
|
|
456
|
+
type: 'mongo',
|
|
457
|
+
db: (await MongoClient.connect('mongodb://url')).db('database'),
|
|
458
|
+
}
|
|
459
|
+
},
|
|
460
|
+
transports,
|
|
461
|
+
from(transport) {
|
|
462
|
+
return `"Awesome App" <${transport.options.from}>`;
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### Using Redis for queue and scheduler
|
|
468
|
+
|
|
469
|
+
*MailTime* uses separate storage for Queue management and Scheduler. In the example below Redis is used for both
|
|
470
|
+
|
|
471
|
+
```js
|
|
472
|
+
import { MailTime, RedisQueue } from 'mail-time';
|
|
473
|
+
import { MongoClient } from 'mongodb';
|
|
474
|
+
import { createClient } from 'redis';
|
|
475
|
+
import { transports } from './transports.js';
|
|
476
|
+
|
|
477
|
+
const redisClient = await createClient({ url: 'redis://url' }).connect();
|
|
478
|
+
const mailQueue = new MailTime({
|
|
479
|
+
queue: new RedisQueue({
|
|
480
|
+
client: redisClient,
|
|
481
|
+
}),
|
|
482
|
+
josk: {
|
|
483
|
+
adapter: {
|
|
484
|
+
type: 'redis',
|
|
485
|
+
client: redisClient,
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
transports,
|
|
489
|
+
from(transport) {
|
|
490
|
+
return `"Awesome App" <${transport.options.from}>`;
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
```
|
|
494
|
+
|
|
265
495
|
### Two `MailTime` instances usage example
|
|
266
496
|
|
|
267
|
-
Create two `MailTime` instances with different settings.
|
|
497
|
+
Create two `MailTime` instances with different settings. One for urgent (*e.g. "transactional" emails*), and another one for other types of emails (*e.g. "marketing" emails*)
|
|
268
498
|
|
|
269
499
|
```js
|
|
500
|
+
import { MailTime, RedisQueue } from 'mail-time';
|
|
501
|
+
import { createClient } from 'redis';
|
|
502
|
+
import { transports } from './transports.js';
|
|
503
|
+
const redisClient = await createClient({ url: 'redis://url' }).connect();
|
|
504
|
+
|
|
270
505
|
// CREATE mailQueue FOR NON-URGENT EMAILS WHICH IS OKAY TO CONCATENATE
|
|
271
506
|
const mailQueue = new MailTime({
|
|
272
|
-
|
|
273
|
-
|
|
507
|
+
queue: new RedisQueue({
|
|
508
|
+
client: redisClient,
|
|
509
|
+
}),
|
|
510
|
+
transports,
|
|
274
511
|
strategy: 'backup',
|
|
275
512
|
failsToNext: 1,
|
|
276
513
|
concatEmails: true,
|
|
277
|
-
|
|
278
|
-
|
|
514
|
+
josk: {
|
|
515
|
+
adapter: {
|
|
516
|
+
type: 'redis',
|
|
517
|
+
client: redisClient
|
|
518
|
+
},
|
|
519
|
+
zombieTime: 120000
|
|
520
|
+
}
|
|
279
521
|
});
|
|
280
522
|
|
|
281
523
|
// CREATE mailInstantQueue FOR TRANSACTIONAL EMAILS AND ALERTS
|
|
282
524
|
const mailInstantQueue = new MailTime({
|
|
283
|
-
|
|
525
|
+
queue: new RedisQueue({
|
|
526
|
+
client: redisClient,
|
|
527
|
+
prefix: 'instant'
|
|
528
|
+
}),
|
|
529
|
+
transports,
|
|
284
530
|
prefix: 'instant',
|
|
285
|
-
|
|
531
|
+
retryDelay: 2000,
|
|
286
532
|
strategy: 'backup',
|
|
287
533
|
failsToNext: 1,
|
|
288
534
|
concatEmails: false,
|
|
289
|
-
|
|
535
|
+
josk: {
|
|
536
|
+
adapter: {
|
|
537
|
+
type: 'redis',
|
|
538
|
+
client: redisClient
|
|
539
|
+
},
|
|
540
|
+
zombieTime: 20000
|
|
541
|
+
}
|
|
290
542
|
});
|
|
291
543
|
|
|
292
|
-
mailQueue.sendMail({
|
|
544
|
+
await mailQueue.sendMail({
|
|
293
545
|
to: 'user@gmail.com',
|
|
294
546
|
subject: 'You\'ve got an email!',
|
|
295
547
|
text: 'Plain text message',
|
|
296
548
|
html: '<h1>HTML</h1><p>Styled message</p>'
|
|
297
549
|
});
|
|
298
550
|
|
|
299
|
-
mailInstantQueue.sendMail({
|
|
551
|
+
await mailInstantQueue.sendMail({
|
|
300
552
|
to: 'user@gmail.com',
|
|
301
553
|
subject: 'Sign in request',
|
|
302
554
|
text: 'Your OTP login code: xxxx:',
|
|
@@ -306,7 +558,7 @@ mailInstantQueue.sendMail({
|
|
|
306
558
|
|
|
307
559
|
### Passing variables to the template
|
|
308
560
|
|
|
309
|
-
All options passed to the `.sendMail()` method
|
|
561
|
+
All options passed to the `.sendMail()` method are available inside `text`, `html`, and global templates
|
|
310
562
|
|
|
311
563
|
```js
|
|
312
564
|
const templates = {
|
|
@@ -318,11 +570,11 @@ const templates = {
|
|
|
318
570
|
};
|
|
319
571
|
|
|
320
572
|
const mailQueue = new MailTime({
|
|
321
|
-
|
|
573
|
+
queue: new RedisQueue({ /* ... */ }),
|
|
322
574
|
template: templates.global
|
|
323
575
|
});
|
|
324
576
|
|
|
325
|
-
mailQueue.sendMail({
|
|
577
|
+
await mailQueue.sendMail({
|
|
326
578
|
to: 'user@gmail.com',
|
|
327
579
|
subject: 'Sign-in request',
|
|
328
580
|
username: 'johndoe',
|
|
@@ -338,53 +590,170 @@ All available constructor options and `.sendMail()` method API overview
|
|
|
338
590
|
|
|
339
591
|
### `new MailTime(opts)` constructor
|
|
340
592
|
|
|
341
|
-
- `opts` {*
|
|
342
|
-
- `opts.
|
|
343
|
-
- `opts.
|
|
344
|
-
- `opts.
|
|
345
|
-
- `opts.
|
|
346
|
-
- `opts.
|
|
347
|
-
- `opts.
|
|
348
|
-
- `opts.
|
|
349
|
-
- `opts.
|
|
350
|
-
- `opts.
|
|
351
|
-
- `opts.
|
|
352
|
-
- `opts.
|
|
353
|
-
- `opts.
|
|
354
|
-
- `opts.
|
|
355
|
-
- `opts.
|
|
356
|
-
- `opts.
|
|
357
|
-
- `opts.
|
|
358
|
-
- `opts.
|
|
359
|
-
- `opts.
|
|
360
|
-
- `opts.
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
-
|
|
365
|
-
- `
|
|
366
|
-
- `
|
|
367
|
-
- `
|
|
368
|
-
- `opts.
|
|
369
|
-
- `
|
|
370
|
-
- `
|
|
593
|
+
- `opts` {*object*} - Configuration object
|
|
594
|
+
- `opts.type` {*string*} - [Optional] `client` or `server`, default - `server`
|
|
595
|
+
- `opts.queue` {*RedisQueue*|*MongoQueue*|*CustomQueue*} - Queue storage driver instance
|
|
596
|
+
- `opts.transports` {*[object]*} - [*Required for "server"*] An array of `nodemailer`'s transports, returned from `nodemailer.createTransport({})`. Required for `{type: 'server'}`
|
|
597
|
+
- `opts.josk` {*object*} - [*Required for "server"*] [`JoSk` package](https://github.com/veliovgroup/josk#api) options
|
|
598
|
+
- `opts.josk.adapter` {*object*|*RedisAdapter*|*MongoAdapter*|*CustomAdapter*} - Config object or *Adapter* instance
|
|
599
|
+
- `opts.josk.adapter.type` {*string*} - One of `mongo` *or* `redis`; Pass `josk.adapter.type` to avoid burden of creating *Adapter* instance manually
|
|
600
|
+
- `opts.josk.adapter.client` {*RedisClient*} - *RedisClient* instance
|
|
601
|
+
- `opts.josk.adapter.db` {*Db*} - Mongo's *Db* instance
|
|
602
|
+
- `opts.josk[option]` {*mix*} - Any other options passed to [`JoSk` instance](https://github.com/veliovgroup/josk#api)
|
|
603
|
+
- `opts.from` {*function*} - [Optional] A function which returns *string* of `from` field, format: `"MyApp" <user@example.com>`
|
|
604
|
+
- `opts.strategy` {*string*} - [Optional] `backup` or `balancer`, default - `backup`. If set to `backup`, first transport will be used unless failed to send `failsToNext` times. If set to `balancer` - transports will be used equally in round robin chain
|
|
605
|
+
- `opts.failsToNext` {*number*} - [Optional] After how many failed "send attempts" switch to the next transport, applied only for `backup` strategy, default - `4`
|
|
606
|
+
- `opts.prefix` {*string*} - [Optional] Use unique prefixes to create multiple `MailTime` instances within the same application
|
|
607
|
+
- `opts.retries` {*number*} - [Optional] How many times resend failed emails, default - `60`
|
|
608
|
+
- `opts.retryDelay` {*number*} - [Optional] Interval in *milliseconds* between send re-tries, default - `60000`
|
|
609
|
+
- `opts.keepHistory` {*boolean*} - [Optional] By default sent emails not stored in the database. Set `{ keepHistory: true }` to keep queue task as it is in the database, default - `false`
|
|
610
|
+
- `opts.concatEmails` {*boolean*} - [Optional] Concatenate email by `to` field (*e.g. to the same addressee*), default - `false`
|
|
611
|
+
- `opts.concatSubject` {*string*} - [Optional] Email subject used in concatenated email, default - `Multiple notifications`
|
|
612
|
+
- `opts.concatDelimiter` {*string*} - [Optional] HTML or plain string delimiter used between concatenated email, default - `<hr>`
|
|
613
|
+
- `opts.concatDelay` {*number*} - [Optional] Time in *milliseconds* while emails are waiting to be concatenated, default - `60000`
|
|
614
|
+
- `opts.revolvingInterval` {*number*} - [Optional] Interval in *milliseconds* in between queue checks, default - `256`
|
|
615
|
+
- `opts.template` {*string*} - [Optional] Mustache-like template, default - `{{{html}}}`, all options passed to `sendMail` is available in Template, like `to`, `subject`, `text`, `html` or any other custom option. Use `{{opt}}` for string placeholders and `{{{opt}}}` for html placeholders
|
|
616
|
+
- `opts.onError(error, email, details)` {*function*} - [Optional] called when email has failed to get sent and exhausted all send attempts (`opts.retries`), called with 3 arguments:
|
|
617
|
+
- `error` {*Error*|*object*} - Error object
|
|
618
|
+
- `email` {*object*} - email's object
|
|
619
|
+
- `details` {*object*} - *not always present*, details from SMTP protocol
|
|
620
|
+
- `opts.onSent(email, details)` {*function*} - [Optional] called when email was successfully handed over to receiving/recipient's SMTP server, called with 2 arguments:
|
|
621
|
+
- `email` {*object*} - email's object
|
|
622
|
+
- `details` {*object*} - *not always present*, details from SMTP server/protocol
|
|
623
|
+
|
|
624
|
+
```js
|
|
625
|
+
import { MailTime, MongoQueue, RedisQueue } from 'mail-time';
|
|
626
|
+
import nodemailer from 'nodemailer';
|
|
627
|
+
import { createClient } from 'redis';
|
|
628
|
+
|
|
629
|
+
const redisClient = await createClient({ url: 'redis://url' }).connect();
|
|
630
|
+
|
|
631
|
+
const mailQueue = new MailTime({
|
|
632
|
+
type: 'server',
|
|
633
|
+
strategy: 'backup',
|
|
634
|
+
prefix: 'appMailQueue',
|
|
635
|
+
transports: [nodemailer.createTransport({/* ... */})],
|
|
636
|
+
failsToNext: 4,
|
|
637
|
+
retries: 60,
|
|
638
|
+
retryDelay: 60000,
|
|
639
|
+
keepHistory: false,
|
|
640
|
+
concatEmails: false,
|
|
641
|
+
concatDelay: 60000,
|
|
642
|
+
concatDelimiter: '<hr>',
|
|
643
|
+
concatSubject: 'Multiple notifications',
|
|
644
|
+
revolvingInterval: 256,
|
|
645
|
+
template: '{{{html}}}',
|
|
646
|
+
queue: new RedisQueue({
|
|
647
|
+
client: redisClient,
|
|
648
|
+
prefix: 'appMailQueue',
|
|
649
|
+
}),
|
|
650
|
+
josk: {
|
|
651
|
+
adapter: {
|
|
652
|
+
type: 'redis',
|
|
653
|
+
client: redisClient,
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
from(transport) {
|
|
657
|
+
// To pass spam-filters `from` field should be correctly set
|
|
658
|
+
// for each transport, check `transport` object for more options
|
|
659
|
+
return `"App Name" <${transport.options.from}>`;
|
|
660
|
+
},
|
|
661
|
+
onError(error, email, details) {
|
|
662
|
+
console.log(`Email "${email.mailOptions.subject}" wasn't sent to ${email.mailOptions.to}`, error, details);
|
|
663
|
+
},
|
|
664
|
+
onSent(email, details) {
|
|
665
|
+
console.log(`Email "${email.mailOptions.subject}" successfully sent to ${email.mailOptions.to}`, details);
|
|
666
|
+
},
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
await mailQueue.sendMail({
|
|
670
|
+
to: 'johndoe@example.com',
|
|
671
|
+
subject: 'Email subject',
|
|
672
|
+
text: 'You have got email!',
|
|
673
|
+
html: '<p>You have got email!</p>',
|
|
674
|
+
});
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
### `new RedisQueue(opts)` constructor
|
|
678
|
+
|
|
679
|
+
*Create Redis Queue instance.* Use for `opts.queue` when creating *MailTime* instance
|
|
680
|
+
|
|
681
|
+
- `opts` {*object*} - Configuration object
|
|
682
|
+
- `opts.client` {*RedisClient*} - Required, Redis'es `RedisClient` instance, like one returned from `await redis.createClient().connect()` method
|
|
683
|
+
- `opts.prefix` {*string*} - Optional prefix for scope isolation; use when creating multiple `MailTime` instances within the single application
|
|
684
|
+
|
|
685
|
+
```js
|
|
686
|
+
import { MailTime, RedisQueue } from 'mail-time';
|
|
687
|
+
import { createClient } from 'redis';
|
|
688
|
+
|
|
689
|
+
new RedisQueue({
|
|
690
|
+
client: await createClient({ url: 'redis://url' }).connect(),
|
|
691
|
+
prefix: 'appMailQueue',
|
|
692
|
+
});
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
### `new MongoQueue(opts)` constructor
|
|
696
|
+
|
|
697
|
+
*Create MongoDB Queue instance.* Use for `opts.queue` when creating *MailTime* instance
|
|
698
|
+
|
|
699
|
+
- `opts` {*object*} - Configuration object
|
|
700
|
+
- `opts.db` {*Db*} - Required, Mongo's `Db` instance, like one returned from `MongoClient#db()`
|
|
701
|
+
- `opts.prefix` {*string*} - Optional prefix for scope isolation; use when creating multiple `MailTime` instances within the single application
|
|
702
|
+
|
|
703
|
+
```js
|
|
704
|
+
import { MailTime, MongoQueue } from 'mail-time';
|
|
705
|
+
import { MongoClient } from 'mongodb';
|
|
706
|
+
|
|
707
|
+
new MongoQueue({
|
|
708
|
+
db: (await MongoClient.connect('mongodb://url')).db('database'),
|
|
709
|
+
prefix: 'appMailQueue',
|
|
710
|
+
});
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
### `sendMail(opts)`
|
|
714
|
+
|
|
715
|
+
*Add email to the queue.* Returns `Promise<string>` unique email's `uuid`
|
|
716
|
+
|
|
717
|
+
- `opts` {*object*} - Configuration object
|
|
718
|
+
- `opts.sendAt` {*number*} - When email should be sent, default - `Date.now()`
|
|
719
|
+
- `opts.template` {*string*} - Email specific template, this will override default template passed to `MailTime` constructor
|
|
720
|
+
- `opts.concatSubject` {*string*} - Email specific concatenation subject, this will override default concatenation subject passed to `MailTime` constructor
|
|
721
|
+
- `opts[key]` {*mix*} - Other custom and NodeMailer specific options, like `text`, `html` and `to`, [learn more here](https://nodemailer.com/message/). __Note:__ if [`attachments`](https://nodemailer.com/message/attachments/) are used via `path` — file must exists on all micro-services servers
|
|
722
|
+
|
|
723
|
+
### `cancelMail(uuid)`
|
|
724
|
+
|
|
725
|
+
*Remove email from queue.* Returns `Promise<boolean>` — `true` if cancelled or `false` if not found, was sent, or was cancelled previously. Throws *Error*
|
|
726
|
+
|
|
727
|
+
- `uuid` {*string*|*promise*} — email's `uuid` returned from `.sendEmail()` method
|
|
728
|
+
|
|
729
|
+
```js
|
|
730
|
+
import { mailQueue } from './mail-queue.js';
|
|
731
|
+
|
|
732
|
+
const uuid = await mailQueue.sendMail({
|
|
733
|
+
to: 'johndoe@example.com',
|
|
734
|
+
subject: 'Email subject',
|
|
735
|
+
text: 'You have got email!',
|
|
736
|
+
html: '<p>You have got email!</p>',
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
await mailQueue.cancelMail(uuid);
|
|
740
|
+
```
|
|
371
741
|
|
|
372
742
|
### `static MailTime.Template`
|
|
373
743
|
|
|
374
744
|
Simple and bulletproof HTML template, see [its source](https://github.com/veliovgroup/mail-time/blob/master/template.html). Usage example:
|
|
375
745
|
|
|
376
746
|
```js
|
|
377
|
-
|
|
747
|
+
import { MailTime, MongoQueue, RedisQueue } from 'mail-time';
|
|
748
|
+
|
|
378
749
|
// Make it default
|
|
379
750
|
const mailQueue = new MailTime({
|
|
380
|
-
db: db, // MongoDB
|
|
381
751
|
/* .. */
|
|
382
752
|
template: MailTime.Template
|
|
383
753
|
});
|
|
384
754
|
|
|
385
755
|
// For single letter
|
|
386
756
|
mailQueue.sendMail({
|
|
387
|
-
to: 'user@gmail.com',
|
|
388
757
|
/* .. */
|
|
389
758
|
template: MailTime.Template
|
|
390
759
|
});
|
|
@@ -408,28 +777,34 @@ mailQueue.sendMail({
|
|
|
408
777
|
## Testing
|
|
409
778
|
|
|
410
779
|
1. Clone this package
|
|
411
|
-
2.
|
|
412
|
-
3.
|
|
413
|
-
|
|
414
|
-
Test NPM package:
|
|
780
|
+
2. Start local or obtain URLs for remote MongoDB and Redis servers
|
|
781
|
+
3. In Terminal (*Console*) go to directory where package was cloned
|
|
782
|
+
4. Then run:
|
|
415
783
|
|
|
416
784
|
```shell
|
|
417
|
-
# Before
|
|
785
|
+
# Before running tests make sure NODE_ENV === development
|
|
418
786
|
# Install NPM dependencies
|
|
419
787
|
npm install --save-dev
|
|
420
788
|
|
|
421
|
-
#
|
|
422
|
-
|
|
789
|
+
# DEFAULT RUN
|
|
790
|
+
REDIS_URL="redis://127.0.0.1:6379" MONGO_URL="mongodb://127.0.0.1:27017/npm-mail-time-test-001" npm test
|
|
791
|
+
|
|
792
|
+
# OPTIONALLY RUN WITH CUSTOM DOMAIN
|
|
793
|
+
EMAIL_DOMAIN="your-domain.com" REDIS_URL="redis://127.0.0.1:6379" MONGO_URL="mongodb://127.0.0.1:27017/npm-mail-time-test-001" npm test
|
|
794
|
+
|
|
795
|
+
# IF SOME TESTS ARE FAILING: ENABLE DEBUG
|
|
796
|
+
DEBUG="true" REDIS_URL="redis://127.0.0.1:6379" MONGO_URL="mongodb://127.0.0.1:27017/npm-mail-time-test-001" npm test
|
|
423
797
|
|
|
424
|
-
# Be patient, tests are taking around
|
|
798
|
+
# Be patient, tests are taking around 8 mins
|
|
425
799
|
```
|
|
426
800
|
|
|
427
801
|
## Support this project:
|
|
428
802
|
|
|
803
|
+
- Upload and share files using [☄️ meteor-files.com](https://meteor-files.com/?ref=github-mail-time-repo-footer) — Continue interrupted file uploads without losing any progress. There is nothing that will stop Meteor from delivering your file to the desired destination
|
|
804
|
+
- Use [▲ ostr.io](https://ostr.io?ref=github-mail-time-repo-footer) for [Server Monitoring](https://snmp-monitoring.com), [Web Analytics](https://ostr.io/info/web-analytics?ref=github-mail-time-repo-footer), [WebSec](https://domain-protection.info), [Web-CRON](https://web-cron.info) and [SEO Pre-rendering](https://prerendering.com) of a website
|
|
429
805
|
- Star on [GitHub](https://github.com/veliovgroup/mail-time)
|
|
430
806
|
- Star on [NPM](https://www.npmjs.com/package/mail-time)
|
|
431
807
|
- Star on [Atmosphere](https://atmospherejs.com/ostrio/mailer)
|
|
432
808
|
- [Sponsor maintainer via GitHub](https://github.com/sponsors/dr-dimitru) — support open source with one-time contribution or on a regular basis
|
|
433
809
|
- [Sponsor veliovgroup via GitHub](https://github.com/sponsors/veliovgroup) — support company behind this package
|
|
434
810
|
- [Support via PayPal](https://paypal.me/veliovgroup) — support our open source contributions
|
|
435
|
-
- Use [ostr.io](https://ostr.io) — [Monitoring](https://snmp-monitoring.com), [Analytics](https://ostr.io/info/web-analytics), [WebSec](https://domain-protection.info), [Web-CRON](https://web-cron.info) and [Pre-rendering](https://prerendering.com) for a website
|