spamscanner 6.0.0 → 6.1.0
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/README.md +569 -42
- package/dist/cjs/arf.cjs +539 -0
- package/dist/cjs/arf.cjs.map +7 -0
- package/dist/cjs/cli.cjs +4729 -0
- package/dist/cjs/cli.cjs.map +7 -0
- package/dist/cjs/{index.js → index.cjs} +1677 -52
- package/dist/cjs/index.cjs.map +7 -0
- package/dist/esm/arf.js +514 -0
- package/dist/esm/arf.js.map +7 -0
- package/dist/esm/cli.js +4713 -0
- package/dist/esm/cli.js.map +7 -0
- package/dist/esm/index.js +1676 -51
- package/dist/esm/index.js.map +4 -4
- package/dist/types/arf.d.ts +129 -0
- package/dist/types/auth.d.ts +157 -0
- package/dist/types/enhanced-idn-detector.d.ts +236 -0
- package/dist/types/get-attributes.d.ts +148 -0
- package/dist/types/index.d.ts +959 -0
- package/dist/types/is-arbitrary.d.ts +231 -0
- package/dist/types/reputation.d.ts +60 -0
- package/package.json +13 -4
- package/dist/cjs/index.js.map +0 -7
|
@@ -0,0 +1,959 @@
|
|
|
1
|
+
import type {ParsedMail, Attachment} from 'mailparser';
|
|
2
|
+
import type {AuthResult, AuthOptions, AuthScoreWeights, AuthScoreResult} from './auth.d.ts';
|
|
3
|
+
import type {ReputationResult, ReputationOptions} from './reputation.d.ts';
|
|
4
|
+
import type {SessionInfo, GetAttributesOptions, ExtractAttributesResult} from './get-attributes.d.ts';
|
|
5
|
+
import type {ArbitraryResult, ArbitraryOptions} from './is-arbitrary.d.ts';
|
|
6
|
+
|
|
7
|
+
// Re-export auth and reputation types
|
|
8
|
+
export type {AuthResult, AuthOptions, AuthScoreWeights, AuthScoreResult} from './auth.d.ts';
|
|
9
|
+
export type {ReputationResult, ReputationOptions} from './reputation.d.ts';
|
|
10
|
+
export type {SessionInfo, GetAttributesOptions, ExtractAttributesResult} from './get-attributes.d.ts';
|
|
11
|
+
export type {ArbitraryResult, ArbitraryOptions} from './is-arbitrary.d.ts';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* ClamScan configuration options
|
|
15
|
+
*/
|
|
16
|
+
export type ClamScanConfig = {
|
|
17
|
+
/** Remove infected files automatically */
|
|
18
|
+
removeInfected?: boolean;
|
|
19
|
+
/** Quarantine infected files */
|
|
20
|
+
quarantineInfected?: boolean;
|
|
21
|
+
/** Path to scan log file */
|
|
22
|
+
scanLog?: string | undefined;
|
|
23
|
+
/** Enable debug mode for ClamScan */
|
|
24
|
+
debugMode?: boolean;
|
|
25
|
+
/** File list to scan */
|
|
26
|
+
fileList?: string | undefined;
|
|
27
|
+
/** Scan directories recursively */
|
|
28
|
+
scanRecursively?: boolean;
|
|
29
|
+
/** Path to clamscan binary */
|
|
30
|
+
clamscanPath?: string;
|
|
31
|
+
/** Path to clamdscan binary */
|
|
32
|
+
clamdscanPath?: string;
|
|
33
|
+
/** Preferred scanner to use */
|
|
34
|
+
preference?: 'clamscan' | 'clamdscan';
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* SpamScanner configuration options
|
|
39
|
+
*/
|
|
40
|
+
export type SpamScannerConfig = {
|
|
41
|
+
/** Enable macro detection in documents */
|
|
42
|
+
enableMacroDetection?: boolean;
|
|
43
|
+
/** Enable performance metrics collection */
|
|
44
|
+
enablePerformanceMetrics?: boolean;
|
|
45
|
+
/** Timeout for operations in milliseconds */
|
|
46
|
+
timeout?: number;
|
|
47
|
+
/** List of supported languages for detection */
|
|
48
|
+
supportedLanguages?: string[];
|
|
49
|
+
/** Enable mixed language detection */
|
|
50
|
+
enableMixedLanguageDetection?: boolean;
|
|
51
|
+
/** Enable advanced pattern recognition */
|
|
52
|
+
enableAdvancedPatternRecognition?: boolean;
|
|
53
|
+
/** Enable debug mode */
|
|
54
|
+
debug?: boolean;
|
|
55
|
+
/** Logger instance */
|
|
56
|
+
logger?: Console | {
|
|
57
|
+
log: (...args: unknown[]) => void;
|
|
58
|
+
error: (...args: unknown[]) => void;
|
|
59
|
+
warn: (...args: unknown[]) => void;
|
|
60
|
+
info: (...args: unknown[]) => void;
|
|
61
|
+
debug: (...args: unknown[]) => void;
|
|
62
|
+
};
|
|
63
|
+
/** ClamScan configuration */
|
|
64
|
+
clamscan?: ClamScanConfig;
|
|
65
|
+
/** Pre-trained classifier data */
|
|
66
|
+
classifier?: Record<string, unknown> | undefined;
|
|
67
|
+
/** Replacement word mappings */
|
|
68
|
+
replacements?: Map<string, string> | Record<string, string> | undefined;
|
|
69
|
+
/** Enable NSFW detection */
|
|
70
|
+
enableNsfwDetection?: boolean;
|
|
71
|
+
/** Enable toxicity detection */
|
|
72
|
+
enableToxicityDetection?: boolean;
|
|
73
|
+
/** Toxicity detection threshold (0-1) */
|
|
74
|
+
toxicityThreshold?: number;
|
|
75
|
+
/** NSFW detection threshold (0-1) */
|
|
76
|
+
nsfwThreshold?: number;
|
|
77
|
+
/** Enable strict IDN detection */
|
|
78
|
+
strictIdnDetection?: boolean;
|
|
79
|
+
/** Enable token hashing */
|
|
80
|
+
hashTokens?: boolean;
|
|
81
|
+
/** Enable email authentication (DKIM/SPF/ARC/DMARC/BIMI) */
|
|
82
|
+
enableAuthentication?: boolean;
|
|
83
|
+
/** Authentication options */
|
|
84
|
+
authOptions?: AuthOptions;
|
|
85
|
+
/** Authentication score weights */
|
|
86
|
+
authScoreWeights?: AuthScoreWeights;
|
|
87
|
+
/** Enable Forward Email reputation checking */
|
|
88
|
+
enableReputation?: boolean;
|
|
89
|
+
/** Reputation API options */
|
|
90
|
+
reputationOptions?: ReputationOptions;
|
|
91
|
+
/** Enable arbitrary spam detection */
|
|
92
|
+
enableArbitraryDetection?: boolean;
|
|
93
|
+
/** Arbitrary spam score threshold */
|
|
94
|
+
arbitraryThreshold?: number;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Classification result
|
|
99
|
+
*/
|
|
100
|
+
export type ClassificationResult = {
|
|
101
|
+
/** Classification category */
|
|
102
|
+
category: 'spam' | 'ham';
|
|
103
|
+
/** Classification probability */
|
|
104
|
+
probability: number;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Phishing detection result
|
|
109
|
+
*/
|
|
110
|
+
export type PhishingResult = {
|
|
111
|
+
/** Type of detection */
|
|
112
|
+
type: 'phishing' | 'suspicious';
|
|
113
|
+
/** The URL that was flagged */
|
|
114
|
+
url: string;
|
|
115
|
+
/** Description of the issue */
|
|
116
|
+
description: string;
|
|
117
|
+
/** Additional details */
|
|
118
|
+
details?: {
|
|
119
|
+
riskFactors?: string[];
|
|
120
|
+
recommendations?: string[];
|
|
121
|
+
confidence?: number;
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Executable detection result
|
|
127
|
+
*/
|
|
128
|
+
export type ExecutableResult = {
|
|
129
|
+
/** Type of detection */
|
|
130
|
+
type: 'executable' | 'archive';
|
|
131
|
+
/** Filename of the attachment */
|
|
132
|
+
filename: string;
|
|
133
|
+
/** File extension */
|
|
134
|
+
extension?: string;
|
|
135
|
+
/** Detected file type */
|
|
136
|
+
detectedType?: string;
|
|
137
|
+
/** Description of the issue */
|
|
138
|
+
description: string;
|
|
139
|
+
/** Risk level */
|
|
140
|
+
risk?: 'low' | 'medium' | 'high';
|
|
141
|
+
/** Warning message */
|
|
142
|
+
warning?: string;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Macro detection result
|
|
147
|
+
*/
|
|
148
|
+
export type MacroResult = {
|
|
149
|
+
/** Type of detection */
|
|
150
|
+
type: 'macro';
|
|
151
|
+
/** Subtype of macro */
|
|
152
|
+
subtype: 'vba' | 'powershell' | 'javascript' | 'batch' | 'script' | 'office_document' | 'legacy_office' | 'pdf_javascript';
|
|
153
|
+
/** Filename if from attachment */
|
|
154
|
+
filename?: string;
|
|
155
|
+
/** Description of the issue */
|
|
156
|
+
description: string;
|
|
157
|
+
/** Risk level */
|
|
158
|
+
risk?: 'low' | 'medium' | 'high';
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Arbitrary detection result (e.g., GTUBE, spam patterns)
|
|
163
|
+
*/
|
|
164
|
+
export type ArbitraryResult = {
|
|
165
|
+
/** Type of detection */
|
|
166
|
+
type: 'arbitrary';
|
|
167
|
+
/** Subtype of arbitrary detection */
|
|
168
|
+
subtype?: 'gtube' | 'pattern';
|
|
169
|
+
/** Description of the issue */
|
|
170
|
+
description: string;
|
|
171
|
+
/** Arbitrary spam score */
|
|
172
|
+
score?: number;
|
|
173
|
+
/** List of reasons why the message was flagged */
|
|
174
|
+
reasons?: string[];
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Virus detection result
|
|
179
|
+
*/
|
|
180
|
+
export type VirusResult = {
|
|
181
|
+
/** Filename of the infected attachment */
|
|
182
|
+
filename: string;
|
|
183
|
+
/** Detected virus names */
|
|
184
|
+
virus: string[];
|
|
185
|
+
/** Type of detection */
|
|
186
|
+
type: 'virus';
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Pattern detection result
|
|
191
|
+
*/
|
|
192
|
+
export type PatternResult = {
|
|
193
|
+
/** Type of detection */
|
|
194
|
+
type: 'pattern' | 'file_path';
|
|
195
|
+
/** Subtype of pattern */
|
|
196
|
+
subtype?: string;
|
|
197
|
+
/** Count of matches */
|
|
198
|
+
count?: number;
|
|
199
|
+
/** Detected path */
|
|
200
|
+
path?: string;
|
|
201
|
+
/** Description of the issue */
|
|
202
|
+
description: string;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* IDN Homograph attack detection result
|
|
207
|
+
*/
|
|
208
|
+
export type IdnHomographResult = {
|
|
209
|
+
/** Whether an attack was detected */
|
|
210
|
+
detected: boolean;
|
|
211
|
+
/** List of suspicious domains */
|
|
212
|
+
domains: IdnDomainAnalysis[];
|
|
213
|
+
/** Overall risk score (0-1) */
|
|
214
|
+
riskScore: number;
|
|
215
|
+
/** Additional details */
|
|
216
|
+
details: string[];
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* IDN domain analysis
|
|
221
|
+
*/
|
|
222
|
+
export type IdnDomainAnalysis = {
|
|
223
|
+
/** The domain analyzed */
|
|
224
|
+
domain: string;
|
|
225
|
+
/** Original URL */
|
|
226
|
+
originalUrl: string;
|
|
227
|
+
/** Normalized URL */
|
|
228
|
+
normalizedUrl: string;
|
|
229
|
+
/** Risk score (0-1) */
|
|
230
|
+
riskScore: number;
|
|
231
|
+
/** Risk factors identified */
|
|
232
|
+
riskFactors: string[];
|
|
233
|
+
/** Recommendations */
|
|
234
|
+
recommendations: string[];
|
|
235
|
+
/** Confidence level */
|
|
236
|
+
confidence: number;
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Toxicity detection result
|
|
241
|
+
*/
|
|
242
|
+
export type ToxicityResult = {
|
|
243
|
+
/** Type of detection */
|
|
244
|
+
type: 'toxicity';
|
|
245
|
+
/** Toxicity category */
|
|
246
|
+
category: string;
|
|
247
|
+
/** Probability of toxicity */
|
|
248
|
+
probability: number;
|
|
249
|
+
/** Description of the issue */
|
|
250
|
+
description: string;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* NSFW detection result
|
|
255
|
+
*/
|
|
256
|
+
export type NsfwResult = {
|
|
257
|
+
/** Type of detection */
|
|
258
|
+
type: 'nsfw';
|
|
259
|
+
/** Filename of the image */
|
|
260
|
+
filename: string;
|
|
261
|
+
/** NSFW category */
|
|
262
|
+
category: 'Porn' | 'Hentai' | 'Sexy' | 'Drawing' | 'Neutral';
|
|
263
|
+
/** Probability of NSFW content */
|
|
264
|
+
probability: number;
|
|
265
|
+
/** Description of the issue */
|
|
266
|
+
description: string;
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* All scan results
|
|
271
|
+
*/
|
|
272
|
+
/**
|
|
273
|
+
* Extended authentication result with score
|
|
274
|
+
*/
|
|
275
|
+
export type AuthenticationResult = AuthResult & {
|
|
276
|
+
/** Authentication score */
|
|
277
|
+
score: AuthScoreResult;
|
|
278
|
+
/** Formatted Authentication-Results header */
|
|
279
|
+
authResultsHeader: string;
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Extended reputation result with details
|
|
284
|
+
*/
|
|
285
|
+
export type ExtendedReputationResult = ReputationResult & {
|
|
286
|
+
/** Values that were checked */
|
|
287
|
+
checkedValues: string[];
|
|
288
|
+
/** Detailed results per value */
|
|
289
|
+
details: Record<string, ReputationResult>;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* All scan results
|
|
294
|
+
*/
|
|
295
|
+
export type ScanResults = {
|
|
296
|
+
/** Classification result */
|
|
297
|
+
classification: ClassificationResult;
|
|
298
|
+
/** Phishing detection results */
|
|
299
|
+
phishing: PhishingResult[];
|
|
300
|
+
/** Executable detection results */
|
|
301
|
+
executables: ExecutableResult[];
|
|
302
|
+
/** Macro detection results */
|
|
303
|
+
macros: MacroResult[];
|
|
304
|
+
/** Arbitrary pattern results */
|
|
305
|
+
arbitrary: ArbitraryResult[];
|
|
306
|
+
/** Virus detection results */
|
|
307
|
+
viruses: VirusResult[];
|
|
308
|
+
/** Pattern detection results */
|
|
309
|
+
patterns: PatternResult[];
|
|
310
|
+
/** IDN homograph attack results */
|
|
311
|
+
idnHomographAttack: IdnHomographResult;
|
|
312
|
+
/** Toxicity detection results */
|
|
313
|
+
toxicity: ToxicityResult[];
|
|
314
|
+
/** NSFW detection results */
|
|
315
|
+
nsfw: NsfwResult[];
|
|
316
|
+
/** Authentication results (if enabled) */
|
|
317
|
+
authentication?: AuthenticationResult | null;
|
|
318
|
+
/** Reputation results (if enabled) */
|
|
319
|
+
reputation?: ExtendedReputationResult | null;
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Performance metrics
|
|
324
|
+
*/
|
|
325
|
+
export type PerformanceMetrics = {
|
|
326
|
+
/** Total processing time in ms */
|
|
327
|
+
totalTime: number;
|
|
328
|
+
/** Classification time in ms */
|
|
329
|
+
classificationTime: number;
|
|
330
|
+
/** Phishing detection time in ms */
|
|
331
|
+
phishingTime: number;
|
|
332
|
+
/** Executable detection time in ms */
|
|
333
|
+
executableTime: number;
|
|
334
|
+
/** Macro detection time in ms */
|
|
335
|
+
macroTime: number;
|
|
336
|
+
/** Virus scan time in ms */
|
|
337
|
+
virusTime: number;
|
|
338
|
+
/** Pattern detection time in ms */
|
|
339
|
+
patternTime: number;
|
|
340
|
+
/** IDN detection time in ms */
|
|
341
|
+
idnTime: number;
|
|
342
|
+
/** Memory usage statistics */
|
|
343
|
+
memoryUsage: NodeJS.MemoryUsage;
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Scanner metrics
|
|
348
|
+
*/
|
|
349
|
+
export type ScannerMetrics = {
|
|
350
|
+
/** Total number of scans performed */
|
|
351
|
+
totalScans: number;
|
|
352
|
+
/** Average scan time in ms */
|
|
353
|
+
averageTime: number;
|
|
354
|
+
/** Last scan time in ms */
|
|
355
|
+
lastScanTime: number;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Scan result
|
|
360
|
+
*/
|
|
361
|
+
export type ScanResult = {
|
|
362
|
+
/** Whether the email is spam */
|
|
363
|
+
isSpam: boolean;
|
|
364
|
+
/** Human-readable message */
|
|
365
|
+
message: string;
|
|
366
|
+
/** Detailed results from all detectors */
|
|
367
|
+
results: ScanResults;
|
|
368
|
+
/** Extracted URLs from the email */
|
|
369
|
+
links: string[];
|
|
370
|
+
/** Extracted tokens from the email */
|
|
371
|
+
tokens: string[];
|
|
372
|
+
/** Parsed mail object */
|
|
373
|
+
mail: ParsedMail;
|
|
374
|
+
/** Performance metrics (if enabled) */
|
|
375
|
+
metrics?: PerformanceMetrics;
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Tokens and mail result from source parsing
|
|
380
|
+
*/
|
|
381
|
+
export type TokensAndMailResult = {
|
|
382
|
+
/** Extracted tokens */
|
|
383
|
+
tokens: string[];
|
|
384
|
+
/** Parsed mail object */
|
|
385
|
+
mail: ParsedMail;
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Parsed URL result using tldts
|
|
390
|
+
*/
|
|
391
|
+
export type ParsedUrl = {
|
|
392
|
+
/** Full domain */
|
|
393
|
+
domain: string | undefined;
|
|
394
|
+
/** Domain without suffix */
|
|
395
|
+
domainWithoutSuffix: string | undefined;
|
|
396
|
+
/** Full hostname */
|
|
397
|
+
hostname: string | undefined;
|
|
398
|
+
/** Public suffix */
|
|
399
|
+
publicSuffix: string | undefined;
|
|
400
|
+
/** Subdomain */
|
|
401
|
+
subdomain: string | undefined;
|
|
402
|
+
/** Whether the hostname is an IP address */
|
|
403
|
+
isIp: boolean;
|
|
404
|
+
/** Whether the domain is ICANN registered */
|
|
405
|
+
isIcann: boolean;
|
|
406
|
+
/** Whether the domain is private */
|
|
407
|
+
isPrivate: boolean;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Mail object for internal processing
|
|
412
|
+
*/
|
|
413
|
+
export type MailObject = {
|
|
414
|
+
/** Plain text content */
|
|
415
|
+
text?: string;
|
|
416
|
+
/** HTML content */
|
|
417
|
+
html?: string;
|
|
418
|
+
/** Email subject */
|
|
419
|
+
subject?: string;
|
|
420
|
+
/** From address */
|
|
421
|
+
from?: Record<string, unknown>;
|
|
422
|
+
/** To addresses */
|
|
423
|
+
to?: unknown[];
|
|
424
|
+
/** Attachments */
|
|
425
|
+
attachments?: Attachment[];
|
|
426
|
+
/** Header lines */
|
|
427
|
+
headerLines?: Array<{line?: string}>;
|
|
428
|
+
/** Headers map */
|
|
429
|
+
headers?: Map<string, unknown> | Record<string, unknown>;
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Source input type for scanning
|
|
434
|
+
*/
|
|
435
|
+
export type ScanSource = string | Uint8Array;
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* SpamScanner class for email spam detection
|
|
439
|
+
*/
|
|
440
|
+
declare class SpamScanner {
|
|
441
|
+
/** Scanner configuration */
|
|
442
|
+
config: SpamScannerConfig & {
|
|
443
|
+
enableMacroDetection: boolean;
|
|
444
|
+
enablePerformanceMetrics: boolean;
|
|
445
|
+
timeout: number;
|
|
446
|
+
supportedLanguages: string[];
|
|
447
|
+
enableMixedLanguageDetection: boolean;
|
|
448
|
+
enableAdvancedPatternRecognition: boolean;
|
|
449
|
+
debug: boolean;
|
|
450
|
+
logger: Console;
|
|
451
|
+
clamscan: ClamScanConfig;
|
|
452
|
+
classifier: Record<string, unknown> | undefined;
|
|
453
|
+
replacements: Map<string, string> | Record<string, string> | undefined;
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
/** Naive Bayes classifier instance */
|
|
457
|
+
classifier: unknown | undefined;
|
|
458
|
+
|
|
459
|
+
/** ClamScan instance */
|
|
460
|
+
clamscan: unknown | undefined;
|
|
461
|
+
|
|
462
|
+
/** Whether the scanner is initialized */
|
|
463
|
+
isInitialized: boolean;
|
|
464
|
+
|
|
465
|
+
/** Replacement word mappings */
|
|
466
|
+
replacements: Map<string, string>;
|
|
467
|
+
|
|
468
|
+
/** Scanner metrics */
|
|
469
|
+
metrics: ScannerMetrics;
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Create a new SpamScanner instance
|
|
473
|
+
* @param options - Configuration options
|
|
474
|
+
*/
|
|
475
|
+
constructor(options?: SpamScannerConfig);
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Initialize the classifier
|
|
479
|
+
*/
|
|
480
|
+
initializeClassifier(): Promise<void>;
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Initialize replacements
|
|
484
|
+
*/
|
|
485
|
+
initializeReplacements(): Promise<void>;
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Initialize regex helpers
|
|
489
|
+
*/
|
|
490
|
+
initializeRegex(): void;
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Scan options for per-scan configuration
|
|
494
|
+
*/
|
|
495
|
+
scanOptions?: {
|
|
496
|
+
/** Enable authentication for this scan */
|
|
497
|
+
enableAuthentication?: boolean;
|
|
498
|
+
/** Authentication options for this scan */
|
|
499
|
+
authOptions?: AuthOptions;
|
|
500
|
+
/** Enable reputation checking for this scan */
|
|
501
|
+
enableReputation?: boolean;
|
|
502
|
+
/** Reputation options for this scan */
|
|
503
|
+
reputationOptions?: ReputationOptions;
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Scan an email for spam
|
|
508
|
+
* @param source - Email source (string, Uint8Array, or file path)
|
|
509
|
+
* @param scanOptions - Optional per-scan configuration
|
|
510
|
+
* @returns Scan result
|
|
511
|
+
*/
|
|
512
|
+
scan(source: ScanSource, scanOptions?: {
|
|
513
|
+
enableAuthentication?: boolean;
|
|
514
|
+
authOptions?: AuthOptions;
|
|
515
|
+
enableReputation?: boolean;
|
|
516
|
+
reputationOptions?: ReputationOptions;
|
|
517
|
+
}): Promise<ScanResult>;
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Get tokens and parsed mail from source
|
|
521
|
+
* @param source - Email source
|
|
522
|
+
* @returns Tokens and mail object
|
|
523
|
+
*/
|
|
524
|
+
getTokensAndMailFromSource(source: ScanSource): Promise<TokensAndMailResult>;
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Get classification result for tokens
|
|
528
|
+
* @param tokens - Array of tokens
|
|
529
|
+
* @returns Classification result
|
|
530
|
+
*/
|
|
531
|
+
getClassification(tokens: string[]): Promise<ClassificationResult>;
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Get phishing detection results
|
|
535
|
+
* @param mail - Parsed mail object
|
|
536
|
+
* @returns Array of phishing results
|
|
537
|
+
*/
|
|
538
|
+
getPhishingResults(mail: MailObject): Promise<PhishingResult[]>;
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Get executable detection results
|
|
542
|
+
* @param mail - Parsed mail object
|
|
543
|
+
* @returns Array of executable results
|
|
544
|
+
*/
|
|
545
|
+
getExecutableResults(mail: MailObject): Promise<ExecutableResult[]>;
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Get macro detection results
|
|
549
|
+
* @param mail - Parsed mail object
|
|
550
|
+
* @returns Array of macro results
|
|
551
|
+
*/
|
|
552
|
+
getMacroResults(mail: MailObject): Promise<MacroResult[]>;
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Get arbitrary pattern results (e.g., GTUBE)
|
|
556
|
+
* @param mail - Parsed mail object
|
|
557
|
+
* @returns Array of arbitrary results
|
|
558
|
+
*/
|
|
559
|
+
getArbitraryResults(mail: MailObject): Promise<ArbitraryResult[]>;
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Get virus scan results
|
|
563
|
+
* @param mail - Parsed mail object
|
|
564
|
+
* @returns Array of virus results
|
|
565
|
+
*/
|
|
566
|
+
getVirusResults(mail: MailObject): Promise<VirusResult[]>;
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Get pattern detection results
|
|
570
|
+
* @param mail - Parsed mail object
|
|
571
|
+
* @returns Array of pattern results
|
|
572
|
+
*/
|
|
573
|
+
getPatternResults(mail: MailObject): Promise<PatternResult[]>;
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Get file path detection results
|
|
577
|
+
* @param mail - Parsed mail object
|
|
578
|
+
* @returns Array of pattern results
|
|
579
|
+
*/
|
|
580
|
+
getFilePathResults(mail: MailObject): Promise<PatternResult[]>;
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Get IDN homograph attack results
|
|
584
|
+
* @param mail - Parsed mail object
|
|
585
|
+
* @returns IDN homograph result
|
|
586
|
+
*/
|
|
587
|
+
getIdnHomographResults(mail: MailObject): Promise<IdnHomographResult>;
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* Get toxicity detection results
|
|
591
|
+
* @param mail - Parsed mail object
|
|
592
|
+
* @returns Array of toxicity results
|
|
593
|
+
*/
|
|
594
|
+
getToxicityResults(mail: MailObject): Promise<ToxicityResult[]>;
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Get NSFW detection results
|
|
598
|
+
* @param mail - Parsed mail object
|
|
599
|
+
* @returns Array of NSFW results
|
|
600
|
+
*/
|
|
601
|
+
getNsfwResults(mail: MailObject): Promise<NsfwResult[]>;
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Get tokens from text
|
|
605
|
+
* @param text - Text to tokenize
|
|
606
|
+
* @param locale - Locale code (default: 'en')
|
|
607
|
+
* @param isHtml - Whether the text is HTML
|
|
608
|
+
* @returns Array of tokens
|
|
609
|
+
*/
|
|
610
|
+
getTokens(text: string, locale?: string, isHtml?: boolean): Promise<string[]>;
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Preprocess text for analysis
|
|
614
|
+
* @param text - Text to preprocess
|
|
615
|
+
* @returns Preprocessed text
|
|
616
|
+
*/
|
|
617
|
+
preprocessText(text: string): Promise<string>;
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Extract URLs from text
|
|
621
|
+
* @param text - Text to extract URLs from
|
|
622
|
+
* @returns Array of URLs
|
|
623
|
+
*/
|
|
624
|
+
getUrls(text: string): string[];
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Extract all URLs from mail and source
|
|
628
|
+
* @param mail - Parsed mail object
|
|
629
|
+
* @param originalSource - Original email source
|
|
630
|
+
* @returns Array of URLs
|
|
631
|
+
*/
|
|
632
|
+
extractAllUrls(mail: MailObject, originalSource: ScanSource): string[];
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Optimize URL parsing with timeout protection
|
|
636
|
+
* @param url - URL to parse
|
|
637
|
+
* @returns Normalized URL
|
|
638
|
+
*/
|
|
639
|
+
optimizeUrlParsing(url: string): Promise<string>;
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Parse URL using tldts
|
|
643
|
+
* @param url - URL to parse
|
|
644
|
+
* @returns Parsed URL result or null
|
|
645
|
+
*/
|
|
646
|
+
parseUrlWithTldts(url: string): ParsedUrl | undefined;
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Check if a domain is blocked by Cloudflare
|
|
650
|
+
* @param hostname - Hostname to check
|
|
651
|
+
* @returns Whether the domain is blocked
|
|
652
|
+
*/
|
|
653
|
+
isCloudflareBlocked(hostname: string): Promise<boolean>;
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Detect language using hybrid approach
|
|
657
|
+
* @param text - Text to analyze
|
|
658
|
+
* @returns Detected language code
|
|
659
|
+
*/
|
|
660
|
+
detectLanguageHybrid(text: string): Promise<string>;
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Parse and normalize locale code
|
|
664
|
+
* @param locale - Locale code to parse
|
|
665
|
+
* @returns Normalized locale code
|
|
666
|
+
*/
|
|
667
|
+
parseLocale(locale: string): string;
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Normalize language code from 3-letter to 2-letter format
|
|
671
|
+
* @param code - Language code to normalize
|
|
672
|
+
* @returns Normalized 2-letter language code
|
|
673
|
+
*/
|
|
674
|
+
normalizeLanguageCode(code: string): string;
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* Validate short text language detection
|
|
678
|
+
* @param text - Text that was analyzed
|
|
679
|
+
* @param detectedLang - Detected language code
|
|
680
|
+
* @returns Whether the detection is valid
|
|
681
|
+
*/
|
|
682
|
+
isValidShortTextDetection(text: string, detectedLang: string): boolean;
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Check if a path is a valid file path
|
|
686
|
+
* @param path - Path to validate
|
|
687
|
+
* @returns Whether the path is valid
|
|
688
|
+
*/
|
|
689
|
+
isValidFilePath(path: string): boolean;
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Get IDN detector instance
|
|
693
|
+
* @returns IDN detector or null
|
|
694
|
+
*/
|
|
695
|
+
getIdnDetector(): Promise<EnhancedIdnDetector | undefined>;
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Get authentication results using mailauth
|
|
699
|
+
* @param source - Email source
|
|
700
|
+
* @param mail - Parsed mail object
|
|
701
|
+
* @param options - Authentication options
|
|
702
|
+
* @returns Authentication result or null
|
|
703
|
+
*/
|
|
704
|
+
getAuthenticationResults(
|
|
705
|
+
source: ScanSource,
|
|
706
|
+
mail: MailObject,
|
|
707
|
+
options?: AuthOptions
|
|
708
|
+
): Promise<AuthenticationResult | null>;
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Get reputation results from Forward Email API
|
|
712
|
+
* @param mail - Parsed mail object
|
|
713
|
+
* @param authOptions - Authentication options (for IP/sender)
|
|
714
|
+
* @param reputationOptions - Reputation API options
|
|
715
|
+
* @returns Reputation result or null
|
|
716
|
+
*/
|
|
717
|
+
getReputationResults(
|
|
718
|
+
mail: MailObject,
|
|
719
|
+
authOptions?: AuthOptions,
|
|
720
|
+
reputationOptions?: ReputationOptions
|
|
721
|
+
): Promise<ExtendedReputationResult | null>;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Enhanced IDN Detector options
|
|
726
|
+
*/
|
|
727
|
+
export type EnhancedIdnDetectorOptions = {
|
|
728
|
+
/** Enable strict mode */
|
|
729
|
+
strictMode?: boolean;
|
|
730
|
+
/** Enable domain whitelist */
|
|
731
|
+
enableWhitelist?: boolean;
|
|
732
|
+
/** Enable brand protection */
|
|
733
|
+
enableBrandProtection?: boolean;
|
|
734
|
+
/** Enable context analysis */
|
|
735
|
+
enableContextAnalysis?: boolean;
|
|
736
|
+
/** Maximum similarity threshold (0-1) */
|
|
737
|
+
maxSimilarityThreshold?: number;
|
|
738
|
+
/** Minimum domain age in days */
|
|
739
|
+
minDomainAge?: number;
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Context for IDN analysis
|
|
744
|
+
*/
|
|
745
|
+
export type IdnAnalysisContext = {
|
|
746
|
+
/** Email content */
|
|
747
|
+
emailContent?: string;
|
|
748
|
+
/** Display text (if different from domain) */
|
|
749
|
+
displayText?: string | undefined;
|
|
750
|
+
/** Sender reputation (0-1) */
|
|
751
|
+
senderReputation?: number;
|
|
752
|
+
/** Email headers */
|
|
753
|
+
emailHeaders?: Map<string, unknown> | Record<string, unknown>;
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* IDN analysis result
|
|
758
|
+
*/
|
|
759
|
+
export type IdnAnalysisResult = {
|
|
760
|
+
/** The domain analyzed */
|
|
761
|
+
domain: string;
|
|
762
|
+
/** Whether the domain is an IDN */
|
|
763
|
+
isIdn: boolean;
|
|
764
|
+
/** Risk score (0-1) */
|
|
765
|
+
riskScore: number;
|
|
766
|
+
/** Risk factors identified */
|
|
767
|
+
riskFactors: string[];
|
|
768
|
+
/** Recommendations */
|
|
769
|
+
recommendations: string[];
|
|
770
|
+
/** Confidence level (0-1) */
|
|
771
|
+
confidence: number;
|
|
772
|
+
};
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* Confusable character analysis result
|
|
776
|
+
*/
|
|
777
|
+
export type ConfusableAnalysis = {
|
|
778
|
+
/** Risk score contribution */
|
|
779
|
+
score: number;
|
|
780
|
+
/** Risk factors identified */
|
|
781
|
+
factors: string[];
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Brand similarity analysis result
|
|
786
|
+
*/
|
|
787
|
+
export type BrandAnalysis = {
|
|
788
|
+
/** Risk score contribution */
|
|
789
|
+
score: number;
|
|
790
|
+
/** Risk factors identified */
|
|
791
|
+
factors: string[];
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Script mixing analysis result
|
|
796
|
+
*/
|
|
797
|
+
export type ScriptAnalysis = {
|
|
798
|
+
/** Risk score contribution */
|
|
799
|
+
score: number;
|
|
800
|
+
/** Risk factors identified */
|
|
801
|
+
factors: string[];
|
|
802
|
+
};
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Context analysis result
|
|
806
|
+
*/
|
|
807
|
+
export type ContextAnalysis = {
|
|
808
|
+
/** Risk score contribution */
|
|
809
|
+
score: number;
|
|
810
|
+
/** Risk factors identified */
|
|
811
|
+
factors: string[];
|
|
812
|
+
};
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Punycode analysis result
|
|
816
|
+
*/
|
|
817
|
+
export type PunycodeAnalysis = {
|
|
818
|
+
/** Risk score contribution */
|
|
819
|
+
score: number;
|
|
820
|
+
/** Risk factors identified */
|
|
821
|
+
factors: string[];
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Enhanced IDN Homograph Attack Detector
|
|
826
|
+
*/
|
|
827
|
+
declare class EnhancedIdnDetector {
|
|
828
|
+
/** Detector options */
|
|
829
|
+
options: EnhancedIdnDetectorOptions & {
|
|
830
|
+
strictMode: boolean;
|
|
831
|
+
enableWhitelist: boolean;
|
|
832
|
+
enableBrandProtection: boolean;
|
|
833
|
+
enableContextAnalysis: boolean;
|
|
834
|
+
maxSimilarityThreshold: number;
|
|
835
|
+
minDomainAge: number;
|
|
836
|
+
};
|
|
837
|
+
|
|
838
|
+
/** Analysis cache */
|
|
839
|
+
cache: Map<string, IdnAnalysisResult>;
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* Create a new EnhancedIdnDetector instance
|
|
843
|
+
* @param options - Configuration options
|
|
844
|
+
*/
|
|
845
|
+
constructor(options?: EnhancedIdnDetectorOptions);
|
|
846
|
+
|
|
847
|
+
/**
|
|
848
|
+
* Detect homograph attack in a domain
|
|
849
|
+
* @param domain - Domain to analyze
|
|
850
|
+
* @param context - Analysis context
|
|
851
|
+
* @returns Analysis result
|
|
852
|
+
*/
|
|
853
|
+
detectHomographAttack(domain: string, context?: IdnAnalysisContext): IdnAnalysisResult;
|
|
854
|
+
|
|
855
|
+
/**
|
|
856
|
+
* Comprehensive analysis of a domain
|
|
857
|
+
* @param domain - Domain to analyze
|
|
858
|
+
* @param context - Analysis context
|
|
859
|
+
* @returns Analysis result
|
|
860
|
+
*/
|
|
861
|
+
analyzeComprehensive(domain: string, context: IdnAnalysisContext): IdnAnalysisResult;
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Check if domain contains IDN characters
|
|
865
|
+
* @param domain - Domain to check
|
|
866
|
+
* @returns Whether the domain is an IDN
|
|
867
|
+
*/
|
|
868
|
+
isIdnDomain(domain: string): boolean;
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* Check if domain is whitelisted
|
|
872
|
+
* @param domain - Domain to check
|
|
873
|
+
* @returns Whether the domain is whitelisted
|
|
874
|
+
*/
|
|
875
|
+
isWhitelisted(domain: string): boolean;
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* Analyze confusable characters in domain
|
|
879
|
+
* @param domain - Domain to analyze
|
|
880
|
+
* @returns Confusable analysis result
|
|
881
|
+
*/
|
|
882
|
+
analyzeConfusableCharacters(domain: string): ConfusableAnalysis;
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Analyze brand similarity
|
|
886
|
+
* @param domain - Domain to analyze
|
|
887
|
+
* @returns Brand analysis result
|
|
888
|
+
*/
|
|
889
|
+
analyzeBrandSimilarity(domain: string): BrandAnalysis;
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* Analyze script mixing patterns
|
|
893
|
+
* @param domain - Domain to analyze
|
|
894
|
+
* @returns Script analysis result
|
|
895
|
+
*/
|
|
896
|
+
analyzeScriptMixing(domain: string): ScriptAnalysis;
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* Analyze context for additional risk factors
|
|
900
|
+
* @param domain - Domain to analyze
|
|
901
|
+
* @param context - Analysis context
|
|
902
|
+
* @returns Context analysis result
|
|
903
|
+
*/
|
|
904
|
+
analyzeContext(domain: string, context: IdnAnalysisContext): ContextAnalysis;
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* Analyze punycode domain
|
|
908
|
+
* @param domain - Domain to analyze
|
|
909
|
+
* @returns Punycode analysis result
|
|
910
|
+
*/
|
|
911
|
+
analyzePunycode(domain: string): PunycodeAnalysis;
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* Normalize domain for comparison
|
|
915
|
+
* @param domain - Domain to normalize
|
|
916
|
+
* @returns Normalized domain
|
|
917
|
+
*/
|
|
918
|
+
normalizeDomain(domain: string): string;
|
|
919
|
+
|
|
920
|
+
/**
|
|
921
|
+
* Calculate string similarity using Levenshtein distance
|
|
922
|
+
* @param string1 - First string
|
|
923
|
+
* @param string2 - Second string
|
|
924
|
+
* @returns Similarity score (0-1)
|
|
925
|
+
*/
|
|
926
|
+
calculateSimilarity(string1: string, string2: string): number;
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* Detect scripts used in domain
|
|
930
|
+
* @param domain - Domain to analyze
|
|
931
|
+
* @returns Set of detected scripts
|
|
932
|
+
*/
|
|
933
|
+
detectScripts(domain: string): Set<string>;
|
|
934
|
+
|
|
935
|
+
/**
|
|
936
|
+
* Decode punycode domain
|
|
937
|
+
* @param domain - Domain to decode
|
|
938
|
+
* @returns Decoded domain
|
|
939
|
+
*/
|
|
940
|
+
decodePunycode(domain: string): string;
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* Generate recommendations based on analysis
|
|
944
|
+
* @param analysis - Analysis result
|
|
945
|
+
* @returns Array of recommendations
|
|
946
|
+
*/
|
|
947
|
+
generateRecommendations(analysis: IdnAnalysisResult): string[];
|
|
948
|
+
|
|
949
|
+
/**
|
|
950
|
+
* Get cache key for analysis
|
|
951
|
+
* @param domain - Domain
|
|
952
|
+
* @param context - Analysis context
|
|
953
|
+
* @returns Cache key
|
|
954
|
+
*/
|
|
955
|
+
getCacheKey(domain: string, context: IdnAnalysisContext): string;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
export default SpamScanner;
|
|
959
|
+
export {SpamScanner, EnhancedIdnDetector};
|