@push.rocks/smartmta 6.4.0 → 6.5.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.
@@ -258,7 +258,9 @@ export declare class RustSecurityBridge extends EventEmitter {
258
258
  private _state;
259
259
  private _restartAttempts;
260
260
  private _restartTimer;
261
+ private _spawnInFlight;
261
262
  private _healthCheckTimer;
263
+ private _healthCheckStrikes;
262
264
  private _deliberateStop;
263
265
  private _smtpServerConfig;
264
266
  /**
@@ -291,9 +293,12 @@ export declare class RustSecurityBridge extends EventEmitter {
291
293
  /** Kill the Rust process deliberately. */
292
294
  stop(): Promise<void>;
293
295
  private attemptRestart;
296
+ private executeRestartAttempt;
294
297
  /**
295
298
  * Restore state after a successful restart:
296
299
  * - Re-send startSmtpServer command if the SMTP server was running
300
+ *
301
+ * @returns `true` if there was nothing to restore or the restore succeeded.
297
302
  */
298
303
  private restoreAfterRestart;
299
304
  private startHealthCheck;
@@ -42,7 +42,9 @@ export class RustSecurityBridge extends EventEmitter {
42
42
  _state = BridgeState.Idle;
43
43
  _restartAttempts = 0;
44
44
  _restartTimer = null;
45
+ _spawnInFlight = false;
45
46
  _healthCheckTimer = null;
47
+ _healthCheckStrikes = 0;
46
48
  _deliberateStop = false;
47
49
  _smtpServerConfig = null;
48
50
  /**
@@ -84,12 +86,15 @@ export class RustSecurityBridge extends EventEmitter {
84
86
  });
85
87
  this.bridge.on('exit', (code, signal) => {
86
88
  this._running = false;
87
- logger.log('warn', `Rust security bridge exited (code=${code}, signal=${signal})`);
89
+ logger.log('error', `Rust security bridge exited (code=${code}, signal=${signal})`);
88
90
  if (this._deliberateStop) {
89
91
  this.setState(BridgeState.Stopped);
90
92
  }
91
- else if (this._state === BridgeState.Running) {
92
- // Unexpected exit attempt restart
93
+ else if (!this._restartTimer && !this._spawnInFlight && this._state !== BridgeState.Starting) {
94
+ // Any unexpected exit triggers recovery, regardless of the state we
95
+ // were in. Exits during Starting resolve through start() itself;
96
+ // exits while a restart is already pending/spawning are absorbed by
97
+ // the in-flight recovery cycle.
93
98
  this.attemptRestart();
94
99
  }
95
100
  });
@@ -161,7 +166,7 @@ export class RustSecurityBridge extends EventEmitter {
161
166
  case BridgeState.Restarting:
162
167
  throw new Error('Rust bridge is restarting after a crash. Commands will resume once it recovers.');
163
168
  case BridgeState.Failed:
164
- throw new Error('Rust bridge has failed after exhausting all restart attempts.');
169
+ throw new Error('Rust bridge is in degraded state after repeated crashes. Recovery attempts continue in the background.');
165
170
  case BridgeState.Stopped:
166
171
  throw new Error('Rust bridge has been stopped. Call start() to restart it.');
167
172
  default:
@@ -181,6 +186,11 @@ export class RustSecurityBridge extends EventEmitter {
181
186
  }
182
187
  this._deliberateStop = false;
183
188
  this._restartAttempts = 0;
189
+ // An explicit start supersedes any pending background recovery attempt
190
+ if (this._restartTimer) {
191
+ clearTimeout(this._restartTimer);
192
+ this._restartTimer = null;
193
+ }
184
194
  this.setState(BridgeState.Starting);
185
195
  try {
186
196
  const ok = await this.bridge.spawn();
@@ -232,62 +242,91 @@ export class RustSecurityBridge extends EventEmitter {
232
242
  attemptRestart() {
233
243
  const config = RustSecurityBridge._resilienceConfig;
234
244
  this._restartAttempts++;
235
- if (this._restartAttempts > config.maxRestartAttempts) {
236
- logger.log('error', `Rust bridge exceeded max restart attempts (${config.maxRestartAttempts}). Giving up.`);
245
+ const exhausted = this._restartAttempts > config.maxRestartAttempts;
246
+ if (exhausted) {
247
+ // Degraded, but never terminal: a mail backend that silently stays dead
248
+ // is worse than one that keeps retrying at the slow cadence. The Failed
249
+ // state signals the degradation to embedders (stateChange event) while
250
+ // recovery attempts continue at restartBackoffMaxMs.
251
+ logger.log('error', `Rust bridge exhausted ${config.maxRestartAttempts} fast restart attempts — continuing in degraded slow-retry every ${config.restartBackoffMaxMs}ms (attempt ${this._restartAttempts})`);
237
252
  this.setState(BridgeState.Failed);
238
- return;
239
253
  }
240
- this.setState(BridgeState.Restarting);
254
+ else {
255
+ this.setState(BridgeState.Restarting);
256
+ }
241
257
  this.stopHealthCheck();
242
- const delay = Math.min(config.restartBackoffBaseMs * Math.pow(2, this._restartAttempts - 1), config.restartBackoffMaxMs);
243
- logger.log('info', `Rust bridge restart attempt ${this._restartAttempts}/${config.maxRestartAttempts} in ${delay}ms`);
244
- this._restartTimer = setTimeout(async () => {
258
+ const delay = exhausted
259
+ ? config.restartBackoffMaxMs
260
+ : Math.min(config.restartBackoffBaseMs * Math.pow(2, this._restartAttempts - 1), config.restartBackoffMaxMs);
261
+ logger.log('info', `Rust bridge restart attempt ${this._restartAttempts} in ${delay}ms`);
262
+ this._restartTimer = setTimeout(() => {
245
263
  this._restartTimer = null;
246
- // Guard: if stop() was called while we were waiting, don't restart
247
- if (this._deliberateStop) {
248
- this.setState(BridgeState.Stopped);
249
- return;
264
+ void this.executeRestartAttempt();
265
+ }, delay);
266
+ }
267
+ async executeRestartAttempt() {
268
+ // Guard: if stop() was called while we were waiting, don't restart
269
+ if (this._deliberateStop) {
270
+ this.setState(BridgeState.Stopped);
271
+ return;
272
+ }
273
+ this._spawnInFlight = true;
274
+ try {
275
+ const ok = await this.bridge.spawn();
276
+ this._running = ok;
277
+ if (!ok) {
278
+ throw new Error('spawn returned false');
250
279
  }
251
- try {
252
- const ok = await this.bridge.spawn();
253
- this._running = ok;
254
- if (ok) {
255
- logger.log('info', 'Rust bridge restarted successfully');
256
- this._restartAttempts = 0;
257
- this.setState(BridgeState.Running);
258
- this.startHealthCheck();
259
- await this.restoreAfterRestart();
280
+ const restored = await this.restoreAfterRestart();
281
+ if (!restored) {
282
+ // A bridge without its SMTP listener must not report Running — kill
283
+ // and go through another restart cycle instead of sitting half-alive.
284
+ logger.log('error', 'Rust bridge restarted but the SMTP server could not be restored — killing process to retry');
285
+ try {
286
+ this.bridge.kill();
260
287
  }
261
- else {
262
- logger.log('warn', 'Rust bridge restart failed (spawn returned false)');
263
- this.attemptRestart();
288
+ catch {
289
+ // Already dead
264
290
  }
291
+ this._running = false;
292
+ throw new Error('SMTP server restore failed');
265
293
  }
266
- catch (err) {
267
- logger.log('error', `Rust bridge restart failed: ${err.message}`);
268
- this.attemptRestart();
269
- }
270
- }, delay);
294
+ logger.log('info', 'Rust bridge restarted successfully');
295
+ this._restartAttempts = 0;
296
+ this.setState(BridgeState.Running);
297
+ this.startHealthCheck();
298
+ }
299
+ catch (err) {
300
+ logger.log('error', `Rust bridge restart failed: ${err.message}`);
301
+ this.attemptRestart();
302
+ }
303
+ finally {
304
+ this._spawnInFlight = false;
305
+ }
271
306
  }
272
307
  /**
273
308
  * Restore state after a successful restart:
274
309
  * - Re-send startSmtpServer command if the SMTP server was running
310
+ *
311
+ * @returns `true` if there was nothing to restore or the restore succeeded.
275
312
  */
276
313
  async restoreAfterRestart() {
277
- if (this._smtpServerConfig) {
278
- try {
279
- logger.log('info', 'Restoring SMTP server after bridge restart');
280
- const result = await this.bridge.sendCommand('startSmtpServer', this._smtpServerConfig);
281
- if (result?.started) {
282
- logger.log('info', 'SMTP server restored after bridge restart');
283
- }
284
- else {
285
- logger.log('warn', 'SMTP server failed to restore after bridge restart');
286
- }
287
- }
288
- catch (err) {
289
- logger.log('error', `Failed to restore SMTP server after restart: ${err.message}`);
314
+ if (!this._smtpServerConfig) {
315
+ return true;
316
+ }
317
+ try {
318
+ logger.log('info', 'Restoring SMTP server after bridge restart');
319
+ const result = await this.bridge.sendCommand('startSmtpServer', this._smtpServerConfig);
320
+ if (result?.started) {
321
+ logger.log('info', 'SMTP server restored after bridge restart');
322
+ return true;
290
323
  }
324
+ logger.log('warn', 'SMTP server failed to restore after bridge restart');
325
+ return false;
326
+ }
327
+ catch (err) {
328
+ logger.log('error', `Failed to restore SMTP server after restart: ${err.message}`);
329
+ return false;
291
330
  }
292
331
  }
293
332
  // -----------------------------------------------------------------------
@@ -296,6 +335,7 @@ export class RustSecurityBridge extends EventEmitter {
296
335
  startHealthCheck() {
297
336
  this.stopHealthCheck();
298
337
  const config = RustSecurityBridge._resilienceConfig;
338
+ this._healthCheckStrikes = 0;
299
339
  this._healthCheckTimer = setInterval(async () => {
300
340
  if (this._state !== BridgeState.Running || !this._running) {
301
341
  return;
@@ -307,9 +347,18 @@ export class RustSecurityBridge extends EventEmitter {
307
347
  if (!res?.pong) {
308
348
  throw new Error('Health check: unexpected ping response');
309
349
  }
350
+ this._healthCheckStrikes = 0;
310
351
  }
311
352
  catch (err) {
312
- logger.log('warn', `Rust bridge health check failed: ${err.message}. Killing process to trigger restart.`);
353
+ // Two consecutive failures before killing: a single missed ping can
354
+ // be momentary load, and killing mid-transaction is expensive.
355
+ this._healthCheckStrikes++;
356
+ if (this._healthCheckStrikes < 2) {
357
+ logger.log('warn', `Rust bridge health check failed (strike ${this._healthCheckStrikes}/2): ${err.message}`);
358
+ return;
359
+ }
360
+ logger.log('error', `Rust bridge health check failed twice in a row: ${err.message}. Killing process to trigger restart.`);
361
+ this._healthCheckStrikes = 0;
313
362
  try {
314
363
  this.bridge.kill();
315
364
  }
@@ -516,4 +565,4 @@ export class RustSecurityBridge extends EventEmitter {
516
565
  this.bridge.off('management:scramCredentialRequest', handler);
517
566
  }
518
567
  }
519
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydXN0c2VjdXJpdHlicmlkZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9zZWN1cml0eS9jbGFzc2VzLnJ1c3RzZWN1cml0eWJyaWRnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEtBQUssS0FBSyxNQUFNLGFBQWEsQ0FBQztBQUNyQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFpV3RDLDhFQUE4RTtBQUM5RSx1QkFBdUI7QUFDdkIsOEVBQThFO0FBRTlFLE1BQU0sQ0FBTixJQUFZLFdBT1g7QUFQRCxXQUFZLFdBQVc7SUFDckIsNEJBQWEsQ0FBQTtJQUNiLG9DQUFxQixDQUFBO0lBQ3JCLGtDQUFtQixDQUFBO0lBQ25CLHdDQUF5QixDQUFBO0lBQ3pCLGdDQUFpQixDQUFBO0lBQ2pCLGtDQUFtQixDQUFBO0FBQ3JCLENBQUMsRUFQVyxXQUFXLEtBQVgsV0FBVyxRQU90QjtBQVVELE1BQU0seUJBQXlCLEdBQTRCO0lBQ3pELGtCQUFrQixFQUFFLENBQUM7SUFDckIscUJBQXFCLEVBQUUsTUFBTTtJQUM3QixvQkFBb0IsRUFBRSxLQUFLO0lBQzNCLG1CQUFtQixFQUFFLE1BQU07SUFDM0Isb0JBQW9CLEVBQUUsS0FBSztDQUM1QixDQUFDO0FBRUYsOEVBQThFO0FBQzlFLHFFQUFxRTtBQUNyRSw4RUFBOEU7QUFFOUU7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxPQUFPLGtCQUFtQixTQUFRLFlBQVk7SUFDMUMsTUFBTSxDQUFDLFFBQVEsR0FBOEIsSUFBSSxDQUFDO0lBQ2xELE1BQU0sQ0FBQyxpQkFBaUIsR0FBNEIsRUFBRSxHQUFHLHlCQUF5QixFQUFFLENBQUM7SUFFckYsTUFBTSxDQUFxRTtJQUMzRSxRQUFRLEdBQUcsS0FBSyxD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
568
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydXN0c2VjdXJpdHlicmlkZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9zZWN1cml0eS9jbGFzc2VzLnJ1c3RzZWN1cml0eWJyaWRnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEtBQUssS0FBSyxNQUFNLGFBQWEsQ0FBQztBQUNyQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFpV3RDLDhFQUE4RTtBQUM5RSx1QkFBdUI7QUFDdkIsOEVBQThFO0FBRTlFLE1BQU0sQ0FBTixJQUFZLFdBT1g7QUFQRCxXQUFZLFdBQVc7SUFDckIsNEJBQWEsQ0FBQTtJQUNiLG9DQUFxQixDQUFBO0lBQ3JCLGtDQUFtQixDQUFBO0lBQ25CLHdDQUF5QixDQUFBO0lBQ3pCLGdDQUFpQixDQUFBO0lBQ2pCLGtDQUFtQixDQUFBO0FBQ3JCLENBQUMsRUFQVyxXQUFXLEtBQVgsV0FBVyxRQU90QjtBQVVELE1BQU0seUJBQXlCLEdBQTRCO0lBQ3pELGtCQUFrQixFQUFFLENBQUM7SUFDckIscUJBQXFCLEVBQUUsTUFBTTtJQUM3QixvQkFBb0IsRUFBRSxLQUFLO0lBQzNCLG1CQUFtQixFQUFFLE1BQU07SUFDM0Isb0JBQW9CLEVBQUUsS0FBSztDQUM1QixDQUFDO0FBRUYsOEVBQThFO0FBQzlFLHFFQUFxRTtBQUNyRSw4RUFBOEU7QUFFOUU7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxPQUFPLGtCQUFtQixTQUFRLFlBQVk7SUFDMUMsTUFBTSxDQUFDLFFBQVEsR0FBOEIsSUFBSSxDQUFDO0lBQ2xELE1BQU0sQ0FBQyxpQkFBaUIsR0FBNEIsRUFBRSxHQUFHLHlCQUF5QixFQUFFLENBQUM7SUFFckYsTUFBTSxDQUFxRTtJQUMzRSxRQUFRLEdBQUcsS0FBSyxD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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartmta",
3
- "version": "6.4.0",
3
+ "version": "6.5.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",
package/readme.md CHANGED
@@ -319,6 +319,8 @@ public async sendEmail(
319
319
  | `forward` | **Relay delivery** — forwards the email to a configured SMTP host (e.g. an internal mail gateway or third-party relay). |
320
320
  | `process` | **Scan + deliver** — runs the content scanning / security pipeline first, then delivers via auto MX resolution. |
321
321
 
322
+ **Self-MX loop guard:** MTA delivery refuses any MX host that equals the server's own hostname (`hostname` or `outbound.hostname`). A domain whose MX record points back at this server would otherwise re-enter the inbound pipeline on every delivery attempt — an infinite mail loop. Such deliveries fail with `MX for <domain> points back at this server — refusing self-delivery to avoid a mail loop`. The comparison is hostname-based; if a target only reveals the loop at the IP level (e.g. an A-record fallback), embedders should add an IP-level guard in their `connectionProxyProvider`.
323
+
322
324
  ### 📬 Direct SMTP Delivery (Low-Level)
323
325
 
324
326
  For cases where you know the exact target SMTP server (e.g. relaying to a specific host), use the lower-level `sendOutboundEmail()`:
@@ -615,6 +617,28 @@ const emailServer = new UnifiedEmailServer(dcRouterRef, {
615
617
  await emailServer.start();
616
618
  ```
617
619
 
620
+ ### 🪵 Logging
621
+
622
+ smartmta logs through its own `Smartlog` instance, exported as `baseLogger`. Console output is enabled by default so an embedded smartmta never logs into the void. Embedders can attach additional destinations (e.g. an ops log buffer):
623
+
624
+ ```typescript
625
+ import { baseLogger } from '@push.rocks/smartmta';
626
+
627
+ baseLogger.addLogDestination(myLogDestination); // any smartlog ILogDestination
628
+ ```
629
+
630
+ ### ♻️ Bridge Resilience
631
+
632
+ The Rust `mailer-bin` process is supervised by `RustSecurityBridge`:
633
+
634
+ - **Concurrent command handling** — outbound SMTP sends run as detached tasks in the Rust management loop; an in-flight delivery never blocks health-check pings, recipient-policy callbacks, or inbound event forwarding.
635
+ - **Health checks** — a `ping` every 30 s; two consecutive failures kill and restart the process.
636
+ - **Auto-restart** — any unexpected exit triggers restart with exponential backoff (1 s → 30 s). After `maxRestartAttempts` fast attempts the bridge enters the `failed` state but keeps retrying at the slow cadence forever — it never silently stays dead.
637
+ - **SMTP server restore** — after a restart the SMTP listener is restored; if the restore fails, the process is killed and the restart cycle continues rather than reporting a half-alive bridge.
638
+ - **State surface** — `UnifiedEmailServer.getBridgeState()` returns `'idle' | 'starting' | 'running' | 'restarting' | 'failed' | 'stopped'`; the server emits `bridgeFailed`, `bridgeRestarting`, and `bridgeRecovered` events for embedders' alerting.
639
+
640
+ Tune with `RustSecurityBridge.configure({ maxRestartAttempts, healthCheckIntervalMs, healthCheckTimeoutMs, restartBackoffBaseMs, restartBackoffMaxMs })`.
641
+
618
642
  ## 🦀 Rust Acceleration Layer
619
643
 
620
644
  Performance-critical operations are implemented in Rust and communicate with the TypeScript runtime via `@push.rocks/smartrust` (JSON-over-stdin/stdout IPC). The Rust workspace lives at `rust/` with four crates:
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartmta',
6
- version: '6.4.0',
6
+ version: '6.5.0',
7
7
  description: 'A high-performance, enterprise-grade Mail Transfer Agent (MTA) built from scratch in TypeScript with Rust acceleration.'
8
8
  }
package/ts/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './00_commitinfo_data.js';
2
2
  export * from './mail/index.js';
3
3
  export * from './security/index.js';
4
+ export { baseLogger, logger } from './logger.js';
package/ts/logger.ts CHANGED
@@ -10,8 +10,9 @@ const envMap: Record<string, 'local' | 'test' | 'staging' | 'production'> = {
10
10
  'production': 'production'
11
11
  };
12
12
 
13
- // Default Smartlog instance
14
- const baseLogger = new plugins.smartlog.Smartlog({
13
+ // Default Smartlog instance (exported so embedders like dcrouter can attach
14
+ // their own destinations — e.g. an ops log buffer — via addLogDestination).
15
+ export const baseLogger = new plugins.smartlog.Smartlog({
15
16
  logContext: {
16
17
  environment: envMap[nodeEnv] || 'production',
17
18
  runtime: 'node',
@@ -19,6 +20,11 @@ const baseLogger = new plugins.smartlog.Smartlog({
19
20
  }
20
21
  });
21
22
 
23
+ // Console output is on by default: without it, an embedded smartmta logs into
24
+ // the void — bridge crashes, restart attempts and delivery failures all become
25
+ // invisible (observed live as an undiagnosable prod mailer death).
26
+ baseLogger.enableConsole();
27
+
22
28
  // Extended logger compatible with the original enhanced logger API
23
29
  class StandardLogger {
24
30
  private defaultContext: Record<string, any> = {};
@@ -547,7 +547,23 @@ export class MultiModeDeliverySystem extends EventEmitter {
547
547
  const results: Array<{ domain: string; success: boolean; error?: string; accepted?: string[]; rejected?: string[] }> = [];
548
548
 
549
549
  for (const [domain, recipients] of domainGroups) {
550
- const mxHosts = await this.resolveMxForDomain(domain);
550
+ const allMxHosts = await this.resolveMxForDomain(domain);
551
+
552
+ // RFC 5321 §5.3.6: never relay to an MX that is this server itself —
553
+ // that is a mail loop (observed live: a managed domain whose MX record
554
+ // points at our own mail hostname re-enters the inbound pipeline).
555
+ const mxHosts = allMxHosts.filter(mx => !this.emailServer!.isSelfHostname(mx.exchange));
556
+ if (mxHosts.length === 0) {
557
+ const selfMx = allMxHosts.map(mx => mx.exchange).join(', ');
558
+ results.push({
559
+ domain,
560
+ success: false,
561
+ error: `MX for ${domain} (${selfMx || 'none'}) points back at this server — refusing self-delivery to avoid a mail loop`,
562
+ });
563
+ logger.log('error', `MTA: refusing self-delivery for ${domain} — MX (${selfMx}) is this server's own hostname (mail loop)`);
564
+ continue;
565
+ }
566
+
551
567
  let delivered = false;
552
568
  let lastError: string | undefined;
553
569
 
@@ -374,6 +374,22 @@ export class UnifiedEmailServer extends EventEmitter {
374
374
  return this.options.outbound?.hostname || this.options.hostname;
375
375
  }
376
376
 
377
+ /**
378
+ * Whether a hostname refers to this server's own SMTP identity.
379
+ * Used by MTA delivery to refuse self-addressed relaying: a domain whose
380
+ * MX resolves back to this server would otherwise mail-loop through the
381
+ * full outbound/inbound pipeline forever.
382
+ */
383
+ public isSelfHostname(hostname: string): boolean {
384
+ const normalize = (name: string) => name.toLowerCase().replace(/\.$/, '');
385
+ const candidate = normalize(hostname);
386
+ if (!candidate) return false;
387
+ return (
388
+ candidate === normalize(this.options.hostname) ||
389
+ candidate === normalize(this.options.outbound?.hostname || '')
390
+ );
391
+ }
392
+
377
393
  /**
378
394
  * Send an outbound email via the Rust SMTP client.
379
395
  * Uses connection pooling in the Rust binary for efficiency.
@@ -1457,6 +1473,16 @@ export class UnifiedEmailServer extends EventEmitter {
1457
1473
  return this.deliveryQueue.listItems();
1458
1474
  }
1459
1475
 
1476
+ /**
1477
+ * Current lifecycle state of the Rust mailer bridge
1478
+ * ('idle' | 'starting' | 'running' | 'restarting' | 'failed' | 'stopped').
1479
+ * Embedders surface this in health/ops endpoints — a bridge in 'failed'
1480
+ * or 'restarting' means mail processing is degraded.
1481
+ */
1482
+ public getBridgeState(): string {
1483
+ return this.rustBridge.state;
1484
+ }
1485
+
1460
1486
  public getQueueItem(id: string): IQueueItem | undefined {
1461
1487
  return this.deliveryQueue.getItem(id);
1462
1488
  }