@plusscommunities/pluss-core-aws 2.0.20 → 2.0.21

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.
Files changed (2) hide show
  1. package/helper/sendEmail.js +98 -41
  2. package/package.json +1 -1
@@ -1,26 +1,52 @@
1
- const nodemailer = require("nodemailer");
1
+ const axios = require("axios");
2
+ const moment = require("moment");
2
3
  const sendEmail = require("../aws/sendEmail");
3
4
  const getEmailServiceInfo = require("../aws/getEmailServiceInfo");
4
5
  const { getConfig } = require("../config");
6
+ const { log } = require("./");
7
+ const getRef = require("../db/common/getRef");
8
+ const updateRef = require("../db/common/updateRef");
5
9
 
6
- const sendFallback = (mailOptions, emailConfig) => {
10
+ const sendFallback = (mailOptions, emailConfig, accessConfig) => {
7
11
  return new Promise((resolve, reject) => {
8
- console.log("Cannot use Amazon SES, fall back to nodemailer", mailOptions);
9
- const transporter = nodemailer.createTransport({
10
- //host: 'smtp.ethereal.email',
11
- service: "gmail",
12
- //port: 587,
13
- auth: emailConfig.fallbackAuth,
14
- });
15
- transporter.sendMail(mailOptions, (error) => {
16
- if (error) {
17
- console.log("Email failed", mailOptions.to, mailOptions.subject, error);
12
+ const logId = log("sendFallback", "Email", mailOptions);
13
+ if (emailConfig.isFallback) {
14
+ log(
15
+ "sendFallback",
16
+ "isFallback",
17
+ "Not allowed to use this account as it is the fallback itself",
18
+ logId
19
+ );
20
+ return reject(
21
+ new Error(
22
+ "Not allowed to use this account as it is the fallback itself"
23
+ )
24
+ );
25
+ }
26
+
27
+ // Calling organisation account as the fallback
28
+ log("sendFallback", "Fallback", emailConfig.fallbackUrl, logId);
29
+ axios({
30
+ method: "POST",
31
+ url: emailConfig.fallbackUrl,
32
+ headers: {
33
+ Authorization: accessConfig.authSecret,
34
+ },
35
+ data: {
36
+ to: mailOptions.to,
37
+ subject: mailOptions.subject,
38
+ body: mailOptions.html,
39
+ from: mailOptions.from,
40
+ },
41
+ })
42
+ .then((response) => {
43
+ log("sendFallback", "response", response.data, logId);
44
+ resolve(response.data);
45
+ })
46
+ .catch((error) => {
47
+ log("sendFallback", "error", error, logId);
18
48
  reject(error);
19
- } else {
20
- console.log("Email success", mailOptions.to, mailOptions.subject);
21
- resolve();
22
- }
23
- });
49
+ });
24
50
  });
25
51
  };
26
52
 
@@ -34,9 +60,37 @@ module.exports = async (
34
60
  excludeClientBranding = false,
35
61
  brandingImage = null,
36
62
  bcc = null,
63
+ rateLimitId = null,
37
64
  } = {}
38
65
  ) => {
39
- const { communityConfig, serverlessConfig, emailConfig } = getConfig();
66
+ const { communityConfig, serverlessConfig, emailConfig, accessConfig } =
67
+ getConfig();
68
+ const now = moment.utc();
69
+ let rateLimitIdToUse;
70
+
71
+ const logId = log("sendEmail", "Email", {
72
+ toEmail,
73
+ subject,
74
+ });
75
+
76
+ if (rateLimitId) {
77
+ try {
78
+ rateLimitIdToUse = `email_${rateLimitId}`;
79
+ const item = await getRef("ratelimit", "Id", rateLimitIdToUse);
80
+ const dayAgo = moment(now).add(-1, "d");
81
+ if (item && item.LastSent && item.LastSent > dayAgo.valueOf()) {
82
+ log(
83
+ "sendEmail",
84
+ "RateLimit",
85
+ `Rate limit reached for ${rateLimitIdToUse}`,
86
+ logId
87
+ );
88
+ return { RateLimited: true };
89
+ }
90
+ } catch (e) {
91
+ // continue
92
+ }
93
+ }
40
94
 
41
95
  if (useTemplate) {
42
96
  content = `<div style="padding: 24px; padding-top: 0px; background-color: #f2f4f8;margin: 0px;">
@@ -48,28 +102,31 @@ module.exports = async (
48
102
  : `
49
103
  <div style='margin-top: 32px; border-top: 2px solid #e0e0e0;'></div>
50
104
  <div style='padding-top: 24px; display: block;'>
51
- <div style='clear: both; height: 30px;'>
52
- <img height="30" width="auto" src="${communityConfig.emailBrandingAbovePoweredBy.image}" style="float: left; height: 30px; width: auto; background-repeat: no-repeat; background-size: contain;"></img>
53
- </div>
105
+ <div style='clear: both; height: 30px;'>
106
+ <img height="30" width="auto" src="${communityConfig.emailBrandingAbovePoweredBy.image}" style="float: left; height: 30px; width: auto; background-repeat: no-repeat; background-size: contain;"></img>
107
+ </div>
54
108
  </div>
55
109
  `
56
110
  }
57
111
  </div>
58
112
  <div style='margin-top: 30px;'>
59
- <div style='margin: 0 auto; width: fit-content;'>
60
- <div style='vertical-align: top; height: 20px; margin-right: 10px; color: #828282; display: inline-block;'>
61
- <span style=' font-size: 13px; line-height: 20px;'>powered by</span>
62
- </div>
63
- <img height="20" width="142" src="https://pluss-prd-uploads.s3.ap-southeast-2.amazonaws.com/uploads/users/ap-southeast-2:80aecdcb-9955-493e-a341-2f2263f64777/public/9c785b064c6abbec00bd4ef12b/logoplusscommunitieslong.png" style="display: inline-block; height: 20px; width: 142px; background-repeat: no-repeat; background-size:contain;"></img>
113
+ <div style='margin: 0 auto; width: fit-content;'>
114
+ <div style='vertical-align: top; height: 20px; margin-right: 10px; color: #828282; display: inline-block;'>
115
+ <span style=' font-size: 13px; line-height: 20px;'>powered by</span>
64
116
  </div>
117
+ <img height="20" width="142" src="https://pluss-prd-uploads.s3.ap-southeast-2.amazonaws.com/uploads/users/ap-southeast-2:80aecdcb-9955-493e-a341-2f2263f64777/public/9c785b064c6abbec00bd4ef12b/logoplusscommunitieslong.png" style="display: inline-block; height: 20px; width: 142px; background-repeat: no-repeat; background-size:contain;"></img>
118
+ </div>
65
119
  </div>
66
120
  </div>`;
67
121
  }
68
122
 
123
+ const sesInfo = await getEmailServiceInfo(
124
+ serverlessConfig.key,
125
+ serverlessConfig.secret
126
+ );
127
+
69
128
  const mailOptions = {
70
- from:
71
- fromEmail ||
72
- `"${communityConfig.name}" noreply@${communityConfig.subdomain}.plusscommunities.com'`,
129
+ from: fromEmail || `${communityConfig.name} <${sesInfo.sender}>`,
73
130
  to: toEmail,
74
131
  bcc,
75
132
  subject,
@@ -77,16 +134,9 @@ module.exports = async (
77
134
  html: content,
78
135
  };
79
136
 
80
- const sesInfo = await getEmailServiceInfo(
81
- serverlessConfig.key,
82
- serverlessConfig.secret
83
- );
84
-
85
137
  if (sesInfo.enabled) {
86
138
  try {
87
- console.log("Using Amazon SES", mailOptions);
88
- mailOptions.from =
89
- fromEmail || `${communityConfig.name} <${sesInfo.sender}>`;
139
+ log("sendEmail", "SES", { toEmail, subject }, logId);
90
140
  const result = await sendEmail(
91
141
  mailOptions.from,
92
142
  mailOptions.to,
@@ -95,12 +145,19 @@ module.exports = async (
95
145
  serverlessConfig,
96
146
  mailOptions.bcc
97
147
  );
98
- console.log("Email success", toEmail, subject, result);
148
+ log("sendEmail", "Success", { toEmail, subject }, logId);
99
149
  } catch (error) {
100
- console.log("Email failed", toEmail, subject, error);
101
- await sendFallback(mailOptions, emailConfig);
150
+ log("sendEmail", "Error:SES", { toEmail, subject, error }, logId);
151
+ await sendFallback(mailOptions, emailConfig, accessConfig);
102
152
  }
103
153
  } else {
104
- await sendFallback(mailOptions, emailConfig);
154
+ await sendFallback(mailOptions, emailConfig, accessConfig);
155
+ }
156
+
157
+ if (rateLimitIdToUse) {
158
+ await updateRef("ratelimit", {
159
+ Id: rateLimitIdToUse,
160
+ LastSent: now.valueOf(),
161
+ });
105
162
  }
106
163
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plusscommunities/pluss-core-aws",
3
- "version": "2.0.20",
3
+ "version": "2.0.21",
4
4
  "description": "Core extension package for Pluss Communities platform",
5
5
  "scripts": {
6
6
  "betapatch": "npm version prepatch --preid=beta",