From aee8f1389999a0e00f2dbc77f99861df56ced7a0 Mon Sep 17 00:00:00 2001 From: Ronni Baslund Date: Sun, 7 Jun 2026 00:16:30 +0200 Subject: [PATCH] feat(mail): tenant alias and distribution-list management via Stalwart Customer-admin Mail settings backed by Stalwart JMAP: per-tenant aliases (extra addresses routing to a mailbox) and distribution lists (one address fanning out to many recipients). Adds StalwartClient x:Alias/x:MailingList methods, a tenant-scoped MailController/MailService, the portal Mail settings page and its proxy routes, and the mailboxAddress field on TenantUserDoc. Removes the old mock mail data now that the page reads live data. --- apps/portal/data/workspace.ts | 32 - apps/portal/pages/admin/mail.vue | 725 +++++++----------- .../api/tenants/[slug]/mail/aliases.get.ts | 13 + .../api/tenants/[slug]/mail/aliases.post.ts | 16 + .../[slug]/mail/aliases/[address].delete.ts | 16 + .../api/tenants/[slug]/mail/lists.get.ts | 13 + .../api/tenants/[slug]/mail/lists.post.ts | 16 + .../tenants/[slug]/mail/lists/[id].delete.ts | 16 + .../tenants/[slug]/mail/lists/[id].patch.ts | 17 + apps/portal/types/workspace.ts | 3 + services/platform-api/src/app.module.ts | 2 + .../src/integrations/stalwart.client.ts | 184 +++++ .../src/mail/dto/create-alias.dto.ts | 17 + .../src/mail/dto/create-list.dto.ts | 23 + .../src/mail/dto/update-list.dto.ts | 9 + .../platform-api/src/mail/mail.controller.ts | 125 +++ services/platform-api/src/mail/mail.module.ts | 26 + .../platform-api/src/mail/mail.service.ts | 243 ++++++ 18 files changed, 1035 insertions(+), 461 deletions(-) create mode 100644 apps/portal/server/api/tenants/[slug]/mail/aliases.get.ts create mode 100644 apps/portal/server/api/tenants/[slug]/mail/aliases.post.ts create mode 100644 apps/portal/server/api/tenants/[slug]/mail/aliases/[address].delete.ts create mode 100644 apps/portal/server/api/tenants/[slug]/mail/lists.get.ts create mode 100644 apps/portal/server/api/tenants/[slug]/mail/lists.post.ts create mode 100644 apps/portal/server/api/tenants/[slug]/mail/lists/[id].delete.ts create mode 100644 apps/portal/server/api/tenants/[slug]/mail/lists/[id].patch.ts create mode 100644 services/platform-api/src/mail/dto/create-alias.dto.ts create mode 100644 services/platform-api/src/mail/dto/create-list.dto.ts create mode 100644 services/platform-api/src/mail/dto/update-list.dto.ts create mode 100644 services/platform-api/src/mail/mail.controller.ts create mode 100644 services/platform-api/src/mail/mail.module.ts create mode 100644 services/platform-api/src/mail/mail.service.ts diff --git a/apps/portal/data/workspace.ts b/apps/portal/data/workspace.ts index a917d67..2c8caa0 100644 --- a/apps/portal/data/workspace.ts +++ b/apps/portal/data/workspace.ts @@ -72,38 +72,6 @@ export const sampleAudit = [ { id: 'a8', when: '09:30:00', actor: 'Anne Baslund', action: 'branding.color_set', target: '#D4FF3A', ip: '92.43.118.4', tone: 'info' as const }, ] -// Org-wide mail aliases — strict port of platform-admin.jsx ORG_ALIASES (line 9) -export const orgAliases = [ - { alias: 'info@dezky.com', dest: 'Distribution · Everyone', active: true, created: '14 Jan 2026' }, - { alias: 'sales@dezky.com', dest: 'frederik@dezky.com', active: true, created: '22 Jan 2026' }, - { alias: 'support@dezky.com', dest: 'sofie@dezky.com', active: true, created: '22 Jan 2026' }, - { alias: 'no-reply@dezky.com', dest: '(discard)', active: true, created: '14 Jan 2026' }, - { alias: 'careers@dezky.com', dest: 'anne@dezky.com', active: true, created: '04 Mar 2026' }, - { alias: 'legal@dezky.com', dest: 'mikkel@dezky.com', active: false, created: '12 Apr 2026' }, -] - -// Forwarding rules — strict port of platform-admin.jsx FORWARDING_RULES (line 18) -export const forwardingRules = [ - { name: 'Out-of-hours to on-call', match: 'support@dezky.com · 18:00–08:00 CET', fwd: 'oncall@dezky.com', enabled: true }, - { name: 'Vendor invoices', match: 'subject: "invoice" · from: *@vendors', fwd: 'finance@dezky.com', enabled: true }, - { name: 'Legal threads', match: 'cc: legal@*', fwd: 'mikkel@dezky.com', enabled: false }, -] - -// Distribution lists — strict port of platform-admin.jsx DISTRIBUTION_LISTS (line 24) -export const distributionLists = [ - { name: 'Everyone', alias: 'everyone@dezky.com', members: 11, owner: 'Anne Baslund', moderation: 'open' as const, external: false }, - { name: 'Engineering', alias: 'eng@dezky.com', members: 4, owner: 'Anne Baslund', moderation: 'closed' as const, external: false }, - { name: 'Leadership', alias: 'leads@dezky.com', members: 3, owner: 'Anne Baslund', moderation: 'closed' as const, external: false }, - { name: 'Customers VIP', alias: 'vip-customers@dezky.com', members: 0, owner: 'Frederik Madsen', moderation: 'closed' as const, external: true }, -] - -// Anti-spam content filters — strict port of platform-admin.jsx ANTI_SPAM_FILTERS (line 31) -export const antiSpamFilters = [ - { name: 'Block executable attachments', match: 'attachment ext in (.exe, .scr, .bat, .cmd)', action: 'reject' as const, enabled: true }, - { name: 'Quarantine cryptocurrency mail', match: 'body contains "wallet address"', action: 'quarantine' as const, enabled: true }, - { name: 'Tag external mail', match: 'from outside @dezky.com', action: 'add tag' as const, enabled: true }, -] - // Full groups list — strict port of platform-admin.jsx GROUPS_FULL (line 64) export const groupsFull = [ { id: 'g_eng', name: 'Engineering', alias: 'engineering@dezky.com', members: 4, description: 'Product engineering team', created: '14 Jan 2026', owner: 'Anne Baslund' }, diff --git a/apps/portal/pages/admin/mail.vue b/apps/portal/pages/admin/mail.vue index 46bb1ac..898bff6 100644 --- a/apps/portal/pages/admin/mail.vue +++ b/apps/portal/pages/admin/mail.vue @@ -1,112 +1,203 @@