@xuda.io/ai_module 1.1.4721 → 1.1.4723
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 +538 -538
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -6869,7 +6869,7 @@ export const is_business_contact_has_person = async function (uid, email, name,
|
|
|
6869
6869
|
|
|
6870
6870
|
model: 'gpt-5-nano',
|
|
6871
6871
|
response_format: z.object({
|
|
6872
|
-
|
|
6872
|
+
business_has_person: z.boolean().describe('true if the email has person, false otherwise'),
|
|
6873
6873
|
}),
|
|
6874
6874
|
metadata: { func: 'is_business_contact_has_person' },
|
|
6875
6875
|
account_profile_info,
|
|
@@ -6877,7 +6877,7 @@ export const is_business_contact_has_person = async function (uid, email, name,
|
|
|
6877
6877
|
try {
|
|
6878
6878
|
if (has_person_ret.code > -1) {
|
|
6879
6879
|
const data = JSON.parse(has_person_ret.data);
|
|
6880
|
-
return data.
|
|
6880
|
+
return data.business_has_person;
|
|
6881
6881
|
}
|
|
6882
6882
|
} catch (error) {}
|
|
6883
6883
|
};
|
|
@@ -9826,635 +9826,635 @@ export const get_person_info = async function (uid, name, email, account_profile
|
|
|
9826
9826
|
}
|
|
9827
9827
|
};
|
|
9828
9828
|
|
|
9829
|
-
export const analyze_email_account_type = async function (uid, name, email, account_profile_info, email_context = '') {
|
|
9830
|
-
|
|
9829
|
+
// export const analyze_email_account_type = async function (uid, name, email, account_profile_info, email_context = '') {
|
|
9830
|
+
// // ========== HELPER FUNCTIONS ==========
|
|
9831
9831
|
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9832
|
+
// function enhanceEmailAnalysis(data, name, email, emailContext) {
|
|
9833
|
+
// const domain = email.split('@')[1] || '';
|
|
9834
|
+
// const localPart = email.split('@')[0] || '';
|
|
9835
|
+
// const nameParts = name.toLowerCase().split(/\s+/);
|
|
9836
|
+
// const firstName = nameParts[0] || '';
|
|
9837
|
+
// const lastName = nameParts.slice(-1)[0] || '';
|
|
9838
9838
|
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9839
|
+
// // Enhanced business company detection
|
|
9840
|
+
// if (data.account_type === 'business' && !data.business_company_name) {
|
|
9841
|
+
// data.business_company_name = inferCompanyFromDomain(domain);
|
|
9842
|
+
// }
|
|
9843
9843
|
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9844
|
+
// // Enhanced person detection
|
|
9845
|
+
// if (!data.is_real_person) {
|
|
9846
|
+
// data.is_real_person = detectRealPerson(localPart, name, domain);
|
|
9847
|
+
// }
|
|
9848
9848
|
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9849
|
+
// if (!data.person_name_in_email) {
|
|
9850
|
+
// data.person_name_in_email = checkNameInEmail(localPart, firstName, lastName);
|
|
9851
|
+
// }
|
|
9852
9852
|
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
9856
|
-
|
|
9853
|
+
// // Enhanced pattern analysis
|
|
9854
|
+
// if (data.email_pattern === 'unknown') {
|
|
9855
|
+
// data.email_pattern = analyzeEmailPattern(localPart, domain);
|
|
9856
|
+
// }
|
|
9857
9857
|
|
|
9858
|
-
|
|
9859
|
-
|
|
9860
|
-
|
|
9861
|
-
|
|
9858
|
+
// // Enhanced personal provider detection
|
|
9859
|
+
// if (data.account_type === 'personal' && !data.personal_account_provider) {
|
|
9860
|
+
// data.personal_account_provider = identifyPersonalProvider(domain);
|
|
9861
|
+
// }
|
|
9862
9862
|
|
|
9863
|
-
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9863
|
+
// // Enhanced risk assessment
|
|
9864
|
+
// if (data.spam_risk_level === 'unknown') {
|
|
9865
|
+
// data.spam_risk_level = assessSpamRisk(localPart, domain, data.account_type);
|
|
9866
|
+
// }
|
|
9867
9867
|
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9868
|
+
// // Enhanced activity assessment
|
|
9869
|
+
// if (!data.is_likely_active) {
|
|
9870
|
+
// data.is_likely_active = assessEmailActivity(localPart, domain, data.account_type, data.business_account_category);
|
|
9871
|
+
// }
|
|
9872
9872
|
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9873
|
+
// // Add domain analysis
|
|
9874
|
+
// data.domain_analysis = {
|
|
9875
|
+
// domain: domain,
|
|
9876
|
+
// is_public_provider: isPublicEmailProvider(domain),
|
|
9877
|
+
// is_custom_domain: isCustomDomain(domain),
|
|
9878
|
+
// is_free_email: isFreeEmailDomain(domain),
|
|
9879
|
+
// is_education: isEducationDomain(domain),
|
|
9880
|
+
// is_government: isGovernmentDomain(domain),
|
|
9881
|
+
// tld: domain.split('.').pop() || '',
|
|
9882
|
+
// };
|
|
9883
9883
|
|
|
9884
|
-
|
|
9885
|
-
|
|
9884
|
+
// // Add name-email correlation score
|
|
9885
|
+
// data.name_email_correlation = calculateNameEmailCorrelation(localPart, firstName, lastName);
|
|
9886
9886
|
|
|
9887
|
-
|
|
9888
|
-
|
|
9887
|
+
// // Add professional score
|
|
9888
|
+
// data.professional_score = calculateProfessionalScore(data);
|
|
9889
9889
|
|
|
9890
|
-
|
|
9891
|
-
|
|
9890
|
+
// // Add structured recommendations
|
|
9891
|
+
// data.recommendations = generateRecommendations(data);
|
|
9892
9892
|
|
|
9893
|
-
|
|
9894
|
-
|
|
9893
|
+
// // Add verification suggestions
|
|
9894
|
+
// data.verification_suggestions = generateVerificationSuggestions(data, emailContext);
|
|
9895
9895
|
|
|
9896
|
-
|
|
9897
|
-
|
|
9896
|
+
// // Add timestamp
|
|
9897
|
+
// data.analysis_timestamp = data.analysis_timestamp || new Date().toISOString();
|
|
9898
9898
|
|
|
9899
|
-
|
|
9900
|
-
|
|
9899
|
+
// return data;
|
|
9900
|
+
// }
|
|
9901
9901
|
|
|
9902
|
-
|
|
9903
|
-
|
|
9902
|
+
// function inferCompanyFromDomain(domain) {
|
|
9903
|
+
// if (!domain) return 'Unknown';
|
|
9904
9904
|
|
|
9905
|
-
|
|
9906
|
-
|
|
9905
|
+
// // Remove common TLDs and public providers
|
|
9906
|
+
// const baseDomain = domain.replace(/\.(com|org|net|co|io|ai|tech|app|dev)$/, '');
|
|
9907
9907
|
|
|
9908
|
-
|
|
9909
|
-
|
|
9908
|
+
// // Remove common subdomains
|
|
9909
|
+
// const cleanDomain = baseDomain.replace(/^(mail\.|email\.|webmail\.|smtp\.|mx\.|imap\.)/, '').replace(/\.(com|org|net)$/, '');
|
|
9910
9910
|
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9911
|
+
// // Convert to readable company name
|
|
9912
|
+
// const companyName = cleanDomain
|
|
9913
|
+
// .split(/[\.\-]/)
|
|
9914
|
+
// .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
9915
|
+
// .join(' ');
|
|
9916
9916
|
|
|
9917
|
-
|
|
9918
|
-
|
|
9917
|
+
// return companyName || 'Unknown';
|
|
9918
|
+
// }
|
|
9919
9919
|
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
|
|
9927
|
-
|
|
9928
|
-
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
|
|
9932
|
-
|
|
9933
|
-
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
|
|
9938
|
-
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
|
|
9946
|
-
|
|
9947
|
-
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
const localLower = localPart.toLowerCase();
|
|
9957
|
-
|
|
9958
|
-
// If it matches generic patterns, likely not a real person
|
|
9959
|
-
if (genericPatterns.some((pattern) => localLower === pattern || localLower.startsWith(pattern + '.') || localLower.endsWith('.' + pattern))) {
|
|
9960
|
-
return false;
|
|
9961
|
-
}
|
|
9920
|
+
// function detectRealPerson(localPart, name, domain) {
|
|
9921
|
+
// // Check for generic email addresses
|
|
9922
|
+
// const genericPatterns = [
|
|
9923
|
+
// 'info',
|
|
9924
|
+
// 'support',
|
|
9925
|
+
// 'sales',
|
|
9926
|
+
// 'contact',
|
|
9927
|
+
// 'hello',
|
|
9928
|
+
// 'noreply',
|
|
9929
|
+
// 'no-reply',
|
|
9930
|
+
// 'admin',
|
|
9931
|
+
// 'administrator',
|
|
9932
|
+
// 'webmaster',
|
|
9933
|
+
// 'postmaster',
|
|
9934
|
+
// 'hostmaster',
|
|
9935
|
+
// 'abuse',
|
|
9936
|
+
// 'security',
|
|
9937
|
+
// 'billing',
|
|
9938
|
+
// 'accounts',
|
|
9939
|
+
// 'finance',
|
|
9940
|
+
// 'hr',
|
|
9941
|
+
// 'humanresources',
|
|
9942
|
+
// 'marketing',
|
|
9943
|
+
// 'pr',
|
|
9944
|
+
// 'press',
|
|
9945
|
+
// 'media',
|
|
9946
|
+
// 'legal',
|
|
9947
|
+
// 'it',
|
|
9948
|
+
// 'techsupport',
|
|
9949
|
+
// 'help',
|
|
9950
|
+
// 'service',
|
|
9951
|
+
// 'customerservice',
|
|
9952
|
+
// 'feedback',
|
|
9953
|
+
// 'inquiries',
|
|
9954
|
+
// ];
|
|
9962
9955
|
|
|
9963
|
-
|
|
9964
|
-
const rolePatterns = ['ceo', 'cto', 'cfo', 'coo', 'cm', 'director', 'manager', 'head', 'lead', 'senior', 'junior', 'associate', 'analyst', 'engineer', 'developer', 'designer', 'architect', 'consultant', 'advisor'];
|
|
9956
|
+
// const localLower = localPart.toLowerCase();
|
|
9965
9957
|
|
|
9966
|
-
|
|
9967
|
-
|
|
9968
|
-
|
|
9958
|
+
// // If it matches generic patterns, likely not a real person
|
|
9959
|
+
// if (genericPatterns.some((pattern) => localLower === pattern || localLower.startsWith(pattern + '.') || localLower.endsWith('.' + pattern))) {
|
|
9960
|
+
// return false;
|
|
9961
|
+
// }
|
|
9969
9962
|
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
}
|
|
9963
|
+
// // Check for role-based patterns
|
|
9964
|
+
// const rolePatterns = ['ceo', 'cto', 'cfo', 'coo', 'cm', 'director', 'manager', 'head', 'lead', 'senior', 'junior', 'associate', 'analyst', 'engineer', 'developer', 'designer', 'architect', 'consultant', 'advisor'];
|
|
9973
9965
|
|
|
9974
|
-
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
}
|
|
9966
|
+
// // If contains role patterns but not name, might be generic
|
|
9967
|
+
// const hasRolePattern = rolePatterns.some((role) => localLower.includes(role));
|
|
9968
|
+
// const hasNameElements = checkNameInEmail(localPart, name.toLowerCase().split(' ')[0], name.toLowerCase().split(' ').slice(-1)[0]);
|
|
9978
9969
|
|
|
9979
|
-
|
|
9980
|
-
|
|
9981
|
-
|
|
9982
|
-
}
|
|
9970
|
+
// if (hasRolePattern && !hasNameElements) {
|
|
9971
|
+
// return false;
|
|
9972
|
+
// }
|
|
9983
9973
|
|
|
9984
|
-
|
|
9985
|
-
|
|
9974
|
+
// // Check for numeric-only or random strings
|
|
9975
|
+
// if (/^\d+$/.test(localPart) || /^[a-f0-9]{32}$/.test(localPart)) {
|
|
9976
|
+
// return false;
|
|
9977
|
+
// }
|
|
9986
9978
|
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
const firstLower = firstName.toLowerCase();
|
|
9992
|
-
const lastLower = lastName.toLowerCase();
|
|
9993
|
-
|
|
9994
|
-
// Check various name patterns
|
|
9995
|
-
const patterns = [
|
|
9996
|
-
`${firstLower}.${lastLower}`, // john.doe
|
|
9997
|
-
`${firstLower}${lastLower}`, // johndoe
|
|
9998
|
-
`${firstLower.charAt(0)}${lastLower}`, // jdoe
|
|
9999
|
-
`${firstLower}_${lastLower}`, // john_doe
|
|
10000
|
-
`${firstLower}-${lastLower}`, // john-doe
|
|
10001
|
-
`${lastLower}.${firstLower}`, // doe.john
|
|
10002
|
-
`${firstLower.charAt(0)}.${lastLower}`, // j.doe
|
|
10003
|
-
`${lastLower}${firstLower}`, // doejohn
|
|
10004
|
-
`${firstLower}`, // john
|
|
10005
|
-
`${lastLower}`, // doe
|
|
10006
|
-
];
|
|
10007
|
-
|
|
10008
|
-
return patterns.some((pattern) => localLower === pattern || localLower.startsWith(pattern + '.') || localLower.includes('.' + pattern));
|
|
10009
|
-
}
|
|
9979
|
+
// // Check for obvious spam patterns
|
|
9980
|
+
// if (localLower.includes('spam') || localLower.includes('bot') || localLower.includes('test')) {
|
|
9981
|
+
// return false;
|
|
9982
|
+
// }
|
|
10010
9983
|
|
|
10011
|
-
|
|
10012
|
-
|
|
9984
|
+
// return true;
|
|
9985
|
+
// }
|
|
10013
9986
|
|
|
10014
|
-
|
|
10015
|
-
|
|
10016
|
-
if (/^[a-z]+[a-z]+$/.test(localLower) && localLower.length > 5) return 'firstlast@company.com';
|
|
10017
|
-
if (/^[a-z]\.[a-z]+$/.test(localLower)) return 'f.last@company.com';
|
|
10018
|
-
if (/^[a-z][a-z]+$/.test(localLower) && localLower.length <= 5) return 'flast@company.com';
|
|
10019
|
-
if (/^[a-z]+$/.test(localLower) && localLower.length <= 8) return 'first@company.com';
|
|
10020
|
-
if (/^[a-z]+\.[a-z]+\.[a-z]+$/.test(localLower)) return 'first.m.last@company.com';
|
|
9987
|
+
// function checkNameInEmail(localPart, firstName, lastName) {
|
|
9988
|
+
// if (!firstName && !lastName) return false;
|
|
10021
9989
|
|
|
10022
|
-
|
|
10023
|
-
|
|
10024
|
-
|
|
9990
|
+
// const localLower = localPart.toLowerCase();
|
|
9991
|
+
// const firstLower = firstName.toLowerCase();
|
|
9992
|
+
// const lastLower = lastName.toLowerCase();
|
|
9993
|
+
|
|
9994
|
+
// // Check various name patterns
|
|
9995
|
+
// const patterns = [
|
|
9996
|
+
// `${firstLower}.${lastLower}`, // john.doe
|
|
9997
|
+
// `${firstLower}${lastLower}`, // johndoe
|
|
9998
|
+
// `${firstLower.charAt(0)}${lastLower}`, // jdoe
|
|
9999
|
+
// `${firstLower}_${lastLower}`, // john_doe
|
|
10000
|
+
// `${firstLower}-${lastLower}`, // john-doe
|
|
10001
|
+
// `${lastLower}.${firstLower}`, // doe.john
|
|
10002
|
+
// `${firstLower.charAt(0)}.${lastLower}`, // j.doe
|
|
10003
|
+
// `${lastLower}${firstLower}`, // doejohn
|
|
10004
|
+
// `${firstLower}`, // john
|
|
10005
|
+
// `${lastLower}`, // doe
|
|
10006
|
+
// ];
|
|
10025
10007
|
|
|
10026
|
-
|
|
10027
|
-
|
|
10028
|
-
if (/^[a-z]+\.[a-z]+$/.test(localLower)) return 'first.last@domain.com';
|
|
10029
|
-
if (/^[a-z]+[0-9]+$/.test(localLower)) return 'personal@provider.com';
|
|
10030
|
-
return 'custom@personal.com';
|
|
10031
|
-
}
|
|
10008
|
+
// return patterns.some((pattern) => localLower === pattern || localLower.startsWith(pattern + '.') || localLower.includes('.' + pattern));
|
|
10009
|
+
// }
|
|
10032
10010
|
|
|
10033
|
-
|
|
10034
|
-
|
|
10011
|
+
// function analyzeEmailPattern(localPart, domain) {
|
|
10012
|
+
// const localLower = localPart.toLowerCase();
|
|
10035
10013
|
|
|
10036
|
-
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
10043
|
-
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
|
|
10047
|
-
|
|
10048
|
-
|
|
10049
|
-
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
'gmx.com': 'GMX Mail',
|
|
10055
|
-
};
|
|
10014
|
+
// // Common business patterns
|
|
10015
|
+
// if (/^[a-z]+\.[a-z]+$/.test(localLower)) return 'first.last@company.com';
|
|
10016
|
+
// if (/^[a-z]+[a-z]+$/.test(localLower) && localLower.length > 5) return 'firstlast@company.com';
|
|
10017
|
+
// if (/^[a-z]\.[a-z]+$/.test(localLower)) return 'f.last@company.com';
|
|
10018
|
+
// if (/^[a-z][a-z]+$/.test(localLower) && localLower.length <= 5) return 'flast@company.com';
|
|
10019
|
+
// if (/^[a-z]+$/.test(localLower) && localLower.length <= 8) return 'first@company.com';
|
|
10020
|
+
// if (/^[a-z]+\.[a-z]+\.[a-z]+$/.test(localLower)) return 'first.m.last@company.com';
|
|
10021
|
+
|
|
10022
|
+
// // Generic patterns
|
|
10023
|
+
// if (/^(info|support|sales|contact|hello)$/.test(localLower)) return 'role@company.com';
|
|
10024
|
+
// if (/^(hr|finance|marketing|it|legal)$/.test(localLower)) return 'department@company.com';
|
|
10025
|
+
|
|
10026
|
+
// // Personal patterns
|
|
10027
|
+
// if (isPublicEmailProvider(domain)) {
|
|
10028
|
+
// if (/^[a-z]+\.[a-z]+$/.test(localLower)) return 'first.last@domain.com';
|
|
10029
|
+
// if (/^[a-z]+[0-9]+$/.test(localLower)) return 'personal@provider.com';
|
|
10030
|
+
// return 'custom@personal.com';
|
|
10031
|
+
// }
|
|
10056
10032
|
|
|
10057
|
-
|
|
10058
|
-
|
|
10033
|
+
// return 'unknown';
|
|
10034
|
+
// }
|
|
10059
10035
|
|
|
10060
|
-
|
|
10061
|
-
|
|
10036
|
+
// function identifyPersonalProvider(domain) {
|
|
10037
|
+
// const providers = {
|
|
10038
|
+
// 'gmail.com': 'Google Gmail',
|
|
10039
|
+
// 'googlemail.com': 'Google Gmail',
|
|
10040
|
+
// 'outlook.com': 'Microsoft Outlook',
|
|
10041
|
+
// 'hotmail.com': 'Microsoft Hotmail',
|
|
10042
|
+
// 'live.com': 'Microsoft Live',
|
|
10043
|
+
// 'yahoo.com': 'Yahoo Mail',
|
|
10044
|
+
// 'ymail.com': 'Yahoo Mail',
|
|
10045
|
+
// 'aol.com': 'AOL Mail',
|
|
10046
|
+
// 'icloud.com': 'Apple iCloud',
|
|
10047
|
+
// 'me.com': 'Apple iCloud',
|
|
10048
|
+
// 'mac.com': 'Apple iCloud',
|
|
10049
|
+
// 'protonmail.com': 'ProtonMail',
|
|
10050
|
+
// 'proton.me': 'ProtonMail',
|
|
10051
|
+
// 'zoho.com': 'Zoho Mail',
|
|
10052
|
+
// 'yandex.com': 'Yandex Mail',
|
|
10053
|
+
// 'mail.com': 'Mail.com',
|
|
10054
|
+
// 'gmx.com': 'GMX Mail',
|
|
10055
|
+
// };
|
|
10062
10056
|
|
|
10063
|
-
|
|
10064
|
-
|
|
10057
|
+
// return providers[domain.toLowerCase()] || 'Custom/Unknown';
|
|
10058
|
+
// }
|
|
10065
10059
|
|
|
10066
|
-
|
|
10067
|
-
|
|
10060
|
+
// function isPublicEmailProvider(domain) {
|
|
10061
|
+
// const publicProviders = ['gmail.com', 'googlemail.com', 'outlook.com', 'hotmail.com', 'live.com', 'yahoo.com', 'ymail.com', 'aol.com', 'icloud.com', 'me.com', 'mac.com', 'protonmail.com', 'proton.me', 'zoho.com', 'yandex.com', 'mail.com', 'gmx.com'];
|
|
10068
10062
|
|
|
10069
|
-
|
|
10070
|
-
|
|
10063
|
+
// return publicProviders.includes(domain.toLowerCase());
|
|
10064
|
+
// }
|
|
10071
10065
|
|
|
10072
|
-
|
|
10073
|
-
|
|
10066
|
+
// function isFreeEmailDomain(domain) {
|
|
10067
|
+
// const freeDomains = ['gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com', 'aol.com', 'mail.com', 'gmx.com', 'yandex.com', 'zoho.com'];
|
|
10074
10068
|
|
|
10075
|
-
|
|
10076
|
-
|
|
10069
|
+
// return freeDomains.includes(domain.toLowerCase());
|
|
10070
|
+
// }
|
|
10077
10071
|
|
|
10078
|
-
|
|
10079
|
-
|
|
10080
|
-
}
|
|
10072
|
+
// function isCustomDomain(domain) {
|
|
10073
|
+
// const publicProviders = ['gmail.com', 'googlemail.com', 'outlook.com', 'hotmail.com', 'live.com', 'yahoo.com', 'ymail.com', 'aol.com', 'icloud.com', 'me.com', 'mac.com', 'protonmail.com', 'proton.me', 'zoho.com', 'yandex.com', 'mail.com', 'gmx.com', 'edu', 'gov', 'mil', 'org', 'net'];
|
|
10081
10074
|
|
|
10082
|
-
|
|
10083
|
-
|
|
10084
|
-
}
|
|
10075
|
+
// return !publicProviders.some((provider) => domain.toLowerCase().includes(provider));
|
|
10076
|
+
// }
|
|
10085
10077
|
|
|
10086
|
-
|
|
10087
|
-
|
|
10078
|
+
// function isEducationDomain(domain) {
|
|
10079
|
+
// return domain.toLowerCase().endsWith('.edu') || domain.toLowerCase().includes('.ac.');
|
|
10080
|
+
// }
|
|
10088
10081
|
|
|
10089
|
-
|
|
10090
|
-
|
|
10091
|
-
|
|
10092
|
-
if (/^\d+$/.test(localLower)) return 'high'; // Numbers only
|
|
10093
|
-
if (localLower.includes('temp') || localLower.includes('throwaway')) return 'high';
|
|
10082
|
+
// function isGovernmentDomain(domain) {
|
|
10083
|
+
// return domain.toLowerCase().endsWith('.gov') || domain.toLowerCase().endsWith('.mil');
|
|
10084
|
+
// }
|
|
10094
10085
|
|
|
10095
|
-
|
|
10096
|
-
|
|
10097
|
-
if (accountType === 'personal' && localLower.includes('+')) return 'medium'; // Plus addressing
|
|
10086
|
+
// function assessSpamRisk(localPart, domain, accountType) {
|
|
10087
|
+
// const localLower = localPart.toLowerCase();
|
|
10098
10088
|
|
|
10099
|
-
|
|
10100
|
-
|
|
10089
|
+
// // High risk indicators
|
|
10090
|
+
// if (localLower.includes('spam') || localLower.includes('bot')) return 'high';
|
|
10091
|
+
// if (/^[a-f0-9]{32}$/.test(localLower)) return 'high'; // MD5 hash-like
|
|
10092
|
+
// if (/^\d+$/.test(localLower)) return 'high'; // Numbers only
|
|
10093
|
+
// if (localLower.includes('temp') || localLower.includes('throwaway')) return 'high';
|
|
10101
10094
|
|
|
10102
|
-
|
|
10103
|
-
|
|
10095
|
+
// // Medium risk indicators
|
|
10096
|
+
// if (localLower.includes('test') || localLower.includes('demo')) return 'medium';
|
|
10097
|
+
// if (accountType === 'personal' && localLower.includes('+')) return 'medium'; // Plus addressing
|
|
10104
10098
|
|
|
10105
|
-
|
|
10106
|
-
|
|
10107
|
-
const disposableDomains = ['tempmail.com', 'mailinator.com', 'guerrillamail.com', '10minutemail.com', 'yopmail.com', 'trashmail.com', 'dispostable.com', 'fakeinbox.com', 'throwawaymail.com', 'temp-mail.org'];
|
|
10099
|
+
// // Check disposable email domains
|
|
10100
|
+
// if (isDisposableDomain(domain)) return 'high';
|
|
10108
10101
|
|
|
10109
|
-
|
|
10110
|
-
|
|
10102
|
+
// return 'low';
|
|
10103
|
+
// }
|
|
10111
10104
|
|
|
10112
|
-
|
|
10113
|
-
|
|
10114
|
-
|
|
10115
|
-
return true;
|
|
10116
|
-
}
|
|
10105
|
+
// function isDisposableDomain(domain) {
|
|
10106
|
+
// // Common disposable/temporary email domains
|
|
10107
|
+
// const disposableDomains = ['tempmail.com', 'mailinator.com', 'guerrillamail.com', '10minutemail.com', 'yopmail.com', 'trashmail.com', 'dispostable.com', 'fakeinbox.com', 'throwawaymail.com', 'temp-mail.org'];
|
|
10117
10108
|
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
return true;
|
|
10121
|
-
}
|
|
10109
|
+
// return disposableDomains.some((d) => domain.toLowerCase().includes(d));
|
|
10110
|
+
// }
|
|
10122
10111
|
|
|
10123
|
-
|
|
10124
|
-
|
|
10125
|
-
|
|
10126
|
-
|
|
10112
|
+
// function assessEmailActivity(localPart, domain, accountType, businessCategory) {
|
|
10113
|
+
// // Generic/role emails are usually monitored
|
|
10114
|
+
// if (accountType === 'business' && ['generic_role', 'department', 'catch_all'].includes(businessCategory)) {
|
|
10115
|
+
// return true;
|
|
10116
|
+
// }
|
|
10127
10117
|
|
|
10128
|
-
|
|
10129
|
-
|
|
10130
|
-
|
|
10131
|
-
|
|
10118
|
+
// // Personal emails with name patterns are likely active
|
|
10119
|
+
// if (accountType === 'personal' && /^[a-z]+\.[a-z]+$/.test(localPart.toLowerCase())) {
|
|
10120
|
+
// return true;
|
|
10121
|
+
// }
|
|
10132
10122
|
|
|
10133
|
-
|
|
10134
|
-
|
|
10135
|
-
|
|
10123
|
+
// // Education and government emails are usually active
|
|
10124
|
+
// if (isEducationDomain(domain) || isGovernmentDomain(domain)) {
|
|
10125
|
+
// return true;
|
|
10126
|
+
// }
|
|
10136
10127
|
|
|
10137
|
-
|
|
10138
|
-
|
|
10128
|
+
// // Disposable domains are usually inactive after short period
|
|
10129
|
+
// if (isDisposableDomain(domain)) {
|
|
10130
|
+
// return false;
|
|
10131
|
+
// }
|
|
10139
10132
|
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
|
|
10143
|
-
const lastLower = lastName.toLowerCase();
|
|
10133
|
+
// // Default assumption
|
|
10134
|
+
// return true;
|
|
10135
|
+
// }
|
|
10144
10136
|
|
|
10145
|
-
|
|
10146
|
-
|
|
10147
|
-
if (localLower === `${firstLower}${lastLower}`) score += 35;
|
|
10148
|
-
if (localLower === `${firstLower.charAt(0)}${lastLower}`) score += 30;
|
|
10149
|
-
if (localLower === `${firstLower}_${lastLower}`) score += 25;
|
|
10137
|
+
// function calculateNameEmailCorrelation(localPart, firstName, lastName) {
|
|
10138
|
+
// if (!firstName && !lastName) return 0;
|
|
10150
10139
|
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10140
|
+
// let score = 0;
|
|
10141
|
+
// const localLower = localPart.toLowerCase();
|
|
10142
|
+
// const firstLower = firstName.toLowerCase();
|
|
10143
|
+
// const lastLower = lastName.toLowerCase();
|
|
10154
10144
|
|
|
10155
|
-
|
|
10156
|
-
|
|
10145
|
+
// // Exact name patterns
|
|
10146
|
+
// if (localLower === `${firstLower}.${lastLower}`) score += 40;
|
|
10147
|
+
// if (localLower === `${firstLower}${lastLower}`) score += 35;
|
|
10148
|
+
// if (localLower === `${firstLower.charAt(0)}${lastLower}`) score += 30;
|
|
10149
|
+
// if (localLower === `${firstLower}_${lastLower}`) score += 25;
|
|
10157
10150
|
|
|
10158
|
-
|
|
10159
|
-
|
|
10151
|
+
// // Partial matches
|
|
10152
|
+
// if (localLower.includes(firstLower)) score += 15;
|
|
10153
|
+
// if (localLower.includes(lastLower)) score += 15;
|
|
10160
10154
|
|
|
10161
|
-
|
|
10162
|
-
|
|
10155
|
+
// // Initial matches
|
|
10156
|
+
// if (localLower.startsWith(firstLower.charAt(0))) score += 10;
|
|
10163
10157
|
|
|
10164
|
-
|
|
10165
|
-
|
|
10158
|
+
// // Length consideration (shorter emails with names are better)
|
|
10159
|
+
// if (localLower.length <= 20) score += 5;
|
|
10166
10160
|
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
else if (data.account_type === 'personal') score += 10;
|
|
10161
|
+
// return Math.min(score, 100);
|
|
10162
|
+
// }
|
|
10170
10163
|
|
|
10171
|
-
|
|
10172
|
-
|
|
10164
|
+
// function calculateProfessionalScore(data) {
|
|
10165
|
+
// let score = 50; // Base score
|
|
10173
10166
|
|
|
10174
|
-
|
|
10175
|
-
|
|
10167
|
+
// // Account type weights
|
|
10168
|
+
// if (data.account_type === 'business') score += 30;
|
|
10169
|
+
// else if (data.account_type === 'personal') score += 10;
|
|
10176
10170
|
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
else if (data.spam_risk_level === 'high') score -= 20;
|
|
10171
|
+
// // Real person bonus
|
|
10172
|
+
// if (data.is_real_person) score += 20;
|
|
10180
10173
|
|
|
10181
|
-
|
|
10182
|
-
|
|
10174
|
+
// // Active email bonus
|
|
10175
|
+
// if (data.is_likely_active) score += 15;
|
|
10183
10176
|
|
|
10184
|
-
|
|
10185
|
-
|
|
10177
|
+
// // Low spam risk bonus
|
|
10178
|
+
// if (data.spam_risk_level === 'low') score += 10;
|
|
10179
|
+
// else if (data.spam_risk_level === 'high') score -= 20;
|
|
10186
10180
|
|
|
10187
|
-
|
|
10188
|
-
|
|
10181
|
+
// // Name-email correlation bonus
|
|
10182
|
+
// score += (data.name_email_correlation / 100) * 20;
|
|
10189
10183
|
|
|
10190
|
-
|
|
10191
|
-
|
|
10184
|
+
// // Business category bonus
|
|
10185
|
+
// if (data.business_account_category === 'personal_employee') score += 15;
|
|
10192
10186
|
|
|
10193
|
-
|
|
10194
|
-
|
|
10195
|
-
recommendations.push('Ideal for direct professional outreach');
|
|
10196
|
-
recommendations.push('Suitable for sales, recruitment, and partnership discussions');
|
|
10197
|
-
} else if (data.business_account_category === 'department') {
|
|
10198
|
-
recommendations.push('Best for department-specific inquiries');
|
|
10199
|
-
recommendations.push('Use for customer support or service requests');
|
|
10200
|
-
}
|
|
10201
|
-
} else if (data.account_type === 'personal') {
|
|
10202
|
-
recommendations.push('Suitable for networking and personal connections');
|
|
10203
|
-
recommendations.push('May be used for freelance or consulting work');
|
|
10204
|
-
}
|
|
10187
|
+
// return Math.max(0, Math.min(100, score));
|
|
10188
|
+
// }
|
|
10205
10189
|
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
}
|
|
10190
|
+
// function generateRecommendations(data) {
|
|
10191
|
+
// const recommendations = [];
|
|
10209
10192
|
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10193
|
+
// if (data.account_type === 'business' && data.is_real_person) {
|
|
10194
|
+
// if (data.business_account_category === 'personal_employee') {
|
|
10195
|
+
// recommendations.push('Ideal for direct professional outreach');
|
|
10196
|
+
// recommendations.push('Suitable for sales, recruitment, and partnership discussions');
|
|
10197
|
+
// } else if (data.business_account_category === 'department') {
|
|
10198
|
+
// recommendations.push('Best for department-specific inquiries');
|
|
10199
|
+
// recommendations.push('Use for customer support or service requests');
|
|
10200
|
+
// }
|
|
10201
|
+
// } else if (data.account_type === 'personal') {
|
|
10202
|
+
// recommendations.push('Suitable for networking and personal connections');
|
|
10203
|
+
// recommendations.push('May be used for freelance or consulting work');
|
|
10204
|
+
// }
|
|
10213
10205
|
|
|
10214
|
-
|
|
10215
|
-
|
|
10206
|
+
// if (data.spam_risk_level === 'high') {
|
|
10207
|
+
// recommendations.push('Consider verifying before important communications');
|
|
10208
|
+
// }
|
|
10216
10209
|
|
|
10217
|
-
|
|
10218
|
-
|
|
10210
|
+
// if (!data.is_likely_active) {
|
|
10211
|
+
// recommendations.push('Email may not be actively monitored');
|
|
10212
|
+
// }
|
|
10219
10213
|
|
|
10220
|
-
|
|
10221
|
-
|
|
10222
|
-
}
|
|
10214
|
+
// return recommendations;
|
|
10215
|
+
// }
|
|
10223
10216
|
|
|
10224
|
-
|
|
10225
|
-
|
|
10226
|
-
}
|
|
10217
|
+
// function generateVerificationSuggestions(data, emailContext) {
|
|
10218
|
+
// const suggestions = [];
|
|
10227
10219
|
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10220
|
+
// if (data.account_type === 'business' && !data.business_company_name) {
|
|
10221
|
+
// suggestions.push('Verify company name through LinkedIn or company website');
|
|
10222
|
+
// }
|
|
10231
10223
|
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10224
|
+
// if (!data.is_real_person && data.account_type === 'business') {
|
|
10225
|
+
// suggestions.push('Check if this is a role-based email that forwards to individuals');
|
|
10226
|
+
// }
|
|
10235
10227
|
|
|
10236
|
-
|
|
10237
|
-
|
|
10228
|
+
// if (data.spam_risk_level === 'medium' || data.spam_risk_level === 'high') {
|
|
10229
|
+
// suggestions.push('Send verification email before important communications');
|
|
10230
|
+
// }
|
|
10238
10231
|
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
|
|
10242
|
-
const nameParts = name.toLowerCase().split(/\s+/);
|
|
10243
|
-
const firstName = nameParts[0] || '';
|
|
10244
|
-
const lastName = nameParts.slice(-1)[0] || '';
|
|
10232
|
+
// if (data.domain_analysis.is_custom_domain) {
|
|
10233
|
+
// suggestions.push('Check company website for email format patterns');
|
|
10234
|
+
// }
|
|
10245
10235
|
|
|
10246
|
-
|
|
10247
|
-
|
|
10248
|
-
const isRealPerson = detectRealPerson(localPart, name, domain);
|
|
10236
|
+
// return suggestions;
|
|
10237
|
+
// }
|
|
10249
10238
|
|
|
10250
|
-
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
|
|
10255
|
-
|
|
10256
|
-
personal_account_type: 'unknown',
|
|
10257
|
-
personal_account_age_indicator: 'unknown',
|
|
10258
|
-
|
|
10259
|
-
business_company_name: !isPublicProvider ? inferCompanyFromDomain(domain) : undefined,
|
|
10260
|
-
business_company_domain: !isPublicProvider ? domain : undefined,
|
|
10261
|
-
business_account_category: !isPublicProvider ? (isRealPerson ? 'personal_employee' : 'generic_role') : undefined,
|
|
10262
|
-
business_account_role: undefined,
|
|
10263
|
-
business_department: undefined,
|
|
10264
|
-
|
|
10265
|
-
is_real_person: isRealPerson,
|
|
10266
|
-
person_name_in_email: checkNameInEmail(localPart, firstName, lastName),
|
|
10267
|
-
person_title_inferred: undefined,
|
|
10268
|
-
|
|
10269
|
-
email_pattern: analyzeEmailPattern(localPart, domain),
|
|
10270
|
-
|
|
10271
|
-
context_supports_business: undefined,
|
|
10272
|
-
context_supports_personal: undefined,
|
|
10273
|
-
context_company_mentions: [],
|
|
10274
|
-
|
|
10275
|
-
is_high_quality_contact: isRealPerson && !isPublicProvider,
|
|
10276
|
-
is_likely_active: true,
|
|
10277
|
-
spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10278
|
-
|
|
10279
|
-
suggested_use_case: isRealPerson && !isPublicProvider ? 'sales_outreach' : 'networking',
|
|
10280
|
-
|
|
10281
|
-
analysis_timestamp: new Date().toISOString(),
|
|
10282
|
-
analysis_notes: ['Default analysis due to API failure'],
|
|
10283
|
-
|
|
10284
|
-
// Enhanced fields
|
|
10285
|
-
domain_analysis: {
|
|
10286
|
-
domain: domain,
|
|
10287
|
-
is_public_provider: isPublicProvider,
|
|
10288
|
-
is_custom_domain: isCustomDomain(domain),
|
|
10289
|
-
is_free_email: isFreeEmailDomain(domain),
|
|
10290
|
-
is_education: isEducationDomain(domain),
|
|
10291
|
-
is_government: isGovernmentDomain(domain),
|
|
10292
|
-
tld: domain.split('.').pop() || '',
|
|
10293
|
-
},
|
|
10239
|
+
// function getDefaultEmailAnalysis(name, email, emailContext = '', error = null) {
|
|
10240
|
+
// const domain = email.split('@')[1] || '';
|
|
10241
|
+
// const localPart = email.split('@')[0] || '';
|
|
10242
|
+
// const nameParts = name.toLowerCase().split(/\s+/);
|
|
10243
|
+
// const firstName = nameParts[0] || '';
|
|
10244
|
+
// const lastName = nameParts.slice(-1)[0] || '';
|
|
10294
10245
|
|
|
10295
|
-
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
is_real_person: isRealPerson,
|
|
10299
|
-
is_likely_active: true,
|
|
10300
|
-
spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10301
|
-
name_email_correlation: calculateNameEmailCorrelation(localPart, firstName, lastName),
|
|
10302
|
-
business_account_category: !isPublicProvider ? (isRealPerson ? 'personal_employee' : 'generic_role') : undefined,
|
|
10303
|
-
}),
|
|
10246
|
+
// const isPublicProvider = isPublicEmailProvider(domain);
|
|
10247
|
+
// const accountType = isPublicProvider ? 'personal' : 'business';
|
|
10248
|
+
// const isRealPerson = detectRealPerson(localPart, name, domain);
|
|
10304
10249
|
|
|
10305
|
-
|
|
10306
|
-
|
|
10307
|
-
|
|
10308
|
-
|
|
10309
|
-
spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10310
|
-
is_likely_active: true,
|
|
10311
|
-
}),
|
|
10250
|
+
// return {
|
|
10251
|
+
// success: false,
|
|
10252
|
+
// account_type: accountType,
|
|
10253
|
+
// account_type_confidence: 70,
|
|
10312
10254
|
|
|
10313
|
-
|
|
10314
|
-
|
|
10315
|
-
|
|
10316
|
-
business_company_name: !isPublicProvider ? inferCompanyFromDomain(domain) : undefined,
|
|
10317
|
-
is_real_person: isRealPerson,
|
|
10318
|
-
spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10319
|
-
domain_analysis: { is_custom_domain: isCustomDomain(domain) },
|
|
10320
|
-
},
|
|
10321
|
-
emailContext,
|
|
10322
|
-
),
|
|
10255
|
+
// personal_account_provider: isPublicProvider ? identifyPersonalProvider(domain) : undefined,
|
|
10256
|
+
// personal_account_type: 'unknown',
|
|
10257
|
+
// personal_account_age_indicator: 'unknown',
|
|
10323
10258
|
|
|
10324
|
-
|
|
10325
|
-
|
|
10326
|
-
|
|
10259
|
+
// business_company_name: !isPublicProvider ? inferCompanyFromDomain(domain) : undefined,
|
|
10260
|
+
// business_company_domain: !isPublicProvider ? domain : undefined,
|
|
10261
|
+
// business_account_category: !isPublicProvider ? (isRealPerson ? 'personal_employee' : 'generic_role') : undefined,
|
|
10262
|
+
// business_account_role: undefined,
|
|
10263
|
+
// business_department: undefined,
|
|
10327
10264
|
|
|
10328
|
-
|
|
10329
|
-
|
|
10330
|
-
|
|
10331
|
-
|
|
10332
|
-
EMAIL CONTEXT (if provided):
|
|
10333
|
-
"${email_context.substring(0, 400)}${email_context.length > 400 ? '...' : ''}"
|
|
10334
|
-
|
|
10335
|
-
ANALYSIS TASKS:
|
|
10336
|
-
1. Determine if this is a PERSONAL or BUSINESS email account
|
|
10337
|
-
2. For BUSINESS accounts:
|
|
10338
|
-
- Identify the company/organization
|
|
10339
|
-
- Determine if this email belongs to a REAL PERSON at the company
|
|
10340
|
-
- Or if it's a generic/role-based account
|
|
10341
|
-
3. For PERSONAL accounts:
|
|
10342
|
-
- Identify which personal email provider is used
|
|
10343
|
-
- Determine if it's likely a primary or secondary personal account
|
|
10344
|
-
|
|
10345
|
-
ANALYSIS CRITERIA:
|
|
10346
|
-
BUSINESS EMAIL INDICATORS:
|
|
10347
|
-
- Domain matches a known company (not public email providers)
|
|
10348
|
-
- Email format matches company naming conventions
|
|
10349
|
-
- Email is mentioned in professional context
|
|
10350
|
-
- Contains company-specific signature or details
|
|
10351
|
-
|
|
10352
|
-
PERSONAL EMAIL INDICATORS:
|
|
10353
|
-
- Domain is from public email providers (gmail.com, outlook.com, yahoo.com, etc.)
|
|
10354
|
-
- Email format is personal/creative
|
|
10355
|
-
- No company affiliation in context
|
|
10356
|
-
- Used for personal communications
|
|
10357
|
-
|
|
10358
|
-
PERSON VS GENERIC BUSINESS ACCOUNT:
|
|
10359
|
-
- PERSON: Contains personal name elements (john.doe@company.com)
|
|
10360
|
-
- GENERIC: info@, support@, sales@, contact@, hello@, noreply@, etc.
|
|
10361
|
-
- DEPARTMENT: hr@, finance@, marketing@, it@, etc.
|
|
10362
|
-
|
|
10363
|
-
COMPANY DETECTION:
|
|
10364
|
-
- Extract company from email domain when possible
|
|
10365
|
-
- Use name patterns to identify likely companies
|
|
10366
|
-
- Consider email context for company references
|
|
10367
|
-
|
|
10368
|
-
PROVIDE DETAILED ANALYSIS WITH CONFIDENCE LEVELS.`,
|
|
10369
|
-
model: 'gpt-5-nano',
|
|
10370
|
-
response_format: z.object({
|
|
10371
|
-
// Primary Classification
|
|
10372
|
-
account_type: z.enum(['personal', 'business', 'ambiguous']),
|
|
10373
|
-
account_type_confidence: z.number().min(0).max(100),
|
|
10374
|
-
|
|
10375
|
-
// Personal Account Details
|
|
10376
|
-
personal_account_provider: z.string().optional().nullable().describe('Email provider for personal accounts'),
|
|
10377
|
-
personal_account_type: z.enum(['primary', 'secondary', 'disposable', 'unknown']).optional().nullable(),
|
|
10378
|
-
personal_account_age_indicator: z.enum(['new', 'established', 'old', 'unknown']).optional().nullable(),
|
|
10379
|
-
|
|
10380
|
-
// Business Account Details
|
|
10381
|
-
business_company_name: z.string().optional().nullable().describe('Company name if business account'),
|
|
10382
|
-
business_company_domain: z.string().optional().nullable().describe('Company domain'),
|
|
10383
|
-
business_account_category: z.enum(['personal_employee', 'generic_role', 'department', 'catch_all', 'unknown']).optional().nullable(),
|
|
10384
|
-
business_account_role: z.string().optional().nullable().describe('Role suggested by email address'),
|
|
10385
|
-
business_department: z.string().optional().nullable().describe('Department if applicable'),
|
|
10386
|
-
|
|
10387
|
-
// Person Analysis
|
|
10388
|
-
is_real_person: z.boolean().describe('Whether email belongs to a real person'),
|
|
10389
|
-
person_name_in_email: z.boolean().describe("Whether person's name appears in email address"),
|
|
10390
|
-
person_title_inferred: z.string().optional().nullable().describe('Inferred job title from email pattern'),
|
|
10391
|
-
|
|
10392
|
-
// Email Pattern Analysis
|
|
10393
|
-
email_pattern: z.enum([
|
|
10394
|
-
'first.last@company.com',
|
|
10395
|
-
'first.last@domain.com',
|
|
10396
|
-
'firstlast@company.com',
|
|
10397
|
-
'flast@company.com',
|
|
10398
|
-
'first@company.com',
|
|
10399
|
-
'f.last@company.com',
|
|
10400
|
-
'initial.last@company.com',
|
|
10401
|
-
'role@company.com',
|
|
10402
|
-
'department@company.com',
|
|
10403
|
-
'info@company.com',
|
|
10404
|
-
'generic@company.com',
|
|
10405
|
-
'personal@provider.com',
|
|
10406
|
-
'custom@personal.com',
|
|
10407
|
-
'unknown',
|
|
10408
|
-
]),
|
|
10409
|
-
|
|
10410
|
-
// Context Analysis
|
|
10411
|
-
context_supports_business: z.boolean().optional().nullable().describe('Email context suggests business use'),
|
|
10412
|
-
context_supports_personal: z.boolean().optional().nullable().describe('Email context suggests personal use'),
|
|
10413
|
-
context_company_mentions: z.array(z.string()).optional().nullable().describe('Companies mentioned in context'),
|
|
10414
|
-
|
|
10415
|
-
// Risk & Quality Assessment
|
|
10416
|
-
is_high_quality_contact: z.boolean().describe('Good contact for professional outreach'),
|
|
10417
|
-
is_likely_active: z.boolean().describe('Email likely actively monitored'),
|
|
10418
|
-
spam_risk_level: z.enum(['low', 'medium', 'high', 'unknown']),
|
|
10419
|
-
|
|
10420
|
-
// Recommendations
|
|
10421
|
-
suggested_use_case: z.enum(['sales_outreach', 'recruitment', 'customer_support', 'partnership', 'networking', 'personal_contact', 'avoid']),
|
|
10265
|
+
// is_real_person: isRealPerson,
|
|
10266
|
+
// person_name_in_email: checkNameInEmail(localPart, firstName, lastName),
|
|
10267
|
+
// person_title_inferred: undefined,
|
|
10422
10268
|
|
|
10423
|
-
|
|
10424
|
-
analysis_timestamp: z.string().describe('When analysis was performed'),
|
|
10425
|
-
analysis_notes: z.array(z.string()).optional().nullable().describe('Key observations from analysis'),
|
|
10426
|
-
}),
|
|
10427
|
-
metadata: {
|
|
10428
|
-
func: 'analyze_email_account_type',
|
|
10429
|
-
person_name: name,
|
|
10430
|
-
person_email: email,
|
|
10431
|
-
has_email_context: !!email_context,
|
|
10432
|
-
email_length: email_context?.length || 0,
|
|
10433
|
-
},
|
|
10434
|
-
account_profile_info,
|
|
10435
|
-
tools: [{ type: 'web_search_preview' }],
|
|
10436
|
-
});
|
|
10269
|
+
// email_pattern: analyzeEmailPattern(localPart, domain),
|
|
10437
10270
|
|
|
10438
|
-
|
|
10439
|
-
|
|
10440
|
-
|
|
10271
|
+
// context_supports_business: undefined,
|
|
10272
|
+
// context_supports_personal: undefined,
|
|
10273
|
+
// context_company_mentions: [],
|
|
10441
10274
|
|
|
10442
|
-
|
|
10443
|
-
|
|
10275
|
+
// is_high_quality_contact: isRealPerson && !isPublicProvider,
|
|
10276
|
+
// is_likely_active: true,
|
|
10277
|
+
// spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10444
10278
|
|
|
10445
|
-
|
|
10446
|
-
|
|
10447
|
-
|
|
10448
|
-
|
|
10449
|
-
|
|
10450
|
-
|
|
10451
|
-
|
|
10452
|
-
|
|
10453
|
-
|
|
10454
|
-
|
|
10455
|
-
|
|
10456
|
-
|
|
10457
|
-
|
|
10279
|
+
// suggested_use_case: isRealPerson && !isPublicProvider ? 'sales_outreach' : 'networking',
|
|
10280
|
+
|
|
10281
|
+
// analysis_timestamp: new Date().toISOString(),
|
|
10282
|
+
// analysis_notes: ['Default analysis due to API failure'],
|
|
10283
|
+
|
|
10284
|
+
// // Enhanced fields
|
|
10285
|
+
// domain_analysis: {
|
|
10286
|
+
// domain: domain,
|
|
10287
|
+
// is_public_provider: isPublicProvider,
|
|
10288
|
+
// is_custom_domain: isCustomDomain(domain),
|
|
10289
|
+
// is_free_email: isFreeEmailDomain(domain),
|
|
10290
|
+
// is_education: isEducationDomain(domain),
|
|
10291
|
+
// is_government: isGovernmentDomain(domain),
|
|
10292
|
+
// tld: domain.split('.').pop() || '',
|
|
10293
|
+
// },
|
|
10294
|
+
|
|
10295
|
+
// name_email_correlation: calculateNameEmailCorrelation(localPart, firstName, lastName),
|
|
10296
|
+
// professional_score: calculateProfessionalScore({
|
|
10297
|
+
// account_type: accountType,
|
|
10298
|
+
// is_real_person: isRealPerson,
|
|
10299
|
+
// is_likely_active: true,
|
|
10300
|
+
// spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10301
|
+
// name_email_correlation: calculateNameEmailCorrelation(localPart, firstName, lastName),
|
|
10302
|
+
// business_account_category: !isPublicProvider ? (isRealPerson ? 'personal_employee' : 'generic_role') : undefined,
|
|
10303
|
+
// }),
|
|
10304
|
+
|
|
10305
|
+
// recommendations: generateRecommendations({
|
|
10306
|
+
// account_type: accountType,
|
|
10307
|
+
// is_real_person: isRealPerson,
|
|
10308
|
+
// business_account_category: !isPublicProvider ? (isRealPerson ? 'personal_employee' : 'generic_role') : undefined,
|
|
10309
|
+
// spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10310
|
+
// is_likely_active: true,
|
|
10311
|
+
// }),
|
|
10312
|
+
|
|
10313
|
+
// verification_suggestions: generateVerificationSuggestions(
|
|
10314
|
+
// {
|
|
10315
|
+
// account_type: accountType,
|
|
10316
|
+
// business_company_name: !isPublicProvider ? inferCompanyFromDomain(domain) : undefined,
|
|
10317
|
+
// is_real_person: isRealPerson,
|
|
10318
|
+
// spam_risk_level: assessSpamRisk(localPart, domain, accountType),
|
|
10319
|
+
// domain_analysis: { is_custom_domain: isCustomDomain(domain) },
|
|
10320
|
+
// },
|
|
10321
|
+
// emailContext,
|
|
10322
|
+
// ),
|
|
10323
|
+
|
|
10324
|
+
// error: error || 'API call failed',
|
|
10325
|
+
// };
|
|
10326
|
+
// }
|
|
10327
|
+
|
|
10328
|
+
// const analysis_ret = await submit_chat_gpt_prompt({
|
|
10329
|
+
// uid,
|
|
10330
|
+
// prompt: `Analyze this email account: "${email}" for person: "${name}"
|
|
10331
|
+
|
|
10332
|
+
// EMAIL CONTEXT (if provided):
|
|
10333
|
+
// "${email_context.substring(0, 400)}${email_context.length > 400 ? '...' : ''}"
|
|
10334
|
+
|
|
10335
|
+
// ANALYSIS TASKS:
|
|
10336
|
+
// 1. Determine if this is a PERSONAL or BUSINESS email account
|
|
10337
|
+
// 2. For BUSINESS accounts:
|
|
10338
|
+
// - Identify the company/organization
|
|
10339
|
+
// - Determine if this email belongs to a REAL PERSON at the company
|
|
10340
|
+
// - Or if it's a generic/role-based account
|
|
10341
|
+
// 3. For PERSONAL accounts:
|
|
10342
|
+
// - Identify which personal email provider is used
|
|
10343
|
+
// - Determine if it's likely a primary or secondary personal account
|
|
10344
|
+
|
|
10345
|
+
// ANALYSIS CRITERIA:
|
|
10346
|
+
// BUSINESS EMAIL INDICATORS:
|
|
10347
|
+
// - Domain matches a known company (not public email providers)
|
|
10348
|
+
// - Email format matches company naming conventions
|
|
10349
|
+
// - Email is mentioned in professional context
|
|
10350
|
+
// - Contains company-specific signature or details
|
|
10351
|
+
|
|
10352
|
+
// PERSONAL EMAIL INDICATORS:
|
|
10353
|
+
// - Domain is from public email providers (gmail.com, outlook.com, yahoo.com, etc.)
|
|
10354
|
+
// - Email format is personal/creative
|
|
10355
|
+
// - No company affiliation in context
|
|
10356
|
+
// - Used for personal communications
|
|
10357
|
+
|
|
10358
|
+
// PERSON VS GENERIC BUSINESS ACCOUNT:
|
|
10359
|
+
// - PERSON: Contains personal name elements (john.doe@company.com)
|
|
10360
|
+
// - GENERIC: info@, support@, sales@, contact@, hello@, noreply@, etc.
|
|
10361
|
+
// - DEPARTMENT: hr@, finance@, marketing@, it@, etc.
|
|
10362
|
+
|
|
10363
|
+
// COMPANY DETECTION:
|
|
10364
|
+
// - Extract company from email domain when possible
|
|
10365
|
+
// - Use name patterns to identify likely companies
|
|
10366
|
+
// - Consider email context for company references
|
|
10367
|
+
|
|
10368
|
+
// PROVIDE DETAILED ANALYSIS WITH CONFIDENCE LEVELS.`,
|
|
10369
|
+
// model: 'gpt-5-nano',
|
|
10370
|
+
// response_format: z.object({
|
|
10371
|
+
// // Primary Classification
|
|
10372
|
+
// account_type: z.enum(['personal', 'business', 'ambiguous']),
|
|
10373
|
+
// account_type_confidence: z.number().min(0).max(100),
|
|
10374
|
+
|
|
10375
|
+
// // Personal Account Details
|
|
10376
|
+
// personal_account_provider: z.string().optional().nullable().describe('Email provider for personal accounts'),
|
|
10377
|
+
// personal_account_type: z.enum(['primary', 'secondary', 'disposable', 'unknown']).optional().nullable(),
|
|
10378
|
+
// personal_account_age_indicator: z.enum(['new', 'established', 'old', 'unknown']).optional().nullable(),
|
|
10379
|
+
|
|
10380
|
+
// // Business Account Details
|
|
10381
|
+
// business_company_name: z.string().optional().nullable().describe('Company name if business account'),
|
|
10382
|
+
// business_company_domain: z.string().optional().nullable().describe('Company domain'),
|
|
10383
|
+
// business_account_category: z.enum(['personal_employee', 'generic_role', 'department', 'catch_all', 'unknown']).optional().nullable(),
|
|
10384
|
+
// business_account_role: z.string().optional().nullable().describe('Role suggested by email address'),
|
|
10385
|
+
// business_department: z.string().optional().nullable().describe('Department if applicable'),
|
|
10386
|
+
|
|
10387
|
+
// // Person Analysis
|
|
10388
|
+
// is_real_person: z.boolean().describe('Whether email belongs to a real person'),
|
|
10389
|
+
// person_name_in_email: z.boolean().describe("Whether person's name appears in email address"),
|
|
10390
|
+
// person_title_inferred: z.string().optional().nullable().describe('Inferred job title from email pattern'),
|
|
10391
|
+
|
|
10392
|
+
// // Email Pattern Analysis
|
|
10393
|
+
// email_pattern: z.enum([
|
|
10394
|
+
// 'first.last@company.com',
|
|
10395
|
+
// 'first.last@domain.com',
|
|
10396
|
+
// 'firstlast@company.com',
|
|
10397
|
+
// 'flast@company.com',
|
|
10398
|
+
// 'first@company.com',
|
|
10399
|
+
// 'f.last@company.com',
|
|
10400
|
+
// 'initial.last@company.com',
|
|
10401
|
+
// 'role@company.com',
|
|
10402
|
+
// 'department@company.com',
|
|
10403
|
+
// 'info@company.com',
|
|
10404
|
+
// 'generic@company.com',
|
|
10405
|
+
// 'personal@provider.com',
|
|
10406
|
+
// 'custom@personal.com',
|
|
10407
|
+
// 'unknown',
|
|
10408
|
+
// ]),
|
|
10409
|
+
|
|
10410
|
+
// // Context Analysis
|
|
10411
|
+
// context_supports_business: z.boolean().optional().nullable().describe('Email context suggests business use'),
|
|
10412
|
+
// context_supports_personal: z.boolean().optional().nullable().describe('Email context suggests personal use'),
|
|
10413
|
+
// context_company_mentions: z.array(z.string()).optional().nullable().describe('Companies mentioned in context'),
|
|
10414
|
+
|
|
10415
|
+
// // Risk & Quality Assessment
|
|
10416
|
+
// is_high_quality_contact: z.boolean().describe('Good contact for professional outreach'),
|
|
10417
|
+
// is_likely_active: z.boolean().describe('Email likely actively monitored'),
|
|
10418
|
+
// spam_risk_level: z.enum(['low', 'medium', 'high', 'unknown']),
|
|
10419
|
+
|
|
10420
|
+
// // Recommendations
|
|
10421
|
+
// suggested_use_case: z.enum(['sales_outreach', 'recruitment', 'customer_support', 'partnership', 'networking', 'personal_contact', 'avoid']),
|
|
10422
|
+
|
|
10423
|
+
// // Metadata
|
|
10424
|
+
// analysis_timestamp: z.string().describe('When analysis was performed'),
|
|
10425
|
+
// analysis_notes: z.array(z.string()).optional().nullable().describe('Key observations from analysis'),
|
|
10426
|
+
// }),
|
|
10427
|
+
// metadata: {
|
|
10428
|
+
// func: 'analyze_email_account_type',
|
|
10429
|
+
// person_name: name,
|
|
10430
|
+
// person_email: email,
|
|
10431
|
+
// has_email_context: !!email_context,
|
|
10432
|
+
// email_length: email_context?.length || 0,
|
|
10433
|
+
// },
|
|
10434
|
+
// account_profile_info,
|
|
10435
|
+
// tools: [{ type: 'web_search_preview' }],
|
|
10436
|
+
// });
|
|
10437
|
+
|
|
10438
|
+
// try {
|
|
10439
|
+
// if (analysis_ret.code > -1) {
|
|
10440
|
+
// const data = typeof analysis_ret.data === 'string' ? JSON.parse(analysis_ret.data) : analysis_ret.data;
|
|
10441
|
+
|
|
10442
|
+
// // Enhance with additional analysis
|
|
10443
|
+
// const enhancedData = enhanceEmailAnalysis(data, name, email, email_context);
|
|
10444
|
+
|
|
10445
|
+
// return {
|
|
10446
|
+
// success: true,
|
|
10447
|
+
// ...enhancedData,
|
|
10448
|
+
// };
|
|
10449
|
+
// } else {
|
|
10450
|
+
// console.error('Email analysis API call failed:', analysis_ret);
|
|
10451
|
+
// return getDefaultEmailAnalysis(name, email, email_context);
|
|
10452
|
+
// }
|
|
10453
|
+
// } catch (error) {
|
|
10454
|
+
// console.error('Error in analyze_email_account_type:', error);
|
|
10455
|
+
// return getDefaultEmailAnalysis(name, email, email_context, error.message);
|
|
10456
|
+
// }
|
|
10457
|
+
// };
|
|
10458
10458
|
|
|
10459
10459
|
// export const detect_email_type = async function (uid, name, email, account_profile_info, email_body = '', email_subject = '') {
|
|
10460
10460
|
// // ========== HELPER FUNCTIONS ==========
|