@push.rocks/smartmta 5.1.2 → 5.2.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.
Files changed (99) hide show
  1. package/changelog.md +14 -0
  2. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  3. package/dist_ts/00_commitinfo_data.js +9 -0
  4. package/dist_ts/index.d.ts +3 -0
  5. package/dist_ts/index.js +4 -0
  6. package/dist_ts/logger.d.ts +17 -0
  7. package/dist_ts/logger.js +76 -0
  8. package/dist_ts/mail/core/classes.bouncemanager.d.ts +185 -0
  9. package/dist_ts/mail/core/classes.bouncemanager.js +569 -0
  10. package/dist_ts/mail/core/classes.email.d.ts +291 -0
  11. package/dist_ts/mail/core/classes.email.js +802 -0
  12. package/dist_ts/mail/core/classes.emailvalidator.d.ts +61 -0
  13. package/dist_ts/mail/core/classes.emailvalidator.js +184 -0
  14. package/dist_ts/mail/core/classes.templatemanager.d.ts +95 -0
  15. package/dist_ts/mail/core/classes.templatemanager.js +240 -0
  16. package/dist_ts/mail/core/index.d.ts +4 -0
  17. package/dist_ts/mail/core/index.js +6 -0
  18. package/dist_ts/mail/delivery/classes.delivery.queue.d.ts +163 -0
  19. package/dist_ts/mail/delivery/classes.delivery.queue.js +488 -0
  20. package/dist_ts/mail/delivery/classes.delivery.system.d.ts +160 -0
  21. package/dist_ts/mail/delivery/classes.delivery.system.js +630 -0
  22. package/dist_ts/mail/delivery/classes.unified.rate.limiter.d.ts +200 -0
  23. package/dist_ts/mail/delivery/classes.unified.rate.limiter.js +820 -0
  24. package/dist_ts/mail/delivery/index.d.ts +4 -0
  25. package/dist_ts/mail/delivery/index.js +6 -0
  26. package/dist_ts/mail/delivery/interfaces.d.ts +140 -0
  27. package/dist_ts/mail/delivery/interfaces.js +17 -0
  28. package/dist_ts/mail/index.d.ts +7 -0
  29. package/dist_ts/mail/index.js +12 -0
  30. package/dist_ts/mail/routing/classes.dkim.manager.d.ts +25 -0
  31. package/dist_ts/mail/routing/classes.dkim.manager.js +127 -0
  32. package/dist_ts/mail/routing/classes.dns.manager.d.ts +79 -0
  33. package/dist_ts/mail/routing/classes.dns.manager.js +415 -0
  34. package/dist_ts/mail/routing/classes.domain.registry.d.ts +54 -0
  35. package/dist_ts/mail/routing/classes.domain.registry.js +119 -0
  36. package/dist_ts/mail/routing/classes.email.action.executor.d.ts +33 -0
  37. package/dist_ts/mail/routing/classes.email.action.executor.js +137 -0
  38. package/dist_ts/mail/routing/classes.email.router.d.ts +171 -0
  39. package/dist_ts/mail/routing/classes.email.router.js +494 -0
  40. package/dist_ts/mail/routing/classes.unified.email.server.d.ts +241 -0
  41. package/dist_ts/mail/routing/classes.unified.email.server.js +935 -0
  42. package/dist_ts/mail/routing/index.d.ts +7 -0
  43. package/dist_ts/mail/routing/index.js +9 -0
  44. package/dist_ts/mail/routing/interfaces.d.ts +187 -0
  45. package/dist_ts/mail/routing/interfaces.js +2 -0
  46. package/dist_ts/mail/security/classes.dkimcreator.d.ts +72 -0
  47. package/dist_ts/mail/security/classes.dkimcreator.js +360 -0
  48. package/dist_ts/mail/security/classes.spfverifier.d.ts +62 -0
  49. package/dist_ts/mail/security/classes.spfverifier.js +87 -0
  50. package/dist_ts/mail/security/index.d.ts +2 -0
  51. package/dist_ts/mail/security/index.js +4 -0
  52. package/dist_ts/paths.d.ts +14 -0
  53. package/dist_ts/paths.js +39 -0
  54. package/dist_ts/plugins.d.ts +24 -0
  55. package/dist_ts/plugins.js +28 -0
  56. package/dist_ts/security/classes.contentscanner.d.ts +130 -0
  57. package/dist_ts/security/classes.contentscanner.js +338 -0
  58. package/dist_ts/security/classes.ipreputationchecker.d.ts +73 -0
  59. package/dist_ts/security/classes.ipreputationchecker.js +263 -0
  60. package/dist_ts/security/classes.rustsecuritybridge.d.ts +398 -0
  61. package/dist_ts/security/classes.rustsecuritybridge.js +484 -0
  62. package/dist_ts/security/classes.securitylogger.d.ts +140 -0
  63. package/dist_ts/security/classes.securitylogger.js +235 -0
  64. package/dist_ts/security/index.d.ts +4 -0
  65. package/dist_ts/security/index.js +5 -0
  66. package/package.json +6 -1
  67. package/readme.md +52 -9
  68. package/ts/00_commitinfo_data.ts +8 -0
  69. package/ts/index.ts +3 -0
  70. package/ts/logger.ts +91 -0
  71. package/ts/mail/core/classes.bouncemanager.ts +731 -0
  72. package/ts/mail/core/classes.email.ts +942 -0
  73. package/ts/mail/core/classes.emailvalidator.ts +239 -0
  74. package/ts/mail/core/classes.templatemanager.ts +320 -0
  75. package/ts/mail/core/index.ts +5 -0
  76. package/ts/mail/delivery/classes.delivery.queue.ts +645 -0
  77. package/ts/mail/delivery/classes.delivery.system.ts +816 -0
  78. package/ts/mail/delivery/classes.unified.rate.limiter.ts +1053 -0
  79. package/ts/mail/delivery/index.ts +5 -0
  80. package/ts/mail/delivery/interfaces.ts +167 -0
  81. package/ts/mail/index.ts +17 -0
  82. package/ts/mail/routing/classes.dkim.manager.ts +157 -0
  83. package/ts/mail/routing/classes.dns.manager.ts +573 -0
  84. package/ts/mail/routing/classes.domain.registry.ts +139 -0
  85. package/ts/mail/routing/classes.email.action.executor.ts +175 -0
  86. package/ts/mail/routing/classes.email.router.ts +575 -0
  87. package/ts/mail/routing/classes.unified.email.server.ts +1207 -0
  88. package/ts/mail/routing/index.ts +9 -0
  89. package/ts/mail/routing/interfaces.ts +202 -0
  90. package/ts/mail/security/classes.dkimcreator.ts +447 -0
  91. package/ts/mail/security/classes.spfverifier.ts +126 -0
  92. package/ts/mail/security/index.ts +3 -0
  93. package/ts/paths.ts +48 -0
  94. package/ts/plugins.ts +53 -0
  95. package/ts/security/classes.contentscanner.ts +400 -0
  96. package/ts/security/classes.ipreputationchecker.ts +315 -0
  97. package/ts/security/classes.rustsecuritybridge.ts +943 -0
  98. package/ts/security/classes.securitylogger.ts +299 -0
  99. package/ts/security/index.ts +40 -0
@@ -0,0 +1,235 @@
1
+ import * as plugins from '../plugins.js';
2
+ import { logger } from '../logger.js';
3
+ /**
4
+ * Log level for security events
5
+ */
6
+ export var SecurityLogLevel;
7
+ (function (SecurityLogLevel) {
8
+ SecurityLogLevel["INFO"] = "info";
9
+ SecurityLogLevel["WARN"] = "warn";
10
+ SecurityLogLevel["ERROR"] = "error";
11
+ SecurityLogLevel["CRITICAL"] = "critical";
12
+ })(SecurityLogLevel || (SecurityLogLevel = {}));
13
+ /**
14
+ * Security event types for categorization
15
+ */
16
+ export var SecurityEventType;
17
+ (function (SecurityEventType) {
18
+ SecurityEventType["AUTHENTICATION"] = "authentication";
19
+ SecurityEventType["ACCESS_CONTROL"] = "access_control";
20
+ SecurityEventType["EMAIL_VALIDATION"] = "email_validation";
21
+ SecurityEventType["EMAIL_PROCESSING"] = "email_processing";
22
+ SecurityEventType["EMAIL_FORWARDING"] = "email_forwarding";
23
+ SecurityEventType["EMAIL_DELIVERY"] = "email_delivery";
24
+ SecurityEventType["DKIM"] = "dkim";
25
+ SecurityEventType["SPF"] = "spf";
26
+ SecurityEventType["DMARC"] = "dmarc";
27
+ SecurityEventType["RATE_LIMIT"] = "rate_limit";
28
+ SecurityEventType["RATE_LIMITING"] = "rate_limiting";
29
+ SecurityEventType["SPAM"] = "spam";
30
+ SecurityEventType["MALWARE"] = "malware";
31
+ SecurityEventType["CONNECTION"] = "connection";
32
+ SecurityEventType["DATA_EXPOSURE"] = "data_exposure";
33
+ SecurityEventType["CONFIGURATION"] = "configuration";
34
+ SecurityEventType["IP_REPUTATION"] = "ip_reputation";
35
+ SecurityEventType["REJECTED_CONNECTION"] = "rejected_connection";
36
+ })(SecurityEventType || (SecurityEventType = {}));
37
+ /**
38
+ * Security logger for enhanced security monitoring
39
+ */
40
+ export class SecurityLogger {
41
+ static instance;
42
+ securityEvents = [];
43
+ maxEventHistory;
44
+ enableNotifications;
45
+ constructor(options) {
46
+ this.maxEventHistory = options?.maxEventHistory || 1000;
47
+ this.enableNotifications = options?.enableNotifications || false;
48
+ }
49
+ /**
50
+ * Get singleton instance
51
+ */
52
+ static getInstance(options) {
53
+ if (!SecurityLogger.instance) {
54
+ SecurityLogger.instance = new SecurityLogger(options);
55
+ }
56
+ return SecurityLogger.instance;
57
+ }
58
+ /**
59
+ * Log a security event
60
+ * @param event The security event to log
61
+ */
62
+ logEvent(event) {
63
+ const fullEvent = {
64
+ ...event,
65
+ timestamp: Date.now()
66
+ };
67
+ // Store in memory buffer
68
+ this.securityEvents.push(fullEvent);
69
+ // Trim history if needed
70
+ if (this.securityEvents.length > this.maxEventHistory) {
71
+ this.securityEvents.shift();
72
+ }
73
+ // Log to regular logger with appropriate level
74
+ switch (event.level) {
75
+ case SecurityLogLevel.INFO:
76
+ logger.log('info', `[SECURITY:${event.type}] ${event.message}`, event.details);
77
+ break;
78
+ case SecurityLogLevel.WARN:
79
+ logger.log('warn', `[SECURITY:${event.type}] ${event.message}`, event.details);
80
+ break;
81
+ case SecurityLogLevel.ERROR:
82
+ case SecurityLogLevel.CRITICAL:
83
+ logger.log('error', `[SECURITY:${event.type}] ${event.message}`, event.details);
84
+ // Send notification for critical events if enabled
85
+ if (event.level === SecurityLogLevel.CRITICAL && this.enableNotifications) {
86
+ this.sendNotification(fullEvent);
87
+ }
88
+ break;
89
+ }
90
+ }
91
+ /**
92
+ * Get recent security events
93
+ * @param limit Maximum number of events to return
94
+ * @param filter Filter for specific event types
95
+ * @returns Recent security events
96
+ */
97
+ getRecentEvents(limit = 100, filter) {
98
+ let filteredEvents = this.securityEvents;
99
+ // Apply filters
100
+ if (filter) {
101
+ if (filter.level) {
102
+ filteredEvents = filteredEvents.filter(event => event.level === filter.level);
103
+ }
104
+ if (filter.type) {
105
+ filteredEvents = filteredEvents.filter(event => event.type === filter.type);
106
+ }
107
+ if (filter.fromTimestamp) {
108
+ filteredEvents = filteredEvents.filter(event => event.timestamp >= filter.fromTimestamp);
109
+ }
110
+ if (filter.toTimestamp) {
111
+ filteredEvents = filteredEvents.filter(event => event.timestamp <= filter.toTimestamp);
112
+ }
113
+ }
114
+ // Return most recent events up to limit
115
+ return filteredEvents
116
+ .sort((a, b) => b.timestamp - a.timestamp)
117
+ .slice(0, limit);
118
+ }
119
+ /**
120
+ * Get events by security level
121
+ * @param level The security level to filter by
122
+ * @param limit Maximum number of events to return
123
+ * @returns Security events matching the level
124
+ */
125
+ getEventsByLevel(level, limit = 100) {
126
+ return this.getRecentEvents(limit, { level });
127
+ }
128
+ /**
129
+ * Get events by security type
130
+ * @param type The event type to filter by
131
+ * @param limit Maximum number of events to return
132
+ * @returns Security events matching the type
133
+ */
134
+ getEventsByType(type, limit = 100) {
135
+ return this.getRecentEvents(limit, { type });
136
+ }
137
+ /**
138
+ * Get security events for a specific IP address
139
+ * @param ipAddress The IP address to filter by
140
+ * @param limit Maximum number of events to return
141
+ * @returns Security events for the IP address
142
+ */
143
+ getEventsByIP(ipAddress, limit = 100) {
144
+ return this.securityEvents
145
+ .filter(event => event.ipAddress === ipAddress)
146
+ .sort((a, b) => b.timestamp - a.timestamp)
147
+ .slice(0, limit);
148
+ }
149
+ /**
150
+ * Get security events for a specific domain
151
+ * @param domain The domain to filter by
152
+ * @param limit Maximum number of events to return
153
+ * @returns Security events for the domain
154
+ */
155
+ getEventsByDomain(domain, limit = 100) {
156
+ return this.securityEvents
157
+ .filter(event => event.domain === domain)
158
+ .sort((a, b) => b.timestamp - a.timestamp)
159
+ .slice(0, limit);
160
+ }
161
+ /**
162
+ * Send a notification for critical security events
163
+ * @param event The security event to notify about
164
+ * @private
165
+ */
166
+ sendNotification(event) {
167
+ // In a production environment, this would integrate with a notification service
168
+ // For now, we'll just log that we would send a notification
169
+ logger.log('error', `[SECURITY NOTIFICATION] ${event.message}`, {
170
+ ...event,
171
+ notificationSent: true
172
+ });
173
+ // Future integration with alerting systems would go here
174
+ }
175
+ /**
176
+ * Clear event history
177
+ */
178
+ clearEvents() {
179
+ this.securityEvents = [];
180
+ }
181
+ /**
182
+ * Get statistical summary of security events
183
+ * @param timeWindow Optional time window in milliseconds
184
+ * @returns Summary of security events
185
+ */
186
+ getEventsSummary(timeWindow) {
187
+ // Filter by time window if provided
188
+ let events = this.securityEvents;
189
+ if (timeWindow) {
190
+ const cutoff = Date.now() - timeWindow;
191
+ events = events.filter(e => e.timestamp >= cutoff);
192
+ }
193
+ // Count by level
194
+ const byLevel = Object.values(SecurityLogLevel).reduce((acc, level) => {
195
+ acc[level] = events.filter(e => e.level === level).length;
196
+ return acc;
197
+ }, {});
198
+ // Count by type
199
+ const byType = Object.values(SecurityEventType).reduce((acc, type) => {
200
+ acc[type] = events.filter(e => e.type === type).length;
201
+ return acc;
202
+ }, {});
203
+ // Count by IP
204
+ const ipCounts = new Map();
205
+ events.forEach(e => {
206
+ if (e.ipAddress) {
207
+ ipCounts.set(e.ipAddress, (ipCounts.get(e.ipAddress) || 0) + 1);
208
+ }
209
+ });
210
+ // Count by domain
211
+ const domainCounts = new Map();
212
+ events.forEach(e => {
213
+ if (e.domain) {
214
+ domainCounts.set(e.domain, (domainCounts.get(e.domain) || 0) + 1);
215
+ }
216
+ });
217
+ // Sort and limit top entries
218
+ const topIPs = Array.from(ipCounts.entries())
219
+ .map(([ip, count]) => ({ ip, count }))
220
+ .sort((a, b) => b.count - a.count)
221
+ .slice(0, 10);
222
+ const topDomains = Array.from(domainCounts.entries())
223
+ .map(([domain, count]) => ({ domain, count }))
224
+ .sort((a, b) => b.count - a.count)
225
+ .slice(0, 10);
226
+ return {
227
+ total: events.length,
228
+ byLevel,
229
+ byType,
230
+ topIPs,
231
+ topDomains
232
+ };
233
+ }
234
+ }
235
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zZWN1cml0eWxvZ2dlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3NlY3VyaXR5L2NsYXNzZXMuc2VjdXJpdHlsb2dnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUV0Qzs7R0FFRztBQUNILE1BQU0sQ0FBTixJQUFZLGdCQUtYO0FBTEQsV0FBWSxnQkFBZ0I7SUFDMUIsaUNBQWEsQ0FBQTtJQUNiLGlDQUFhLENBQUE7SUFDYixtQ0FBZSxDQUFBO0lBQ2YseUNBQXFCLENBQUE7QUFDdkIsQ0FBQyxFQUxXLGdCQUFnQixLQUFoQixnQkFBZ0IsUUFLM0I7QUFFRDs7R0FFRztBQUNILE1BQU0sQ0FBTixJQUFZLGlCQW1CWDtBQW5CRCxXQUFZLGlCQUFpQjtJQUMzQixzREFBaUMsQ0FBQTtJQUNqQyxzREFBaUMsQ0FBQTtJQUNqQywwREFBcUMsQ0FBQTtJQUNyQywwREFBcUMsQ0FBQTtJQUNyQywwREFBcUMsQ0FBQTtJQUNyQyxzREFBaUMsQ0FBQTtJQUNqQyxrQ0FBYSxDQUFBO0lBQ2IsZ0NBQVcsQ0FBQTtJQUNYLG9DQUFlLENBQUE7SUFDZiw4Q0FBeUIsQ0FBQTtJQUN6QixvREFBK0IsQ0FBQTtJQUMvQixrQ0FBYSxDQUFBO0lBQ2Isd0NBQW1CLENBQUE7SUFDbkIsOENBQXlCLENBQUE7SUFDekIsb0RBQStCLENBQUE7SUFDL0Isb0RBQStCLENBQUE7SUFDL0Isb0RBQStCLENBQUE7SUFDL0IsZ0VBQTJDLENBQUE7QUFDN0MsQ0FBQyxFQW5CVyxpQkFBaUIsS0FBakIsaUJBQWlCLFFBbUI1QjtBQXFCRDs7R0FFRztBQUNILE1BQU0sT0FBTyxjQUFjO0lBQ2pCLE1BQU0sQ0FBQyxRQUFRLENBQWlCO0lBQ2hDLGNBQWMsR0FBcUIsRUFBRSxDQUFDO0lBQ3RDLGVBQWUsQ0FBUztJQUN4QixtQkFBbUIsQ0FBVTtJQUVyQyxZQUFvQixPQUduQjtRQUNDLElBQUksQ0FBQyxlQUFlLEdBQUcsT0FBTyxFQUFFLGVBQWUsSUFBSSxJQUFJLENBQUM7UUFDeEQsSUFBSSxDQUFDLG1CQUFtQixHQUFHLE9BQU8sRUFBRSxtQkFBbUIsSUFBSSxLQUFLLENBQUM7SUFDbkUsQ0FBQztJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUd6QjtRQUNDLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDN0IsY0FBYyxDQUFDLFFBQVEsR0FBRyxJQUFJLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBQ0QsT0FBTyxjQUFjLENBQUMsUUFBUSxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7O09BR0c7SUFDSSxRQUFRLENBQUMsS0FBd0M7UUFDdEQsTUFBTSxTQUFTLEdBQW1CO1lBQ2hDLEdBQUcsS0FBSztZQUNSLFNBQVMsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO1NBQ3RCLENBQUM7UUFFRix5QkFBeUI7UUFDekIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFcEMseUJBQXlCO1FBQ3pCLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3RELElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDOUIsQ0FBQztRQUVELCtDQUErQztRQUMvQyxRQUFRLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNwQixLQUFLLGdCQUFnQixDQUFDLElBQUk7Z0JBQ3hCLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLGFBQWEsS0FBSyxDQUFDLElBQUksS0FBSyxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUMvRSxNQUFNO1lBQ1IsS0FBSyxnQkFBZ0IsQ0FBQyxJQUFJO2dCQUN4QixNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxhQUFhLEtBQUssQ0FBQyxJQUFJLEtBQUssS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDL0UsTUFBTTtZQUNSLEtBQUssZ0JBQWdCLENBQUMsS0FBSyxDQUFDO1lBQzVCLEtBQUssZ0JBQWdCLENBQUMsUUFBUTtnQkFDNUIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsYUFBYSxLQUFLLENBQUMsSUFBSSxLQUFLLEtBQUssQ0FBQyxPQUFPLEVBQUUsRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBRWhGLG1EQUFtRDtnQkFDbkQsSUFBSSxLQUFLLENBQUMsS0FBSyxLQUFLLGdCQUFnQixDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztvQkFDMUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUNuQyxDQUFDO2dCQUNELE1BQU07UUFDVixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksZUFBZSxDQUFDLFFBQWdCLEdBQUcsRUFBRSxNQUszQztRQUNDLElBQUksY0FBYyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUM7UUFFekMsZ0JBQWdCO1FBQ2hCLElBQUksTUFBTSxFQUFFLENBQUM7WUFDWCxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDakIsY0FBYyxHQUFHLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxLQUFLLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNoRixDQUFDO1lBRUQsSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ2hCLGNBQWMsR0FBRyxjQUFjLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUUsQ0FBQztZQUVELElBQUksTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDO2dCQUN6QixjQUFjLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxTQUFTLElBQUksTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQzNGLENBQUM7WUFFRCxJQUFJLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDdkIsY0FBYyxHQUFHLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsU0FBUyxJQUFJLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN6RixDQUFDO1FBQ0gsQ0FBQztRQUVELHdDQUF3QztRQUN4QyxPQUFPLGNBQWM7YUFDbEIsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDO2FBQ3pDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDckIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksZ0JBQWdCLENBQUMsS0FBdUIsRUFBRSxRQUFnQixHQUFHO1FBQ2xFLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ2hELENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLGVBQWUsQ0FBQyxJQUF1QixFQUFFLFFBQWdCLEdBQUc7UUFDakUsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksYUFBYSxDQUFDLFNBQWlCLEVBQUUsUUFBZ0IsR0FBRztRQUN6RCxPQUFPLElBQUksQ0FBQyxjQUFjO2FBQ3ZCLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxTQUFTLEtBQUssU0FBUyxDQUFDO2FBQzlDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQzthQUN6QyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3JCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLGlCQUFpQixDQUFDLE1BQWMsRUFBRSxRQUFnQixHQUFHO1FBQzFELE9BQU8sSUFBSSxDQUFDLGNBQWM7YUFDdkIsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sS0FBSyxNQUFNLENBQUM7YUFDeEMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDO2FBQ3pDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDckIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxnQkFBZ0IsQ0FBQyxLQUFxQjtRQUM1QyxnRkFBZ0Y7UUFDaEYsNERBQTREO1FBQzVELE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLDJCQUEyQixLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDOUQsR0FBRyxLQUFLO1lBQ1IsZ0JBQWdCLEVBQUUsSUFBSTtTQUN2QixDQUFDLENBQUM7UUFFSCx5REFBeUQ7SUFDM0QsQ0FBQztJQUVEOztPQUVHO0lBQ0ksV0FBVztRQUNoQixJQUFJLENBQUMsY0FBYyxHQUFHLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLGdCQUFnQixDQUFDLFVBQW1CO1FBT3pDLG9DQUFvQztRQUNwQyxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBQ2pDLElBQUksVUFBVSxFQUFFLENBQUM7WUFDZixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsVUFBVSxDQUFDO1lBQ3ZDLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsSUFBSSxNQUFNLENBQUMsQ0FBQztRQUNyRCxDQUFDO1FBRUQsaUJBQWlCO1FBQ2pCLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDcEUsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQztZQUMxRCxPQUFPLEdBQUcsQ0FBQztRQUNiLENBQUMsRUFBRSxFQUFzQyxDQUFDLENBQUM7UUFFM0MsZ0JBQWdCO1FBQ2hCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDbkUsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQztZQUN2RCxPQUFPLEdBQUcsQ0FBQztRQUNiLENBQUMsRUFBRSxFQUF1QyxDQUFDLENBQUM7UUFFNUMsY0FBYztRQUNkLE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO1FBQzNDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDakIsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2hCLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ2xFLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILGtCQUFrQjtRQUNsQixNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztRQUMvQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ2pCLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNiLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3BFLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILDZCQUE2QjtRQUM3QixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQzthQUMxQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO2FBQ3JDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQzthQUNqQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWhCLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxDQUFDO2FBQ2xELEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7YUFDN0MsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDO2FBQ2pDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFaEIsT0FBTztZQUNMLEtBQUssRUFBRSxNQUFNLENBQUMsTUFBTTtZQUNwQixPQUFPO1lBQ1AsTUFBTTtZQUNOLE1BQU07WUFDTixVQUFVO1NBQ1gsQ0FBQztJQUNKLENBQUM7Q0FDRiJ9
@@ -0,0 +1,4 @@
1
+ export { SecurityLogger, SecurityLogLevel, SecurityEventType, type ISecurityEvent } from './classes.securitylogger.js';
2
+ export { IPReputationChecker, ReputationThreshold, IPType, type IReputationResult, type IIPReputationOptions } from './classes.ipreputationchecker.js';
3
+ export { ContentScanner, ThreatCategory, type IScanResult, type IContentScannerOptions } from './classes.contentscanner.js';
4
+ export { RustSecurityBridge, BridgeState, type IBridgeResilienceConfig, type IDkimVerificationResult, type ISpfResult, type IDmarcResult, type IEmailSecurityResult, type IValidationResult, type IBounceDetection, type IRustReputationResult, type IVersionInfo, type IOutboundEmail, type ISmtpSendResult, type ISmtpSendOptions, type ISmtpVerifyResult, type ISmtpPoolStatus, } from './classes.rustsecuritybridge.js';
@@ -0,0 +1,5 @@
1
+ export { SecurityLogger, SecurityLogLevel, SecurityEventType } from './classes.securitylogger.js';
2
+ export { IPReputationChecker, ReputationThreshold, IPType } from './classes.ipreputationchecker.js';
3
+ export { ContentScanner, ThreatCategory } from './classes.contentscanner.js';
4
+ export { RustSecurityBridge, BridgeState, } from './classes.rustsecuritybridge.js';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9zZWN1cml0eS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsY0FBYyxFQUNkLGdCQUFnQixFQUNoQixpQkFBaUIsRUFFbEIsTUFBTSw2QkFBNkIsQ0FBQztBQUVyQyxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLG1CQUFtQixFQUNuQixNQUFNLEVBR1AsTUFBTSxrQ0FBa0MsQ0FBQztBQUUxQyxPQUFPLEVBQ0wsY0FBYyxFQUNkLGNBQWMsRUFHZixNQUFNLDZCQUE2QixDQUFDO0FBRXJDLE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsV0FBVyxHQWVaLE1BQU0saUNBQWlDLENBQUMifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartmta",
3
- "version": "5.1.2",
3
+ "version": "5.2.0",
4
4
  "description": "A high-performance, enterprise-grade Mail Transfer Agent (MTA) built from scratch in TypeScript with Rust acceleration.",
5
5
  "keywords": [
6
6
  "mta",
@@ -27,6 +27,9 @@
27
27
  "author": "Task Venture Capital GmbH",
28
28
  "license": "MIT",
29
29
  "type": "module",
30
+ "exports": {
31
+ ".": "./dist_ts/index.js"
32
+ },
30
33
  "bin": {
31
34
  "mailer": "./bin/mailer-wrapper.js"
32
35
  },
@@ -56,6 +59,8 @@
56
59
  "uuid": "^13.0.0"
57
60
  },
58
61
  "files": [
62
+ "ts/**/*",
63
+ "dist_ts/**/*",
59
64
  "bin/",
60
65
  "scripts/install-binary.js",
61
66
  "dist_rust/**/*",
package/readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @push.rocks/smartmta
2
2
 
3
- A high-performance, enterprise-grade Mail Transfer Agent (MTA) built from scratch in TypeScript with a Rust-powered SMTP engine — no nodemailer, no shortcuts. 🚀
3
+ A high-performance, enterprise-grade Mail Transfer Agent (MTA) built from scratch in TypeScript with a Rust-powered SMTP engine — no nodemailer, no shortcuts. Automatic MX record discovery means you just call `sendEmail()` and smartmta figures out where to deliver. 🚀
4
4
 
5
5
  ## Issue Reporting and Security
6
6
 
@@ -78,9 +78,10 @@ After installation, run `pnpm build` to compile the Rust binary (`mailer-bin`).
78
78
 
79
79
  **Data flow for outbound mail:**
80
80
 
81
- 1. 📝 TypeScript constructs the email and resolves DKIM keys for the sender domain
82
- 2. 🦀 Sends to Rust via IPC Rust builds the RFC 2822 message, signs with DKIM, and delivers via its SMTP client with connection pooling
83
- 3. 📬 Result (accepted/rejected recipients, server response) returned to TypeScript
81
+ 1. 📝 TypeScript constructs the email and calls `sendEmail()` (defaults to MTA mode)
82
+ 2. 🔍 MTA mode automatically resolves MX records for each recipient domain, sorts by priority, and groups recipients for efficient delivery
83
+ 3. 🦀 Sends to Rust via IPC — Rust builds the RFC 2822 message, signs with DKIM, and delivers via its SMTP client with connection pooling
84
+ 4. 📬 Result (accepted/rejected recipients, server response) returned to TypeScript
84
85
 
85
86
  ## Usage
86
87
 
@@ -169,9 +170,9 @@ await emailServer.start();
169
170
 
170
171
  > 🔒 **Note:** `start()` will throw if the Rust binary is not compiled. Run `pnpm build` first.
171
172
 
172
- ### 📧 Sending Outbound Emails
173
+ ### 📧 Sending Emails (Automatic MX Discovery)
173
174
 
174
- All outbound email delivery goes through the Rust SMTP client, accessed via `UnifiedEmailServer.sendOutboundEmail()`. The Rust client handles connection pooling, TLS negotiation, and DKIM signing automatically:
175
+ The recommended way to send email is `sendEmail()`. It defaults to **MTA mode**, which automatically resolves MX records for each recipient domain via DNS you don't need to know the destination mail server:
175
176
 
176
177
  ```typescript
177
178
  import { Email, UnifiedEmailServer } from '@push.rocks/smartmta';
@@ -179,8 +180,7 @@ import { Email, UnifiedEmailServer } from '@push.rocks/smartmta';
179
180
  // Build an email
180
181
  const email = new Email({
181
182
  from: 'sender@example.com',
182
- to: ['recipient@example.com'],
183
- cc: ['cc@example.com'],
183
+ to: ['alice@gmail.com', 'bob@company.org'],
184
184
  subject: 'Hello from smartmta! 🚀',
185
185
  text: 'Plain text body',
186
186
  html: '<h1>Hello!</h1><p>HTML body with <strong>formatting</strong></p>',
@@ -194,7 +194,50 @@ const email = new Email({
194
194
  ],
195
195
  });
196
196
 
197
- // Send via the Rust SMTP client (connection pooling, TLS, DKIM signing)
197
+ // Send MTA mode auto-discovers MX servers for gmail.com and company.org
198
+ const emailId = await emailServer.sendEmail(email);
199
+
200
+ // Optionally specify a delivery mode explicitly
201
+ const emailId2 = await emailServer.sendEmail(email, 'mta');
202
+ ```
203
+
204
+ In MTA mode, smartmta:
205
+ - 🔍 Resolves MX records for each recipient domain (e.g. `gmail.com`, `company.org`)
206
+ - 📊 Sorts MX hosts by priority (lowest = highest priority per RFC 5321)
207
+ - 🔄 Tries each MX host in order until delivery succeeds
208
+ - 🌐 Falls back to the domain's A record if no MX records exist
209
+ - 📦 Groups recipients by domain for efficient batch delivery
210
+ - 🔑 Signs outbound mail with DKIM automatically
211
+
212
+ ### 📮 Delivery Modes
213
+
214
+ `sendEmail()` accepts a mode parameter that controls how the email is delivered:
215
+
216
+ ```typescript
217
+ public async sendEmail(
218
+ email: Email,
219
+ mode: EmailProcessingMode = 'mta', // 'mta' | 'forward' | 'process'
220
+ route?: IEmailRoute,
221
+ options?: {
222
+ skipSuppressionCheck?: boolean;
223
+ ipAddress?: string;
224
+ isTransactional?: boolean;
225
+ }
226
+ ): Promise<string>
227
+ ```
228
+
229
+ | Mode | Description |
230
+ |---|---|
231
+ | `mta` (default) | **Auto MX discovery** — resolves MX records via DNS, delivers directly to the recipient's mail server. No relay configuration needed. |
232
+ | `forward` | **Relay delivery** — forwards the email to a configured SMTP host (e.g. an internal mail gateway or third-party relay). |
233
+ | `process` | **Scan + deliver** — runs the content scanning / security pipeline first, then delivers via auto MX resolution. |
234
+
235
+ ### 📬 Direct SMTP Delivery (Low-Level)
236
+
237
+ For cases where you know the exact target SMTP server (e.g. relaying to a specific host), use the lower-level `sendOutboundEmail()`:
238
+
239
+ ```typescript
240
+ // Send directly to a known SMTP server (bypasses MX resolution)
198
241
  const result = await emailServer.sendOutboundEmail('smtp.example.com', 587, email, {
199
242
  auth: { user: 'sender@example.com', pass: 'your-password' },
200
243
  dkimDomain: 'example.com',
@@ -0,0 +1,8 @@
1
+ /**
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
+ */
4
+ export const commitinfo = {
5
+ name: '@push.rocks/smartmta',
6
+ version: '5.2.0',
7
+ description: 'A high-performance, enterprise-grade Mail Transfer Agent (MTA) built from scratch in TypeScript with Rust acceleration.'
8
+ }
package/ts/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './00_commitinfo_data.js';
2
+ export * from './mail/index.js';
3
+ export * from './security/index.js';
package/ts/logger.ts ADDED
@@ -0,0 +1,91 @@
1
+ import * as plugins from './plugins.js';
2
+ import { randomUUID } from 'node:crypto';
3
+
4
+ // Map NODE_ENV to valid TEnvironment
5
+ const nodeEnv = process.env.NODE_ENV || 'production';
6
+ const envMap: Record<string, 'local' | 'test' | 'staging' | 'production'> = {
7
+ 'development': 'local',
8
+ 'test': 'test',
9
+ 'staging': 'staging',
10
+ 'production': 'production'
11
+ };
12
+
13
+ // Default Smartlog instance
14
+ const baseLogger = new plugins.smartlog.Smartlog({
15
+ logContext: {
16
+ environment: envMap[nodeEnv] || 'production',
17
+ runtime: 'node',
18
+ zone: 'serve.zone',
19
+ }
20
+ });
21
+
22
+ // Extended logger compatible with the original enhanced logger API
23
+ class StandardLogger {
24
+ private defaultContext: Record<string, any> = {};
25
+ private correlationId: string | null = null;
26
+
27
+ constructor() {}
28
+
29
+ // Log methods
30
+ public log(level: 'error' | 'warn' | 'info' | 'success' | 'debug', message: string, context: Record<string, any> = {}) {
31
+ const combinedContext = {
32
+ ...this.defaultContext,
33
+ ...context
34
+ };
35
+
36
+ if (this.correlationId) {
37
+ combinedContext.correlation_id = this.correlationId;
38
+ }
39
+
40
+ baseLogger.log(level, message, combinedContext);
41
+ }
42
+
43
+ public error(message: string, context: Record<string, any> = {}) {
44
+ this.log('error', message, context);
45
+ }
46
+
47
+ public warn(message: string, context: Record<string, any> = {}) {
48
+ this.log('warn', message, context);
49
+ }
50
+
51
+ public info(message: string, context: Record<string, any> = {}) {
52
+ this.log('info', message, context);
53
+ }
54
+
55
+ public success(message: string, context: Record<string, any> = {}) {
56
+ this.log('success', message, context);
57
+ }
58
+
59
+ public debug(message: string, context: Record<string, any> = {}) {
60
+ this.log('debug', message, context);
61
+ }
62
+
63
+ // Context management
64
+ public setContext(context: Record<string, any>, overwrite: boolean = false) {
65
+ if (overwrite) {
66
+ this.defaultContext = context;
67
+ } else {
68
+ this.defaultContext = {
69
+ ...this.defaultContext,
70
+ ...context
71
+ };
72
+ }
73
+ }
74
+
75
+ // Correlation ID management
76
+ public setCorrelationId(id: string | null = null): string {
77
+ this.correlationId = id || randomUUID();
78
+ return this.correlationId;
79
+ }
80
+
81
+ public getCorrelationId(): string | null {
82
+ return this.correlationId;
83
+ }
84
+
85
+ public clearCorrelationId(): void {
86
+ this.correlationId = null;
87
+ }
88
+ }
89
+
90
+ // Export a singleton instance
91
+ export const logger = new StandardLogger();