@b2y/email-service 1.0.9 → 1.2.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/Config.js +44 -39
- package/Logger.js +5 -5
- package/README.md +18 -18
- package/constants/AppConstants.js +8 -0
- package/constants/StatusMessageConstants.js +39 -38
- package/enum/EmailProvider.js +8 -7
- package/index.js +82 -77
- package/model/Connect.js +23 -23
- package/model/EmailTemplate.js +51 -51
- package/package.json +55 -53
- package/providers/AmazonSESProvider.js +83 -76
- package/providers/BaseProvider.js +85 -73
- package/providers/MailgunProvider.js +85 -0
- package/providers/NodeMailerProvider.js +52 -51
- package/providers/PostmarkProvider.js +61 -61
- package/providers/SendgridProvider.js +60 -60
- package/service/EmailService.js +101 -98
- package/utils/TemplateEngine.js +98 -98
package/package.json
CHANGED
|
@@ -1,53 +1,55 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@b2y/email-service",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"main": "index.js",
|
|
5
|
-
"exports": {
|
|
6
|
-
".": "./index.js",
|
|
7
|
-
"./providers": "./providers/index.js",
|
|
8
|
-
"./providers/base": "./providers/BaseProvider.js",
|
|
9
|
-
"./providers/nodemailer": "./providers/NodeMailerProvider.js",
|
|
10
|
-
"./providers/sendgrid": "./providers/SendGridProvider.js",
|
|
11
|
-
"./utils/templateEngine": "./utils/TemplateEngine.js",
|
|
12
|
-
"./EmailService": "./service/EmailService.js"
|
|
13
|
-
},
|
|
14
|
-
"files": [
|
|
15
|
-
"providers/",
|
|
16
|
-
"templates/",
|
|
17
|
-
"utils/",
|
|
18
|
-
"constants/",
|
|
19
|
-
"enum/",
|
|
20
|
-
"model/",
|
|
21
|
-
"service/",
|
|
22
|
-
"*.js"
|
|
23
|
-
],
|
|
24
|
-
"scripts": {
|
|
25
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
26
|
-
"start": "node test.js"
|
|
27
|
-
},
|
|
28
|
-
"author": "",
|
|
29
|
-
"license": "ISC",
|
|
30
|
-
"description": "A flexible email service with support for multiple providers and custom templates",
|
|
31
|
-
"keywords": [
|
|
32
|
-
"email",
|
|
33
|
-
"templates",
|
|
34
|
-
"nodemailer",
|
|
35
|
-
"sendgrid"
|
|
36
|
-
],
|
|
37
|
-
"publishConfig": {
|
|
38
|
-
"access": "public"
|
|
39
|
-
},
|
|
40
|
-
"dependencies": {
|
|
41
|
-
"@aws-sdk/client-ses": "^3.957.0",
|
|
42
|
-
"@sendgrid/mail": "^8.1.5",
|
|
43
|
-
"b2y-logger": "^1.1.0",
|
|
44
|
-
"dotenv": "^16.5.0",
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@b2y/email-service",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./index.js",
|
|
7
|
+
"./providers": "./providers/index.js",
|
|
8
|
+
"./providers/base": "./providers/BaseProvider.js",
|
|
9
|
+
"./providers/nodemailer": "./providers/NodeMailerProvider.js",
|
|
10
|
+
"./providers/sendgrid": "./providers/SendGridProvider.js",
|
|
11
|
+
"./utils/templateEngine": "./utils/TemplateEngine.js",
|
|
12
|
+
"./EmailService": "./service/EmailService.js"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"providers/",
|
|
16
|
+
"templates/",
|
|
17
|
+
"utils/",
|
|
18
|
+
"constants/",
|
|
19
|
+
"enum/",
|
|
20
|
+
"model/",
|
|
21
|
+
"service/",
|
|
22
|
+
"*.js"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
26
|
+
"start": "node test.js"
|
|
27
|
+
},
|
|
28
|
+
"author": "",
|
|
29
|
+
"license": "ISC",
|
|
30
|
+
"description": "A flexible email service with support for multiple providers and custom templates",
|
|
31
|
+
"keywords": [
|
|
32
|
+
"email",
|
|
33
|
+
"templates",
|
|
34
|
+
"nodemailer",
|
|
35
|
+
"sendgrid"
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@aws-sdk/client-ses": "^3.957.0",
|
|
42
|
+
"@sendgrid/mail": "^8.1.5",
|
|
43
|
+
"b2y-logger": "^1.1.0",
|
|
44
|
+
"dotenv": "^16.5.0",
|
|
45
|
+
"form-data": "^4.0.5",
|
|
46
|
+
"handlebars": "^4.7.8",
|
|
47
|
+
"log4js": "^6.9.1",
|
|
48
|
+
"mailgun.js": "^12.7.0",
|
|
49
|
+
"nodemailer": "^6.10.0",
|
|
50
|
+
"pg": "^8.16.3",
|
|
51
|
+
"pg-hstore": "^2.3.4",
|
|
52
|
+
"postmark": "^4.0.5",
|
|
53
|
+
"sequelize": "^6.37.7"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -1,77 +1,84 @@
|
|
|
1
|
-
// providers/AmazonSES.js
|
|
2
|
-
const { SESClient, SendEmailCommand } = require('@aws-sdk/client-ses');
|
|
3
|
-
const BaseProvider = require('./BaseProvider');
|
|
4
|
-
const Config = require('../Config');
|
|
5
|
-
const logger = require('../Logger');
|
|
6
|
-
const StatusMessage = require('../constants/StatusMessageConstants');
|
|
7
|
-
const { EmailProvider } = require('../enum/EmailProvider');
|
|
8
|
-
|
|
9
|
-
class AmazonSESProvider extends BaseProvider {
|
|
10
|
-
constructor() {
|
|
11
|
-
super();
|
|
12
|
-
this.client = new SESClient({
|
|
13
|
-
region: Config.awsRegion,
|
|
14
|
-
credentials: {
|
|
15
|
-
accessKeyId: Config.awsAccessKeyId,
|
|
16
|
-
secretAccessKey: Config.awsSecretAccessKey
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async sendEmail(options) {
|
|
22
|
-
try {
|
|
23
|
-
this.validateEmailOptions(options);
|
|
24
|
-
|
|
25
|
-
const toAddresses = this.formatRecipients(options.to);
|
|
26
|
-
const ccAddresses = options.cc ? this.formatRecipients(options.cc) : [];
|
|
27
|
-
const bccAddresses = options.bcc ? this.formatRecipients(options.bcc) : [];
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
1
|
+
// providers/AmazonSES.js
|
|
2
|
+
const { SESClient, SendEmailCommand } = require('@aws-sdk/client-ses');
|
|
3
|
+
const BaseProvider = require('./BaseProvider');
|
|
4
|
+
const Config = require('../Config');
|
|
5
|
+
const logger = require('../Logger');
|
|
6
|
+
const StatusMessage = require('../constants/StatusMessageConstants');
|
|
7
|
+
const { EmailProvider } = require('../enum/EmailProvider');
|
|
8
|
+
|
|
9
|
+
class AmazonSESProvider extends BaseProvider {
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.client = new SESClient({
|
|
13
|
+
region: Config.awsRegion,
|
|
14
|
+
credentials: {
|
|
15
|
+
accessKeyId: Config.awsAccessKeyId,
|
|
16
|
+
secretAccessKey: Config.awsSecretAccessKey
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async sendEmail(options) {
|
|
22
|
+
try {
|
|
23
|
+
this.validateEmailOptions(options);
|
|
24
|
+
|
|
25
|
+
const toAddresses = this.formatRecipients(options.to);
|
|
26
|
+
const ccAddresses = options.cc ? this.formatRecipients(options.cc) : [];
|
|
27
|
+
const bccAddresses = options.bcc ? this.formatRecipients(options.bcc) : [];
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
const fromAddress = this.formatFromAddress(
|
|
31
|
+
options.from || Config.awsFromEmail,
|
|
32
|
+
options.fromName || Config.fromName
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const params = {
|
|
36
|
+
Source: fromAddress,
|
|
37
|
+
Destination: {
|
|
38
|
+
ToAddresses: toAddresses,
|
|
39
|
+
...(ccAddresses.length > 0 && { CcAddresses: ccAddresses }),
|
|
40
|
+
...(bccAddresses.length > 0 && { BccAddresses: bccAddresses })
|
|
41
|
+
},
|
|
42
|
+
Message: {
|
|
43
|
+
Subject: {
|
|
44
|
+
Data: options.subject,
|
|
45
|
+
Charset: 'UTF-8'
|
|
46
|
+
},
|
|
47
|
+
Body: {
|
|
48
|
+
Html: {
|
|
49
|
+
Data: options.html,
|
|
50
|
+
Charset: 'UTF-8'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Add attachments if present (SES requires using SendRawEmail for attachments)
|
|
57
|
+
if (options.attachments && options.attachments.length > 0) {
|
|
58
|
+
logger.warn('SES provider: Attachments require SendRawEmail. Consider implementing raw email support.');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const command = new SendEmailCommand(params);
|
|
62
|
+
const result = await this.client.send(command);
|
|
63
|
+
|
|
64
|
+
logger.info('Email sent successfully via Amazon SES', {
|
|
65
|
+
messageId: result.MessageId,
|
|
66
|
+
recipients: { to: options.to, cc: options.cc, bcc: options.bcc },
|
|
67
|
+
tenantId: options.tenantId,
|
|
68
|
+
from: fromAddress
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
success: true,
|
|
73
|
+
messageId: result.MessageId,
|
|
74
|
+
provider: EmailProvider.SES,
|
|
75
|
+
tenantId: options.tenantId
|
|
76
|
+
};
|
|
77
|
+
} catch (error) {
|
|
78
|
+
logger.error(`Amazon SES failed to send email: ${error.message}`);
|
|
79
|
+
throw new Error(`${StatusMessage.AMAZON_SES_SEND_ERROR}: ${error.message}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
77
84
|
module.exports = AmazonSESProvider;
|
|
@@ -1,74 +1,86 @@
|
|
|
1
|
-
// providers/BaseProvider.js
|
|
2
|
-
const logger = require('../Logger');
|
|
3
|
-
const StatusMessage = require('../constants/StatusMessageConstants');
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
1
|
+
// providers/BaseProvider.js
|
|
2
|
+
const logger = require('../Logger');
|
|
3
|
+
const StatusMessage = require('../constants/StatusMessageConstants');
|
|
4
|
+
const Config = require('../Config');
|
|
5
|
+
|
|
6
|
+
class BaseProvider {
|
|
7
|
+
constructor() {
|
|
8
|
+
if (new.target === BaseProvider) {
|
|
9
|
+
throw new Error(StatusMessage.CANNOT_INSTANTIATE_BASE);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async sendEmail(options) {
|
|
14
|
+
logger.error('sendEmail method not implemented in BaseProvider');
|
|
15
|
+
throw new Error(StatusMessage.PROVIDER_NOT_IMPLEMENTED);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
validateEmailOptions(options) {
|
|
19
|
+
const { to, subject, html, from } = options;
|
|
20
|
+
|
|
21
|
+
if (!to || (Array.isArray(to) && to.length === 0)) {
|
|
22
|
+
throw new Error(StatusMessage.RECIPIENTS_REQUIRED);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!subject) {
|
|
26
|
+
throw new Error(StatusMessage.SUBJECT_REQUIRED);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!html) {
|
|
30
|
+
throw new Error(StatusMessage.HTML_CONTENT_REQUIRED);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
formatRecipients(recipients) {
|
|
37
|
+
if (!recipients) return [];
|
|
38
|
+
|
|
39
|
+
if (typeof recipients === 'string') {
|
|
40
|
+
return recipients.split(',').map(r => r.trim());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (Array.isArray(recipients)) {
|
|
44
|
+
return recipients;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
formatFromAddress(email, name = null) {
|
|
51
|
+
const fromName = name || Config.fromName;
|
|
52
|
+
const fromEmail = email || Config.fromEmail;
|
|
53
|
+
|
|
54
|
+
if (!fromEmail) {
|
|
55
|
+
throw new Error('FROM_EMAIL is required');
|
|
56
|
+
}
|
|
57
|
+
return fromName ? `"${fromName}" <${fromEmail}>` : fromEmail;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
buildMailOptions(options) {
|
|
61
|
+
const { to, cc, bcc, subject, html, from, fromName, attachments } = options;
|
|
62
|
+
|
|
63
|
+
const mailOptions = {
|
|
64
|
+
from: this.formatFromAddress(from, fromName),
|
|
65
|
+
to: this.formatRecipients(to),
|
|
66
|
+
subject,
|
|
67
|
+
html,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
if (cc && cc.length > 0) {
|
|
71
|
+
mailOptions.cc = this.formatRecipients(cc);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (bcc && bcc.length > 0) {
|
|
75
|
+
mailOptions.bcc = this.formatRecipients(bcc);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (attachments && attachments.length > 0) {
|
|
79
|
+
mailOptions.attachments = attachments;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return mailOptions;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
74
86
|
module.exports = BaseProvider;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// providers/MailgunProvider.js
|
|
2
|
+
const formData = require('form-data');
|
|
3
|
+
const Mailgun = require('mailgun.js');
|
|
4
|
+
const BaseProvider = require('./BaseProvider');
|
|
5
|
+
const Config = require('../Config');
|
|
6
|
+
const logger = require('../Logger');
|
|
7
|
+
const StatusMessage = require('../constants/StatusMessageConstants');
|
|
8
|
+
const { EmailProvider } = require('../enum/EmailProvider');
|
|
9
|
+
const AppConstants = require('../constants/AppConstants');
|
|
10
|
+
class MailgunProvider extends BaseProvider {
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
|
|
14
|
+
if (!Config.mailgunApiKey) {
|
|
15
|
+
throw new Error('Mailgun API key is required');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (!Config.mailgunDomain) {
|
|
19
|
+
throw new Error('Mailgun domain is required');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const mailgun = new Mailgun(formData);
|
|
23
|
+
this.client = mailgun.client({
|
|
24
|
+
username: AppConstants.MAILGUN_AUTH_USERNAME,
|
|
25
|
+
key: Config.mailgunApiKey
|
|
26
|
+
});
|
|
27
|
+
this.domain = Config.mailgunDomain;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async sendEmail(options) {
|
|
31
|
+
try {
|
|
32
|
+
this.validateEmailOptions(options);
|
|
33
|
+
|
|
34
|
+
const messageData = {
|
|
35
|
+
from: this.formatFromAddress(
|
|
36
|
+
options.from || Config.fromEmail,
|
|
37
|
+
options.fromName || Config.fromName
|
|
38
|
+
),
|
|
39
|
+
to: this.formatRecipients(options.to),
|
|
40
|
+
subject: options.subject,
|
|
41
|
+
html: options.html
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Add CC if present
|
|
45
|
+
if (options.cc && options.cc.length > 0) {
|
|
46
|
+
messageData.cc = this.formatRecipients(options.cc);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Add BCC if present
|
|
50
|
+
if (options.bcc && options.bcc.length > 0) {
|
|
51
|
+
messageData.bcc = this.formatRecipients(options.bcc);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Add attachments if present
|
|
55
|
+
if (options.attachments && options.attachments.length > 0) {
|
|
56
|
+
messageData.attachment = options.attachments.map(att => ({
|
|
57
|
+
filename: att.filename,
|
|
58
|
+
data: att.content,
|
|
59
|
+
contentType: att.contentType
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const result = await this.client.messages.create(this.domain, messageData);
|
|
64
|
+
|
|
65
|
+
logger.info('Email sent successfully via Mailgun', {
|
|
66
|
+
messageId: result.id,
|
|
67
|
+
recipients: { to: options.to, cc: options.cc, bcc: options.bcc },
|
|
68
|
+
tenantId: options.tenantId,
|
|
69
|
+
from: messageData.from
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
success: true,
|
|
74
|
+
messageId: result.id,
|
|
75
|
+
provider: EmailProvider.MAILGUN,
|
|
76
|
+
tenantId: options.tenantId
|
|
77
|
+
};
|
|
78
|
+
} catch (error) {
|
|
79
|
+
logger.error('Mailgun failed to send email:', error);
|
|
80
|
+
throw new Error(StatusMessage.MAILGUN_SEND_ERROR);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = MailgunProvider;
|
|
@@ -1,52 +1,53 @@
|
|
|
1
|
-
// providers/NodeMailerProvider.js
|
|
2
|
-
const nodemailer = require('nodemailer');
|
|
3
|
-
const BaseProvider = require('./BaseProvider');
|
|
4
|
-
const Config = require('../Config');
|
|
5
|
-
const logger = require('../Logger');
|
|
6
|
-
const StatusMessage = require('../constants/StatusMessageConstants');
|
|
7
|
-
const { EmailProvider } = require('../enum/EmailProvider');
|
|
8
|
-
|
|
9
|
-
class NodeMailerProvider extends BaseProvider {
|
|
10
|
-
constructor() {
|
|
11
|
-
super();
|
|
12
|
-
this.transporter = nodemailer.createTransport({
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
this.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
});
|
|
31
|
-
const result = await this.transporter.sendMail(mailOptions);
|
|
32
|
-
|
|
33
|
-
logger.info('Email sent successfully via Nodemailer', {
|
|
34
|
-
messageId: result.messageId,
|
|
35
|
-
recipients: { to: options.to, cc: options.cc, bcc: options.bcc },
|
|
36
|
-
tenantId: options.tenantId
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
1
|
+
// providers/NodeMailerProvider.js
|
|
2
|
+
const nodemailer = require('nodemailer');
|
|
3
|
+
const BaseProvider = require('./BaseProvider');
|
|
4
|
+
const Config = require('../Config');
|
|
5
|
+
const logger = require('../Logger');
|
|
6
|
+
const StatusMessage = require('../constants/StatusMessageConstants');
|
|
7
|
+
const { EmailProvider } = require('../enum/EmailProvider');
|
|
8
|
+
|
|
9
|
+
class NodeMailerProvider extends BaseProvider {
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.transporter = nodemailer.createTransport({
|
|
13
|
+
host: Config.emailHost,
|
|
14
|
+
port: Config.smtpPort,
|
|
15
|
+
secure: Config.smtpPort,
|
|
16
|
+
auth: {
|
|
17
|
+
user: Config.emailUser,
|
|
18
|
+
pass: Config.emailPass,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async sendEmail(options) {
|
|
24
|
+
try {
|
|
25
|
+
this.validateEmailOptions(options);
|
|
26
|
+
const mailOptions = this.buildMailOptions({
|
|
27
|
+
...options,
|
|
28
|
+
from: options.from || Config.fromEmail,
|
|
29
|
+
fromName: options.fromName || Config.fromName
|
|
30
|
+
});
|
|
31
|
+
const result = await this.transporter.sendMail(mailOptions);
|
|
32
|
+
|
|
33
|
+
logger.info('Email sent successfully via Nodemailer', {
|
|
34
|
+
messageId: result.messageId,
|
|
35
|
+
recipients: { to: options.to, cc: options.cc, bcc: options.bcc },
|
|
36
|
+
tenantId: options.tenantId,
|
|
37
|
+
from: mailOptions.from
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
success: true,
|
|
42
|
+
messageId: result.messageId,
|
|
43
|
+
provider: EmailProvider.NODE_MAILER,
|
|
44
|
+
tenantId: options.tenantId
|
|
45
|
+
};
|
|
46
|
+
} catch (error) {
|
|
47
|
+
logger.error(`Nodemailer failed to send email: ${error.message}`);
|
|
48
|
+
throw new Error(`${StatusMessage.NODEMAILER_SEND_ERROR}: ${error.message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
52
53
|
module.exports = NodeMailerProvider;
|