@xuda.io/account_module 1.2.1871 → 1.2.1872

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 +56 -34
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -3455,36 +3455,26 @@ function isLikelySpamEmail(email) {
3455
3455
 
3456
3456
  if (!localPart || !domain) return true;
3457
3457
 
3458
- // 1. Obvious syntax/format red flags (RFC 5321/5322 inspired)
3459
- if (
3460
- localPart.length > 64 ||
3461
- domain.length > 255 ||
3462
- localPart.startsWith('.') ||
3463
- localPart.endsWith('.') ||
3464
- localPart.includes('..') ||
3465
- domain.includes('..') ||
3466
- domain.startsWith('-') ||
3467
- domain.endsWith('-') ||
3468
- /[^\w.!#$%&'*+/=?^`{|}~-]/.test(localPart) // illegal chars
3469
- ) {
3458
+ // 1. Obvious syntax/format red flags (unchanged strict is good here)
3459
+ if (localPart.length > 64 || domain.length > 255 || localPart.startsWith('.') || localPart.endsWith('.') || localPart.includes('..') || domain.includes('..') || domain.startsWith('-') || domain.endsWith('-') || /[^\w.!#$%&'*+/=?^`{|}~-]/.test(localPart)) {
3470
3460
  return true;
3471
3461
  }
3472
3462
 
3473
- // 2. Common spam patterns in local part
3463
+ // 2. Common spam patterns (unchanged these are strong signals)
3474
3464
  const spamPatterns = [
3475
3465
  /\d{8,}/, // long consecutive digits
3476
- /[a-z]{20,}/, // very long random lowercase (raised threshold)
3466
+ /[a-z]{20,}/, // very long random lowercase
3477
3467
  /unsubscribe/i,
3478
3468
  /free|win|bonus|deal|promo/i,
3479
- /\+\d+$/, // + followed only by digits
3480
- /^[\d\W_]+$/, // only digits/symbols/underscores
3469
+ /\+\d+$/,
3470
+ /^[\d\W_]+$/,
3481
3471
  ];
3482
3472
 
3483
3473
  if (spamPatterns.some((p) => p.test(localPart))) {
3484
3474
  return true;
3485
3475
  }
3486
3476
 
3487
- // 3. Free / major disposable providers
3477
+ // 3. Free / major disposable providers — RELAXED
3488
3478
  const freeOrDisposableDomains = new Set([
3489
3479
  'gmail.com',
3490
3480
  'yahoo.com',
@@ -3513,44 +3503,76 @@ function isLikelySpamEmail(email) {
3513
3503
  'mailinator.com',
3514
3504
  'yopmail.com',
3515
3505
  'sharklasers.com',
3516
- // For real disposables: load dynamically from https://raw.githubusercontent.com/disposable/disposable/master/domains.txt
3517
- // or https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/main/disposable_email_blocklist.conf
3518
- // Example: fetch once on startup and build a larger Set
3506
+ // Consider dynamic loading for real disposables (see comment above)
3519
3507
  ]);
3520
3508
 
3521
3509
  if (freeOrDisposableDomains.has(domain)) {
3522
- const cleanLocal = localPart.split('+')[0]; // ignore +tag completely
3510
+ const cleanLocal = localPart.split('+')[0].toLowerCase(); // ignore +tag
3511
+
3512
+ // Expanded serious/role keywords
3513
+ const roleKeywords = ['info', 'support', 'sales', 'contact', 'hello', 'team', 'admin', 'office', 'billing', 'help', 'service', 'orders', 'bookings', 'quotes', 'enquiries', 'noreply', 'no-reply'];
3514
+
3515
+ // New: business/service descriptive keywords (very common for small trades on Gmail)
3516
+ const businessKeywords = [
3517
+ 'locksmith',
3518
+ 'doors',
3519
+ 'garage',
3520
+ 'repair',
3521
+ 'pro',
3522
+ 'expert',
3523
+ '247',
3524
+ '24hr',
3525
+ 'emergency',
3526
+ 'mobile',
3527
+ 'auto',
3528
+ 'key',
3529
+ 'security',
3530
+ 'home',
3531
+ 'commercial',
3532
+ 'residential',
3533
+ 'plumbing',
3534
+ 'electric',
3535
+ 'hvac',
3536
+ 'cleaning',
3537
+ 'pest',
3538
+ 'movers',
3539
+ 'towing',
3540
+ 'tutor',
3541
+ // Add more relevant to your audience/use-case
3542
+ ];
3523
3543
 
3524
- const seriousPrefixes = ['info', 'support', 'sales', 'contact', 'hello', 'team', 'admin', 'office', 'billing', 'help', 'service', 'orders', 'bookings', 'quotes', 'enquiries', 'noreply', 'no-reply', 'business', 'shop', 'store'];
3544
+ const allKeywords = [...roleKeywords, ...businessKeywords];
3525
3545
 
3526
- // Better detection: any segment contains a serious keyword
3546
+ // Check if any segment contains a keyword
3527
3547
  const parts = cleanLocal.split(/[\.-]/);
3528
- const looksLikeRoleOrBrand = seriousPrefixes.some((p) => parts.some((part) => part.includes(p)));
3548
+ const looksTrusted = allKeywords.some((kw) => parts.some((part) => part.includes(kw)) || cleanLocal.includes(kw));
3529
3549
 
3530
- if (looksLikeRoleOrBrand) {
3531
- return false; // trusted-looking on free provider
3550
+ if (looksTrusted) {
3551
+ return false; // early pass for role or descriptive business names
3532
3552
  }
3533
3553
 
3534
- // Extra scrutiny if not role-like
3535
- if (cleanLocal.length > 24 || /\d{6,}/.test(cleanLocal)) {
3554
+ // Relaxed extra scrutiny
3555
+ if (cleanLocal.length > 32 || /\d{8,}/.test(cleanLocal)) {
3556
+ // ← raised thresholds
3536
3557
  return true;
3537
3558
  }
3538
3559
 
3539
- return false; // default: allow typical personal use on Gmail etc.
3560
+ return false; // default: allow most personal / semi-descriptive Gmail use
3540
3561
  }
3541
3562
 
3542
- // 4. Very short / meaningless / bot-like local parts
3543
- if (localPart.length < 2 || /^[a-z\d]{1,5}$/.test(localPart)) {
3544
- return true; // e.g. a1@, xyz12@, but allow real short like "tim@"
3563
+ // 4. Very short / meaningless / bot-like SLIGHTLY relaxed
3564
+ if (localPart.length < 2 || /^[a-z\d]{1,6}$/.test(localPart)) {
3565
+ // up to 6 chars
3566
+ return true;
3545
3567
  }
3546
3568
 
3547
- // 5. Suspicious new/low-trust TLDs (still relevant in 2026)
3569
+ // 5. Suspicious TLDs (unchanged still useful)
3548
3570
  const suspiciousTlds = ['.top', '.xyz', '.club', '.online', '.site', '.fun', '.buzz', '.shop', '.store', '.live', '.digital', '.monster'];
3549
3571
  if (suspiciousTlds.some((tld) => domain.endsWith(tld))) {
3550
3572
  return true;
3551
3573
  }
3552
3574
 
3553
- // Extra: very long local parts are rare for humans
3575
+ // Extra: very long local parts (unchanged)
3554
3576
  if (localPart.length > 40) {
3555
3577
  return true;
3556
3578
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xuda.io/account_module",
3
- "version": "1.2.1871",
3
+ "version": "1.2.1872",
4
4
  "description": "Xuda Account Server Module",
5
5
  "main": "index.mjs",
6
6
  "dependencies": {