@xuda.io/account_module 1.2.1869 → 1.2.1870

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/index.mjs +49 -48
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -3443,55 +3443,47 @@ export const process_accounts_emails = async function () {
3443
3443
  };
3444
3444
 
3445
3445
  function isLikelySpamEmail(email) {
3446
- debugger;
3447
- if (!email || typeof email !== 'string') return true; // Invalid input → treat as spam
3446
+ if (!email || typeof email !== 'string') return true;
3448
3447
 
3449
3448
  const lower = email.toLowerCase().trim();
3450
3449
 
3451
- // Basic format validation (must have @ and domain)
3450
+ // Must have exactly one @ and non-empty parts
3452
3451
  if (!lower.includes('@') || lower.split('@').length !== 2) return true;
3453
3452
 
3454
3453
  const [localPart, domain] = lower.split('@');
3455
3454
 
3456
3455
  if (!localPart || !domain) return true;
3457
3456
 
3458
- // ────────────────────────────────────────────────
3459
- // 1. Obvious syntax / format red flags
3460
- // ────────────────────────────────────────────────
3457
+ // 1. Obvious syntax/format red flags (RFC 5321/5322 inspired)
3461
3458
  if (
3462
- localPart.length > 64 || // RFC 5321 local-part max
3463
- domain.length > 255 || // RFC 5321 domain max
3459
+ localPart.length > 64 ||
3460
+ domain.length > 255 ||
3464
3461
  localPart.startsWith('.') ||
3465
3462
  localPart.endsWith('.') ||
3466
3463
  localPart.includes('..') ||
3467
3464
  domain.includes('..') ||
3468
3465
  domain.startsWith('-') ||
3469
3466
  domain.endsWith('-') ||
3470
- localPart.match(/[^\w.!#$%&'*+/=?^`{|}~-]/) !== null // illegal chars in local part
3467
+ /[^\w.!#$%&'*+/=?^`{|}~-]/.test(localPart) // illegal chars
3471
3468
  ) {
3472
3469
  return true;
3473
3470
  }
3474
3471
 
3475
- // ────────────────────────────────────────────────
3476
- // 2. Very common spam patterns in local part
3477
- // ────────────────────────────────────────────────
3472
+ // 2. Common spam patterns in local part
3478
3473
  const spamPatterns = [
3479
- /\d{8,}/, // long number strings (e.g. 1234567890user)
3480
- /[a-z]{20,}/, // very long random letters
3481
- /unsubscribe/i, // rare but classic spam sign
3482
- /free|win|bonus|deal|promo/i, // promotional keywords in address
3483
- /\+\d+$/, // + followed only by numbers (often disposable)
3484
- /^[\d\W_]+$/, // only digits & symbols (very suspicious)
3474
+ /\d{8,}/, // long consecutive digits
3475
+ /[a-z]{20,}/, // very long random lowercase (raised threshold)
3476
+ /unsubscribe/i,
3477
+ /free|win|bonus|deal|promo/i,
3478
+ /\+\d+$/, // + followed only by digits
3479
+ /^[\d\W_]+$/, // only digits/symbols/underscores
3485
3480
  ];
3486
3481
 
3487
3482
  if (spamPatterns.some((p) => p.test(localPart))) {
3488
3483
  return true;
3489
3484
  }
3490
3485
 
3491
- // ────────────────────────────────────────────────
3492
- // 3. Common free / disposable / temporary providers
3493
- // (update this list periodically – 2026 common ones)
3494
- // ────────────────────────────────────────────────
3486
+ // 3. Free / major disposable providers
3495
3487
  const freeOrDisposableDomains = new Set([
3496
3488
  'gmail.com',
3497
3489
  'yahoo.com',
@@ -3520,39 +3512,48 @@ function isLikelySpamEmail(email) {
3520
3512
  'mailinator.com',
3521
3513
  'yopmail.com',
3522
3514
  'sharklasers.com',
3523
- // Add more from disposable lists if needed
3515
+ // For real disposables: load dynamically from https://raw.githubusercontent.com/disposable/disposable/master/domains.txt
3516
+ // or https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/main/disposable_email_blocklist.conf
3517
+ // Example: fetch once on startup and build a larger Set
3524
3518
  ]);
3525
3519
 
3526
3520
  if (freeOrDisposableDomains.has(domain)) {
3527
- // Still allow if it looks like a serious role or branded use
3528
- const seriousPrefixes = ['info', 'support', 'sales', 'contact', 'hello', 'team', 'admin', 'office', 'billing'];
3529
- const prefix = localPart.split('+')[0].split('.')[0]; // rough prefix
3530
-
3531
- if (!seriousPrefixes.some((p) => prefix.includes(p))) {
3532
- // Extra lenient length check for free providers
3533
- if (localPart.length > 24 || localPart.match(/\d{6,}/)) {
3534
- return true;
3535
- }
3521
+ const cleanLocal = localPart.split('+')[0]; // ignore +tag completely
3522
+
3523
+ const seriousPrefixes = ['info', 'support', 'sales', 'contact', 'hello', 'team', 'admin', 'office', 'billing', 'help', 'service', 'orders', 'bookings', 'quotes', 'enquiries', 'noreply', 'no-reply', 'business', 'shop', 'store'];
3524
+
3525
+ // Better detection: any segment contains a serious keyword
3526
+ const parts = cleanLocal.split(/[\.-]/);
3527
+ const looksLikeRoleOrBrand = seriousPrefixes.some((p) => parts.some((part) => part.includes(p)));
3528
+
3529
+ if (looksLikeRoleOrBrand) {
3530
+ return false; // trusted-looking on free provider
3531
+ }
3532
+
3533
+ // Extra scrutiny if not role-like
3534
+ if (cleanLocal.length > 24 || /\d{6,}/.test(cleanLocal)) {
3535
+ return true;
3536
3536
  }
3537
- // Otherwise: free provider but looks somewhat legitimate → not spam
3538
- return false;
3537
+
3538
+ return false; // default: allow typical personal use on Gmail etc.
3539
3539
  }
3540
3540
 
3541
- // // ────────────────────────────────────────────────
3542
- // // 4. Very short / meaningless / bot-like local parts
3543
- // // ────────────────────────────────────────────────
3544
- // if (localPart.length < 3 || localPart.match(/^[a-z\d]{1,4}$/)) {
3545
- // return true; // e.g. a1@b.com, xyz@temp.com
3546
- // }
3541
+ // 4. Very short / meaningless / bot-like local parts
3542
+ if (localPart.length < 2 || /^[a-z\d]{1,5}$/.test(localPart)) {
3543
+ return true; // e.g. a1@, xyz12@, but allow real short like "tim@"
3544
+ }
3547
3545
 
3548
- // // ────────────────────────────────────────────────
3549
- // // 5. Suspicious TLDs sometimes used in spam (2026 context)
3550
- // // ────────────────────────────────────────────────
3551
- // const suspiciousTlds = ['.top', '.xyz', '.club', '.online', '.site', '.fun', '.buzz'];
3552
- // if (suspiciousTlds.some((tld) => domain.endsWith(tld))) {
3553
- // return true;
3554
- // }
3546
+ // 5. Suspicious new/low-trust TLDs (still relevant in 2026)
3547
+ const suspiciousTlds = ['.top', '.xyz', '.club', '.online', '.site', '.fun', '.buzz', '.shop', '.store', '.live', '.digital', '.monster'];
3548
+ if (suspiciousTlds.some((tld) => domain.endsWith(tld))) {
3549
+ return true;
3550
+ }
3551
+
3552
+ // Extra: very long local parts are rare for humans
3553
+ if (localPart.length > 40) {
3554
+ return true;
3555
+ }
3555
3556
 
3556
- // Passed most checks probably not spam
3557
+ // Passed → likely legitimate
3557
3558
  return false;
3558
3559
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xuda.io/account_module",
3
- "version": "1.2.1869",
3
+ "version": "1.2.1870",
4
4
  "description": "Xuda Account Server Module",
5
5
  "main": "index.mjs",
6
6
  "dependencies": {