@novacraft-engineering/mailbox 0.4.19 → 0.4.21

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.
Files changed (2) hide show
  1. package/lib/mailbox.ts +25 -5
  2. package/package.json +1 -1
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', 'beneficiary', 'late client', 'deceased client',
543
- 'unclaimed', 'inheritance', 'died without', 'without a will', 'fund transfer',
544
- 'business proposal', 'strictly confidential', 'bank draft', 'consignment',
545
- 'compensation fund', 'lottery', 'winning notification', 'atm card', 'western union',
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. */
@@ -573,6 +578,17 @@ const listFrom = (raw: string | undefined, fallback: Iterable<string>): Set<stri
573
578
  // Read per call, so a deployment can change any of them without a release.
574
579
  const freeProviders = () => listFrom(process.env.MAIL_FREE_PROVIDERS, FREE_MAIL_DEFAULT)
575
580
  const throwawayTlds = () => listFrom(process.env.MAIL_THROWAWAY_TLDS, THROWAWAY_TLDS_DEFAULT)
581
+
582
+ // Bulk senders put their own bounce domain in From and the real correspondent in Reply-To.
583
+ // That is how the campaign gets replies, not an attempt to redirect them somewhere unexpected.
584
+ const BULK_SENDERS_DEFAULT = new Set([
585
+ 'mailchimpapp.com', 'mcsv.net', 'rsgsv.net', 'mailchimp.com',
586
+ 'sendgrid.net', 'sendgrid.com', 'sparkpostmail.com', 'amazonses.com',
587
+ 'mailgun.org', 'mandrillapp.com', 'postmarkapp.com', 'sendinblue.com',
588
+ 'brevo.com', 'constantcontact.com', 'cmail19.com', 'createsend.com',
589
+ 'hubspotemail.net', 'mailerlite.com', 'klaviyomail.com', 'salesforce.com',
590
+ ])
591
+ const bulkSenders = () => listFrom(process.env.MAIL_BULK_SENDERS, BULK_SENDERS_DEFAULT)
576
592
  const scamPhrases = () => [...listFrom(process.env.MAIL_SCAM_PHRASES, SCAM_PHRASES_DEFAULT)]
577
593
 
578
594
  /** Weight at which a message stops being labelled and is held out of the inbox instead. */
@@ -635,7 +651,11 @@ export function judgeMessage(signals: RiskSignals, standing: SenderStanding): Ri
635
651
  .filter(entry => entry && entry !== fromDomain)
636
652
  const free = freeProviders()
637
653
  const freeReply = replyDomains.find(entry => free.has(entry))
638
- if (freeReply && fromDomain && !free.has(fromDomain)) {
654
+ const bulk = bulkSenders().has(fromDomain)
655
+ if (bulk) {
656
+ // Nothing to say: a campaign's replies are meant to land somewhere other than the
657
+ // sending platform, and treating that as misdirection buries ordinary bulk mail.
658
+ } else if (freeReply && fromDomain && !free.has(fromDomain)) {
639
659
  add(4, `Replies to this message go to ${freeReply}, not to ${fromDomain}`, true)
640
660
  } else if (replyDomains.length) {
641
661
  add(1, `Replies go to ${replyDomains[0]} rather than ${fromDomain || 'the sender'}`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@novacraft-engineering/mailbox",
3
- "version": "0.4.19",
3
+ "version": "0.4.21",
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",