diff --git a/package.json b/package.json
index 9e7fb46..1338eea 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
"@api.global/typedserver": "^3.0.74",
"@api.global/typedsocket": "^3.0.0",
"@apiclient.xyz/cloudflare": "^6.4.1",
- "@design.estate/dees-catalog": "^1.10.2",
+ "@design.estate/dees-catalog": "^1.10.7",
"@design.estate/dees-element": "^2.0.45",
"@push.rocks/projectinfo": "^5.0.1",
"@push.rocks/qenv": "^6.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 94cdea5..e7bee98 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -24,8 +24,8 @@ importers:
specifier: ^6.4.1
version: 6.4.1
'@design.estate/dees-catalog':
- specifier: ^1.10.2
- version: 1.10.2(@tiptap/pm@2.23.0)
+ specifier: ^1.10.7
+ version: 1.10.7(@tiptap/pm@2.23.0)
'@design.estate/dees-element':
specifier: ^2.0.45
version: 2.0.45
@@ -344,8 +344,8 @@ packages:
'@dabh/diagnostics@2.0.3':
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
- '@design.estate/dees-catalog@1.10.2':
- resolution: {integrity: sha512-hLdXbRUWpyYspZFhmp/S/GtOnhMPfa03ruMOX3dhkzTKoVymp2WxSjUID0zQlv+Y/P1iNMnwIfhzGkJsInhCTQ==}
+ '@design.estate/dees-catalog@1.10.7':
+ resolution: {integrity: sha512-q5ukOfTzVaOSocrNQIOCc4sugw3flPW3RzvCfEISmRh0ziq6oadRcPcTgg8cYTOVT58C/oIWZZgsAz22W3RyZQ==}
'@design.estate/dees-comms@1.0.27':
resolution: {integrity: sha512-GvzTUwkV442LD60T08iqSoqvhA02Mou5lFvvqBPc4yBUiU7cZISqBx+76xvMgMIEI9Dx9JfTl4/2nW8MoVAanw==}
@@ -5500,7 +5500,7 @@ snapshots:
enabled: 2.0.0
kuler: 2.0.0
- '@design.estate/dees-catalog@1.10.2(@tiptap/pm@2.23.0)':
+ '@design.estate/dees-catalog@1.10.7(@tiptap/pm@2.23.0)':
dependencies:
'@design.estate/dees-domtools': 2.3.3
'@design.estate/dees-element': 2.0.45
diff --git a/ts/classes.dcrouter.ts b/ts/classes.dcrouter.ts
index 7e54f79..622abb8 100644
--- a/ts/classes.dcrouter.ts
+++ b/ts/classes.dcrouter.ts
@@ -5,7 +5,7 @@ import * as paths from './paths.js';
// Import the email server and its configuration
import { UnifiedEmailServer, type IUnifiedEmailServerOptions } from './mail/routing/classes.unified.email.server.js';
-import type { IEmailRoute } from './mail/routing/interfaces.js';
+import type { IEmailRoute, IEmailDomainConfig } from './mail/routing/interfaces.js';
import { logger } from './logger.js';
// Import the email configuration helpers directly from mail/delivery
import { configureEmailStorage, configureEmailServer } from './mail/delivery/index.js';
@@ -640,9 +640,28 @@ export class DcRouter {
465: 10465 // SMTPS
};
+ // Transform domains if they are provided as strings
+ let transformedDomains = this.options.emailConfig.domains;
+ if (transformedDomains && transformedDomains.length > 0) {
+ // Check if domains are strings (for backward compatibility)
+ if (typeof transformedDomains[0] === 'string') {
+ transformedDomains = (transformedDomains as any).map((domain: string) => ({
+ domain,
+ dnsMode: 'external-dns' as const,
+ dkim: {
+ selector: 'default',
+ keySize: 2048,
+ rotateKeys: false,
+ rotationInterval: 90
+ }
+ }));
+ }
+ }
+
// Create config with mapped ports
const emailConfig: IUnifiedEmailServerOptions = {
...this.options.emailConfig,
+ domains: transformedDomains,
ports: this.options.emailConfig.ports.map(port => portMapping[port] || port + 10000),
hostname: 'localhost' // Listen on localhost for SmartProxy forwarding
};
diff --git a/ts/mail/routing/classes.unified.email.server.ts b/ts/mail/routing/classes.unified.email.server.ts
index 287e489..c6158c7 100644
--- a/ts/mail/routing/classes.unified.email.server.ts
+++ b/ts/mail/routing/classes.unified.email.server.ts
@@ -158,7 +158,7 @@ export class UnifiedEmailServer extends EventEmitter {
private dcRouter: DcRouter;
private options: IUnifiedEmailServerOptions;
private emailRouter: EmailRouter;
- private domainRegistry: DomainRegistry;
+ public domainRegistry: DomainRegistry;
private servers: any[] = [];
private stats: IServerStats;
diff --git a/ts/opsserver/handlers/config.handler.ts b/ts/opsserver/handlers/config.handler.ts
index 3ac93b9..06f12c3 100644
--- a/ts/opsserver/handlers/config.handler.ts
+++ b/ts/opsserver/handlers/config.handler.ts
@@ -65,6 +65,7 @@ export class ConfigHandler {
perHour: number;
perDay: number;
};
+ domains?: string[];
};
dns: {
enabled: boolean;
@@ -88,6 +89,17 @@ export class ConfigHandler {
}> {
const dcRouter = this.opsServerRef.dcRouterRef;
+ // Get email domains if email server is configured
+ let emailDomains: string[] = [];
+ if (dcRouter.emailServer && dcRouter.emailServer.domainRegistry) {
+ emailDomains = dcRouter.emailServer.domainRegistry.getAllDomains();
+ } else if (dcRouter.options.emailConfig?.domains) {
+ // Fallback: get domains from email config options
+ emailDomains = dcRouter.options.emailConfig.domains.map(d =>
+ typeof d === 'string' ? d : d.domain
+ );
+ }
+
return {
email: {
enabled: !!dcRouter.emailServer,
@@ -98,6 +110,7 @@ export class ConfigHandler {
perHour: 100,
perDay: 1000,
},
+ domains: emailDomains,
},
dns: {
enabled: !!dcRouter.dnsServer,
diff --git a/ts_web/elements/ops-view-emails.ts b/ts_web/elements/ops-view-emails.ts
index ee8d271..53c78fa 100644
--- a/ts_web/elements/ops-view-emails.ts
+++ b/ts_web/elements/ops-view-emails.ts
@@ -50,9 +50,13 @@ export class OpsViewEmails extends DeesElement {
@state()
private searchTerm = '';
+ @state()
+ private emailDomains: string[] = [];
+
constructor() {
super();
this.loadEmails();
+ this.loadEmailDomains();
}
public static styles = [
@@ -436,6 +440,11 @@ export class OpsViewEmails extends DeesElement {
private async openComposeModal(replyTo?: IEmail, replyAll = false, forward = false) {
const { DeesModal } = await import('@design.estate/dees-catalog');
+ // Ensure domains are loaded before opening modal
+ if (this.emailDomains.length === 0) {
+ await this.loadEmailDomains();
+ }
+
await DeesModal.createAndShow({
heading: forward ? 'Forward Email' : replyTo ? 'Reply to Email' : 'New Email',
width: 'large',
@@ -447,18 +456,27 @@ export class OpsViewEmails extends DeesElement {
const modals = document.querySelectorAll('dees-modal');
modals.forEach(m => (m as any).destroy?.());
}}>
-