@asd20/ui-next 2.31.6 → 2.31.8
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
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.31.8](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.31.7...ui-next-v2.31.8) (2026-10-12)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* refine 'send an email' functionality - help text, failure messaging, rate limits, spam detection ([a9c4a28](https://github.com/academydistrict20/asd20-ui-next/commit/a9c4a28f1fdab4c0c551aa2cfb6808fbc29742d2))
|
|
9
|
+
|
|
10
|
+
## [2.31.7](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.31.6...ui-next-v2.31.7) (2026-10-12)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* update pdfservice docs; implement new email moderation for phishing ([1beb60d](https://github.com/academydistrict20/asd20-ui-next/commit/1beb60d764a8136d00773a1d81cc11a64fdc335b))
|
|
16
|
+
|
|
3
17
|
## [2.31.6](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.31.5...ui-next-v2.31.6) (2026-10-12)
|
|
4
18
|
|
|
5
19
|
|
package/package.json
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
:validator="validateMessageBody"
|
|
42
42
|
label="Message"
|
|
43
43
|
maxlength="8000"
|
|
44
|
-
help-text="
|
|
44
|
+
:help-text="messageHelpText"
|
|
45
45
|
required
|
|
46
46
|
@validated="validationErrors.messageBody = $event"
|
|
47
47
|
/>
|
|
@@ -124,6 +124,8 @@ import Asd20Button from '../../atoms/Asd20Button'
|
|
|
124
124
|
import Recaptcha from '../../utils/Recaptcha'
|
|
125
125
|
import sendEmail from '../../../helpers/sendEmail.js'
|
|
126
126
|
|
|
127
|
+
const MIN_MESSAGE_LENGTH = 10
|
|
128
|
+
|
|
127
129
|
export default {
|
|
128
130
|
name: 'Asd20ComposeEmailModal',
|
|
129
131
|
components: {
|
|
@@ -161,6 +163,11 @@ export default {
|
|
|
161
163
|
},
|
|
162
164
|
}),
|
|
163
165
|
computed: {
|
|
166
|
+
messageHelpText() {
|
|
167
|
+
return String(this.emailMessage.messageBody || '').trim().length < MIN_MESSAGE_LENGTH
|
|
168
|
+
? 'Please provide more detail.'
|
|
169
|
+
: ''
|
|
170
|
+
},
|
|
164
171
|
modalTitle() {
|
|
165
172
|
return 'Send an Email'
|
|
166
173
|
},
|
|
@@ -228,8 +235,8 @@ export default {
|
|
|
228
235
|
},
|
|
229
236
|
validateMessageBody({ value, validationErrors }) {
|
|
230
237
|
const message = String(value || '').trim()
|
|
231
|
-
if (message && message.length <
|
|
232
|
-
validationErrors.push('
|
|
238
|
+
if (message && message.length < MIN_MESSAGE_LENGTH)
|
|
239
|
+
validationErrors.push('Please provide more detail.')
|
|
233
240
|
return validationErrors
|
|
234
241
|
},
|
|
235
242
|
getFormValidationMessages() {
|
|
@@ -247,8 +254,8 @@ export default {
|
|
|
247
254
|
messages.push('Enter a valid email address.')
|
|
248
255
|
if (!subject) messages.push('A subject is required.')
|
|
249
256
|
if (!messageBody) messages.push('A message is required.')
|
|
250
|
-
else if (messageBody.length <
|
|
251
|
-
messages.push('
|
|
257
|
+
else if (messageBody.length < MIN_MESSAGE_LENGTH)
|
|
258
|
+
messages.push('Please provide more detail.')
|
|
252
259
|
|
|
253
260
|
return messages
|
|
254
261
|
},
|
|
@@ -304,11 +311,25 @@ export default {
|
|
|
304
311
|
const statusMatch = String(error?.message || '').match(/\b(\d{3})\b/)
|
|
305
312
|
return statusMatch ? Number(statusMatch[1]) : null
|
|
306
313
|
},
|
|
314
|
+
isDeliveryUnconfirmed(error) {
|
|
315
|
+
return this.getSendEmailResponseData(error)?.code === 'delivery_unconfirmed' || this.getSendEmailErrorStatus(error) === null
|
|
316
|
+
},
|
|
307
317
|
getSendEmailFailureMessage(error) {
|
|
318
|
+
if (this.isDeliveryUnconfirmed(error)) {
|
|
319
|
+
return "We couldn't confirm that your message was sent. Please check with the school before sending it again."
|
|
320
|
+
}
|
|
308
321
|
if (this.getSendEmailErrorStatus(error) === 429) {
|
|
322
|
+
const response = this.getSendEmailResponseData(error)
|
|
323
|
+
if (response?.code === 'rate_limited' && typeof response.error === 'string' && response.error.trim()) {
|
|
324
|
+
return response.error
|
|
325
|
+
}
|
|
309
326
|
return 'We could not send your message right now. Please wait and try again later.'
|
|
310
327
|
}
|
|
311
328
|
|
|
329
|
+
const response = this.getSendEmailResponseData(error)
|
|
330
|
+
if (['captcha_failed', 'email_unavailable'].includes(response?.code) && typeof response.error === 'string' && response.error.trim()) {
|
|
331
|
+
return response.error
|
|
332
|
+
}
|
|
312
333
|
return 'Something went wrong while sending your email. Please try again later.'
|
|
313
334
|
},
|
|
314
335
|
getSendEmailResponseData(error) {
|
|
@@ -326,7 +347,9 @@ export default {
|
|
|
326
347
|
},
|
|
327
348
|
isModerationRejection(error) {
|
|
328
349
|
return (
|
|
329
|
-
|
|
350
|
+
['moderation_rejected', 'moderation_unavailable'].includes(
|
|
351
|
+
this.getSendEmailResponseData(error)?.code
|
|
352
|
+
)
|
|
330
353
|
)
|
|
331
354
|
},
|
|
332
355
|
getServerValidationMessages(error) {
|
|
@@ -339,7 +362,7 @@ export default {
|
|
|
339
362
|
'Enter a valid email address.',
|
|
340
363
|
'messageBody is required.': 'A message is required.',
|
|
341
364
|
'messageBody is too short.':
|
|
342
|
-
'
|
|
365
|
+
'Please provide more detail.',
|
|
343
366
|
'messageBody is too long.':
|
|
344
367
|
'The message must be 8,000 characters or fewer.',
|
|
345
368
|
'Recipient was not found or does not have a public email address.':
|
|
@@ -363,16 +386,27 @@ export default {
|
|
|
363
386
|
}
|
|
364
387
|
|
|
365
388
|
if (this.isModerationRejection(error)) {
|
|
389
|
+
const response = this.getSendEmailResponseData(error)
|
|
390
|
+
const submissionId = String(response?.submissionId || '')
|
|
391
|
+
const reference = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(submissionId)
|
|
392
|
+
? [`Reference: ${submissionId}`]
|
|
393
|
+
: []
|
|
366
394
|
this.showFeedback(
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
395
|
+
response?.code === 'moderation_unavailable'
|
|
396
|
+
? 'Email temporarily unavailable'
|
|
397
|
+
: 'Message not sent',
|
|
398
|
+
typeof response?.error === 'string' && response.error.trim()
|
|
399
|
+
? response.error
|
|
400
|
+
: response?.code === 'moderation_unavailable'
|
|
401
|
+
? "We couldn't send your message right now. Please try again later. If the problem persists, please contact the Academy District 20 Help Desk at help@asd20.org or 719-234-1777."
|
|
402
|
+
: 'Your message could not be sent through this form.',
|
|
403
|
+
reference
|
|
370
404
|
)
|
|
371
405
|
return
|
|
372
406
|
}
|
|
373
407
|
|
|
374
408
|
this.showFeedback(
|
|
375
|
-
'Email not sent',
|
|
409
|
+
this.isDeliveryUnconfirmed(error) ? 'Delivery not confirmed' : 'Email not sent',
|
|
376
410
|
this.getSendEmailFailureMessage(error),
|
|
377
411
|
[]
|
|
378
412
|
)
|