@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.
- package/index.mjs +696 -696
- 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
|
-
|
|
10423
|
-
|
|
10424
|
-
|
|
10425
|
-
|
|
10426
|
-
|
|
10427
|
-
|
|
10428
|
-
|
|
10429
|
-
|
|
10430
|
-
|
|
10431
|
-
|
|
10432
|
-
|
|
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
|
-
|
|
10664
|
-
|
|
10665
|
-
|
|
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
|
-
|
|
10668
|
-
|
|
10463
|
+
// // Behavioral patterns
|
|
10464
|
+
// behavioral_patterns: detectBehavioralPatterns(emailBody, emailSubject),
|
|
10669
10465
|
|
|
10670
|
-
|
|
10671
|
-
|
|
10672
|
-
const firstName = nameParts[0] || '';
|
|
10673
|
-
const lastName = nameParts.slice(-1)[0] || '';
|
|
10466
|
+
// // Domain reputation
|
|
10467
|
+
// domain_reputation: assessDomainReputation(email),
|
|
10674
10468
|
|
|
10675
|
-
|
|
10469
|
+
// // Add comprehensive risk assessment
|
|
10470
|
+
// comprehensive_risk_score: calculateComprehensiveRisk(data, localAnalysis),
|
|
10676
10471
|
|
|
10677
|
-
|
|
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
|
-
|
|
10687
|
-
|
|
10688
|
-
|
|
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
|
-
|
|
10691
|
-
|
|
10692
|
-
}
|
|
10482
|
+
// // Relationship context
|
|
10483
|
+
// relationship_context: analyzeRelationshipContext(emailBody, emailSubject, name),
|
|
10693
10484
|
|
|
10694
|
-
|
|
10695
|
-
|
|
10696
|
-
|
|
10485
|
+
// // Update timestamp
|
|
10486
|
+
// analysis_timestamp: new Date().toISOString(),
|
|
10487
|
+
// content_length: emailBody.length,
|
|
10488
|
+
// };
|
|
10697
10489
|
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
}
|
|
10490
|
+
// // Calculate final classification confidence
|
|
10491
|
+
// combinedData.final_confidence = calculateFinalConfidence(combinedData);
|
|
10701
10492
|
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
}
|
|
10493
|
+
// // Generate detailed explanation
|
|
10494
|
+
// combinedData.explanation = generateExplanation(combinedData);
|
|
10705
10495
|
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
}
|
|
10496
|
+
// // Add compliance flags
|
|
10497
|
+
// combinedData.compliance_flags = checkCompliance(emailBody, emailSubject);
|
|
10709
10498
|
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
}
|
|
10499
|
+
// return combinedData;
|
|
10500
|
+
// }
|
|
10713
10501
|
|
|
10714
|
-
|
|
10715
|
-
|
|
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
|
-
|
|
10719
|
-
|
|
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
|
-
|
|
10723
|
-
|
|
10624
|
+
// function analyzeSender(email, name, body) {
|
|
10625
|
+
// const domain = email.split('@')[1] || '';
|
|
10626
|
+
// const localPart = email.split('@')[0] || '';
|
|
10724
10627
|
|
|
10725
|
-
|
|
10726
|
-
|
|
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
|
-
|
|
10729
|
-
|
|
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
|
-
|
|
10732
|
-
|
|
10733
|
-
}
|
|
10644
|
+
// function isGenericSender(localPart, name) {
|
|
10645
|
+
// const genericSenders = ['info', 'support', 'sales', 'contact', 'hello', 'noreply', 'admin', 'newsletter', 'marketing', 'team', 'notifications'];
|
|
10734
10646
|
|
|
10735
|
-
|
|
10736
|
-
|
|
10737
|
-
const tld = domain.split('.').pop() || '';
|
|
10647
|
+
// const localLower = localPart.toLowerCase();
|
|
10648
|
+
// const nameLower = name.toLowerCase();
|
|
10738
10649
|
|
|
10739
|
-
|
|
10740
|
-
|
|
10741
|
-
}
|
|
10650
|
+
// return genericSenders.some((sender) => localLower.includes(sender) || nameLower.includes(sender));
|
|
10651
|
+
// }
|
|
10742
10652
|
|
|
10743
|
-
|
|
10744
|
-
|
|
10745
|
-
|
|
10746
|
-
|
|
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
|
-
|
|
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
|
-
|
|
10753
|
-
|
|
10663
|
+
// function checkSenderConsistency(name, email, body) {
|
|
10664
|
+
// const emailName = email.split('@')[0].toLowerCase();
|
|
10665
|
+
// const bodyName = name.toLowerCase();
|
|
10754
10666
|
|
|
10755
|
-
|
|
10756
|
-
|
|
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
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
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
|
-
|
|
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
|
-
|
|
10795
|
-
if (aiData.is_unsolicited) risk += 20;
|
|
10677
|
+
// const consistent = patterns.some((pattern) => emailName.includes(pattern.toLowerCase()));
|
|
10796
10678
|
|
|
10797
|
-
|
|
10798
|
-
|
|
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
|
-
|
|
10801
|
-
|
|
10686
|
+
// function calculateUppercaseRatio(text) {
|
|
10687
|
+
// const letters = text.replace(/[^a-zA-Z]/g, '');
|
|
10688
|
+
// if (letters.length === 0) return 0;
|
|
10802
10689
|
|
|
10803
|
-
|
|
10804
|
-
|
|
10805
|
-
|
|
10690
|
+
// const uppercase = letters.replace(/[^A-Z]/g, '');
|
|
10691
|
+
// return (uppercase.length / letters.length) * 100;
|
|
10692
|
+
// }
|
|
10806
10693
|
|
|
10807
|
-
|
|
10808
|
-
|
|
10809
|
-
|
|
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
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
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
|
-
|
|
10819
|
-
|
|
10820
|
-
|
|
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
|
-
|
|
10824
|
-
|
|
10706
|
+
// if (/\$\d+|\d+\s*%|\d+\s*off|discount|save|sale/i.test(text)) {
|
|
10707
|
+
// patterns.push('monetary_offer');
|
|
10708
|
+
// }
|
|
10825
10709
|
|
|
10826
|
-
|
|
10827
|
-
|
|
10828
|
-
|
|
10710
|
+
// if (/urgent|important|alert|attention|warning/i.test(text)) {
|
|
10711
|
+
// patterns.push('urgency_tactic');
|
|
10712
|
+
// }
|
|
10829
10713
|
|
|
10830
|
-
|
|
10831
|
-
|
|
10714
|
+
// if (/(?:please|kindly)\s+(?:help|assist|reply)/i.test(text)) {
|
|
10715
|
+
// patterns.push('polite_request');
|
|
10716
|
+
// }
|
|
10832
10717
|
|
|
10833
|
-
|
|
10834
|
-
|
|
10718
|
+
// if (/unsubscribe|opt.?out|preference|manage subscription/i.test(text)) {
|
|
10719
|
+
// patterns.push('subscription_management');
|
|
10720
|
+
// }
|
|
10835
10721
|
|
|
10836
|
-
|
|
10837
|
-
|
|
10722
|
+
// return patterns;
|
|
10723
|
+
// }
|
|
10838
10724
|
|
|
10839
|
-
|
|
10840
|
-
|
|
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
|
-
|
|
10845
|
-
|
|
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
|
-
|
|
10850
|
-
|
|
10851
|
-
|
|
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
|
-
|
|
10735
|
+
// // Professional domains
|
|
10736
|
+
// const professionalTLDs = ['com', 'org', 'net', 'edu', 'gov', 'io', 'ai', 'tech'];
|
|
10737
|
+
// const tld = domain.split('.').pop() || '';
|
|
10858
10738
|
|
|
10859
|
-
|
|
10860
|
-
|
|
10861
|
-
|
|
10862
|
-
likely_known_sender: relationshipScore >= 40,
|
|
10863
|
-
};
|
|
10864
|
-
}
|
|
10739
|
+
// if (professionalTLDs.includes(tld.toLowerCase())) {
|
|
10740
|
+
// return 'professional_domain';
|
|
10741
|
+
// }
|
|
10865
10742
|
|
|
10866
|
-
|
|
10867
|
-
|
|
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
|
-
|
|
10870
|
-
|
|
10871
|
-
confidence -= 20;
|
|
10872
|
-
}
|
|
10749
|
+
// return 'neutral';
|
|
10750
|
+
// }
|
|
10873
10751
|
|
|
10874
|
-
|
|
10875
|
-
|
|
10876
|
-
confidence += 15;
|
|
10877
|
-
}
|
|
10752
|
+
// function calculateComprehensiveRisk(aiData, localAnalysis) {
|
|
10753
|
+
// let risk = 0;
|
|
10878
10754
|
|
|
10879
|
-
|
|
10880
|
-
|
|
10881
|
-
|
|
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
|
-
|
|
10885
|
-
|
|
10886
|
-
|
|
10887
|
-
}
|
|
10774
|
+
// // Add local analysis scores
|
|
10775
|
+
// risk += localAnalysis.spamScore * 0.2;
|
|
10776
|
+
// risk += localAnalysis.phishingScore * 0.3;
|
|
10888
10777
|
|
|
10889
|
-
|
|
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
|
-
|
|
10893
|
-
|
|
10794
|
+
// // Adjust for unsolicited
|
|
10795
|
+
// if (aiData.is_unsolicited) risk += 20;
|
|
10894
10796
|
|
|
10895
|
-
|
|
10896
|
-
|
|
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
|
-
|
|
10903
|
-
|
|
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
|
-
|
|
10910
|
-
|
|
10911
|
-
|
|
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
|
-
|
|
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
|
-
|
|
10920
|
-
|
|
10921
|
-
|
|
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
|
-
|
|
10924
|
-
|
|
10925
|
-
|
|
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
|
-
|
|
10929
|
-
|
|
10930
|
-
}
|
|
10823
|
+
// return filters;
|
|
10824
|
+
// }
|
|
10931
10825
|
|
|
10932
|
-
|
|
10933
|
-
|
|
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
|
-
|
|
10937
|
-
|
|
10938
|
-
flags.push('gdpr_mentions');
|
|
10939
|
-
}
|
|
10830
|
+
// return patterns.some((pattern) => pattern.test(text));
|
|
10831
|
+
// }
|
|
10940
10832
|
|
|
10941
|
-
|
|
10942
|
-
|
|
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
|
-
|
|
10946
|
-
|
|
10836
|
+
// return datePatterns.some((pattern) => pattern.test(body.toLowerCase()));
|
|
10837
|
+
// }
|
|
10947
10838
|
|
|
10948
|
-
|
|
10949
|
-
|
|
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
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
|
|
10955
|
-
|
|
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
|
-
|
|
10958
|
-
const phishingRisk = localAnalysis.phishingScore > 50 ? 'medium' : 'low';
|
|
10857
|
+
// const relationshipScore = Object.values(indicators).filter(Boolean).length * 20;
|
|
10959
10858
|
|
|
10960
|
-
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
|
|
10964
|
-
|
|
10859
|
+
// return {
|
|
10860
|
+
// ...indicators,
|
|
10861
|
+
// relationship_score: Math.min(relationshipScore, 100),
|
|
10862
|
+
// likely_known_sender: relationshipScore >= 40,
|
|
10863
|
+
// };
|
|
10864
|
+
// }
|
|
10965
10865
|
|
|
10966
|
-
|
|
10967
|
-
|
|
10968
|
-
malware_risk: 'none',
|
|
10866
|
+
// function calculateFinalConfidence(data) {
|
|
10867
|
+
// let confidence = data.email_type_confidence;
|
|
10969
10868
|
|
|
10970
|
-
|
|
10971
|
-
|
|
10972
|
-
|
|
10973
|
-
|
|
10869
|
+
// // Adjust based on local analysis
|
|
10870
|
+
// if (data.local_analysis.spamScore > 70 && data.email_type !== 'spam') {
|
|
10871
|
+
// confidence -= 20;
|
|
10872
|
+
// }
|
|
10974
10873
|
|
|
10975
|
-
|
|
10976
|
-
|
|
10874
|
+
// // Adjust based on phishing risk
|
|
10875
|
+
// if (data.phishing_risk === 'critical' || data.phishing_risk === 'high') {
|
|
10876
|
+
// confidence += 15;
|
|
10877
|
+
// }
|
|
10977
10878
|
|
|
10978
|
-
|
|
10979
|
-
|
|
10980
|
-
|
|
10981
|
-
|
|
10982
|
-
contains_address: localAnalysis.hasAddress,
|
|
10879
|
+
// // Adjust based on personalization
|
|
10880
|
+
// if (data.is_personalized) {
|
|
10881
|
+
// confidence += 10;
|
|
10882
|
+
// }
|
|
10983
10883
|
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
10884
|
+
// // Adjust based on content stats
|
|
10885
|
+
// if (data.content_stats.link_count > 5) {
|
|
10886
|
+
// confidence += 5;
|
|
10887
|
+
// }
|
|
10987
10888
|
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
inbox_priority: emailType === 'spam' ? 'ignore' : 'normal',
|
|
10889
|
+
// return Math.max(0, Math.min(100, confidence));
|
|
10890
|
+
// }
|
|
10991
10891
|
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
legitimacy_signals: [],
|
|
10892
|
+
// function generateExplanation(data) {
|
|
10893
|
+
// const explanations = [];
|
|
10995
10894
|
|
|
10996
|
-
|
|
10997
|
-
|
|
10998
|
-
|
|
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
|
-
|
|
11001
|
-
|
|
11002
|
-
|
|
11003
|
-
|
|
11004
|
-
|
|
11005
|
-
|
|
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
|
-
|
|
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
|
-
|
|
11016
|
-
|
|
11017
|
-
error: error || 'API call failed',
|
|
11018
|
-
};
|
|
11019
|
-
}
|
|
10916
|
+
// return explanations.join('\n');
|
|
10917
|
+
// }
|
|
11020
10918
|
|
|
11021
|
-
|
|
11022
|
-
|
|
11023
|
-
|
|
10919
|
+
// function checkCompliance(body, subject) {
|
|
10920
|
+
// const text = (subject + ' ' + body).toLowerCase();
|
|
10921
|
+
// const flags = [];
|
|
11024
10922
|
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
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
|
-
|
|
10928
|
+
// if (/\b\d{10}\b/.test(body.replace(/\D/g, ''))) {
|
|
10929
|
+
// flags.push('contains_phone_number');
|
|
10930
|
+
// }
|
|
11030
10931
|
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
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
|
-
|
|
11133
|
-
|
|
11134
|
-
|
|
11135
|
-
|
|
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
|
-
|
|
11138
|
-
|
|
11139
|
-
|
|
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
|
-
|
|
11144
|
-
|
|
11145
|
-
sender_intent: z.enum(['inform', 'sell', 'scam', 'build_relationship', 'request_action', 'unknown']),
|
|
10945
|
+
// return flags;
|
|
10946
|
+
// }
|
|
11146
10947
|
|
|
11147
|
-
|
|
11148
|
-
|
|
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
|
-
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
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
|
-
|
|
11160
|
-
|
|
10957
|
+
// const spamConfidence = localAnalysis.spamScore;
|
|
10958
|
+
// const phishingRisk = localAnalysis.phishingScore > 50 ? 'medium' : 'low';
|
|
11161
10959
|
|
|
11162
|
-
|
|
11163
|
-
|
|
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
|
-
|
|
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
|
-
|
|
11169
|
-
|
|
11170
|
-
|
|
11171
|
-
|
|
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
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
|
|
11181
|
-
|
|
11182
|
-
|
|
11183
|
-
|
|
11184
|
-
|
|
11185
|
-
|
|
11186
|
-
|
|
11187
|
-
|
|
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
|
-
|
|
11191
|
-
|
|
11192
|
-
|
|
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
|
-
|
|
11195
|
-
|
|
11194
|
+
// // Enhance with additional analysis
|
|
11195
|
+
// const enhancedData = enhanceEmailDetection(data, name, email, email_body, email_subject);
|
|
11196
11196
|
|
|
11197
|
-
|
|
11198
|
-
|
|
11199
|
-
|
|
11200
|
-
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
|
|
11204
|
-
|
|
11205
|
-
|
|
11206
|
-
|
|
11207
|
-
|
|
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
|
+
// };
|