@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,5 @@
1
+ // Email delivery components
2
+ export * from './classes.delivery.queue.js';
3
+ export * from './classes.delivery.system.js';
4
+ export { DeliveryStatus } from './classes.delivery.system.js';
5
+ export * from './classes.unified.rate.limiter.js';
@@ -0,0 +1,167 @@
1
+ /**
2
+ * SMTP and email delivery interface definitions
3
+ */
4
+
5
+ /**
6
+ * SMTP session state enumeration
7
+ */
8
+ export enum SmtpState {
9
+ GREETING = 'GREETING',
10
+ AFTER_EHLO = 'AFTER_EHLO',
11
+ MAIL_FROM = 'MAIL_FROM',
12
+ RCPT_TO = 'RCPT_TO',
13
+ DATA = 'DATA',
14
+ DATA_RECEIVING = 'DATA_RECEIVING',
15
+ FINISHED = 'FINISHED'
16
+ }
17
+
18
+ /**
19
+ * Email processing mode type
20
+ */
21
+ export type EmailProcessingMode = 'forward' | 'mta' | 'process';
22
+
23
+ /**
24
+ * Envelope recipient information
25
+ */
26
+ export interface IEnvelopeRecipient {
27
+ /**
28
+ * Email address of the recipient
29
+ */
30
+ address: string;
31
+
32
+ /**
33
+ * Additional SMTP command arguments
34
+ */
35
+ args: Record<string, string>;
36
+ }
37
+
38
+ /**
39
+ * SMTP session envelope information
40
+ */
41
+ export interface ISmtpEnvelope {
42
+ /**
43
+ * Envelope sender (MAIL FROM) information
44
+ */
45
+ mailFrom: {
46
+ /**
47
+ * Email address of the sender
48
+ */
49
+ address: string;
50
+
51
+ /**
52
+ * Additional SMTP command arguments
53
+ */
54
+ args: Record<string, string>;
55
+ };
56
+
57
+ /**
58
+ * Envelope recipients (RCPT TO) information
59
+ */
60
+ rcptTo: IEnvelopeRecipient[];
61
+ }
62
+
63
+ /**
64
+ * SMTP Session interface - represents an active SMTP connection
65
+ */
66
+ export interface ISmtpSession {
67
+ /**
68
+ * Unique session identifier
69
+ */
70
+ id: string;
71
+
72
+ /**
73
+ * Current session state in the SMTP conversation
74
+ */
75
+ state: SmtpState;
76
+
77
+ /**
78
+ * Hostname provided by the client in EHLO/HELO command
79
+ */
80
+ clientHostname: string;
81
+
82
+ /**
83
+ * MAIL FROM email address (legacy format)
84
+ */
85
+ mailFrom: string;
86
+
87
+ /**
88
+ * RCPT TO email addresses (legacy format)
89
+ */
90
+ rcptTo: string[];
91
+
92
+ /**
93
+ * Raw email data being received
94
+ */
95
+ emailData: string;
96
+
97
+ /**
98
+ * Chunks of email data for more efficient buffer management
99
+ */
100
+ emailDataChunks?: string[];
101
+
102
+ /**
103
+ * Whether the connection is using TLS
104
+ */
105
+ useTLS: boolean;
106
+
107
+ /**
108
+ * Whether the connection has ended
109
+ */
110
+ connectionEnded: boolean;
111
+
112
+ /**
113
+ * Remote IP address of the client
114
+ */
115
+ remoteAddress: string;
116
+
117
+ /**
118
+ * Whether the connection is secure (TLS)
119
+ */
120
+ secure: boolean;
121
+
122
+ /**
123
+ * Whether the client has been authenticated
124
+ */
125
+ authenticated: boolean;
126
+
127
+ /**
128
+ * SMTP envelope information (structured format)
129
+ */
130
+ envelope: ISmtpEnvelope;
131
+
132
+ /**
133
+ * Email processing mode to use for this session
134
+ */
135
+ processingMode?: EmailProcessingMode;
136
+
137
+ /**
138
+ * Timestamp of last activity for session timeout tracking
139
+ */
140
+ lastActivity?: number;
141
+
142
+ /**
143
+ * Timeout ID for DATA command timeout
144
+ */
145
+ dataTimeoutId?: NodeJS.Timeout;
146
+ }
147
+
148
+ /**
149
+ * SMTP authentication data
150
+ */
151
+ export interface ISmtpAuth {
152
+ /**
153
+ * Authentication method used
154
+ */
155
+ method: 'PLAIN' | 'LOGIN' | 'OAUTH2' | string;
156
+
157
+ /**
158
+ * Username for authentication
159
+ */
160
+ username: string;
161
+
162
+ /**
163
+ * Password or token for authentication
164
+ */
165
+ password: string;
166
+ }
167
+
@@ -0,0 +1,17 @@
1
+ // Export all mail modules for simplified imports
2
+ export * from './routing/index.js';
3
+ export * from './security/index.js';
4
+
5
+ // Make the core and delivery modules accessible
6
+ import * as Core from './core/index.js';
7
+ import * as Delivery from './delivery/index.js';
8
+
9
+ export { Core, Delivery };
10
+
11
+ // For direct imports
12
+ import { Email } from './core/classes.email.js';
13
+
14
+ // Re-export commonly used classes
15
+ export {
16
+ Email,
17
+ };
@@ -0,0 +1,157 @@
1
+ import { logger } from '../../logger.js';
2
+ import { DKIMCreator } from '../security/classes.dkimcreator.js';
3
+ import { DomainRegistry } from './classes.domain.registry.js';
4
+ import { RustSecurityBridge } from '../../security/classes.rustsecuritybridge.js';
5
+ import { Email } from '../core/classes.email.js';
6
+
7
+ /** External DcRouter interface shape used by DkimManager */
8
+ interface DcRouter {
9
+ storageManager: any;
10
+ dnsServer?: any;
11
+ }
12
+
13
+ /**
14
+ * Manages DKIM key setup, rotation, and signing for all configured domains
15
+ */
16
+ export class DkimManager {
17
+ private dkimKeys: Map<string, string> = new Map();
18
+
19
+ constructor(
20
+ private dkimCreator: DKIMCreator,
21
+ private domainRegistry: DomainRegistry,
22
+ private dcRouter: DcRouter,
23
+ private rustBridge: RustSecurityBridge,
24
+ ) {}
25
+
26
+ async setupDkimForDomains(): Promise<void> {
27
+ const domainConfigs = this.domainRegistry.getAllConfigs();
28
+
29
+ if (domainConfigs.length === 0) {
30
+ logger.log('warn', 'No domains configured for DKIM');
31
+ return;
32
+ }
33
+
34
+ for (const domainConfig of domainConfigs) {
35
+ const domain = domainConfig.domain;
36
+ const selector = domainConfig.dkim?.selector || 'default';
37
+
38
+ try {
39
+ let keyPair: { privateKey: string; publicKey: string };
40
+
41
+ try {
42
+ keyPair = await this.dkimCreator.readDKIMKeys(domain);
43
+ logger.log('info', `Using existing DKIM keys for domain: ${domain}`);
44
+ } catch (error) {
45
+ keyPair = await this.dkimCreator.createDKIMKeys();
46
+ await this.dkimCreator.createAndStoreDKIMKeys(domain);
47
+ logger.log('info', `Generated new DKIM keys for domain: ${domain}`);
48
+ }
49
+
50
+ this.dkimKeys.set(domain, keyPair.privateKey);
51
+ logger.log('info', `DKIM keys loaded for domain: ${domain} with selector: ${selector}`);
52
+ } catch (error) {
53
+ logger.log('error', `Failed to set up DKIM for domain ${domain}: ${error.message}`);
54
+ }
55
+ }
56
+ }
57
+
58
+ async checkAndRotateDkimKeys(): Promise<void> {
59
+ const domainConfigs = this.domainRegistry.getAllConfigs();
60
+
61
+ for (const domainConfig of domainConfigs) {
62
+ const domain = domainConfig.domain;
63
+ const selector = domainConfig.dkim?.selector || 'default';
64
+ const rotateKeys = domainConfig.dkim?.rotateKeys || false;
65
+ const rotationInterval = domainConfig.dkim?.rotationInterval || 90;
66
+ const keySize = domainConfig.dkim?.keySize || 2048;
67
+
68
+ if (!rotateKeys) {
69
+ logger.log('debug', `DKIM key rotation disabled for ${domain}`);
70
+ continue;
71
+ }
72
+
73
+ try {
74
+ const needsRotation = await this.dkimCreator.needsRotation(domain, selector, rotationInterval);
75
+
76
+ if (needsRotation) {
77
+ logger.log('info', `DKIM keys need rotation for ${domain} (selector: ${selector})`);
78
+
79
+ const newSelector = await this.dkimCreator.rotateDkimKeys(domain, selector, keySize);
80
+
81
+ domainConfig.dkim = {
82
+ ...domainConfig.dkim,
83
+ selector: newSelector
84
+ };
85
+
86
+ if (domainConfig.dnsMode === 'internal-dns' && this.dcRouter.dnsServer) {
87
+ const keyPair = await this.dkimCreator.readDKIMKeysForSelector(domain, newSelector);
88
+ const publicKeyBase64 = keyPair.publicKey
89
+ .replace(/-----BEGIN PUBLIC KEY-----/g, '')
90
+ .replace(/-----END PUBLIC KEY-----/g, '')
91
+ .replace(/\s/g, '');
92
+
93
+ const ttl = domainConfig.dns?.internal?.ttl || 3600;
94
+
95
+ this.dcRouter.dnsServer.registerHandler(
96
+ `${newSelector}._domainkey.${domain}`,
97
+ ['TXT'],
98
+ () => ({
99
+ name: `${newSelector}._domainkey.${domain}`,
100
+ type: 'TXT',
101
+ class: 'IN',
102
+ ttl: ttl,
103
+ data: `v=DKIM1; k=rsa; p=${publicKeyBase64}`
104
+ })
105
+ );
106
+
107
+ logger.log('info', `DKIM DNS handler registered for new selector: ${newSelector}._domainkey.${domain}`);
108
+
109
+ await this.dcRouter.storageManager.set(
110
+ `/email/dkim/${domain}/public.key`,
111
+ keyPair.publicKey
112
+ );
113
+ }
114
+
115
+ this.dkimCreator.cleanupOldKeys(domain, 30).catch(error => {
116
+ logger.log('warn', `Failed to cleanup old DKIM keys for ${domain}: ${error.message}`);
117
+ });
118
+
119
+ } else {
120
+ logger.log('debug', `DKIM keys for ${domain} are up to date`);
121
+ }
122
+ } catch (error) {
123
+ logger.log('error', `Failed to check/rotate DKIM keys for ${domain}: ${error.message}`);
124
+ }
125
+ }
126
+ }
127
+
128
+ async handleDkimSigning(email: Email, domain: string, selector: string): Promise<void> {
129
+ try {
130
+ await this.dkimCreator.handleDKIMKeysForDomain(domain);
131
+ const { privateKey } = await this.dkimCreator.readDKIMKeys(domain);
132
+ const rawEmail = email.toRFC822String();
133
+
134
+ // Detect key type from PEM header
135
+ const keyType = privateKey.includes('ED25519') ? 'ed25519' : 'rsa';
136
+
137
+ const signResult = await this.rustBridge.signDkim({
138
+ rawMessage: rawEmail,
139
+ domain,
140
+ selector,
141
+ privateKey,
142
+ keyType,
143
+ });
144
+
145
+ if (signResult.header) {
146
+ email.addHeader('DKIM-Signature', signResult.header);
147
+ logger.log('info', `Successfully added DKIM signature for ${domain}`);
148
+ }
149
+ } catch (error) {
150
+ logger.log('error', `Failed to sign email with DKIM: ${error.message}`);
151
+ }
152
+ }
153
+
154
+ getDkimKey(domain: string): string | undefined {
155
+ return this.dkimKeys.get(domain);
156
+ }
157
+ }