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