@xuda.io/ai_module 1.1.4711 → 1.1.4712

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 +696 -696
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -10418,792 +10418,792 @@ PROVIDE DETAILED ANALYSIS WITH CONFIDENCE LEVELS.`,
10418
10418
  }
10419
10419
  };
10420
10420
 
10421
- export const detect_email_type = async function (uid, name, email, account_profile_info, email_body = '', email_subject = '') {
10422
- // ========== HELPER FUNCTIONS ==========
10423
-
10424
- async function hashString(str) {
10425
- const encoder = new TextEncoder();
10426
- const data = encoder.encode(str);
10427
- const hashBuffer = await crypto.subtle.digest('SHA-256', data);
10428
- const hashArray = Array.from(new Uint8Array(hashBuffer));
10429
- return hashArray
10430
- .map((b) => b.toString(16).padStart(2, '0'))
10431
- .join('')
10432
- .substring(0, 16);
10433
- }
10434
-
10435
- function enhanceEmailDetection(data, name, email, emailBody, emailSubject) {
10436
- // Run additional local analysis
10437
- const localAnalysis = analyzeEmailLocally(emailBody, emailSubject, email, name);
10438
-
10439
- // Combine AI analysis with local analysis
10440
- const combinedData = {
10441
- ...data,
10442
- // Override with local analysis if confidence is high
10443
- spam_confidence: Math.max(data.spam_confidence, localAnalysis.spamScore),
10444
- phishing_risk: localAnalysis.phishingScore > 70 ? 'high' : data.phishing_risk,
10445
-
10446
- // Add local analysis results
10447
- local_analysis: localAnalysis,
10448
-
10449
- // Enhance sender analysis
10450
- sender_analysis: analyzeSender(email, name, emailBody),
10451
-
10452
- // Content statistics
10453
- content_stats: {
10454
- word_count: (emailBody.match(/\S+/g) || []).length,
10455
- sentence_count: (emailBody.match(/[.!?]+/g) || []).length,
10456
- link_count: (emailBody.match(/https?:\/\/[^\s]+/g) || []).length,
10457
- uppercase_ratio: calculateUppercaseRatio(emailBody),
10458
- exclamation_count: (emailBody.match(/!/g) || []).length,
10459
- dollar_sign_count: (emailBody.match(/\$/g) || []).length,
10460
- phone_patterns: (emailBody.match(/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g) || []).length,
10461
- },
10462
-
10463
- // Behavioral patterns
10464
- behavioral_patterns: detectBehavioralPatterns(emailBody, emailSubject),
10465
-
10466
- // Domain reputation
10467
- domain_reputation: assessDomainReputation(email),
10468
-
10469
- // Add comprehensive risk assessment
10470
- comprehensive_risk_score: calculateComprehensiveRisk(data, localAnalysis),
10471
-
10472
- // Filter rules that matched
10473
- matched_filters: detectMatchedFilters(emailBody, emailSubject, email, name),
10474
-
10475
- // Timeline analysis
10476
- temporal_analysis: {
10477
- is_time_sensitive: detectTimeSensitivity(emailBody),
10478
- has_expiry: detectExpiryDate(emailBody),
10479
- is_follow_up: detectFollowUpPattern(emailBody, emailSubject),
10480
- },
10481
-
10482
- // Relationship context
10483
- relationship_context: analyzeRelationshipContext(emailBody, emailSubject, name),
10484
-
10485
- // Update timestamp
10486
- analysis_timestamp: new Date().toISOString(),
10487
- content_length: emailBody.length,
10488
- };
10489
-
10490
- // Calculate final classification confidence
10491
- combinedData.final_confidence = calculateFinalConfidence(combinedData);
10492
-
10493
- // Generate detailed explanation
10494
- combinedData.explanation = generateExplanation(combinedData);
10495
-
10496
- // Add compliance flags
10497
- combinedData.compliance_flags = checkCompliance(emailBody, emailSubject);
10498
-
10499
- return combinedData;
10500
- }
10501
-
10502
- function analyzeEmailLocally(body, subject, email, name) {
10503
- const text = (subject + ' ' + body).toLowerCase();
10504
- let spamScore = 0;
10505
- let phishingScore = 0;
10506
- let promotionalScore = 0;
10507
- let transactionalScore = 0;
10508
-
10509
- // SPAM indicators
10510
- const spamKeywords = [
10511
- 'congratulations',
10512
- 'winner',
10513
- 'prize',
10514
- 'lottery',
10515
- 'free',
10516
- 'guaranteed',
10517
- 'risk-free',
10518
- 'act now',
10519
- 'limited time',
10520
- 'urgent',
10521
- 'important',
10522
- 'attention',
10523
- 'alert',
10524
- 'click here',
10525
- 'buy now',
10526
- 'order now',
10527
- 'discount',
10528
- 'save big',
10529
- 'cheap',
10530
- 'viagra',
10531
- 'cialis',
10532
- 'pharmacy',
10533
- 'prescription',
10534
- 'enlarge',
10535
- 'weight loss',
10536
- 'nigerian',
10537
- 'prince',
10538
- 'inheritance',
10539
- 'unclaimed',
10540
- 'bank account',
10541
- 'password',
10542
- 'account suspended',
10543
- 'verify',
10544
- 'security alert',
10545
- 'dear friend',
10546
- 'dear customer',
10547
- 'dear account holder',
10548
- ];
10549
-
10550
- spamKeywords.forEach((keyword) => {
10551
- if (text.includes(keyword)) spamScore += 2;
10552
- });
10553
-
10554
- // Phishing indicators
10555
- const phishingPatterns = [/login\s*(?:here|now)/i, /verify\s*(?:your|my)\s*account/i, /password\s*(?:reset|expired|change)/i, /suspended\s*account/i, /unauthorized\s*activity/i, /security\s*breach/i, /update\s*(?:your|my)\s*information/i, /confirm\s*(?:your|my)\s*identity/i];
10556
-
10557
- phishingPatterns.forEach((pattern) => {
10558
- if (pattern.test(text)) phishingScore += 15;
10559
- });
10560
-
10561
- // Promotional indicators
10562
- const promotionalKeywords = ['newsletter', 'subscribe', 'unsubscribe', 'marketing', 'promotion', 'sale', 'offer', 'deal', 'coupon', 'voucher', 'discount code', 'new product', 'announcement', 'launch', 'event', 'webinar', 'limited offer', 'exclusive', 'special offer', 'members only'];
10563
-
10564
- promotionalKeywords.forEach((keyword) => {
10565
- if (text.includes(keyword)) promotionalScore += 3;
10566
- });
10567
-
10568
- // Transactional indicators
10569
- const transactionalKeywords = ['order', 'invoice', 'receipt', 'payment', 'booking', 'reservation', 'confirmation', 'shipping', 'delivery', 'tracking', 'shipment', 'appointment', 'meeting', 'reminder', 'bill', 'statement', 'account', 'statement', 'balance', 'transaction'];
10570
-
10571
- transactionalKeywords.forEach((keyword) => {
10572
- if (text.includes(keyword)) transactionalScore += 3;
10573
- });
10574
-
10575
- // Link analysis
10576
- const links = body.match(/https?:\/\/[^\s]+/g) || [];
10577
- const suspiciousDomains = ['bit.ly', 'tinyurl', 'shorte.st', 'adf.ly', 'goo.gl'];
10578
-
10579
- links.forEach((link) => {
10580
- if (suspiciousDomains.some((domain) => link.includes(domain))) {
10581
- spamScore += 10;
10582
- phishingScore += 10;
10583
- }
10584
- });
10585
-
10586
- // Grammar/spelling analysis (simple)
10587
- const misspellings = body.match(/\b(?:recieve|seperate|definately|occured|tomm?orrow)\b/gi) || [];
10588
- spamScore += misspellings.length * 2;
10589
-
10590
- // Urgency analysis
10591
- const urgencyWords = ['urgent', 'immediately', 'asap', 'right now', 'today only'];
10592
- let urgencyCount = 0;
10593
- urgencyWords.forEach((word) => {
10594
- if (text.includes(word)) urgencyCount++;
10595
- });
10596
- spamScore += urgencyCount * 5;
10597
-
10598
- // Personalization check
10599
- const hasName = name && body.toLowerCase().includes(name.toLowerCase().split(' ')[0]);
10600
- const personalPronouns = ['you', 'your', 'yours'];
10601
- let personalCount = 0;
10602
- personalPronouns.forEach((pronoun) => {
10603
- const regex = new RegExp(`\\b${pronoun}\\b`, 'gi');
10604
- personalCount += (body.match(regex) || []).length;
10605
- });
10606
-
10607
- const personalizationScore = hasName ? 30 : Math.min(personalCount * 2, 20);
10608
-
10609
- return {
10610
- spamScore: Math.min(spamScore, 100),
10611
- phishingScore: Math.min(phishingScore, 100),
10612
- promotionalScore: Math.min(promotionalScore, 100),
10613
- transactionalScore: Math.min(transactionalScore, 100),
10614
- personalizationScore,
10615
- linkCount: links.length,
10616
- hasUnsubscribe: text.includes('unsubscribe') || text.includes('opt-out'),
10617
- hasPhone: /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/.test(body),
10618
- hasAddress: /\b\d+\s+[\w\s]+(?:street|st|avenue|ave|road|rd|boulevard|blvd|way)\b/i.test(body),
10619
- urgencyCount,
10620
- misspellingCount: misspellings.length,
10621
- };
10622
- }
10623
-
10624
- function analyzeSender(email, name, body) {
10625
- const domain = email.split('@')[1] || '';
10626
- const localPart = email.split('@')[0] || '';
10627
-
10628
- return {
10629
- email: email,
10630
- domain: domain,
10631
- local_part: localPart,
10632
- is_public_domain: isPublicEmailDomain(domain),
10633
- is_generic_sender: isGenericSender(localPart, name),
10634
- domain_age_indicator: assessDomainAge(domain),
10635
- sender_consistency: checkSenderConsistency(name, email, body),
10636
- };
10637
- }
10638
-
10639
- function isPublicEmailDomain(domain) {
10640
- const publicDomains = ['gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com', 'aol.com', 'icloud.com', 'protonmail.com', 'zoho.com', 'yandex.com'];
10641
- return publicDomains.includes(domain.toLowerCase());
10642
- }
10643
-
10644
- function isGenericSender(localPart, name) {
10645
- const genericSenders = ['info', 'support', 'sales', 'contact', 'hello', 'noreply', 'admin', 'newsletter', 'marketing', 'team', 'notifications'];
10646
-
10647
- const localLower = localPart.toLowerCase();
10648
- const nameLower = name.toLowerCase();
10649
-
10650
- return genericSenders.some((sender) => localLower.includes(sender) || nameLower.includes(sender));
10651
- }
10652
-
10653
- function assessDomainAge(domain) {
10654
- // This is a simplified version - in production, you'd use a domain age API
10655
- const newDomains = ['xyz', 'online', 'site', 'top', 'club', 'shop'];
10656
- const tld = domain.split('.').pop() || '';
10657
-
10658
- if (newDomains.includes(tld)) return 'likely_new';
10659
- if (['com', 'org', 'net', 'edu', 'gov'].includes(tld)) return 'likely_established';
10660
- return 'unknown';
10661
- }
10421
+ // export const detect_email_type = async function (uid, name, email, account_profile_info, email_body = '', email_subject = '') {
10422
+ // // ========== HELPER FUNCTIONS ==========
10423
+
10424
+ // async function hashString(str) {
10425
+ // const encoder = new TextEncoder();
10426
+ // const data = encoder.encode(str);
10427
+ // const hashBuffer = await crypto.subtle.digest('SHA-256', data);
10428
+ // const hashArray = Array.from(new Uint8Array(hashBuffer));
10429
+ // return hashArray
10430
+ // .map((b) => b.toString(16).padStart(2, '0'))
10431
+ // .join('')
10432
+ // .substring(0, 16);
10433
+ // }
10662
10434
 
10663
- function checkSenderConsistency(name, email, body) {
10664
- const emailName = email.split('@')[0].toLowerCase();
10665
- const bodyName = name.toLowerCase();
10435
+ // function enhanceEmailDetection(data, name, email, emailBody, emailSubject) {
10436
+ // // Run additional local analysis
10437
+ // const localAnalysis = analyzeEmailLocally(emailBody, emailSubject, email, name);
10438
+
10439
+ // // Combine AI analysis with local analysis
10440
+ // const combinedData = {
10441
+ // ...data,
10442
+ // // Override with local analysis if confidence is high
10443
+ // spam_confidence: Math.max(data.spam_confidence, localAnalysis.spamScore),
10444
+ // phishing_risk: localAnalysis.phishingScore > 70 ? 'high' : data.phishing_risk,
10445
+
10446
+ // // Add local analysis results
10447
+ // local_analysis: localAnalysis,
10448
+
10449
+ // // Enhance sender analysis
10450
+ // sender_analysis: analyzeSender(email, name, emailBody),
10451
+
10452
+ // // Content statistics
10453
+ // content_stats: {
10454
+ // word_count: (emailBody.match(/\S+/g) || []).length,
10455
+ // sentence_count: (emailBody.match(/[.!?]+/g) || []).length,
10456
+ // link_count: (emailBody.match(/https?:\/\/[^\s]+/g) || []).length,
10457
+ // uppercase_ratio: calculateUppercaseRatio(emailBody),
10458
+ // exclamation_count: (emailBody.match(/!/g) || []).length,
10459
+ // dollar_sign_count: (emailBody.match(/\$/g) || []).length,
10460
+ // phone_patterns: (emailBody.match(/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g) || []).length,
10461
+ // },
10666
10462
 
10667
- // Check if name appears in body
10668
- const nameInBody = body.toLowerCase().includes(bodyName.split(' ')[0]);
10463
+ // // Behavioral patterns
10464
+ // behavioral_patterns: detectBehavioralPatterns(emailBody, emailSubject),
10669
10465
 
10670
- // Check email-name consistency patterns
10671
- const nameParts = bodyName.split(' ');
10672
- const firstName = nameParts[0] || '';
10673
- const lastName = nameParts.slice(-1)[0] || '';
10466
+ // // Domain reputation
10467
+ // domain_reputation: assessDomainReputation(email),
10674
10468
 
10675
- const patterns = [`${firstName}.${lastName}`, `${firstName}${lastName}`, `${firstName.charAt(0)}${lastName}`, `${firstName}`];
10469
+ // // Add comprehensive risk assessment
10470
+ // comprehensive_risk_score: calculateComprehensiveRisk(data, localAnalysis),
10676
10471
 
10677
- const consistent = patterns.some((pattern) => emailName.includes(pattern.toLowerCase()));
10678
-
10679
- return {
10680
- name_in_body: nameInBody,
10681
- email_name_consistent: consistent,
10682
- consistency_score: (nameInBody ? 40 : 0) + (consistent ? 60 : 0),
10683
- };
10684
- }
10472
+ // // Filter rules that matched
10473
+ // matched_filters: detectMatchedFilters(emailBody, emailSubject, email, name),
10685
10474
 
10686
- function calculateUppercaseRatio(text) {
10687
- const letters = text.replace(/[^a-zA-Z]/g, '');
10688
- if (letters.length === 0) return 0;
10475
+ // // Timeline analysis
10476
+ // temporal_analysis: {
10477
+ // is_time_sensitive: detectTimeSensitivity(emailBody),
10478
+ // has_expiry: detectExpiryDate(emailBody),
10479
+ // is_follow_up: detectFollowUpPattern(emailBody, emailSubject),
10480
+ // },
10689
10481
 
10690
- const uppercase = letters.replace(/[^A-Z]/g, '');
10691
- return (uppercase.length / letters.length) * 100;
10692
- }
10482
+ // // Relationship context
10483
+ // relationship_context: analyzeRelationshipContext(emailBody, emailSubject, name),
10693
10484
 
10694
- function detectBehavioralPatterns(body, subject) {
10695
- const text = (subject + ' ' + body).toLowerCase();
10696
- const patterns = [];
10485
+ // // Update timestamp
10486
+ // analysis_timestamp: new Date().toISOString(),
10487
+ // content_length: emailBody.length,
10488
+ // };
10697
10489
 
10698
- if (/(?:click|tap)\s+(?:here|this|link|button)/i.test(text)) {
10699
- patterns.push('call_to_action_link');
10700
- }
10490
+ // // Calculate final classification confidence
10491
+ // combinedData.final_confidence = calculateFinalConfidence(combinedData);
10701
10492
 
10702
- if (/limited\s+time|offer\s+expires|only\s+\d+\s+left/i.test(text)) {
10703
- patterns.push('scarcity_tactic');
10704
- }
10493
+ // // Generate detailed explanation
10494
+ // combinedData.explanation = generateExplanation(combinedData);
10705
10495
 
10706
- if (/\$\d+|\d+\s*%|\d+\s*off|discount|save|sale/i.test(text)) {
10707
- patterns.push('monetary_offer');
10708
- }
10496
+ // // Add compliance flags
10497
+ // combinedData.compliance_flags = checkCompliance(emailBody, emailSubject);
10709
10498
 
10710
- if (/urgent|important|alert|attention|warning/i.test(text)) {
10711
- patterns.push('urgency_tactic');
10712
- }
10499
+ // return combinedData;
10500
+ // }
10713
10501
 
10714
- if (/(?:please|kindly)\s+(?:help|assist|reply)/i.test(text)) {
10715
- patterns.push('polite_request');
10716
- }
10502
+ // function analyzeEmailLocally(body, subject, email, name) {
10503
+ // const text = (subject + ' ' + body).toLowerCase();
10504
+ // let spamScore = 0;
10505
+ // let phishingScore = 0;
10506
+ // let promotionalScore = 0;
10507
+ // let transactionalScore = 0;
10508
+
10509
+ // // SPAM indicators
10510
+ // const spamKeywords = [
10511
+ // 'congratulations',
10512
+ // 'winner',
10513
+ // 'prize',
10514
+ // 'lottery',
10515
+ // 'free',
10516
+ // 'guaranteed',
10517
+ // 'risk-free',
10518
+ // 'act now',
10519
+ // 'limited time',
10520
+ // 'urgent',
10521
+ // 'important',
10522
+ // 'attention',
10523
+ // 'alert',
10524
+ // 'click here',
10525
+ // 'buy now',
10526
+ // 'order now',
10527
+ // 'discount',
10528
+ // 'save big',
10529
+ // 'cheap',
10530
+ // 'viagra',
10531
+ // 'cialis',
10532
+ // 'pharmacy',
10533
+ // 'prescription',
10534
+ // 'enlarge',
10535
+ // 'weight loss',
10536
+ // 'nigerian',
10537
+ // 'prince',
10538
+ // 'inheritance',
10539
+ // 'unclaimed',
10540
+ // 'bank account',
10541
+ // 'password',
10542
+ // 'account suspended',
10543
+ // 'verify',
10544
+ // 'security alert',
10545
+ // 'dear friend',
10546
+ // 'dear customer',
10547
+ // 'dear account holder',
10548
+ // ];
10549
+
10550
+ // spamKeywords.forEach((keyword) => {
10551
+ // if (text.includes(keyword)) spamScore += 2;
10552
+ // });
10553
+
10554
+ // // Phishing indicators
10555
+ // const phishingPatterns = [/login\s*(?:here|now)/i, /verify\s*(?:your|my)\s*account/i, /password\s*(?:reset|expired|change)/i, /suspended\s*account/i, /unauthorized\s*activity/i, /security\s*breach/i, /update\s*(?:your|my)\s*information/i, /confirm\s*(?:your|my)\s*identity/i];
10556
+
10557
+ // phishingPatterns.forEach((pattern) => {
10558
+ // if (pattern.test(text)) phishingScore += 15;
10559
+ // });
10560
+
10561
+ // // Promotional indicators
10562
+ // const promotionalKeywords = ['newsletter', 'subscribe', 'unsubscribe', 'marketing', 'promotion', 'sale', 'offer', 'deal', 'coupon', 'voucher', 'discount code', 'new product', 'announcement', 'launch', 'event', 'webinar', 'limited offer', 'exclusive', 'special offer', 'members only'];
10563
+
10564
+ // promotionalKeywords.forEach((keyword) => {
10565
+ // if (text.includes(keyword)) promotionalScore += 3;
10566
+ // });
10567
+
10568
+ // // Transactional indicators
10569
+ // const transactionalKeywords = ['order', 'invoice', 'receipt', 'payment', 'booking', 'reservation', 'confirmation', 'shipping', 'delivery', 'tracking', 'shipment', 'appointment', 'meeting', 'reminder', 'bill', 'statement', 'account', 'statement', 'balance', 'transaction'];
10570
+
10571
+ // transactionalKeywords.forEach((keyword) => {
10572
+ // if (text.includes(keyword)) transactionalScore += 3;
10573
+ // });
10574
+
10575
+ // // Link analysis
10576
+ // const links = body.match(/https?:\/\/[^\s]+/g) || [];
10577
+ // const suspiciousDomains = ['bit.ly', 'tinyurl', 'shorte.st', 'adf.ly', 'goo.gl'];
10578
+
10579
+ // links.forEach((link) => {
10580
+ // if (suspiciousDomains.some((domain) => link.includes(domain))) {
10581
+ // spamScore += 10;
10582
+ // phishingScore += 10;
10583
+ // }
10584
+ // });
10585
+
10586
+ // // Grammar/spelling analysis (simple)
10587
+ // const misspellings = body.match(/\b(?:recieve|seperate|definately|occured|tomm?orrow)\b/gi) || [];
10588
+ // spamScore += misspellings.length * 2;
10589
+
10590
+ // // Urgency analysis
10591
+ // const urgencyWords = ['urgent', 'immediately', 'asap', 'right now', 'today only'];
10592
+ // let urgencyCount = 0;
10593
+ // urgencyWords.forEach((word) => {
10594
+ // if (text.includes(word)) urgencyCount++;
10595
+ // });
10596
+ // spamScore += urgencyCount * 5;
10597
+
10598
+ // // Personalization check
10599
+ // const hasName = name && body.toLowerCase().includes(name.toLowerCase().split(' ')[0]);
10600
+ // const personalPronouns = ['you', 'your', 'yours'];
10601
+ // let personalCount = 0;
10602
+ // personalPronouns.forEach((pronoun) => {
10603
+ // const regex = new RegExp(`\\b${pronoun}\\b`, 'gi');
10604
+ // personalCount += (body.match(regex) || []).length;
10605
+ // });
10606
+
10607
+ // const personalizationScore = hasName ? 30 : Math.min(personalCount * 2, 20);
10717
10608
 
10718
- if (/unsubscribe|opt.?out|preference|manage subscription/i.test(text)) {
10719
- patterns.push('subscription_management');
10720
- }
10609
+ // return {
10610
+ // spamScore: Math.min(spamScore, 100),
10611
+ // phishingScore: Math.min(phishingScore, 100),
10612
+ // promotionalScore: Math.min(promotionalScore, 100),
10613
+ // transactionalScore: Math.min(transactionalScore, 100),
10614
+ // personalizationScore,
10615
+ // linkCount: links.length,
10616
+ // hasUnsubscribe: text.includes('unsubscribe') || text.includes('opt-out'),
10617
+ // hasPhone: /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/.test(body),
10618
+ // hasAddress: /\b\d+\s+[\w\s]+(?:street|st|avenue|ave|road|rd|boulevard|blvd|way)\b/i.test(body),
10619
+ // urgencyCount,
10620
+ // misspellingCount: misspellings.length,
10621
+ // };
10622
+ // }
10721
10623
 
10722
- return patterns;
10723
- }
10624
+ // function analyzeSender(email, name, body) {
10625
+ // const domain = email.split('@')[1] || '';
10626
+ // const localPart = email.split('@')[0] || '';
10724
10627
 
10725
- function assessDomainReputation(email) {
10726
- const domain = email.split('@')[1] || '';
10628
+ // return {
10629
+ // email: email,
10630
+ // domain: domain,
10631
+ // local_part: localPart,
10632
+ // is_public_domain: isPublicEmailDomain(domain),
10633
+ // is_generic_sender: isGenericSender(localPart, name),
10634
+ // domain_age_indicator: assessDomainAge(domain),
10635
+ // sender_consistency: checkSenderConsistency(name, email, body),
10636
+ // };
10637
+ // }
10727
10638
 
10728
- // Known spam domains (simplified list)
10729
- const spamDomains = ['spam4.me', 'trashmail.com', 'mailinator.com', 'guerrillamail.com', 'tempmail.com', 'yopmail.com', 'dispostable.com'];
10639
+ // function isPublicEmailDomain(domain) {
10640
+ // const publicDomains = ['gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com', 'aol.com', 'icloud.com', 'protonmail.com', 'zoho.com', 'yandex.com'];
10641
+ // return publicDomains.includes(domain.toLowerCase());
10642
+ // }
10730
10643
 
10731
- if (spamDomains.includes(domain.toLowerCase())) {
10732
- return 'known_spam_domain';
10733
- }
10644
+ // function isGenericSender(localPart, name) {
10645
+ // const genericSenders = ['info', 'support', 'sales', 'contact', 'hello', 'noreply', 'admin', 'newsletter', 'marketing', 'team', 'notifications'];
10734
10646
 
10735
- // Professional domains
10736
- const professionalTLDs = ['com', 'org', 'net', 'edu', 'gov', 'io', 'ai', 'tech'];
10737
- const tld = domain.split('.').pop() || '';
10647
+ // const localLower = localPart.toLowerCase();
10648
+ // const nameLower = name.toLowerCase();
10738
10649
 
10739
- if (professionalTLDs.includes(tld.toLowerCase())) {
10740
- return 'professional_domain';
10741
- }
10650
+ // return genericSenders.some((sender) => localLower.includes(sender) || nameLower.includes(sender));
10651
+ // }
10742
10652
 
10743
- // New/suspicious TLDs
10744
- const suspiciousTLDs = ['xyz', 'top', 'win', 'bid', 'download', 'stream'];
10745
- if (suspiciousTLDs.includes(tld.toLowerCase())) {
10746
- return 'suspicious_tld';
10747
- }
10653
+ // function assessDomainAge(domain) {
10654
+ // // This is a simplified version - in production, you'd use a domain age API
10655
+ // const newDomains = ['xyz', 'online', 'site', 'top', 'club', 'shop'];
10656
+ // const tld = domain.split('.').pop() || '';
10748
10657
 
10749
- return 'neutral';
10750
- }
10658
+ // if (newDomains.includes(tld)) return 'likely_new';
10659
+ // if (['com', 'org', 'net', 'edu', 'gov'].includes(tld)) return 'likely_established';
10660
+ // return 'unknown';
10661
+ // }
10751
10662
 
10752
- function calculateComprehensiveRisk(aiData, localAnalysis) {
10753
- let risk = 0;
10663
+ // function checkSenderConsistency(name, email, body) {
10664
+ // const emailName = email.split('@')[0].toLowerCase();
10665
+ // const bodyName = name.toLowerCase();
10754
10666
 
10755
- // Base on AI classification
10756
- switch (aiData.email_type) {
10757
- case 'spam':
10758
- risk += 80;
10759
- break;
10760
- case 'promotional':
10761
- risk += 30;
10762
- break;
10763
- case 'transactional':
10764
- risk += 10;
10765
- break;
10766
- case 'personal':
10767
- risk += 5;
10768
- break;
10769
- case 'business':
10770
- risk += 15;
10771
- break;
10772
- }
10667
+ // // Check if name appears in body
10668
+ // const nameInBody = body.toLowerCase().includes(bodyName.split(' ')[0]);
10773
10669
 
10774
- // Add local analysis scores
10775
- risk += localAnalysis.spamScore * 0.2;
10776
- risk += localAnalysis.phishingScore * 0.3;
10670
+ // // Check email-name consistency patterns
10671
+ // const nameParts = bodyName.split(' ');
10672
+ // const firstName = nameParts[0] || '';
10673
+ // const lastName = nameParts.slice(-1)[0] || '';
10777
10674
 
10778
- // Adjust for phishing risk
10779
- switch (aiData.phishing_risk) {
10780
- case 'critical':
10781
- risk += 40;
10782
- break;
10783
- case 'high':
10784
- risk += 30;
10785
- break;
10786
- case 'medium':
10787
- risk += 15;
10788
- break;
10789
- case 'low':
10790
- risk += 5;
10791
- break;
10792
- }
10675
+ // const patterns = [`${firstName}.${lastName}`, `${firstName}${lastName}`, `${firstName.charAt(0)}${lastName}`, `${firstName}`];
10793
10676
 
10794
- // Adjust for unsolicited
10795
- if (aiData.is_unsolicited) risk += 20;
10677
+ // const consistent = patterns.some((pattern) => emailName.includes(pattern.toLowerCase()));
10796
10678
 
10797
- // Adjust for urgency
10798
- if (aiData.is_urgent) risk += 10;
10679
+ // return {
10680
+ // name_in_body: nameInBody,
10681
+ // email_name_consistent: consistent,
10682
+ // consistency_score: (nameInBody ? 40 : 0) + (consistent ? 60 : 0),
10683
+ // };
10684
+ // }
10799
10685
 
10800
- return Math.min(risk, 100);
10801
- }
10686
+ // function calculateUppercaseRatio(text) {
10687
+ // const letters = text.replace(/[^a-zA-Z]/g, '');
10688
+ // if (letters.length === 0) return 0;
10802
10689
 
10803
- function detectMatchedFilters(body, subject, email, name) {
10804
- const filters = [];
10805
- const text = (subject + ' ' + body).toLowerCase();
10690
+ // const uppercase = letters.replace(/[^A-Z]/g, '');
10691
+ // return (uppercase.length / letters.length) * 100;
10692
+ // }
10806
10693
 
10807
- // Spam filters
10808
- if (/(?:viagra|cialis|penis|enlarge)/i.test(text)) filters.push('adult_content_filter');
10809
- if (/(?:lottery|winner|prize|jackpot)/i.test(text)) filters.push('lottery_scam_filter');
10810
- if (/(?:nigerian|prince|inheritance|unclaimed)/i.test(text)) filters.push('inheritance_scam_filter');
10811
- if (/password\s+reset|verify\s+account/i.test(text)) filters.push('account_verification_filter');
10694
+ // function detectBehavioralPatterns(body, subject) {
10695
+ // const text = (subject + ' ' + body).toLowerCase();
10696
+ // const patterns = [];
10812
10697
 
10813
- // Promotional filters
10814
- if (/newsletter|subscribe|unsubscribe/i.test(text)) filters.push('newsletter_filter');
10815
- if (/sale|discount|offer|coupon/i.test(text)) filters.push('promotional_offer_filter');
10816
- if (/webinar|event|conference/i.test(text)) filters.push('event_filter');
10698
+ // if (/(?:click|tap)\s+(?:here|this|link|button)/i.test(text)) {
10699
+ // patterns.push('call_to_action_link');
10700
+ // }
10817
10701
 
10818
- // Transactional filters
10819
- if (/order|invoice|receipt|payment/i.test(text)) filters.push('transaction_filter');
10820
- if (/shipping|delivery|tracking/i.test(text)) filters.push('shipping_filter');
10821
- if (/appointment|meeting|reminder/i.test(text)) filters.push('calendar_filter');
10702
+ // if (/limited\s+time|offer\s+expires|only\s+\d+\s+left/i.test(text)) {
10703
+ // patterns.push('scarcity_tactic');
10704
+ // }
10822
10705
 
10823
- return filters;
10824
- }
10706
+ // if (/\$\d+|\d+\s*%|\d+\s*off|discount|save|sale/i.test(text)) {
10707
+ // patterns.push('monetary_offer');
10708
+ // }
10825
10709
 
10826
- function detectTimeSensitivity(body) {
10827
- const text = body.toLowerCase();
10828
- const patterns = [/today|tomorrow|this\s+week|immediately|asap/i, /deadline|due\s+by|expires|limited\s+time/i, /urgent|important|attention|alert/i];
10710
+ // if (/urgent|important|alert|attention|warning/i.test(text)) {
10711
+ // patterns.push('urgency_tactic');
10712
+ // }
10829
10713
 
10830
- return patterns.some((pattern) => pattern.test(text));
10831
- }
10714
+ // if (/(?:please|kindly)\s+(?:help|assist|reply)/i.test(text)) {
10715
+ // patterns.push('polite_request');
10716
+ // }
10832
10717
 
10833
- function detectExpiryDate(body) {
10834
- const datePatterns = [/\b\d{1,2}\/\d{1,2}\/\d{2,4}\b/g, /\b\d{1,2}\s+(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{2,4}\b/gi, /\bexpires?\s+(?:on|by)?\s*[:]?\s*\d{1,2}\/\d{1,2}\/\d{2,4}\b/gi];
10718
+ // if (/unsubscribe|opt.?out|preference|manage subscription/i.test(text)) {
10719
+ // patterns.push('subscription_management');
10720
+ // }
10835
10721
 
10836
- return datePatterns.some((pattern) => pattern.test(body.toLowerCase()));
10837
- }
10722
+ // return patterns;
10723
+ // }
10838
10724
 
10839
- function detectFollowUpPattern(body, subject) {
10840
- const text = (subject + ' ' + body).toLowerCase();
10841
- return /follow.?up|following.?up|checking.?in|touch.?base|re:.?re:/i.test(text);
10842
- }
10725
+ // function assessDomainReputation(email) {
10726
+ // const domain = email.split('@')[1] || '';
10843
10727
 
10844
- function analyzeRelationshipContext(body, subject, name) {
10845
- const text = (subject + ' ' + body).toLowerCase();
10846
- const nameParts = name.toLowerCase().split(' ');
10847
- const firstName = nameParts[0] || '';
10728
+ // // Known spam domains (simplified list)
10729
+ // const spamDomains = ['spam4.me', 'trashmail.com', 'mailinator.com', 'guerrillamail.com', 'tempmail.com', 'yopmail.com', 'dispostable.com'];
10848
10730
 
10849
- const indicators = {
10850
- uses_name: firstName && text.includes(firstName),
10851
- uses_personal_pronouns: /\b(?:i|me|my|mine|you|your|yours)\b/gi.test(text),
10852
- has_greeting: /^(?:hi|hello|hey|dear|greetings)\b/im.test(body),
10853
- has_signature: /(?:best|regards|sincerely|thanks|thank you)\s*[,]?\s*\n/im.test(body),
10854
- has_questions: /\?/.test(text) && /(?:can|could|would|will|do|are|is)\s+you/i.test(text),
10855
- };
10731
+ // if (spamDomains.includes(domain.toLowerCase())) {
10732
+ // return 'known_spam_domain';
10733
+ // }
10856
10734
 
10857
- const relationshipScore = Object.values(indicators).filter(Boolean).length * 20;
10735
+ // // Professional domains
10736
+ // const professionalTLDs = ['com', 'org', 'net', 'edu', 'gov', 'io', 'ai', 'tech'];
10737
+ // const tld = domain.split('.').pop() || '';
10858
10738
 
10859
- return {
10860
- ...indicators,
10861
- relationship_score: Math.min(relationshipScore, 100),
10862
- likely_known_sender: relationshipScore >= 40,
10863
- };
10864
- }
10739
+ // if (professionalTLDs.includes(tld.toLowerCase())) {
10740
+ // return 'professional_domain';
10741
+ // }
10865
10742
 
10866
- function calculateFinalConfidence(data) {
10867
- let confidence = data.email_type_confidence;
10743
+ // // New/suspicious TLDs
10744
+ // const suspiciousTLDs = ['xyz', 'top', 'win', 'bid', 'download', 'stream'];
10745
+ // if (suspiciousTLDs.includes(tld.toLowerCase())) {
10746
+ // return 'suspicious_tld';
10747
+ // }
10868
10748
 
10869
- // Adjust based on local analysis
10870
- if (data.local_analysis.spamScore > 70 && data.email_type !== 'spam') {
10871
- confidence -= 20;
10872
- }
10749
+ // return 'neutral';
10750
+ // }
10873
10751
 
10874
- // Adjust based on phishing risk
10875
- if (data.phishing_risk === 'critical' || data.phishing_risk === 'high') {
10876
- confidence += 15;
10877
- }
10752
+ // function calculateComprehensiveRisk(aiData, localAnalysis) {
10753
+ // let risk = 0;
10878
10754
 
10879
- // Adjust based on personalization
10880
- if (data.is_personalized) {
10881
- confidence += 10;
10882
- }
10755
+ // // Base on AI classification
10756
+ // switch (aiData.email_type) {
10757
+ // case 'spam':
10758
+ // risk += 80;
10759
+ // break;
10760
+ // case 'promotional':
10761
+ // risk += 30;
10762
+ // break;
10763
+ // case 'transactional':
10764
+ // risk += 10;
10765
+ // break;
10766
+ // case 'personal':
10767
+ // risk += 5;
10768
+ // break;
10769
+ // case 'business':
10770
+ // risk += 15;
10771
+ // break;
10772
+ // }
10883
10773
 
10884
- // Adjust based on content stats
10885
- if (data.content_stats.link_count > 5) {
10886
- confidence += 5;
10887
- }
10774
+ // // Add local analysis scores
10775
+ // risk += localAnalysis.spamScore * 0.2;
10776
+ // risk += localAnalysis.phishingScore * 0.3;
10888
10777
 
10889
- return Math.max(0, Math.min(100, confidence));
10890
- }
10778
+ // // Adjust for phishing risk
10779
+ // switch (aiData.phishing_risk) {
10780
+ // case 'critical':
10781
+ // risk += 40;
10782
+ // break;
10783
+ // case 'high':
10784
+ // risk += 30;
10785
+ // break;
10786
+ // case 'medium':
10787
+ // risk += 15;
10788
+ // break;
10789
+ // case 'low':
10790
+ // risk += 5;
10791
+ // break;
10792
+ // }
10891
10793
 
10892
- function generateExplanation(data) {
10893
- const explanations = [];
10794
+ // // Adjust for unsolicited
10795
+ // if (aiData.is_unsolicited) risk += 20;
10894
10796
 
10895
- if (data.email_type === 'spam') {
10896
- explanations.push('Classified as spam due to:');
10897
- if (data.spam_confidence > 70) explanations.push(`- High spam confidence (${data.spam_confidence}%)`);
10898
- if (data.phishing_risk !== 'none') explanations.push(`- ${data.phishing_risk} phishing risk`);
10899
- if (data.local_analysis.spamScore > 60) explanations.push('- Contains spam indicators');
10900
- }
10797
+ // // Adjust for urgency
10798
+ // if (aiData.is_urgent) risk += 10;
10901
10799
 
10902
- if (data.email_type === 'promotional') {
10903
- explanations.push('Classified as promotional due to:');
10904
- if (data.is_commercial) explanations.push('- Commercial intent detected');
10905
- if (data.local_analysis.hasUnsubscribe) explanations.push('- Contains unsubscribe option');
10906
- if (data.local_analysis.promotionalScore > 30) explanations.push('- Promotional content detected');
10907
- }
10800
+ // return Math.min(risk, 100);
10801
+ // }
10908
10802
 
10909
- if (data.key_indicators && data.key_indicators.length > 0) {
10910
- explanations.push('Key indicators:');
10911
- data.key_indicators.forEach((indicator) => {
10912
- explanations.push(`- ${indicator}`);
10913
- });
10914
- }
10803
+ // function detectMatchedFilters(body, subject, email, name) {
10804
+ // const filters = [];
10805
+ // const text = (subject + ' ' + body).toLowerCase();
10915
10806
 
10916
- return explanations.join('\n');
10917
- }
10807
+ // // Spam filters
10808
+ // if (/(?:viagra|cialis|penis|enlarge)/i.test(text)) filters.push('adult_content_filter');
10809
+ // if (/(?:lottery|winner|prize|jackpot)/i.test(text)) filters.push('lottery_scam_filter');
10810
+ // if (/(?:nigerian|prince|inheritance|unclaimed)/i.test(text)) filters.push('inheritance_scam_filter');
10811
+ // if (/password\s+reset|verify\s+account/i.test(text)) filters.push('account_verification_filter');
10918
10812
 
10919
- function checkCompliance(body, subject) {
10920
- const text = (subject + ' ' + body).toLowerCase();
10921
- const flags = [];
10813
+ // // Promotional filters
10814
+ // if (/newsletter|subscribe|unsubscribe/i.test(text)) filters.push('newsletter_filter');
10815
+ // if (/sale|discount|offer|coupon/i.test(text)) filters.push('promotional_offer_filter');
10816
+ // if (/webinar|event|conference/i.test(text)) filters.push('event_filter');
10922
10817
 
10923
- // CAN-SPAM Act compliance (US)
10924
- if (text.includes('unsubscribe') || text.includes('opt-out')) {
10925
- flags.push('has_unsubscribe_option');
10926
- }
10818
+ // // Transactional filters
10819
+ // if (/order|invoice|receipt|payment/i.test(text)) filters.push('transaction_filter');
10820
+ // if (/shipping|delivery|tracking/i.test(text)) filters.push('shipping_filter');
10821
+ // if (/appointment|meeting|reminder/i.test(text)) filters.push('calendar_filter');
10927
10822
 
10928
- if (/\b\d{10}\b/.test(body.replace(/\D/g, ''))) {
10929
- flags.push('contains_phone_number');
10930
- }
10823
+ // return filters;
10824
+ // }
10931
10825
 
10932
- if (/address\s*[:]?\s*\d+\s+[\w\s]+/i.test(body)) {
10933
- flags.push('contains_physical_address');
10934
- }
10826
+ // function detectTimeSensitivity(body) {
10827
+ // const text = body.toLowerCase();
10828
+ // const patterns = [/today|tomorrow|this\s+week|immediately|asap/i, /deadline|due\s+by|expires|limited\s+time/i, /urgent|important|attention|alert/i];
10935
10829
 
10936
- // GDPR indicators (EU)
10937
- if (/privacy\s+policy|gdpr|data\s+protection/i.test(text)) {
10938
- flags.push('gdpr_mentions');
10939
- }
10830
+ // return patterns.some((pattern) => pattern.test(text));
10831
+ // }
10940
10832
 
10941
- if (/consent|opt.?in|permission/i.test(text)) {
10942
- flags.push('consent_mentions');
10943
- }
10833
+ // function detectExpiryDate(body) {
10834
+ // const datePatterns = [/\b\d{1,2}\/\d{1,2}\/\d{2,4}\b/g, /\b\d{1,2}\s+(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{2,4}\b/gi, /\bexpires?\s+(?:on|by)?\s*[:]?\s*\d{1,2}\/\d{1,2}\/\d{2,4}\b/gi];
10944
10835
 
10945
- return flags;
10946
- }
10836
+ // return datePatterns.some((pattern) => pattern.test(body.toLowerCase()));
10837
+ // }
10947
10838
 
10948
- function getDefaultEmailDetection(name, email, emailBody, emailSubject, error = null) {
10949
- const localAnalysis = analyzeEmailLocally(emailBody, emailSubject, email, name);
10839
+ // function detectFollowUpPattern(body, subject) {
10840
+ // const text = (subject + ' ' + body).toLowerCase();
10841
+ // return /follow.?up|following.?up|checking.?in|touch.?base|re:.?re:/i.test(text);
10842
+ // }
10950
10843
 
10951
- // Determine type based on local analysis
10952
- let emailType = 'ambiguous';
10953
- if (localAnalysis.spamScore > 70) emailType = 'spam';
10954
- else if (localAnalysis.promotionalScore > localAnalysis.transactionalScore && localAnalysis.promotionalScore > 30) emailType = 'promotional';
10955
- else if (localAnalysis.transactionalScore > 40) emailType = 'transactional';
10844
+ // function analyzeRelationshipContext(body, subject, name) {
10845
+ // const text = (subject + ' ' + body).toLowerCase();
10846
+ // const nameParts = name.toLowerCase().split(' ');
10847
+ // const firstName = nameParts[0] || '';
10848
+
10849
+ // const indicators = {
10850
+ // uses_name: firstName && text.includes(firstName),
10851
+ // uses_personal_pronouns: /\b(?:i|me|my|mine|you|your|yours)\b/gi.test(text),
10852
+ // has_greeting: /^(?:hi|hello|hey|dear|greetings)\b/im.test(body),
10853
+ // has_signature: /(?:best|regards|sincerely|thanks|thank you)\s*[,]?\s*\n/im.test(body),
10854
+ // has_questions: /\?/.test(text) && /(?:can|could|would|will|do|are|is)\s+you/i.test(text),
10855
+ // };
10956
10856
 
10957
- const spamConfidence = localAnalysis.spamScore;
10958
- const phishingRisk = localAnalysis.phishingScore > 50 ? 'medium' : 'low';
10857
+ // const relationshipScore = Object.values(indicators).filter(Boolean).length * 20;
10959
10858
 
10960
- return {
10961
- success: false,
10962
- email_type: emailType,
10963
- email_type_confidence: Math.max(50, spamConfidence),
10964
- email_subtype: 'personal_message',
10859
+ // return {
10860
+ // ...indicators,
10861
+ // relationship_score: Math.min(relationshipScore, 100),
10862
+ // likely_known_sender: relationshipScore >= 40,
10863
+ // };
10864
+ // }
10965
10865
 
10966
- spam_confidence: spamConfidence,
10967
- phishing_risk: phishingRisk,
10968
- malware_risk: 'none',
10866
+ // function calculateFinalConfidence(data) {
10867
+ // let confidence = data.email_type_confidence;
10969
10868
 
10970
- is_unsolicited: true,
10971
- is_commercial: localAnalysis.promotionalScore > 30,
10972
- is_urgent: localAnalysis.urgencyCount > 0,
10973
- is_personalized: localAnalysis.personalizationScore > 20,
10869
+ // // Adjust based on local analysis
10870
+ // if (data.local_analysis.spamScore > 70 && data.email_type !== 'spam') {
10871
+ // confidence -= 20;
10872
+ // }
10974
10873
 
10975
- sender_legitimacy: 'unknown',
10976
- sender_intent: 'unknown',
10874
+ // // Adjust based on phishing risk
10875
+ // if (data.phishing_risk === 'critical' || data.phishing_risk === 'high') {
10876
+ // confidence += 15;
10877
+ // }
10977
10878
 
10978
- contains_links: localAnalysis.linkCount > 0,
10979
- contains_attachments: false,
10980
- contains_unsubscribe: localAnalysis.hasUnsubscribe,
10981
- contains_phone_number: localAnalysis.hasPhone,
10982
- contains_address: localAnalysis.hasAddress,
10879
+ // // Adjust based on personalization
10880
+ // if (data.is_personalized) {
10881
+ // confidence += 10;
10882
+ // }
10983
10883
 
10984
- language_quality: localAnalysis.misspellingCount > 3 ? 'poor' : 'average',
10985
- urgency_level: localAnalysis.urgencyCount > 2 ? 'high' : 'low',
10986
- personalization_score: localAnalysis.personalizationScore,
10884
+ // // Adjust based on content stats
10885
+ // if (data.content_stats.link_count > 5) {
10886
+ // confidence += 5;
10887
+ // }
10987
10888
 
10988
- suggested_action: emailType === 'spam' ? 'mark_as_spam' : 'keep_in_inbox',
10989
- auto_filter_suggestion: emailType === 'spam' ? 'spam_filter' : 'no_filter',
10990
- inbox_priority: emailType === 'spam' ? 'ignore' : 'normal',
10889
+ // return Math.max(0, Math.min(100, confidence));
10890
+ // }
10991
10891
 
10992
- key_indicators: ['Local analysis only - API failed'],
10993
- risk_factors: [],
10994
- legitimacy_signals: [],
10892
+ // function generateExplanation(data) {
10893
+ // const explanations = [];
10995
10894
 
10996
- analysis_timestamp: new Date().toISOString(),
10997
- content_length: emailBody.length,
10998
- analysis_complexity: 'simple',
10895
+ // if (data.email_type === 'spam') {
10896
+ // explanations.push('Classified as spam due to:');
10897
+ // if (data.spam_confidence > 70) explanations.push(`- High spam confidence (${data.spam_confidence}%)`);
10898
+ // if (data.phishing_risk !== 'none') explanations.push(`- ${data.phishing_risk} phishing risk`);
10899
+ // if (data.local_analysis.spamScore > 60) explanations.push('- Contains spam indicators');
10900
+ // }
10999
10901
 
11000
- // Enhanced fields
11001
- local_analysis: localAnalysis,
11002
- sender_analysis: analyzeSender(email, name, emailBody),
11003
- content_stats: {
11004
- word_count: (emailBody.match(/\S+/g) || []).length,
11005
- sentence_count: (emailBody.match(/[.!?]+/g) || []).length,
11006
- link_count: localAnalysis.linkCount,
11007
- uppercase_ratio: calculateUppercaseRatio(emailBody),
11008
- exclamation_count: (emailBody.match(/!/g) || []).length,
11009
- dollar_sign_count: (emailBody.match(/\$/g) || []).length,
11010
- phone_patterns: (emailBody.match(/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g) || []).length,
11011
- },
10902
+ // if (data.email_type === 'promotional') {
10903
+ // explanations.push('Classified as promotional due to:');
10904
+ // if (data.is_commercial) explanations.push('- Commercial intent detected');
10905
+ // if (data.local_analysis.hasUnsubscribe) explanations.push('- Contains unsubscribe option');
10906
+ // if (data.local_analysis.promotionalScore > 30) explanations.push('- Promotional content detected');
10907
+ // }
11012
10908
 
11013
- comprehensive_risk_score: calculateComprehensiveRisk({ email_type: emailType, phishing_risk: phishingRisk, is_unsolicited: true, is_urgent: localAnalysis.urgencyCount > 0 }, localAnalysis),
10909
+ // if (data.key_indicators && data.key_indicators.length > 0) {
10910
+ // explanations.push('Key indicators:');
10911
+ // data.key_indicators.forEach((indicator) => {
10912
+ // explanations.push(`- ${indicator}`);
10913
+ // });
10914
+ // }
11014
10915
 
11015
- final_confidence: Math.max(50, spamConfidence),
11016
- explanation: 'Default analysis due to API failure',
11017
- error: error || 'API call failed',
11018
- };
11019
- }
10916
+ // return explanations.join('\n');
10917
+ // }
11020
10918
 
11021
- const detection_ret = await submit_chat_gpt_prompt({
11022
- uid,
11023
- prompt: `Analyze this email and determine if it's SPAM, PROMOTIONAL, TRANSACTIONAL, or PERSONAL/BUSINESS communication.
10919
+ // function checkCompliance(body, subject) {
10920
+ // const text = (subject + ' ' + body).toLowerCase();
10921
+ // const flags = [];
11024
10922
 
11025
- FROM: "${name}" <${email}>
11026
- SUBJECT: "${email_subject}"
11027
- BODY: "${email_body.substring(0, 800)}${email_body.length > 800 ? '...' : ''}"
10923
+ // // CAN-SPAM Act compliance (US)
10924
+ // if (text.includes('unsubscribe') || text.includes('opt-out')) {
10925
+ // flags.push('has_unsubscribe_option');
10926
+ // }
11028
10927
 
11029
- ANALYSIS CRITERIA:
10928
+ // if (/\b\d{10}\b/.test(body.replace(/\D/g, ''))) {
10929
+ // flags.push('contains_phone_number');
10930
+ // }
11030
10931
 
11031
- SPAM INDICATORS:
11032
- - Unsolicited commercial content
11033
- - Phishing attempts or suspicious links
11034
- - Poor grammar/spelling
11035
- - Urgent/panic-inducing language
11036
- - Requests for personal information
11037
- - Too good to be true offers
11038
- - Hidden/unclear sender identity
11039
- - Multiple recipient addresses visible
11040
- - Stock/"spammy" subject lines
11041
-
11042
- PROMOTIONAL INDICATORS:
11043
- - Marketing/sales content
11044
- - Product announcements
11045
- - Newsletter content
11046
- - Discount/coupon offers
11047
- - Event invitations (commercial)
11048
- - Company updates (marketing focused)
11049
- - Clear opt-out/unsubscribe option
11050
- - Professional branding/templates
11051
- - Call-to-action buttons
11052
-
11053
- TRANSACTIONAL INDICATORS:
11054
- - Order confirmations
11055
- - Shipping notifications
11056
- - Invoice/billing
11057
- - Account notifications
11058
- - Password resets
11059
- - Booking confirmations
11060
- - Appointment reminders
11061
- - Payment receipts
11062
- - Service updates
11063
-
11064
- PERSONAL/BUSINESS INDICATORS:
11065
- - Direct communication to you
11066
- - Known sender relationship
11067
- - Work/project related
11068
- - Personal conversations
11069
- - One-on-one correspondence
11070
- - Contains your name specifically
11071
- - Contextually relevant to you
11072
-
11073
- ADDITIONAL FACTORS TO CONSIDER:
11074
- - Sender reputation (company vs personal)
11075
- - Your relationship with sender
11076
- - Email formatting quality
11077
- - Personalization level
11078
- - Expected vs unexpected content
11079
- - Action requested (if any)
11080
-
11081
- PROVIDE DETAILED ANALYSIS WITH CONFIDENCE SCORES.`,
11082
- model: 'gpt-5-nano',
11083
- response_format: z.object({
11084
- // Primary Classification
11085
- email_type: z.enum(['spam', 'promotional', 'transactional', 'personal', 'business', 'ambiguous']),
11086
- email_type_confidence: z.number().min(0).max(100),
11087
-
11088
- // Sub-classification
11089
- email_subtype: z.enum([
11090
- // Spam types
11091
- 'phishing_attempt',
11092
- 'scam_offer',
11093
- 'malware_risk',
11094
- 'adult_content',
11095
- 'financial_scam',
11096
- 'lottery_scam',
11097
- 'inheritance_scam',
11098
- 'romance_scam',
11099
- 'tech_support_scam',
11100
-
11101
- // Promotional types
11102
- 'marketing_newsletter',
11103
- 'product_announcement',
11104
- 'discount_offer',
11105
- 'event_invitation',
11106
- 'company_update',
11107
- 'blog_newsletter',
11108
- 'educational_content',
11109
- 'lead_magnet',
11110
-
11111
- // Transactional types
11112
- 'order_confirmation',
11113
- 'shipping_notification',
11114
- 'invoice_billing',
11115
- 'payment_receipt',
11116
- 'account_verification',
11117
- 'password_reset',
11118
- 'appointment_reminder',
11119
- 'service_notification',
11120
-
11121
- // Personal/Business types
11122
- 'personal_message',
11123
- 'work_collaboration',
11124
- 'client_communication',
11125
- 'team_announcement',
11126
- 'meeting_invitation',
11127
- 'project_update',
11128
- 'direct_inquiry',
11129
- 'networking_request',
11130
- ]),
10932
+ // if (/address\s*[:]?\s*\d+\s+[\w\s]+/i.test(body)) {
10933
+ // flags.push('contains_physical_address');
10934
+ // }
11131
10935
 
11132
- // Risk Assessment
11133
- spam_confidence: z.number().min(0).max(100).describe('Confidence this is spam'),
11134
- phishing_risk: z.enum(['none', 'low', 'medium', 'high', 'critical']),
11135
- malware_risk: z.enum(['none', 'low', 'medium', 'high']),
10936
+ // // GDPR indicators (EU)
10937
+ // if (/privacy\s+policy|gdpr|data\s+protection/i.test(text)) {
10938
+ // flags.push('gdpr_mentions');
10939
+ // }
11136
10940
 
11137
- // Content Analysis
11138
- is_unsolicited: z.boolean().describe('Email was not requested/expected'),
11139
- is_commercial: z.boolean().describe('Contains commercial intent'),
11140
- is_urgent: z.boolean().describe('Uses urgent/time-sensitive language'),
11141
- is_personalized: z.boolean().describe('Content is personalized to recipient'),
10941
+ // if (/consent|opt.?in|permission/i.test(text)) {
10942
+ // flags.push('consent_mentions');
10943
+ // }
11142
10944
 
11143
- // Sender Analysis
11144
- sender_legitimacy: z.enum(['verified', 'likely_legitimate', 'suspicious', 'likely_fake', 'unknown']),
11145
- sender_intent: z.enum(['inform', 'sell', 'scam', 'build_relationship', 'request_action', 'unknown']),
10945
+ // return flags;
10946
+ // }
11146
10947
 
11147
- // Content Characteristics
11148
- contains_links: z.boolean(),
11149
- contains_attachments: z.boolean(),
11150
- contains_unsubscribe: z.boolean(),
11151
- contains_phone_number: z.boolean(),
11152
- contains_address: z.boolean(),
10948
+ // function getDefaultEmailDetection(name, email, emailBody, emailSubject, error = null) {
10949
+ // const localAnalysis = analyzeEmailLocally(emailBody, emailSubject, email, name);
11153
10950
 
11154
- // Language Analysis
11155
- language_quality: z.enum(['excellent', 'good', 'average', 'poor', 'spammy']),
11156
- urgency_level: z.enum(['none', 'low', 'medium', 'high', 'extreme']),
11157
- personalization_score: z.number().min(0).max(100).describe('How personalized the content is'),
10951
+ // // Determine type based on local analysis
10952
+ // let emailType = 'ambiguous';
10953
+ // if (localAnalysis.spamScore > 70) emailType = 'spam';
10954
+ // else if (localAnalysis.promotionalScore > localAnalysis.transactionalScore && localAnalysis.promotionalScore > 30) emailType = 'promotional';
10955
+ // else if (localAnalysis.transactionalScore > 40) emailType = 'transactional';
11158
10956
 
11159
- // Action Recommendations
11160
- suggested_action: z.enum(['delete_immediately', 'mark_as_spam', 'move_to_promotions', 'respond_politely', 'follow_up', 'archive', 'keep_in_inbox', 'add_to_contacts', 'report_phishing']),
10957
+ // const spamConfidence = localAnalysis.spamScore;
10958
+ // const phishingRisk = localAnalysis.phishingScore > 50 ? 'medium' : 'low';
11161
10959
 
11162
- // Filter Recommendations
11163
- auto_filter_suggestion: z.enum(['spam_filter', 'promotions_filter', 'social_filter', 'updates_filter', 'primary_inbox', 'no_filter']),
10960
+ // return {
10961
+ // success: false,
10962
+ // email_type: emailType,
10963
+ // email_type_confidence: Math.max(50, spamConfidence),
10964
+ // email_subtype: 'personal_message',
10965
+
10966
+ // spam_confidence: spamConfidence,
10967
+ // phishing_risk: phishingRisk,
10968
+ // malware_risk: 'none',
10969
+
10970
+ // is_unsolicited: true,
10971
+ // is_commercial: localAnalysis.promotionalScore > 30,
10972
+ // is_urgent: localAnalysis.urgencyCount > 0,
10973
+ // is_personalized: localAnalysis.personalizationScore > 20,
10974
+
10975
+ // sender_legitimacy: 'unknown',
10976
+ // sender_intent: 'unknown',
10977
+
10978
+ // contains_links: localAnalysis.linkCount > 0,
10979
+ // contains_attachments: false,
10980
+ // contains_unsubscribe: localAnalysis.hasUnsubscribe,
10981
+ // contains_phone_number: localAnalysis.hasPhone,
10982
+ // contains_address: localAnalysis.hasAddress,
10983
+
10984
+ // language_quality: localAnalysis.misspellingCount > 3 ? 'poor' : 'average',
10985
+ // urgency_level: localAnalysis.urgencyCount > 2 ? 'high' : 'low',
10986
+ // personalization_score: localAnalysis.personalizationScore,
10987
+
10988
+ // suggested_action: emailType === 'spam' ? 'mark_as_spam' : 'keep_in_inbox',
10989
+ // auto_filter_suggestion: emailType === 'spam' ? 'spam_filter' : 'no_filter',
10990
+ // inbox_priority: emailType === 'spam' ? 'ignore' : 'normal',
10991
+
10992
+ // key_indicators: ['Local analysis only - API failed'],
10993
+ // risk_factors: [],
10994
+ // legitimacy_signals: [],
10995
+
10996
+ // analysis_timestamp: new Date().toISOString(),
10997
+ // content_length: emailBody.length,
10998
+ // analysis_complexity: 'simple',
10999
+
11000
+ // // Enhanced fields
11001
+ // local_analysis: localAnalysis,
11002
+ // sender_analysis: analyzeSender(email, name, emailBody),
11003
+ // content_stats: {
11004
+ // word_count: (emailBody.match(/\S+/g) || []).length,
11005
+ // sentence_count: (emailBody.match(/[.!?]+/g) || []).length,
11006
+ // link_count: localAnalysis.linkCount,
11007
+ // uppercase_ratio: calculateUppercaseRatio(emailBody),
11008
+ // exclamation_count: (emailBody.match(/!/g) || []).length,
11009
+ // dollar_sign_count: (emailBody.match(/\$/g) || []).length,
11010
+ // phone_patterns: (emailBody.match(/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g) || []).length,
11011
+ // },
11164
11012
 
11165
- // Priority
11166
- inbox_priority: z.enum(['critical', 'high', 'normal', 'low', 'ignore']),
11013
+ // comprehensive_risk_score: calculateComprehensiveRisk({ email_type: emailType, phishing_risk: phishingRisk, is_unsolicited: true, is_urgent: localAnalysis.urgencyCount > 0 }, localAnalysis),
11167
11014
 
11168
- // Detailed Analysis
11169
- key_indicators: z.array(z.string()).describe('Key factors influencing classification'),
11170
- risk_factors: z.array(z.string()).describe('Specific risks identified'),
11171
- legitimacy_signals: z.array(z.string()).describe('Signals of legitimate communication'),
11015
+ // final_confidence: Math.max(50, spamConfidence),
11016
+ // explanation: 'Default analysis due to API failure',
11017
+ // error: error || 'API call failed',
11018
+ // };
11019
+ // }
11172
11020
 
11173
- // Metadata
11174
- analysis_timestamp: z.string(),
11175
- content_length: z.number().describe('Length of email body analyzed'),
11176
- analysis_complexity: z.enum(['simple', 'moderate', 'complex', 'ambiguous']),
11177
- }),
11178
- metadata: {
11179
- func: 'detect_email_type',
11180
- sender_name: name,
11181
- sender_email: email,
11182
- subject_length: email_subject?.length || 0,
11183
- body_length: email_body?.length || 0,
11184
- body_preview_hash: await hashString(email_body.substring(0, 200)),
11185
- },
11186
- account_profile_info,
11187
- tools: [{ type: 'web_search_preview' }],
11188
- });
11021
+ // const detection_ret = await submit_chat_gpt_prompt({
11022
+ // uid,
11023
+ // prompt: `Analyze this email and determine if it's SPAM, PROMOTIONAL, TRANSACTIONAL, or PERSONAL/BUSINESS communication.
11024
+
11025
+ // FROM: "${name}" <${email}>
11026
+ // SUBJECT: "${email_subject}"
11027
+ // BODY: "${email_body.substring(0, 800)}${email_body.length > 800 ? '...' : ''}"
11028
+
11029
+ // ANALYSIS CRITERIA:
11030
+
11031
+ // SPAM INDICATORS:
11032
+ // - Unsolicited commercial content
11033
+ // - Phishing attempts or suspicious links
11034
+ // - Poor grammar/spelling
11035
+ // - Urgent/panic-inducing language
11036
+ // - Requests for personal information
11037
+ // - Too good to be true offers
11038
+ // - Hidden/unclear sender identity
11039
+ // - Multiple recipient addresses visible
11040
+ // - Stock/"spammy" subject lines
11041
+
11042
+ // PROMOTIONAL INDICATORS:
11043
+ // - Marketing/sales content
11044
+ // - Product announcements
11045
+ // - Newsletter content
11046
+ // - Discount/coupon offers
11047
+ // - Event invitations (commercial)
11048
+ // - Company updates (marketing focused)
11049
+ // - Clear opt-out/unsubscribe option
11050
+ // - Professional branding/templates
11051
+ // - Call-to-action buttons
11052
+
11053
+ // TRANSACTIONAL INDICATORS:
11054
+ // - Order confirmations
11055
+ // - Shipping notifications
11056
+ // - Invoice/billing
11057
+ // - Account notifications
11058
+ // - Password resets
11059
+ // - Booking confirmations
11060
+ // - Appointment reminders
11061
+ // - Payment receipts
11062
+ // - Service updates
11063
+
11064
+ // PERSONAL/BUSINESS INDICATORS:
11065
+ // - Direct communication to you
11066
+ // - Known sender relationship
11067
+ // - Work/project related
11068
+ // - Personal conversations
11069
+ // - One-on-one correspondence
11070
+ // - Contains your name specifically
11071
+ // - Contextually relevant to you
11072
+
11073
+ // ADDITIONAL FACTORS TO CONSIDER:
11074
+ // - Sender reputation (company vs personal)
11075
+ // - Your relationship with sender
11076
+ // - Email formatting quality
11077
+ // - Personalization level
11078
+ // - Expected vs unexpected content
11079
+ // - Action requested (if any)
11080
+
11081
+ // PROVIDE DETAILED ANALYSIS WITH CONFIDENCE SCORES.`,
11082
+ // model: 'gpt-5-nano',
11083
+ // response_format: z.object({
11084
+ // // Primary Classification
11085
+ // email_type: z.enum(['spam', 'promotional', 'transactional', 'personal', 'business', 'ambiguous']),
11086
+ // email_type_confidence: z.number().min(0).max(100),
11087
+
11088
+ // // Sub-classification
11089
+ // email_subtype: z.enum([
11090
+ // // Spam types
11091
+ // 'phishing_attempt',
11092
+ // 'scam_offer',
11093
+ // 'malware_risk',
11094
+ // 'adult_content',
11095
+ // 'financial_scam',
11096
+ // 'lottery_scam',
11097
+ // 'inheritance_scam',
11098
+ // 'romance_scam',
11099
+ // 'tech_support_scam',
11100
+
11101
+ // // Promotional types
11102
+ // 'marketing_newsletter',
11103
+ // 'product_announcement',
11104
+ // 'discount_offer',
11105
+ // 'event_invitation',
11106
+ // 'company_update',
11107
+ // 'blog_newsletter',
11108
+ // 'educational_content',
11109
+ // 'lead_magnet',
11110
+
11111
+ // // Transactional types
11112
+ // 'order_confirmation',
11113
+ // 'shipping_notification',
11114
+ // 'invoice_billing',
11115
+ // 'payment_receipt',
11116
+ // 'account_verification',
11117
+ // 'password_reset',
11118
+ // 'appointment_reminder',
11119
+ // 'service_notification',
11120
+
11121
+ // // Personal/Business types
11122
+ // 'personal_message',
11123
+ // 'work_collaboration',
11124
+ // 'client_communication',
11125
+ // 'team_announcement',
11126
+ // 'meeting_invitation',
11127
+ // 'project_update',
11128
+ // 'direct_inquiry',
11129
+ // 'networking_request',
11130
+ // ]),
11131
+
11132
+ // // Risk Assessment
11133
+ // spam_confidence: z.number().min(0).max(100).describe('Confidence this is spam'),
11134
+ // phishing_risk: z.enum(['none', 'low', 'medium', 'high', 'critical']),
11135
+ // malware_risk: z.enum(['none', 'low', 'medium', 'high']),
11136
+
11137
+ // // Content Analysis
11138
+ // is_unsolicited: z.boolean().describe('Email was not requested/expected'),
11139
+ // is_commercial: z.boolean().describe('Contains commercial intent'),
11140
+ // is_urgent: z.boolean().describe('Uses urgent/time-sensitive language'),
11141
+ // is_personalized: z.boolean().describe('Content is personalized to recipient'),
11142
+
11143
+ // // Sender Analysis
11144
+ // sender_legitimacy: z.enum(['verified', 'likely_legitimate', 'suspicious', 'likely_fake', 'unknown']),
11145
+ // sender_intent: z.enum(['inform', 'sell', 'scam', 'build_relationship', 'request_action', 'unknown']),
11146
+
11147
+ // // Content Characteristics
11148
+ // contains_links: z.boolean(),
11149
+ // contains_attachments: z.boolean(),
11150
+ // contains_unsubscribe: z.boolean(),
11151
+ // contains_phone_number: z.boolean(),
11152
+ // contains_address: z.boolean(),
11153
+
11154
+ // // Language Analysis
11155
+ // language_quality: z.enum(['excellent', 'good', 'average', 'poor', 'spammy']),
11156
+ // urgency_level: z.enum(['none', 'low', 'medium', 'high', 'extreme']),
11157
+ // personalization_score: z.number().min(0).max(100).describe('How personalized the content is'),
11158
+
11159
+ // // Action Recommendations
11160
+ // suggested_action: z.enum(['delete_immediately', 'mark_as_spam', 'move_to_promotions', 'respond_politely', 'follow_up', 'archive', 'keep_in_inbox', 'add_to_contacts', 'report_phishing']),
11161
+
11162
+ // // Filter Recommendations
11163
+ // auto_filter_suggestion: z.enum(['spam_filter', 'promotions_filter', 'social_filter', 'updates_filter', 'primary_inbox', 'no_filter']),
11164
+
11165
+ // // Priority
11166
+ // inbox_priority: z.enum(['critical', 'high', 'normal', 'low', 'ignore']),
11167
+
11168
+ // // Detailed Analysis
11169
+ // key_indicators: z.array(z.string()).describe('Key factors influencing classification'),
11170
+ // risk_factors: z.array(z.string()).describe('Specific risks identified'),
11171
+ // legitimacy_signals: z.array(z.string()).describe('Signals of legitimate communication'),
11172
+
11173
+ // // Metadata
11174
+ // analysis_timestamp: z.string(),
11175
+ // content_length: z.number().describe('Length of email body analyzed'),
11176
+ // analysis_complexity: z.enum(['simple', 'moderate', 'complex', 'ambiguous']),
11177
+ // }),
11178
+ // metadata: {
11179
+ // func: 'detect_email_type',
11180
+ // sender_name: name,
11181
+ // sender_email: email,
11182
+ // subject_length: email_subject?.length || 0,
11183
+ // body_length: email_body?.length || 0,
11184
+ // body_preview_hash: await hashString(email_body.substring(0, 200)),
11185
+ // },
11186
+ // account_profile_info,
11187
+ // tools: [{ type: 'web_search_preview' }],
11188
+ // });
11189
11189
 
11190
- try {
11191
- if (detection_ret.code > -1) {
11192
- const data = typeof detection_ret.data === 'string' ? JSON.parse(detection_ret.data) : detection_ret.data;
11190
+ // try {
11191
+ // if (detection_ret.code > -1) {
11192
+ // const data = typeof detection_ret.data === 'string' ? JSON.parse(detection_ret.data) : detection_ret.data;
11193
11193
 
11194
- // Enhance with additional analysis
11195
- const enhancedData = enhanceEmailDetection(data, name, email, email_body, email_subject);
11194
+ // // Enhance with additional analysis
11195
+ // const enhancedData = enhanceEmailDetection(data, name, email, email_body, email_subject);
11196
11196
 
11197
- return {
11198
- success: true,
11199
- ...enhancedData,
11200
- };
11201
- } else {
11202
- console.error('Email detection API call failed:', detection_ret);
11203
- return getDefaultEmailDetection(name, email, email_body, email_subject);
11204
- }
11205
- } catch (error) {
11206
- console.error('Error in detect_email_type:', error);
11207
- return getDefaultEmailDetection(name, email, email_body, email_subject, error.message);
11208
- }
11209
- };
11197
+ // return {
11198
+ // success: true,
11199
+ // ...enhancedData,
11200
+ // };
11201
+ // } else {
11202
+ // console.error('Email detection API call failed:', detection_ret);
11203
+ // return getDefaultEmailDetection(name, email, email_body, email_subject);
11204
+ // }
11205
+ // } catch (error) {
11206
+ // console.error('Error in detect_email_type:', error);
11207
+ // return getDefaultEmailDetection(name, email, email_body, email_subject, error.message);
11208
+ // }
11209
+ // };