medusa-plugin-ses 2.0.7 → 2.0.10
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/CHANGELOG.md +21 -0
- package/LICENSE +21 -0
- package/README.md +46 -21
- package/api/index.js +3 -2
- package/package.json +2 -1
- package/services/ses.js +296 -288
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
## 2.0.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Remove extraneous code from index.js
|
|
8
|
+
|
|
9
|
+
## 2.0.9
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- The API endpoint will now return a more useful error when the templates are not found or compile errors are encountered rather than simply returning false.
|
|
14
|
+
|
|
15
|
+
## 2.0.8
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Added CHANGELOG
|
|
20
|
+
- The template path option can now be absolute or relative to the Medusa root folder
|
|
21
|
+
- No error will be thrown if html.hbs or text.hbs does not exist, so long as the other exists.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Lacey Pevey
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -2,19 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
Notifications plugin for Medusa ecommerce server that sends transactional emails via AWS SES (Simple Email Service).
|
|
4
4
|
|
|
5
|
+
[Documentation](https://pevey.com/medusa-plugin-ses)
|
|
6
|
+
|
|
7
|
+
If you are not familiar with Medusa, you can learn more on [the project web site](https://www.medusajs.com/).
|
|
8
|
+
|
|
9
|
+
> Medusa is a set of commerce modules and tools that allow you to build rich, reliable, and performant commerce applications without reinventing core commerce logic. The modules can be customized and used to build advanced ecommerce stores, marketplaces, or any product that needs foundational commerce primitives. All modules are open-source and freely available on npm.
|
|
10
|
+
|
|
5
11
|
## Features
|
|
6
12
|
|
|
7
|
-
-
|
|
8
|
-
- ~~Uses the email templating features built into AWS SES~~ Changed in version 2.0. Templates are now stored locally. See Configuration section below.
|
|
13
|
+
- Templates are stored locally.
|
|
9
14
|
- Templates are based on handlebars, so they are compatible with Sendgrid email templates
|
|
10
|
-
-
|
|
11
|
-
- An API endpoint for testing and that can be used with other (non-Medusa)
|
|
15
|
+
- You can refer to the Medusa template reference to see all data fields that are available for each event: [Template Reference](https://docs.medusajs.com/plugins/notifications/sendgrid#template-reference)
|
|
16
|
+
- An API endpoint that is useful for testing and that can be used with other (non-Medusa) portions of your storefront application is included. By default, the endpoint does nothing for security reasons. See configuration options below to enable it.
|
|
17
|
+
|
|
18
|
+
## Changes in 2.0.8
|
|
19
|
+
|
|
20
|
+
- The template path option can now be absolute or relative to the Medusa root folder
|
|
21
|
+
- No error will be thrown if html.hbs or text.hbs does not exist, so long as the other exists.
|
|
22
|
+
|
|
23
|
+
## Node v20
|
|
24
|
+
|
|
25
|
+
- If you are starting to test out Node v20, be sure you give runtime permission for fs reads due to the new Node permissions API. Otherwise, this plugin will not be able to read your email templates from the file system.
|
|
12
26
|
|
|
13
27
|
## Configuration
|
|
14
28
|
|
|
15
29
|
Enable in your medusa-config.js file similar to other plugins:
|
|
16
30
|
|
|
17
|
-
```
|
|
31
|
+
```bash
|
|
18
32
|
{
|
|
19
33
|
resolve: `medusa-plugin-ses`,
|
|
20
34
|
options: {
|
|
@@ -41,23 +55,33 @@ Enable in your medusa-config.js file similar to other plugins:
|
|
|
41
55
|
},
|
|
42
56
|
```
|
|
43
57
|
|
|
44
|
-
The credentials and region are pulled from env variables.
|
|
45
|
-
|
|
58
|
+
The credentials and region are pulled from env variables.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
46
61
|
SES_REGION=""
|
|
47
62
|
SES_ACCESS_KEY_ID=""
|
|
48
63
|
SES_SECRET_ACCESS_KEY=""
|
|
49
64
|
SES_FROM="Cool Company <orders@example.com>"
|
|
50
65
|
SES_ENABLE_ENDPOINT=false
|
|
51
|
-
SES_TEMPLATE_PATH="
|
|
66
|
+
SES_TEMPLATE_PATH="data/templates"
|
|
52
67
|
```
|
|
68
|
+
|
|
53
69
|
- SES_REGION will be for example "us-east-1"
|
|
54
70
|
|
|
55
71
|
- Obtain the access key id and secret access key by creating an IAM user with SES send permissions.
|
|
56
72
|
|
|
57
73
|
- The SES_FROM email address must be a verified sender in your AWS account.
|
|
58
74
|
|
|
59
|
-
-
|
|
60
|
-
|
|
75
|
+
- From version 2.0.8 and on, SES_TEMPLATE_PATH can be absolute (starting with '/', e.g., '/home/pevey/www/medusa/data/templates') or relative (e.g., 'data/templates')
|
|
76
|
+
|
|
77
|
+
Remember that the from email address must be a verified sender in your AWS console.
|
|
78
|
+
Also remember that if your AWS account is still in sandbox mode, you can only SEND emails to verified sender email addresses.
|
|
79
|
+
|
|
80
|
+
## Templates
|
|
81
|
+
|
|
82
|
+
The template path must be the full absolute path to the folder. For example, if your build runs from /home/medusa/medusa-server/, create a 'data/templates' folder and include the entire path in the SES_TEMPLATE_PATH variable.
|
|
83
|
+
|
|
84
|
+
```bash
|
|
61
85
|
medusa-server // root directory
|
|
62
86
|
|-data
|
|
63
87
|
|-templates
|
|
@@ -72,24 +96,25 @@ medusa-server // root directory
|
|
|
72
96
|
|- etc
|
|
73
97
|
```
|
|
74
98
|
|
|
75
|
-
|
|
76
|
-
* subject is required
|
|
77
|
-
* either html or text is required, but one or the other can be blank.
|
|
78
|
-
- The template reference here explains the variables that can be used: https://docs.medusajs.com/add-plugins/sendgrid/#template-reference
|
|
99
|
+
When emails are sent, each of the three parts will be compiled.
|
|
79
100
|
|
|
101
|
+
- Subject is required
|
|
102
|
+
- Either html or text is required, but one or the other can be blank.
|
|
103
|
+
- From version 2.0.8 on, if either the html.hbs or text.hbs does not exist, no error will be thrown so long as the other exists.
|
|
104
|
+
|
|
105
|
+
## Testing
|
|
106
|
+
|
|
107
|
+
This plugin adds an endpoint at http://[server]/ses/send
|
|
80
108
|
|
|
81
|
-
- This plugin adds an endpoint at http://[server]/ses/send
|
|
82
109
|
By default, the endpoint will refuse to send any emails.
|
|
83
|
-
This endpoint may be useful for testing purposes
|
|
84
|
-
|
|
85
|
-
Most people will NOT need to enable this endpoint.
|
|
110
|
+
This endpoint may be useful for testing purposes in a development environment or for use by related applications.
|
|
111
|
+
|
|
112
|
+
There is NO SECURITY on the endpoint by default. Most people will NOT need to enable this endpoint.
|
|
86
113
|
If you are certain that you want to enable it and that you know what you are doing,
|
|
87
114
|
set the environment variable SES_ENABLE_ENDPOINT to "42" (string).
|
|
88
115
|
The unsual setting is meant to prevent enabling by accident or without thought.
|
|
89
116
|
To use the endpoint, POST a json req.body with: template_id, from, to, and data to /ses/send.
|
|
90
|
-
Remember that the from email address must be a verified sender in your AWS console.
|
|
91
|
-
Also remember that if your AWS account is still in sandbox mode, you can only SEND emails to verified sender email addresses.
|
|
92
117
|
|
|
93
118
|
## Acknowledgement
|
|
94
119
|
|
|
95
|
-
This plugin borrows extensively from medusa-plugin-sendgrid by Oliver Juhl.
|
|
120
|
+
This plugin borrows extensively from medusa-plugin-sendgrid by Oliver Juhl.
|
package/api/index.js
CHANGED
|
@@ -22,11 +22,12 @@ var _default = function _default(app) {
|
|
|
22
22
|
});
|
|
23
23
|
var _schema$safeParse = schema.safeParse(req.body),
|
|
24
24
|
success = _schema$safeParse.success,
|
|
25
|
-
error = _schema$safeParse.error
|
|
25
|
+
error = _schema$safeParse.error,
|
|
26
|
+
data = _schema$safeParse.data;
|
|
26
27
|
if (!success) {
|
|
27
28
|
throw new _medusaCoreUtils.MedusaError(_medusaCoreUtils.MedusaError.Types.INVALID_DATA, error);
|
|
28
29
|
}
|
|
29
|
-
sesService.sendEmail(
|
|
30
|
+
sesService.sendEmail(data.template_id, data.from, data.to, data.data).then(function (result) {
|
|
30
31
|
return res.json({
|
|
31
32
|
result: result
|
|
32
33
|
});
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "medusa-plugin-ses",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.10",
|
|
4
4
|
"description": "AWS SES transactional emails using local handlebars templates",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/pevey/medusa-plugin-ses"
|
|
9
9
|
},
|
|
10
|
+
"homepage:": "https://pevey.com/medusa-plugin-ses",
|
|
10
11
|
"author": "Lacey Pevey",
|
|
11
12
|
"license": "MIT",
|
|
12
13
|
"devDependencies": {
|
package/services/ses.js
CHANGED
|
@@ -38,18 +38,18 @@ var SESService = /*#__PURE__*/function (_NotificationService) {
|
|
|
38
38
|
_inherits(SESService, _NotificationService);
|
|
39
39
|
var _super = _createSuper(SESService);
|
|
40
40
|
/**
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
41
|
+
* @param {Object} options - options defined in `medusa-config.js`
|
|
42
|
+
* e.g.
|
|
43
|
+
* {
|
|
44
|
+
* access_key_id: process.env.SES_ACCESS_KEY_ID,
|
|
45
|
+
* secret_access_key: process.env.SES_SECRET_ACCESS_KEY,
|
|
46
|
+
* region: process.env.SES_REGION,
|
|
47
|
+
* from: process.env.SES_FROM,
|
|
48
|
+
* enable_endpoint: process.env.SES_ENABLE_ENDPOINT,
|
|
49
|
+
* template_path: process.env.SES_TEMPLATE_PATH,
|
|
50
|
+
* order_placed_template: 'order_placed',
|
|
51
|
+
* }
|
|
52
|
+
*/
|
|
53
53
|
function SESService(_ref, options) {
|
|
54
54
|
var _this;
|
|
55
55
|
var storeService = _ref.storeService,
|
|
@@ -93,119 +93,238 @@ var SESService = /*#__PURE__*/function (_NotificationService) {
|
|
|
93
93
|
return _this;
|
|
94
94
|
}
|
|
95
95
|
_createClass(SESService, [{
|
|
96
|
-
key: "
|
|
96
|
+
key: "sendNotification",
|
|
97
97
|
value: function () {
|
|
98
|
-
var
|
|
99
|
-
var
|
|
98
|
+
var _sendNotification = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(event, eventData, attachmentGenerator) {
|
|
99
|
+
var templateId, data, _yield$this$compileTe, subject, html, text, sendOptions, attachments, status;
|
|
100
100
|
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
101
101
|
while (1) switch (_context.prev = _context.next) {
|
|
102
102
|
case 0:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
templateId = this.getTemplateId(event);
|
|
104
|
+
if (templateId) {
|
|
105
|
+
_context.next = 3;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
return _context.abrupt("return", false);
|
|
106
109
|
case 3:
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
_context.next = 5;
|
|
111
|
+
return this.fetchData(event, eventData, attachmentGenerator);
|
|
112
|
+
case 5:
|
|
113
|
+
data = _context.sent;
|
|
114
|
+
if (data) {
|
|
115
|
+
_context.next = 8;
|
|
111
116
|
break;
|
|
112
117
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
name: "return-label",
|
|
121
|
-
base64: d.base_64,
|
|
122
|
-
type: d.type
|
|
123
|
-
};
|
|
124
|
-
}));
|
|
118
|
+
return _context.abrupt("return", false);
|
|
119
|
+
case 8:
|
|
120
|
+
if (data.locale) {
|
|
121
|
+
templateId = this.getLocalizedTemplateId(event, data.locale) || templateId;
|
|
122
|
+
}
|
|
123
|
+
_context.next = 11;
|
|
124
|
+
return this.compileTemplate(templateId, data);
|
|
125
125
|
case 11:
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
_yield$this$compileTe = _context.sent;
|
|
127
|
+
subject = _yield$this$compileTe.subject;
|
|
128
|
+
html = _yield$this$compileTe.html;
|
|
129
|
+
text = _yield$this$compileTe.text;
|
|
130
|
+
if (!(!subject || !html && !text)) {
|
|
131
|
+
_context.next = 17;
|
|
128
132
|
break;
|
|
129
133
|
}
|
|
130
|
-
_context.
|
|
131
|
-
return attachmentGenerator.createReturnInvoice(data.order, data.return_request.items);
|
|
132
|
-
case 14:
|
|
133
|
-
base64 = _context.sent;
|
|
134
|
-
attachments.push({
|
|
135
|
-
name: "invoice",
|
|
136
|
-
base64: base64,
|
|
137
|
-
type: "application/pdf"
|
|
138
|
-
});
|
|
139
|
-
case 16:
|
|
140
|
-
return _context.abrupt("return", attachments);
|
|
134
|
+
return _context.abrupt("return", false);
|
|
141
135
|
case 17:
|
|
142
|
-
|
|
143
|
-
|
|
136
|
+
sendOptions = {
|
|
137
|
+
from: this.options_.from,
|
|
138
|
+
to: data.email,
|
|
139
|
+
subject: subject,
|
|
140
|
+
html: html,
|
|
141
|
+
text: text
|
|
142
|
+
};
|
|
143
|
+
_context.next = 20;
|
|
144
|
+
return this.fetchAttachments(event, data, attachmentGenerator);
|
|
145
|
+
case 20:
|
|
146
|
+
attachments = _context.sent;
|
|
147
|
+
if (attachments !== null && attachments !== void 0 && attachments.length) {
|
|
148
|
+
sendOptions.attachments = attachments.map(function (a) {
|
|
149
|
+
return {
|
|
150
|
+
content: a.base64,
|
|
151
|
+
filename: a.name,
|
|
152
|
+
encoding: 'base64',
|
|
153
|
+
contentType: a.type
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
//const status = await this.transporter_.sendMail(sendOptions).then(() => "sent").catch(() => "failed")
|
|
159
|
+
_context.next = 24;
|
|
160
|
+
return this.transporter_.sendMail(sendOptions).then(function () {
|
|
161
|
+
status = "sent";
|
|
162
|
+
})["catch"](function (error) {
|
|
163
|
+
status = "failed";
|
|
164
|
+
console.log(error);
|
|
165
|
+
});
|
|
166
|
+
case 24:
|
|
167
|
+
// We don't want heavy docs stored in DB
|
|
168
|
+
delete sendOptions.attachments;
|
|
169
|
+
return _context.abrupt("return", {
|
|
170
|
+
to: data.email,
|
|
171
|
+
status: status,
|
|
172
|
+
data: sendOptions
|
|
173
|
+
});
|
|
174
|
+
case 26:
|
|
144
175
|
case "end":
|
|
145
176
|
return _context.stop();
|
|
146
177
|
}
|
|
147
178
|
}, _callee, this);
|
|
148
179
|
}));
|
|
149
|
-
function
|
|
150
|
-
return
|
|
180
|
+
function sendNotification(_x, _x2, _x3) {
|
|
181
|
+
return _sendNotification.apply(this, arguments);
|
|
151
182
|
}
|
|
152
|
-
return
|
|
183
|
+
return sendNotification;
|
|
153
184
|
}()
|
|
154
185
|
}, {
|
|
155
|
-
key: "
|
|
186
|
+
key: "resendNotification",
|
|
156
187
|
value: function () {
|
|
157
|
-
var
|
|
188
|
+
var _resendNotification = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(notification, config, attachmentGenerator) {
|
|
189
|
+
var sendOptions, attachs, status;
|
|
158
190
|
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
159
191
|
while (1) switch (_context2.prev = _context2.next) {
|
|
160
192
|
case 0:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
193
|
+
sendOptions = _objectSpread(_objectSpread({}, notification.data), {}, {
|
|
194
|
+
to: config.to || notification.to
|
|
195
|
+
});
|
|
196
|
+
_context2.next = 3;
|
|
197
|
+
return this.fetchAttachments(notification.event_name, notification.data.dynamic_template_data, attachmentGenerator);
|
|
164
198
|
case 3:
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
199
|
+
attachs = _context2.sent;
|
|
200
|
+
sendOptions.attachments = attachs.map(function (a) {
|
|
201
|
+
return {
|
|
202
|
+
content: a.base64,
|
|
203
|
+
filename: a.name,
|
|
204
|
+
encoding: 'base64',
|
|
205
|
+
contentType: a.type
|
|
206
|
+
};
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
//const status = await this.transporter_.sendMail(sendOptions).then(() => "sent").catch(() => "failed")
|
|
210
|
+
_context2.next = 7;
|
|
211
|
+
return this.transporter_.sendMail(sendOptions).then(function () {
|
|
212
|
+
status = "sent";
|
|
213
|
+
})["catch"](function (error) {
|
|
214
|
+
status = "failed";
|
|
215
|
+
console.log(error);
|
|
216
|
+
});
|
|
172
217
|
case 7:
|
|
173
|
-
return _context2.abrupt("return",
|
|
218
|
+
return _context2.abrupt("return", {
|
|
219
|
+
to: sendOptions.to,
|
|
220
|
+
status: status,
|
|
221
|
+
data: sendOptions
|
|
222
|
+
});
|
|
174
223
|
case 8:
|
|
175
|
-
return _context2.abrupt("return", this.swapCreatedData(eventData, attachmentGenerator));
|
|
176
|
-
case 9:
|
|
177
|
-
return _context2.abrupt("return", this.gcCreatedData(eventData, attachmentGenerator));
|
|
178
|
-
case 10:
|
|
179
|
-
return _context2.abrupt("return", this.gcCreatedData(eventData, attachmentGenerator));
|
|
180
|
-
case 11:
|
|
181
|
-
return _context2.abrupt("return", this.orderPlacedData(eventData, attachmentGenerator));
|
|
182
|
-
case 12:
|
|
183
|
-
return _context2.abrupt("return", this.orderShipmentCreatedData(eventData, attachmentGenerator));
|
|
184
|
-
case 13:
|
|
185
|
-
return _context2.abrupt("return", this.orderCanceledData(eventData, attachmentGenerator));
|
|
186
|
-
case 14:
|
|
187
|
-
return _context2.abrupt("return", this.userPasswordResetData(eventData, attachmentGenerator));
|
|
188
|
-
case 15:
|
|
189
|
-
return _context2.abrupt("return", this.customerPasswordResetData(eventData, attachmentGenerator));
|
|
190
|
-
case 16:
|
|
191
|
-
_context2.next = 18;
|
|
192
|
-
return this.restockNotificationData(eventData, attachmentGenerator);
|
|
193
|
-
case 18:
|
|
194
|
-
return _context2.abrupt("return", _context2.sent);
|
|
195
|
-
case 19:
|
|
196
|
-
return _context2.abrupt("return", this.orderRefundCreatedData(eventData, attachmentGenerator));
|
|
197
|
-
case 20:
|
|
198
|
-
return _context2.abrupt("return", {});
|
|
199
|
-
case 21:
|
|
200
224
|
case "end":
|
|
201
225
|
return _context2.stop();
|
|
202
226
|
}
|
|
203
227
|
}, _callee2, this);
|
|
204
228
|
}));
|
|
205
|
-
function
|
|
206
|
-
return
|
|
229
|
+
function resendNotification(_x4, _x5, _x6) {
|
|
230
|
+
return _resendNotification.apply(this, arguments);
|
|
207
231
|
}
|
|
208
|
-
return
|
|
232
|
+
return resendNotification;
|
|
233
|
+
}()
|
|
234
|
+
/**
|
|
235
|
+
* Sends an email using SES.
|
|
236
|
+
* @param {string} template_id - id of template to use
|
|
237
|
+
* @param {string} from - sender of email
|
|
238
|
+
* @param {string} to - receiver of email
|
|
239
|
+
* @param {Object} data - data to send in mail (match with template)
|
|
240
|
+
* @return {Promise} result of the send operation
|
|
241
|
+
*/
|
|
242
|
+
}, {
|
|
243
|
+
key: "sendEmail",
|
|
244
|
+
value: function () {
|
|
245
|
+
var _sendEmail = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(template_id, from, to, data) {
|
|
246
|
+
var _yield$this$compileTe2, subject, html, text;
|
|
247
|
+
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
|
248
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
249
|
+
case 0:
|
|
250
|
+
if (!(this.options_.enable_endpoint !== '42')) {
|
|
251
|
+
_context3.next = 2;
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
return _context3.abrupt("return", false);
|
|
255
|
+
case 2:
|
|
256
|
+
_context3.prev = 2;
|
|
257
|
+
_context3.next = 5;
|
|
258
|
+
return this.compileTemplate(template_id, data);
|
|
259
|
+
case 5:
|
|
260
|
+
_yield$this$compileTe2 = _context3.sent;
|
|
261
|
+
subject = _yield$this$compileTe2.subject;
|
|
262
|
+
html = _yield$this$compileTe2.html;
|
|
263
|
+
text = _yield$this$compileTe2.text;
|
|
264
|
+
if (!(!subject || !html && !text)) {
|
|
265
|
+
_context3.next = 11;
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
return _context3.abrupt("return", {
|
|
269
|
+
message: "Message not sent. Templates were not found or a compile error was encountered.",
|
|
270
|
+
results: {
|
|
271
|
+
subject: subject,
|
|
272
|
+
html: html,
|
|
273
|
+
text: text
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
case 11:
|
|
277
|
+
return _context3.abrupt("return", this.transporter_.sendMail({
|
|
278
|
+
from: from,
|
|
279
|
+
to: to,
|
|
280
|
+
subject: subject,
|
|
281
|
+
html: html,
|
|
282
|
+
text: text
|
|
283
|
+
}));
|
|
284
|
+
case 14:
|
|
285
|
+
_context3.prev = 14;
|
|
286
|
+
_context3.t0 = _context3["catch"](2);
|
|
287
|
+
throw _context3.t0;
|
|
288
|
+
case 17:
|
|
289
|
+
case "end":
|
|
290
|
+
return _context3.stop();
|
|
291
|
+
}
|
|
292
|
+
}, _callee3, this, [[2, 14]]);
|
|
293
|
+
}));
|
|
294
|
+
function sendEmail(_x7, _x8, _x9, _x10) {
|
|
295
|
+
return _sendEmail.apply(this, arguments);
|
|
296
|
+
}
|
|
297
|
+
return sendEmail;
|
|
298
|
+
}()
|
|
299
|
+
}, {
|
|
300
|
+
key: "compileTemplate",
|
|
301
|
+
value: function () {
|
|
302
|
+
var _compileTemplate = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(templateId, data) {
|
|
303
|
+
var base, subjectTemplate, htmlTemplate, textTemplate;
|
|
304
|
+
return _regeneratorRuntime().wrap(function _callee4$(_context4) {
|
|
305
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
306
|
+
case 0:
|
|
307
|
+
base = this.options_.template_path.startsWith('/') ? _path["default"].resolve(this.options_.template_path, templateId) :
|
|
308
|
+
// The path given in options is absolute
|
|
309
|
+
_path["default"].join(__dirname, '../../..', this.options_.template_path, templateId); // The path given in options is relative
|
|
310
|
+
subjectTemplate = _fs["default"].existsSync(_path["default"].join(base, 'subject.hbs')) ? _handlebars["default"].compile(_fs["default"].readFileSync(_path["default"].join(base, 'subject.hbs'), "utf8")) : null;
|
|
311
|
+
htmlTemplate = _fs["default"].existsSync(_path["default"].join(base, 'html.hbs')) ? _handlebars["default"].compile(_fs["default"].readFileSync(_path["default"].join(base, 'html.hbs'), "utf8")) : null;
|
|
312
|
+
textTemplate = _fs["default"].existsSync(_path["default"].join(base, 'text.hbs')) ? _handlebars["default"].compile(_fs["default"].readFileSync(_path["default"].join(base, 'text.hbs'), "utf8")) : null;
|
|
313
|
+
return _context4.abrupt("return", {
|
|
314
|
+
subject: subjectTemplate ? subjectTemplate(data) : null,
|
|
315
|
+
html: htmlTemplate ? htmlTemplate(data) : null,
|
|
316
|
+
text: textTemplate ? textTemplate(data) : null
|
|
317
|
+
});
|
|
318
|
+
case 5:
|
|
319
|
+
case "end":
|
|
320
|
+
return _context4.stop();
|
|
321
|
+
}
|
|
322
|
+
}, _callee4, this);
|
|
323
|
+
}));
|
|
324
|
+
function compileTemplate(_x11, _x12) {
|
|
325
|
+
return _compileTemplate.apply(this, arguments);
|
|
326
|
+
}
|
|
327
|
+
return compileTemplate;
|
|
209
328
|
}()
|
|
210
329
|
}, {
|
|
211
330
|
key: "getLocalizedTemplateId",
|
|
@@ -288,230 +407,119 @@ var SESService = /*#__PURE__*/function (_NotificationService) {
|
|
|
288
407
|
}
|
|
289
408
|
}
|
|
290
409
|
}, {
|
|
291
|
-
key: "
|
|
292
|
-
value: function () {
|
|
293
|
-
var _compileTemplate = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(templateId, data) {
|
|
294
|
-
var base, subjectTemplate, htmlTemplate, textTemplate;
|
|
295
|
-
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
|
296
|
-
while (1) switch (_context3.prev = _context3.next) {
|
|
297
|
-
case 0:
|
|
298
|
-
//const base = path.resolve(__dirname, '../../../', this.options_.template_path, templateId)
|
|
299
|
-
base = _path["default"].resolve(this.options_.template_path, templateId);
|
|
300
|
-
subjectTemplate = _handlebars["default"].compile(_fs["default"].readFileSync(_path["default"].join(base, 'subject.hbs'), "utf8"));
|
|
301
|
-
htmlTemplate = _handlebars["default"].compile(_fs["default"].readFileSync(_path["default"].join(base, 'html.hbs'), "utf8"));
|
|
302
|
-
textTemplate = _handlebars["default"].compile(_fs["default"].readFileSync(_path["default"].join(base, 'text.hbs'), "utf8"));
|
|
303
|
-
return _context3.abrupt("return", {
|
|
304
|
-
subject: subjectTemplate(data),
|
|
305
|
-
html: htmlTemplate(data),
|
|
306
|
-
text: textTemplate(data)
|
|
307
|
-
});
|
|
308
|
-
case 5:
|
|
309
|
-
case "end":
|
|
310
|
-
return _context3.stop();
|
|
311
|
-
}
|
|
312
|
-
}, _callee3, this);
|
|
313
|
-
}));
|
|
314
|
-
function compileTemplate(_x7, _x8) {
|
|
315
|
-
return _compileTemplate.apply(this, arguments);
|
|
316
|
-
}
|
|
317
|
-
return compileTemplate;
|
|
318
|
-
}()
|
|
319
|
-
}, {
|
|
320
|
-
key: "sendNotification",
|
|
410
|
+
key: "fetchAttachments",
|
|
321
411
|
value: function () {
|
|
322
|
-
var
|
|
323
|
-
var
|
|
324
|
-
return _regeneratorRuntime().wrap(function
|
|
325
|
-
while (1) switch (
|
|
412
|
+
var _fetchAttachments = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(event, data, attachmentGenerator) {
|
|
413
|
+
var attachments, _data$return_request, shipping_method, shipping_data, provider, lbl, base64;
|
|
414
|
+
return _regeneratorRuntime().wrap(function _callee5$(_context5) {
|
|
415
|
+
while (1) switch (_context5.prev = _context5.next) {
|
|
326
416
|
case 0:
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
break;
|
|
331
|
-
}
|
|
332
|
-
return _context4.abrupt("return", false);
|
|
417
|
+
_context5.t0 = event;
|
|
418
|
+
_context5.next = _context5.t0 === "swap.created" ? 3 : _context5.t0 === "order.return_requested" ? 3 : 17;
|
|
419
|
+
break;
|
|
333
420
|
case 3:
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (data) {
|
|
339
|
-
_context4.next = 8;
|
|
421
|
+
attachments = [];
|
|
422
|
+
_data$return_request = data.return_request, shipping_method = _data$return_request.shipping_method, shipping_data = _data$return_request.shipping_data;
|
|
423
|
+
if (!shipping_method) {
|
|
424
|
+
_context5.next = 11;
|
|
340
425
|
break;
|
|
341
426
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
427
|
+
provider = shipping_method.shipping_option.provider_id;
|
|
428
|
+
_context5.next = 9;
|
|
429
|
+
return this.fulfillmentProviderService_.retrieveDocuments(provider, shipping_data, "label");
|
|
430
|
+
case 9:
|
|
431
|
+
lbl = _context5.sent;
|
|
432
|
+
attachments = attachments.concat(lbl.map(function (d) {
|
|
433
|
+
return {
|
|
434
|
+
name: "return-label",
|
|
435
|
+
base64: d.base_64,
|
|
436
|
+
type: d.type
|
|
437
|
+
};
|
|
438
|
+
}));
|
|
349
439
|
case 11:
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
html = _yield$this$compileTe.html;
|
|
353
|
-
text = _yield$this$compileTe.text;
|
|
354
|
-
if (!(!subject || !html && !text)) {
|
|
355
|
-
_context4.next = 17;
|
|
440
|
+
if (!(attachmentGenerator && attachmentGenerator.createReturnInvoice)) {
|
|
441
|
+
_context5.next = 16;
|
|
356
442
|
break;
|
|
357
443
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
};
|
|
367
|
-
_context4.next = 20;
|
|
368
|
-
return this.fetchAttachments(event, data, attachmentGenerator);
|
|
369
|
-
case 20:
|
|
370
|
-
attachments = _context4.sent;
|
|
371
|
-
if (attachments !== null && attachments !== void 0 && attachments.length) {
|
|
372
|
-
sendOptions.attachments = attachments.map(function (a) {
|
|
373
|
-
return {
|
|
374
|
-
content: a.base64,
|
|
375
|
-
filename: a.name,
|
|
376
|
-
encoding: 'base64',
|
|
377
|
-
contentType: a.type
|
|
378
|
-
};
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
//const status = await this.transporter_.sendMail(sendOptions).then(() => "sent").catch(() => "failed")
|
|
383
|
-
_context4.next = 24;
|
|
384
|
-
return this.transporter_.sendMail(sendOptions).then(function () {
|
|
385
|
-
status = "sent";
|
|
386
|
-
})["catch"](function (error) {
|
|
387
|
-
status = "failed";
|
|
388
|
-
console.log(error);
|
|
389
|
-
});
|
|
390
|
-
case 24:
|
|
391
|
-
// We don't want heavy docs stored in DB
|
|
392
|
-
delete sendOptions.attachments;
|
|
393
|
-
return _context4.abrupt("return", {
|
|
394
|
-
to: data.email,
|
|
395
|
-
status: status,
|
|
396
|
-
data: sendOptions
|
|
397
|
-
});
|
|
398
|
-
case 26:
|
|
399
|
-
case "end":
|
|
400
|
-
return _context4.stop();
|
|
401
|
-
}
|
|
402
|
-
}, _callee4, this);
|
|
403
|
-
}));
|
|
404
|
-
function sendNotification(_x9, _x10, _x11) {
|
|
405
|
-
return _sendNotification.apply(this, arguments);
|
|
406
|
-
}
|
|
407
|
-
return sendNotification;
|
|
408
|
-
}()
|
|
409
|
-
}, {
|
|
410
|
-
key: "resendNotification",
|
|
411
|
-
value: function () {
|
|
412
|
-
var _resendNotification = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(notification, config, attachmentGenerator) {
|
|
413
|
-
var sendOptions, attachs, status;
|
|
414
|
-
return _regeneratorRuntime().wrap(function _callee5$(_context5) {
|
|
415
|
-
while (1) switch (_context5.prev = _context5.next) {
|
|
416
|
-
case 0:
|
|
417
|
-
sendOptions = _objectSpread(_objectSpread({}, notification.data), {}, {
|
|
418
|
-
to: config.to || notification.to
|
|
419
|
-
});
|
|
420
|
-
_context5.next = 3;
|
|
421
|
-
return this.fetchAttachments(notification.event_name, notification.data.dynamic_template_data, attachmentGenerator);
|
|
422
|
-
case 3:
|
|
423
|
-
attachs = _context5.sent;
|
|
424
|
-
sendOptions.attachments = attachs.map(function (a) {
|
|
425
|
-
return {
|
|
426
|
-
content: a.base64,
|
|
427
|
-
filename: a.name,
|
|
428
|
-
encoding: 'base64',
|
|
429
|
-
contentType: a.type
|
|
430
|
-
};
|
|
431
|
-
});
|
|
432
|
-
|
|
433
|
-
//const status = await this.transporter_.sendMail(sendOptions).then(() => "sent").catch(() => "failed")
|
|
434
|
-
_context5.next = 7;
|
|
435
|
-
return this.transporter_.sendMail(sendOptions).then(function () {
|
|
436
|
-
status = "sent";
|
|
437
|
-
})["catch"](function (error) {
|
|
438
|
-
status = "failed";
|
|
439
|
-
console.log(error);
|
|
440
|
-
});
|
|
441
|
-
case 7:
|
|
442
|
-
return _context5.abrupt("return", {
|
|
443
|
-
to: sendOptions.to,
|
|
444
|
-
status: status,
|
|
445
|
-
data: sendOptions
|
|
444
|
+
_context5.next = 14;
|
|
445
|
+
return attachmentGenerator.createReturnInvoice(data.order, data.return_request.items);
|
|
446
|
+
case 14:
|
|
447
|
+
base64 = _context5.sent;
|
|
448
|
+
attachments.push({
|
|
449
|
+
name: "invoice",
|
|
450
|
+
base64: base64,
|
|
451
|
+
type: "application/pdf"
|
|
446
452
|
});
|
|
447
|
-
case
|
|
453
|
+
case 16:
|
|
454
|
+
return _context5.abrupt("return", attachments);
|
|
455
|
+
case 17:
|
|
456
|
+
return _context5.abrupt("return", []);
|
|
457
|
+
case 18:
|
|
448
458
|
case "end":
|
|
449
459
|
return _context5.stop();
|
|
450
460
|
}
|
|
451
461
|
}, _callee5, this);
|
|
452
462
|
}));
|
|
453
|
-
function
|
|
454
|
-
return
|
|
463
|
+
function fetchAttachments(_x13, _x14, _x15) {
|
|
464
|
+
return _fetchAttachments.apply(this, arguments);
|
|
455
465
|
}
|
|
456
|
-
return
|
|
466
|
+
return fetchAttachments;
|
|
457
467
|
}()
|
|
458
|
-
/**
|
|
459
|
-
* Sends an email using SES.
|
|
460
|
-
* @param {string} template_id - id of template to use
|
|
461
|
-
* @param {string} from - sender of email
|
|
462
|
-
* @param {string} to - receiver of email
|
|
463
|
-
* @param {Object} data - data to send in mail (match with template)
|
|
464
|
-
* @return {Promise} result of the send operation
|
|
465
|
-
*/
|
|
466
468
|
}, {
|
|
467
|
-
key: "
|
|
469
|
+
key: "fetchData",
|
|
468
470
|
value: function () {
|
|
469
|
-
var
|
|
470
|
-
var _yield$this$compileTe2, subject, html, text;
|
|
471
|
+
var _fetchData = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(event, eventData, attachmentGenerator) {
|
|
471
472
|
return _regeneratorRuntime().wrap(function _callee6$(_context6) {
|
|
472
473
|
while (1) switch (_context6.prev = _context6.next) {
|
|
473
474
|
case 0:
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
return _context6.abrupt("return",
|
|
479
|
-
case 2:
|
|
480
|
-
_context6.next = 4;
|
|
481
|
-
return this.compileTemplate(template_id, data);
|
|
475
|
+
_context6.t0 = event;
|
|
476
|
+
_context6.next = _context6.t0 === "order.return_requested" ? 3 : _context6.t0 === "swap.shipment_created" ? 4 : _context6.t0 === "claim.shipment_created" ? 5 : _context6.t0 === "order.items_returned" ? 6 : _context6.t0 === "swap.received" ? 7 : _context6.t0 === "swap.created" ? 8 : _context6.t0 === "gift_card.created" ? 9 : _context6.t0 === "order.gift_card_created" ? 10 : _context6.t0 === "order.placed" ? 11 : _context6.t0 === "order.shipment_created" ? 12 : _context6.t0 === "order.canceled" ? 13 : _context6.t0 === "user.password_reset" ? 14 : _context6.t0 === "customer.password_reset" ? 15 : _context6.t0 === "restock-notification.restocked" ? 16 : _context6.t0 === "order.refund_created" ? 19 : 20;
|
|
477
|
+
break;
|
|
478
|
+
case 3:
|
|
479
|
+
return _context6.abrupt("return", this.returnRequestedData(eventData, attachmentGenerator));
|
|
482
480
|
case 4:
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
return _context6.abrupt("return",
|
|
481
|
+
return _context6.abrupt("return", this.swapShipmentCreatedData(eventData, attachmentGenerator));
|
|
482
|
+
case 5:
|
|
483
|
+
return _context6.abrupt("return", this.claimShipmentCreatedData(eventData, attachmentGenerator));
|
|
484
|
+
case 6:
|
|
485
|
+
return _context6.abrupt("return", this.itemsReturnedData(eventData, attachmentGenerator));
|
|
486
|
+
case 7:
|
|
487
|
+
return _context6.abrupt("return", this.swapReceivedData(eventData, attachmentGenerator));
|
|
488
|
+
case 8:
|
|
489
|
+
return _context6.abrupt("return", this.swapCreatedData(eventData, attachmentGenerator));
|
|
490
|
+
case 9:
|
|
491
|
+
return _context6.abrupt("return", this.gcCreatedData(eventData, attachmentGenerator));
|
|
492
492
|
case 10:
|
|
493
|
-
_context6.
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
}));
|
|
493
|
+
return _context6.abrupt("return", this.gcCreatedData(eventData, attachmentGenerator));
|
|
494
|
+
case 11:
|
|
495
|
+
return _context6.abrupt("return", this.orderPlacedData(eventData, attachmentGenerator));
|
|
496
|
+
case 12:
|
|
497
|
+
return _context6.abrupt("return", this.orderShipmentCreatedData(eventData, attachmentGenerator));
|
|
498
|
+
case 13:
|
|
499
|
+
return _context6.abrupt("return", this.orderCanceledData(eventData, attachmentGenerator));
|
|
501
500
|
case 14:
|
|
502
|
-
_context6.
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
case
|
|
501
|
+
return _context6.abrupt("return", this.userPasswordResetData(eventData, attachmentGenerator));
|
|
502
|
+
case 15:
|
|
503
|
+
return _context6.abrupt("return", this.customerPasswordResetData(eventData, attachmentGenerator));
|
|
504
|
+
case 16:
|
|
505
|
+
_context6.next = 18;
|
|
506
|
+
return this.restockNotificationData(eventData, attachmentGenerator);
|
|
507
|
+
case 18:
|
|
508
|
+
return _context6.abrupt("return", _context6.sent);
|
|
509
|
+
case 19:
|
|
510
|
+
return _context6.abrupt("return", this.orderRefundCreatedData(eventData, attachmentGenerator));
|
|
511
|
+
case 20:
|
|
512
|
+
return _context6.abrupt("return", {});
|
|
513
|
+
case 21:
|
|
506
514
|
case "end":
|
|
507
515
|
return _context6.stop();
|
|
508
516
|
}
|
|
509
|
-
}, _callee6, this
|
|
517
|
+
}, _callee6, this);
|
|
510
518
|
}));
|
|
511
|
-
function
|
|
512
|
-
return
|
|
519
|
+
function fetchData(_x16, _x17, _x18) {
|
|
520
|
+
return _fetchData.apply(this, arguments);
|
|
513
521
|
}
|
|
514
|
-
return
|
|
522
|
+
return fetchData;
|
|
515
523
|
}()
|
|
516
524
|
}, {
|
|
517
525
|
key: "orderShipmentCreatedData",
|