@novacraft-engineering/mailbox 0.4.20 → 0.4.22
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/app/mail/page.tsx +16 -8
- package/lib/mailbox.ts +9 -4
- package/package.json +1 -1
package/app/mail/page.tsx
CHANGED
|
@@ -663,6 +663,12 @@ function htmlToQuoteText(html: string | null, text: string | null): string {
|
|
|
663
663
|
* imported without ids fall back to the names mail clients give such parts. Anything
|
|
664
664
|
* larger, or not an image, is a real file.
|
|
665
665
|
*/
|
|
666
|
+
// Some senders put the plain-text body straight into the HTML part. Rendered as markup its
|
|
667
|
+
// line breaks are just whitespace and the message collapses into one paragraph, so a part
|
|
668
|
+
// carrying no tags has to be treated as the text it actually is.
|
|
669
|
+
const hasMarkup = (html: string | null | undefined): html is string =>
|
|
670
|
+
typeof html === 'string' && /<[a-z!/][^>]*>/i.test(html)
|
|
671
|
+
|
|
666
672
|
const INLINE_IMAGE_MAX_BYTES = 150_000
|
|
667
673
|
const INLINE_IMAGE_NAME = /^(image\d*|outlook-[\w-]+|blocked|[0-9a-f]{8}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.(png|gif|jpe?g)$/i
|
|
668
674
|
function inlineAttachmentNames(message: InboundEmail): Set<string> {
|
|
@@ -4978,7 +4984,7 @@ export default function DevMailPage() {
|
|
|
4978
4984
|
img { max-width: 100%; }
|
|
4979
4985
|
</style>`
|
|
4980
4986
|
doc.open()
|
|
4981
|
-
doc.write(`<!doctype html><html><head><meta charset="utf-8"><title>${escapeHtml(subject)}</title>${printCss}</head><body>${meta}${html ? stripOwnPixel(html) : `<pre style="font-family:Arial,sans-serif;white-space:pre-wrap;">${escapeHtml(text
|
|
4987
|
+
doc.write(`<!doctype html><html><head><meta charset="utf-8"><title>${escapeHtml(subject)}</title>${printCss}</head><body>${meta}${hasMarkup(html) ? stripOwnPixel(html) : `<pre style="font-family:Arial,sans-serif;white-space:pre-wrap;">${escapeHtml(text?.trim() || html || '')}</pre>`}</body></html>`)
|
|
4982
4988
|
doc.close()
|
|
4983
4989
|
frame.contentWindow?.focus()
|
|
4984
4990
|
window.setTimeout(() => {
|
|
@@ -5881,13 +5887,14 @@ export default function DevMailPage() {
|
|
|
5881
5887
|
if (readerMode === 'html') return <pre className={styles.readerSource}>{formatHtmlSource(message.html ?? '')}</pre>
|
|
5882
5888
|
if (readerMode === 'raw') return <pre className={styles.readerSource}>{rawInboundMessage(message)}</pre>
|
|
5883
5889
|
// preview
|
|
5884
|
-
if (!message.html) {
|
|
5885
|
-
const
|
|
5890
|
+
if (!hasMarkup(message.html)) {
|
|
5891
|
+
const source = message.text?.trim() ? message.text : (message.html ?? '')
|
|
5892
|
+
const plain = splitQuotedText(source)
|
|
5886
5893
|
const textShown = quoteOpen.has(message.id)
|
|
5887
5894
|
return (
|
|
5888
5895
|
<>
|
|
5889
|
-
{(textShown ?
|
|
5890
|
-
? <pre className={styles.readerText}>{textShown ?
|
|
5896
|
+
{(textShown ? source : plain.head)
|
|
5897
|
+
? <pre className={styles.readerText}>{textShown ? source : plain.head}</pre>
|
|
5891
5898
|
: renderBodylessAttachment(inboundAttachments[message.id] ?? []) ?? <pre className={styles.readerText}>(no content)</pre>}
|
|
5892
5899
|
{plain.tail && renderQuoteLine(message.id, textShown)}
|
|
5893
5900
|
</>
|
|
@@ -5936,7 +5943,7 @@ export default function DevMailPage() {
|
|
|
5936
5943
|
const renderSentBody = (sent: SentEmail) => {
|
|
5937
5944
|
const detail = detailCache[sent.id]
|
|
5938
5945
|
if (!detail) return <div className={styles.threadPending}>Loading message…</div>
|
|
5939
|
-
if (detail.html
|
|
5946
|
+
if (hasMarkup(detail.html)) {
|
|
5940
5947
|
return (
|
|
5941
5948
|
<iframe
|
|
5942
5949
|
className={styles.threadFrame}
|
|
@@ -5952,8 +5959,9 @@ export default function DevMailPage() {
|
|
|
5952
5959
|
/>
|
|
5953
5960
|
)
|
|
5954
5961
|
}
|
|
5955
|
-
|
|
5956
|
-
|
|
5962
|
+
const plainSent = detail.text?.trim() ? detail.text : (detail.html ?? '').trim()
|
|
5963
|
+
return plainSent
|
|
5964
|
+
? <pre className={styles.readerText}>{plainSent}</pre>
|
|
5957
5965
|
: renderBodylessAttachment(detail.attachments ?? []) ?? <pre className={styles.readerText}>(no content)</pre>
|
|
5958
5966
|
}
|
|
5959
5967
|
|
package/lib/mailbox.ts
CHANGED
|
@@ -538,11 +538,16 @@ const THROWAWAY_TLDS_DEFAULT = new Set([
|
|
|
538
538
|
])
|
|
539
539
|
|
|
540
540
|
/** The shape of an advance-fee approach. Counted, never single-word: one alone is innocent. */
|
|
541
|
+
// Only wording that is odd in ordinary business correspondence belongs here. A single
|
|
542
|
+
// generic term is not evidence of anything: an insurance broker writes "beneficiary" and
|
|
543
|
+
// "bank draft" all day, a logistics firm writes "consignment", and every sales team sends
|
|
544
|
+
// a "business proposal". Add them per deployment through MAIL_SCAM_PHRASES if a mailbox
|
|
545
|
+
// genuinely never sees them.
|
|
541
546
|
const SCAM_PHRASES_DEFAULT = [
|
|
542
|
-
'next of kin', 'sole beneficiary', '
|
|
543
|
-
'
|
|
544
|
-
'
|
|
545
|
-
'
|
|
547
|
+
'next of kin', 'sole beneficiary', 'late client', 'deceased client',
|
|
548
|
+
'inheritance', 'died without', 'without a will', 'unclaimed inheritance',
|
|
549
|
+
'winning notification', 'lottery winner', 'western union', 'atm card',
|
|
550
|
+
'transfer to your account immediately', 'strictly confidential and urgent',
|
|
546
551
|
]
|
|
547
552
|
|
|
548
553
|
/** The registrable domain behind an address, for reputation to be keyed on. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novacraft-engineering/mailbox",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.22",
|
|
4
4
|
"description": "A shared webmail app: one codebase, one deployment per mailbox. Threads, a rich composer with signatures, attachments on S3-compatible storage, sharing links, full-text search, web push and PWA install.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"webmail",
|