@stacksjs/email 0.58.59 → 0.58.61

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/email",
3
3
  "type": "module",
4
- "version": "0.58.59",
4
+ "version": "0.58.61",
5
5
  "description": "The Stacks Email integration. Painlessly create & manage your inboxes, templates, and send emails.",
6
6
  "author": "Chris Breuer",
7
7
  "license": "MIT",
@@ -71,6 +71,7 @@
71
71
  "@stacksjs/error-handling": "latest",
72
72
  "@stacksjs/types": "latest",
73
73
  "@types/mailparser": "^3.4.4",
74
+ "aws-sdk": "^2.1555.0",
74
75
  "mailparser": "^3.6.7",
75
76
  "mime": "^4.0.1",
76
77
  "moment": "^2.30.1",
@@ -12,7 +12,7 @@ const s3 = new AWS.S3({
12
12
 
13
13
  // This lambda will read RAW emails and convert them in easy to read formats
14
14
  // like: HTML and text
15
- exports.handler = (event) => {
15
+ exports.handler = (event: any) => {
16
16
  // 1. We need to process the path received by S3 since AWS dose escape the
17
17
  // string in a special way. They escape the string in a HTML style
18
18
  // but for whatever reason they convert spaces in to +ses.
@@ -57,7 +57,7 @@ exports.handler = (event) => {
57
57
  }
58
58
 
59
59
  // Load the email that triggered the function from S3
60
- function load_the_email(container) {
60
+ function load_the_email(container: any) {
61
61
  return new Promise((resolve, reject) => {
62
62
  console.info('load_the_email')
63
63
 
@@ -68,7 +68,7 @@ function load_the_email(container) {
68
68
  }
69
69
 
70
70
  // -> Execute the query
71
- s3.getObject(params, (error, data) => {
71
+ s3.getObject(params, (error: any, data: any) => {
72
72
  // 1. Check for internal errors
73
73
  if (error)
74
74
  return reject(error)
@@ -84,7 +84,7 @@ function load_the_email(container) {
84
84
 
85
85
  // Since the raw email is saved with an extension we need to remove it
86
86
  // before we can save other converted versions.
87
- function remove_extension(container) {
87
+ function remove_extension(container: any) {
88
88
  return new Promise((resolve, reject) => {
89
89
  console.info('remove_extension')
90
90
 
@@ -105,11 +105,11 @@ function remove_extension(container) {
105
105
  }
106
106
 
107
107
  // Convert the raw email in to HTML and Text, and extract also the attachments
108
- function parse_the_email(container) {
108
+ function parse_the_email(container: any) {
109
109
  return new Promise((resolve, reject) => {
110
- // 1. Parse the email and extract all the it necessary.
111
- parser(container.raw_email, (error, parsed) => {
112
- // 1. Check for internal errors.
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
113
  if (error)
114
114
  return reject(error)
115
115
 
@@ -125,7 +125,7 @@ function parse_the_email(container) {
125
125
  }
126
126
 
127
127
  // After the conversion we save the Text version to S3.
128
- function save_text(container) {
128
+ function save_text(container: any) {
129
129
  return new Promise((resolve, reject) => {
130
130
  console.info('save_text')
131
131
 
@@ -137,7 +137,7 @@ function save_text(container) {
137
137
  }
138
138
 
139
139
  // -> Execute the query.
140
- s3.putObject(params, (error, data) => {
140
+ s3.putObject(params, (error: any, data: any) => {
141
141
  // 1. Check for internal errors.
142
142
  if (error)
143
143
  return reject(error)
@@ -149,10 +149,10 @@ function save_text(container) {
149
149
  }
150
150
 
151
151
  // Then if we have a HTML version we try to save that.
152
- function save_html(container) {
152
+ function save_html(container: any) {
153
153
  return new Promise((resolve, reject) => {
154
154
  // <>> When the body of an email have only one version, meaning it
155
- // dose have only the pure text version and no HTML.
155
+ // does have only the pure text version and no HTML.
156
156
  // Nodemailer won't generate the HTML for you, it just grabs
157
157
  // what is in the Email body.
158
158
  // So, this value will be false, when there is no HTML content in
@@ -174,7 +174,7 @@ function save_html(container) {
174
174
  }
175
175
 
176
176
  // -> Execute the query.
177
- s3.putObject(params, (error, data) => {
177
+ s3.putObject(params, (error: any, data: any) => {
178
178
  // 1. Check for internal errors.
179
179
  if (error)
180
180
  return reject(error)
@@ -187,12 +187,12 @@ function save_html(container) {
187
187
 
188
188
  // Last thing to do is to save the attachments if there are any. If the
189
189
  // array is empty the loop will skip itself.
190
- function save_attachments(container) {
190
+ function save_attachments(container: any) {
191
191
  return new Promise((resolve, reject) => {
192
192
  console.info('save_attachments')
193
193
 
194
194
  // Start the loop which save all the attachments.
195
- loop(1, (error) => {
195
+ loop(1, (error: any) => {
196
196
  // <<> Check if there was an error.
197
197
  if (error) {
198
198
  // -> Stop everything and surface the error.
@@ -204,7 +204,7 @@ function save_attachments(container) {
204
204
  })
205
205
 
206
206
  // This loop will upload all the individual attachments found in a email
207
- function loop(count, callback) {
207
+ function loop(count: any, callback: any) {
208
208
  // 1. Pop the last element in the array if any.
209
209
  const file = container.parsed.attachments.pop()
210
210
 
@@ -213,7 +213,7 @@ function save_attachments(container) {
213
213
  return callback()
214
214
 
215
215
  // 3. Get the file name which also contain the file extension.
216
- file_name = file.filename
216
+ let file_name = file.filename
217
217
 
218
218
  // 4. An email attachment is not required to have a name, this
219
219
  // mean we need to check if we have a file name and, if not
@@ -258,7 +258,7 @@ function save_attachments(container) {
258
258
  }
259
259
 
260
260
  // 8. Then save the buffer of the attachment.
261
- file_body = file.content
261
+ const file_body = file.content
262
262
 
263
263
  // 9. Split the S3 Key (path) so we can remove the last element. Since
264
264
  // we don't want the object name, we care only about the path.
@@ -292,7 +292,7 @@ function save_attachments(container) {
292
292
  }
293
293
 
294
294
  // -> Execute the query.
295
- s3.putObject(params, (error, data) => {
295
+ s3.putObject(params, (error: any, data: any) => {
296
296
  // 1. Check for internal errors.
297
297
  if (error)
298
298
  return callback(error)
@@ -55,7 +55,7 @@ interface S3Event {
55
55
  }
56
56
 
57
57
  // This Lambda will filter all the incoming emails based on their From and To field
58
- export function handler(event: S3Event): Promise<boolean> {
58
+ export function handler(event: S3Event): Promise<any> {
59
59
  // if (!event.Records.length)
60
60
  // throw new Error('No records in the event')
61
61
 
@@ -96,6 +96,8 @@ export function handler(event: S3Event): Promise<boolean> {
96
96
 
97
97
  return false
98
98
  })
99
+
100
+ return Promise.resolve()
99
101
  }
100
102
 
101
103
  // List all the emails added to SES, so we can use them to decided where to
@@ -202,7 +204,8 @@ function parse_the_email(container: Container): Promise<Container> {
202
204
  // Save the parsed email for the next promise.
203
205
  container.date = data.date
204
206
  container.from = data.from?.value[0]?.address
205
- container.to = data.to?.value[0]?.address
207
+ // container.to = data.to?.value[0]?.address
208
+ container.to = data.from?.value[0]?.address
206
209
  container.subject = data.subject || 'No Subject'
207
210
  container.message_id = data.messageId
208
211
 
@@ -236,13 +239,26 @@ function extract_data(container: Container): Promise<Container> {
236
239
  // Since the email string can come in a form of:
237
240
  // Name Last <name@example.com>
238
241
  // We have to extract just the email address, and discard the rest
239
- const tmp_to = container.to
240
- .match(/(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|\\[\x01-\x09\x0B\x0C\x0E-\x7F])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21-\x5A\x53-\x7F]|\\[\x01-\x09\x0B\x0C\x0E-\x7F])+)\])/gm)[0]
241
- .split('@')
242
+ let tmp_to
243
+ if (container?.to) {
244
+ const matchResult = container.to.match(/(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|\\[\x01-\x09\x0B\x0C\x0E-\x7F])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21-\x5A\x53-\x7F]|\\[\x01-\x09\x0B\x0C\x0E-\x7F])+)\])/gm);
245
+ if (matchResult) {
246
+ tmp_to = matchResult[0].split('@');
247
+ // Continue with your logic using tmp_to
248
+ }
249
+ }
250
+
251
+ let tmp_from
252
+ if (container?.from) {
253
+ const matchResult = container.from.match(/(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|\\[\x01-\x09\x0B\x0C\x0E-\x7F])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21-\x5A\x53-\x7F]|\\[\x01-\x09\x0B\x0C\x0E-\x7F])+)\])/gm)
254
+ if (matchResult) {
255
+ tmp_from = matchResult[0].split('@');
256
+ // Continue with your logic using tmp_to
257
+ }
258
+ }
242
259
 
243
- const tmp_from = container.from
244
- .match(/(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|\\[\x01-\x09\x0B\x0C\x0E-\x7F])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21-\x5A\x53-\x7F]|\\[\x01-\x09\x0B\x0C\x0E-\x7F])+)\])/gm)[0]
245
- .split('@')
260
+ if (!tmp_to || !tmp_from)
261
+ return reject(Error('No To or From field in the email'))
246
262
 
247
263
  // Get the domain name of the receiving end, so we can group
248
264
  // emails by all the domain that were added to SES.
@@ -18,7 +18,7 @@ const ses = new AWS.SES({
18
18
 
19
19
  // This lambda will read outgoing emails formatted in JSON, convert them
20
20
  // in to a raw email, send them using SES, and store them in S3.
21
- exports.handler = (event) => {
21
+ exports.handler = (event: any) => {
22
22
  // This JS object will contain all the data within the chain
23
23
  const container = {
24
24
  bucket: event.Records[0].s3.bucket.name,
@@ -56,7 +56,7 @@ exports.handler = (event) => {
56
56
  }
57
57
 
58
58
  // Load the JSON email that triggered this Lambda.
59
- function load_the_email(container) {
59
+ function load_the_email(container: any) {
60
60
  return new Promise((resolve, reject) => {
61
61
  console.info('load_the_email')
62
62
 
@@ -67,7 +67,7 @@ function load_the_email(container) {
67
67
  }
68
68
 
69
69
  // -> Execute the query.
70
- s3.getObject(params, (error, data) => {
70
+ s3.getObject(params, (error: any, data: any) => {
71
71
  // 1. Check for internal errors.
72
72
  if (error)
73
73
  return reject(error)
@@ -82,7 +82,7 @@ function load_the_email(container) {
82
82
  }
83
83
 
84
84
  // Extract all the data necessary to organize the incoming emails.
85
- function extract_data(container) {
85
+ function extract_data(container: any) {
86
86
  return new Promise((resolve, reject) => {
87
87
  console.info('extract_data')
88
88
 
@@ -116,7 +116,7 @@ function extract_data(container) {
116
116
 
117
117
  // 6. Create a human readable time stamp that matches the format
118
118
  // S3 Provides in its Event.
119
- date = moment().format('ddd, DD MMM YYYY HH:MM:SS ZZ')
119
+ const date = moment().format('ddd, DD MMM YYYY HH:MM:SS ZZ')
120
120
 
121
121
  // 7. Create the path where the email needs to be moved
122
122
  // so it is properly organized.
@@ -145,7 +145,7 @@ function extract_data(container) {
145
145
 
146
146
  // From the JSON file that we loaded in to memory we generate a RAW version that
147
147
  // can be used by SES, and later on stored and converted in multiple formats
148
- function generate_the_raw_email(container, callback) {
148
+ function generate_the_raw_email(container: any) {
149
149
  return new Promise((resolve, reject) => {
150
150
  console.info('generate_the_raw_email')
151
151
 
@@ -154,7 +154,7 @@ function generate_the_raw_email(container, callback) {
154
154
  const mail = new MailComposer(container.email.json)
155
155
 
156
156
  // 2. Take the email and compile it down to its text form for storage.
157
- mail.compile().build((error, raw_message) => {
157
+ mail.compile().build((error: any, raw_message: any) => {
158
158
  // 1. Check if there was an error
159
159
  if (error)
160
160
  return reject(error)
@@ -169,7 +169,7 @@ function generate_the_raw_email(container, callback) {
169
169
  }
170
170
 
171
171
  // Use the newly generated RAW email and send it using SES.
172
- function send_email(container) {
172
+ function send_email(container: any) {
173
173
  return new Promise((resolve, reject) => {
174
174
  console.info('send_email')
175
175
 
@@ -181,7 +181,7 @@ function send_email(container) {
181
181
  }
182
182
 
183
183
  // -> Send the email out
184
- ses.sendRawEmail(params, (error, data) => {
184
+ ses.sendRawEmail(params, (error: any, data: any) => {
185
185
  // 1. Check if there was an error
186
186
  if (error)
187
187
  return reject(error)
@@ -202,7 +202,7 @@ function send_email(container) {
202
202
  // and then we copy the object to the final destination, which triggers
203
203
  // the Convert action, and once the convert action makes a PUT nothing else
204
204
  // happens.
205
- function save_raw_email(container) {
205
+ function save_raw_email(container: any) {
206
206
  return new Promise((resolve, reject) => {
207
207
  console.info('save_raw_email')
208
208
 
@@ -214,7 +214,7 @@ function save_raw_email(container) {
214
214
  }
215
215
 
216
216
  // -> Execute the query.
217
- s3.putObject(params, (error, data) => {
217
+ s3.putObject(params, (error: any, data: any) => {
218
218
  // 1. Check for internal errors.
219
219
  if (error)
220
220
  return reject(error)
@@ -226,7 +226,7 @@ function save_raw_email(container) {
226
226
  }
227
227
 
228
228
  // Now that we have our RAW email saved we do a copy event so it will trigger the Conversion Lambda
229
- function copy_raw_email(container) {
229
+ function copy_raw_email(container: any) {
230
230
  return new Promise((resolve, reject) => {
231
231
  console.info('copy_raw_email')
232
232
 
@@ -238,7 +238,7 @@ function copy_raw_email(container) {
238
238
  }
239
239
 
240
240
  // -> Execute the query.
241
- s3.copyObject(params, (error, data) => {
241
+ s3.copyObject(params, (error: any, data: any) => {
242
242
  // 1. Check for internal errors.
243
243
  if (error)
244
244
  return reject(error)
@@ -250,7 +250,7 @@ function copy_raw_email(container) {
250
250
  }
251
251
 
252
252
  // And before we finish we clean up the environment by deleting the JSON email,
253
- function delete_json_email(container) {
253
+ function delete_json_email(container: any) {
254
254
  return new Promise((resolve, reject) => {
255
255
  console.info('delete_json_email')
256
256
 
@@ -261,7 +261,7 @@ function delete_json_email(container) {
261
261
  }
262
262
 
263
263
  // -> Execute the query.
264
- s3.deleteObject(params, (error, data) => {
264
+ s3.deleteObject(params, (error: any, data: any) => {
265
265
  // 1. Check for internal errors.
266
266
  if (error)
267
267
  return reject(error)
@@ -273,7 +273,7 @@ function delete_json_email(container) {
273
273
  }
274
274
 
275
275
  // And the temporary RAW email.
276
- function delete_raw_email(container) {
276
+ function delete_raw_email(container: any) {
277
277
  return new Promise((resolve, reject) => {
278
278
  console.info('delete_raw_email')
279
279
 
@@ -284,7 +284,7 @@ function delete_raw_email(container) {
284
284
  }
285
285
 
286
286
  // -> Execute the query.
287
- s3.deleteObject(params, (error, data) => {
287
+ s3.deleteObject(params, (error: any, data: any) => {
288
288
  // 1. Check for internal errors.
289
289
  if (error)
290
290
  return reject(error)