@stacksjs/email 0.58.72 → 0.59.1

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.
@@ -1,305 +1,305 @@
1
- /* eslint-disable eslint-comments/no-unlimited-disable */
2
- /* eslint-disable */
3
-
4
- const AWS = require('aws-sdk')
5
- const mime = require('mime')
6
- const parser = require('mailparser').simpleParser
7
-
8
- // Initialize S3.
9
- const s3 = new AWS.S3({
10
- apiVersion: '2006-03-01',
11
- })
12
-
13
- // This lambda will read RAW emails and convert them in easy to read formats
14
- // like: HTML and text
15
- exports.handler = (event: any) => {
16
- // 1. We need to process the path received by S3 since AWS dose escape the
17
- // string in a special way. They escape the string in a HTML style
18
- // but for whatever reason they convert spaces in to +ses.
19
- const s3_key = event.Records[0].s3.object.key
20
-
21
- // 2. So first we convert the + in to spaces
22
- const plus_to_space = s3_key.replace(/\+/g, ' ')
23
-
24
- // 3. And then we unescape the string, other wise we lose real + characters
25
- const unescaped_key = decodeURIComponent(plus_to_space)
26
-
27
- // 4. This JS object will contain all the data within the chain
28
- const container = {
29
- bucket: event.Records[0].s3.bucket.name,
30
- key: unescaped_key,
31
- parsed: {
32
- html: '',
33
- text: '',
34
- attachments: [],
35
- },
36
- }
37
-
38
- // -> Start the chain.
39
- load_the_email(container)
40
- .then((container) => {
41
- return remove_extension(container)
42
- }).then((container) => {
43
- return parse_the_email(container)
44
- }).then((container) => {
45
- return save_text(container)
46
- }).then((container) => {
47
- return save_html(container)
48
- }).then((container) => {
49
- return save_attachments(container)
50
- }).then((container) => {
51
- return true
52
- }).catch((error) => {
53
- console.error(error)
54
-
55
- return false
56
- })
57
- }
58
-
59
- // Load the email that triggered the function from S3
60
- function load_the_email(container: any) {
61
- return new Promise((resolve, reject) => {
62
- console.info('load_the_email')
63
-
64
- // 1. Set the query.
65
- const params = {
66
- Bucket: container.bucket,
67
- Key: container.key,
68
- }
69
-
70
- // -> Execute the query
71
- s3.getObject(params, (error: any, data: any) => {
72
- // 1. Check for internal errors
73
- if (error)
74
- return reject(error)
75
-
76
- // 2. Save the email for the next promise
77
- container.raw_email = data.Body
78
-
79
- // -> Move to the next chain.
80
- return resolve(container)
81
- })
82
- })
83
- }
84
-
85
- // Since the raw email is saved with an extension we need to remove it
86
- // before we can save other converted versions.
87
- function remove_extension(container: any) {
88
- return new Promise((resolve, reject) => {
89
- console.info('remove_extension')
90
-
91
- // 1. Split the string.
92
- const tmp = container.key.split('.')
93
-
94
- // 2. Remove the last element from the array which is `eml`.
95
- tmp.pop()
96
-
97
- // 2. Join the array back to how it was, minus the extension.
98
- // We need to do this, since we don't know how many dots
99
- // were in the email title for example.
100
- container.key = tmp.join('.')
101
-
102
- // -> Move to the next chain.
103
- return resolve(container)
104
- })
105
- }
106
-
107
- // Convert the raw email in to HTML and Text, and extract also the attachments
108
- function parse_the_email(container: any) {
109
- return new Promise((resolve, reject) => {
110
- // 1. Parse the email and extract all the necessary
111
- parser(container.raw_email, (error: any, parsed: any) => {
112
- // 1. Check for internal errors
113
- if (error)
114
- return reject(error)
115
-
116
- // 2. Save the parsed email for the next promise.
117
- container.parsed.html = parsed.html
118
- container.parsed.text = parsed.text
119
- container.parsed.attachments = parsed.attachments
120
-
121
- // -> Move to the next chain.
122
- return resolve(container)
123
- })
124
- })
125
- }
126
-
127
- // After the conversion we save the Text version to S3.
128
- function save_text(container: any) {
129
- return new Promise((resolve, reject) => {
130
- console.info('save_text')
131
-
132
- // 1. Set the query
133
- const params = {
134
- Bucket: container.bucket,
135
- Key: `${container.key}.txt`,
136
- Body: container.parsed.text,
137
- }
138
-
139
- // -> Execute the query.
140
- s3.putObject(params, (error: any, data: any) => {
141
- // 1. Check for internal errors.
142
- if (error)
143
- return reject(error)
144
-
145
- // -> Move to the next chain.
146
- return resolve(container)
147
- })
148
- })
149
- }
150
-
151
- // Then if we have a HTML version we try to save that.
152
- function save_html(container: any) {
153
- return new Promise((resolve, reject) => {
154
- // <>> When the body of an email have only one version, meaning it
155
- // does have only the pure text version and no HTML.
156
- // Nodemailer won't generate the HTML for you, it just grabs
157
- // what is in the Email body.
158
- // So, this value will be false, when there is no HTML content in
159
- // the email, and thus we skip this step.
160
- if (!container.parsed.html) {
161
- console.info('save_html - skipped')
162
-
163
- // -> Move to the next chain.
164
- return resolve(container)
165
- }
166
-
167
- console.info('save_html')
168
-
169
- // 1. Set the query.
170
- const params = {
171
- Bucket: container.bucket,
172
- Key: `${container.key}.html`,
173
- Body: container.parsed.html,
174
- }
175
-
176
- // -> Execute the query.
177
- s3.putObject(params, (error: any, data: any) => {
178
- // 1. Check for internal errors.
179
- if (error)
180
- return reject(error)
181
-
182
- // -> Move to the next chain.
183
- return resolve(container)
184
- })
185
- })
186
- }
187
-
188
- // Last thing to do is to save the attachments if there are any. If the
189
- // array is empty the loop will skip itself.
190
- function save_attachments(container: any) {
191
- return new Promise((resolve, reject) => {
192
- console.info('save_attachments')
193
-
194
- // Start the loop which save all the attachments.
195
- loop(1, (error: any) => {
196
- // <<> Check if there was an error.
197
- if (error) {
198
- // -> Stop everything and surface the error.
199
- return reject(container)
200
- }
201
-
202
- // -> Move to the next chain.
203
- return resolve(container)
204
- })
205
-
206
- // This loop will upload all the individual attachments found in a email
207
- function loop(count: any, callback: any) {
208
- // 1. Pop the last element in the array if any.
209
- const file = container.parsed.attachments.pop()
210
-
211
- // 2. If there is nothing left then we stop the loop.
212
- if (!file)
213
- return callback()
214
-
215
- // 3. Get the file name which also contain the file extension.
216
- let file_name = file.filename
217
-
218
- // 4. An email attachment is not required to have a name, this
219
- // mean we need to check if we have a file name and, if not
220
- // we create a general name, so all attachments can be saved
221
- // and accounted for.
222
- if (!file_name) {
223
- // 1. Set the generic name with the count name so we give
224
- // unique names to each attachment.
225
- file_name = `Mail Attachment ${count}`
226
-
227
- // 2. We only count the times we had to set a generic name.
228
- count++
229
- }
230
-
231
- // 5. Split the string to and get the last element of the array
232
- // which should be the file extension.
233
- const extension = file_name.split('.').pop()
234
-
235
- // 6. Then we check if the last element is an extension.
236
- const is_extension = mime.getType(extension)
237
-
238
- // 7. If it isn't, we get one from the content-type header.
239
- if (!is_extension) {
240
- // 1. Make sure we have a content type, since I'm sure
241
- // some emails won't have it if they were malformed.
242
- if (file.contentType) {
243
- // 1. Try to find out the file extension from the
244
- // content-type found in the email message.
245
- let file_type = mime.getExtension(file.contentType)
246
-
247
- // 2. If the extension was not found, then we set a
248
- // default one which will let the user know
249
- // that we don't know the type of the file, while
250
- // also setting the type to txt (for convenience)
251
- // so it can be open by any editor and inspected.
252
- if (!file_type)
253
- file_type = 'unknown_extension.txt'
254
-
255
- // 3. Attach the extension to the file.
256
- file_name += `.${file_type}`
257
- }
258
- }
259
-
260
- // 8. Then save the buffer of the attachment.
261
- const file_body = file.content
262
-
263
- // 9. Split the S3 Key (path) so we can remove the last element. Since
264
- // we don't want the object name, we care only about the path.
265
- const tmp = container.key.split('/')
266
-
267
- // 10. Now remove the last element from the array which is the
268
- // file name that contains the raw email, which we don't want.
269
- tmp.pop()
270
-
271
- // 11. After all this, we recombine the array in to a single
272
- // string which becomes again the S3 Key minus the file name.
273
- const path = tmp.join('/')
274
-
275
- // 12. This variable is used if there are two files of the same name.
276
- let cid = ''
277
-
278
- // 13. If the CID is set then it means that two files have the same names
279
- if (file.cid) {
280
- // 1. Add the CID in front of the name of the file so they won't be overwritten
281
- cid = `${file.cid} - `
282
- }
283
-
284
- // 14. Create the full key path with the object at the end.
285
- const key = `${path}/attachments/${cid}${file_name}`
286
-
287
- // 15. Set the query.
288
- const params = {
289
- Bucket: container.bucket,
290
- Key: key,
291
- Body: file_body,
292
- }
293
-
294
- // -> Execute the query.
295
- s3.putObject(params, (error: any, data: any) => {
296
- // 1. Check for internal errors.
297
- if (error)
298
- return callback(error)
299
-
300
- // -> Move to the next chain.
301
- return loop(count, callback)
302
- })
303
- }
304
- })
305
- }
1
+ // /* eslint-disable eslint-comments/no-unlimited-disable */
2
+ // /* eslint-disable */
3
+ //
4
+ // const AWS = require('aws-sdk')
5
+ // const mime = require('mime')
6
+ // const parser = require('mailparser').simpleParser
7
+ //
8
+ // // Initialize S3.
9
+ // const s3 = new AWS.S3({
10
+ // apiVersion: '2006-03-01',
11
+ // })
12
+ //
13
+ // // This lambda will read RAW emails and convert them in easy to read formats
14
+ // // like: HTML and text
15
+ // exports.handler = (event: any) => {
16
+ // // 1. We need to process the path received by S3 since AWS dose escape the
17
+ // // string in a special way. They escape the string in a HTML style
18
+ // // but for whatever reason they convert spaces in to +ses.
19
+ // const s3_key = event.Records[0].s3.object.key
20
+ //
21
+ // // 2. So first we convert the + in to spaces
22
+ // const plus_to_space = s3_key.replace(/\+/g, ' ')
23
+ //
24
+ // // 3. And then we unescape the string, other wise we lose real + characters
25
+ // const unescaped_key = decodeURIComponent(plus_to_space)
26
+ //
27
+ // // 4. This JS object will contain all the data within the chain
28
+ // const container = {
29
+ // bucket: event.Records[0].s3.bucket.name,
30
+ // key: unescaped_key,
31
+ // parsed: {
32
+ // html: '',
33
+ // text: '',
34
+ // attachments: [],
35
+ // },
36
+ // }
37
+ //
38
+ // // -> Start the chain.
39
+ // load_the_email(container)
40
+ // .then((container) => {
41
+ // return remove_extension(container)
42
+ // }).then((container) => {
43
+ // return parse_the_email(container)
44
+ // }).then((container) => {
45
+ // return save_text(container)
46
+ // }).then((container) => {
47
+ // return save_html(container)
48
+ // }).then((container) => {
49
+ // return save_attachments(container)
50
+ // }).then((container) => {
51
+ // return true
52
+ // }).catch((error) => {
53
+ // console.error(error)
54
+ //
55
+ // return false
56
+ // })
57
+ // }
58
+ //
59
+ // // Load the email that triggered the function from S3
60
+ // function load_the_email(container: any) {
61
+ // return new Promise((resolve, reject) => {
62
+ // console.info('load_the_email')
63
+ //
64
+ // // 1. Set the query.
65
+ // const params = {
66
+ // Bucket: container.bucket,
67
+ // Key: container.key,
68
+ // }
69
+ //
70
+ // // -> Execute the query
71
+ // s3.getObject(params, (error: any, data: any) => {
72
+ // // 1. Check for internal errors
73
+ // if (error)
74
+ // return reject(error)
75
+ //
76
+ // // 2. Save the email for the next promise
77
+ // container.raw_email = data.Body
78
+ //
79
+ // // -> Move to the next chain.
80
+ // return resolve(container)
81
+ // })
82
+ // })
83
+ // }
84
+ //
85
+ // // Since the raw email is saved with an extension we need to remove it
86
+ // // before we can save other converted versions.
87
+ // function remove_extension(container: any) {
88
+ // return new Promise((resolve, reject) => {
89
+ // console.info('remove_extension')
90
+ //
91
+ // // 1. Split the string.
92
+ // const tmp = container.key.split('.')
93
+ //
94
+ // // 2. Remove the last element from the array which is `eml`.
95
+ // tmp.pop()
96
+ //
97
+ // // 2. Join the array back to how it was, minus the extension.
98
+ // // We need to do this, since we don't know how many dots
99
+ // // were in the email title for example.
100
+ // container.key = tmp.join('.')
101
+ //
102
+ // // -> Move to the next chain.
103
+ // return resolve(container)
104
+ // })
105
+ // }
106
+ //
107
+ // // Convert the raw email in to HTML and Text, and extract also the attachments
108
+ // function parse_the_email(container: any) {
109
+ // return new Promise((resolve, reject) => {
110
+ // // 1. Parse the email and extract all the necessary
111
+ // parser(container.raw_email, (error: any, parsed: any) => {
112
+ // // 1. Check for internal errors
113
+ // if (error)
114
+ // return reject(error)
115
+ //
116
+ // // 2. Save the parsed email for the next promise.
117
+ // container.parsed.html = parsed.html
118
+ // container.parsed.text = parsed.text
119
+ // container.parsed.attachments = parsed.attachments
120
+ //
121
+ // // -> Move to the next chain.
122
+ // return resolve(container)
123
+ // })
124
+ // })
125
+ // }
126
+ //
127
+ // // After the conversion we save the Text version to S3.
128
+ // function save_text(container: any) {
129
+ // return new Promise((resolve, reject) => {
130
+ // console.info('save_text')
131
+ //
132
+ // // 1. Set the query
133
+ // const params = {
134
+ // Bucket: container.bucket,
135
+ // Key: `${container.key}.txt`,
136
+ // Body: container.parsed.text,
137
+ // }
138
+ //
139
+ // // -> Execute the query.
140
+ // s3.putObject(params, (error: any, data: any) => {
141
+ // // 1. Check for internal errors.
142
+ // if (error)
143
+ // return reject(error)
144
+ //
145
+ // // -> Move to the next chain.
146
+ // return resolve(container)
147
+ // })
148
+ // })
149
+ // }
150
+ //
151
+ // // Then if we have a HTML version we try to save that.
152
+ // function save_html(container: any) {
153
+ // return new Promise((resolve, reject) => {
154
+ // // <>> When the body of an email have only one version, meaning it
155
+ // // does have only the pure text version and no HTML.
156
+ // // Nodemailer won't generate the HTML for you, it just grabs
157
+ // // what is in the Email body.
158
+ // // So, this value will be false, when there is no HTML content in
159
+ // // the email, and thus we skip this step.
160
+ // if (!container.parsed.html) {
161
+ // console.info('save_html - skipped')
162
+ //
163
+ // // -> Move to the next chain.
164
+ // return resolve(container)
165
+ // }
166
+ //
167
+ // console.info('save_html')
168
+ //
169
+ // // 1. Set the query.
170
+ // const params = {
171
+ // Bucket: container.bucket,
172
+ // Key: `${container.key}.html`,
173
+ // Body: container.parsed.html,
174
+ // }
175
+ //
176
+ // // -> Execute the query.
177
+ // s3.putObject(params, (error: any, data: any) => {
178
+ // // 1. Check for internal errors.
179
+ // if (error)
180
+ // return reject(error)
181
+ //
182
+ // // -> Move to the next chain.
183
+ // return resolve(container)
184
+ // })
185
+ // })
186
+ // }
187
+ //
188
+ // // Last thing to do is to save the attachments if there are any. If the
189
+ // // array is empty the loop will skip itself.
190
+ // function save_attachments(container: any) {
191
+ // return new Promise((resolve, reject) => {
192
+ // console.info('save_attachments')
193
+ //
194
+ // // Start the loop which save all the attachments.
195
+ // loop(1, (error: any) => {
196
+ // // <<> Check if there was an error.
197
+ // if (error) {
198
+ // // -> Stop everything and surface the error.
199
+ // return reject(container)
200
+ // }
201
+ //
202
+ // // -> Move to the next chain.
203
+ // return resolve(container)
204
+ // })
205
+ //
206
+ // // This loop will upload all the individual attachments found in a email
207
+ // function loop(count: any, callback: any) {
208
+ // // 1. Pop the last element in the array if any.
209
+ // const file = container.parsed.attachments.pop()
210
+ //
211
+ // // 2. If there is nothing left then we stop the loop.
212
+ // if (!file)
213
+ // return callback()
214
+ //
215
+ // // 3. Get the file name which also contain the file extension.
216
+ // let file_name = file.filename
217
+ //
218
+ // // 4. An email attachment is not required to have a name, this
219
+ // // mean we need to check if we have a file name and, if not
220
+ // // we create a general name, so all attachments can be saved
221
+ // // and accounted for.
222
+ // if (!file_name) {
223
+ // // 1. Set the generic name with the count name so we give
224
+ // // unique names to each attachment.
225
+ // file_name = `Mail Attachment ${count}`
226
+ //
227
+ // // 2. We only count the times we had to set a generic name.
228
+ // count++
229
+ // }
230
+ //
231
+ // // 5. Split the string to and get the last element of the array
232
+ // // which should be the file extension.
233
+ // const extension = file_name.split('.').pop()
234
+ //
235
+ // // 6. Then we check if the last element is an extension.
236
+ // const is_extension = mime.getType(extension)
237
+ //
238
+ // // 7. If it isn't, we get one from the content-type header.
239
+ // if (!is_extension) {
240
+ // // 1. Make sure we have a content type, since I'm sure
241
+ // // some emails won't have it if they were malformed.
242
+ // if (file.contentType) {
243
+ // // 1. Try to find out the file extension from the
244
+ // // content-type found in the email message.
245
+ // let file_type = mime.getExtension(file.contentType)
246
+ //
247
+ // // 2. If the extension was not found, then we set a
248
+ // // default one which will let the user know
249
+ // // that we don't know the type of the file, while
250
+ // // also setting the type to txt (for convenience)
251
+ // // so it can be open by any editor and inspected.
252
+ // if (!file_type)
253
+ // file_type = 'unknown_extension.txt'
254
+ //
255
+ // // 3. Attach the extension to the file.
256
+ // file_name += `.${file_type}`
257
+ // }
258
+ // }
259
+ //
260
+ // // 8. Then save the buffer of the attachment.
261
+ // const file_body = file.content
262
+ //
263
+ // // 9. Split the S3 Key (path) so we can remove the last element. Since
264
+ // // we don't want the object name, we care only about the path.
265
+ // const tmp = container.key.split('/')
266
+ //
267
+ // // 10. Now remove the last element from the array which is the
268
+ // // file name that contains the raw email, which we don't want.
269
+ // tmp.pop()
270
+ //
271
+ // // 11. After all this, we recombine the array in to a single
272
+ // // string which becomes again the S3 Key minus the file name.
273
+ // const path = tmp.join('/')
274
+ //
275
+ // // 12. This variable is used if there are two files of the same name.
276
+ // let cid = ''
277
+ //
278
+ // // 13. If the CID is set then it means that two files have the same names
279
+ // if (file.cid) {
280
+ // // 1. Add the CID in front of the name of the file so they won't be overwritten
281
+ // cid = `${file.cid} - `
282
+ // }
283
+ //
284
+ // // 14. Create the full key path with the object at the end.
285
+ // const key = `${path}/attachments/${cid}${file_name}`
286
+ //
287
+ // // 15. Set the query.
288
+ // const params = {
289
+ // Bucket: container.bucket,
290
+ // Key: key,
291
+ // Body: file_body,
292
+ // }
293
+ //
294
+ // // -> Execute the query.
295
+ // s3.putObject(params, (error: any, data: any) => {
296
+ // // 1. Check for internal errors.
297
+ // if (error)
298
+ // return callback(error)
299
+ //
300
+ // // -> Move to the next chain.
301
+ // return loop(count, callback)
302
+ // })
303
+ // }
304
+ // })
305
+ // }