176 lines
6.5 KiB
TypeScript
176 lines
6.5 KiB
TypeScript
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
|
import { WorkAppMailManager } from '../ts/email/classes.workapp-mail-manager.js';
|
|
import type { IUnifiedEmailServerOptions } from '@push.rocks/smartmta';
|
|
|
|
class MemoryStorageManager {
|
|
public store = new Map<string, string>();
|
|
|
|
public async get(key: string): Promise<string | null> {
|
|
return this.store.get(key) || null;
|
|
}
|
|
|
|
public async set(key: string, value: string): Promise<void> {
|
|
this.store.set(key, value);
|
|
}
|
|
}
|
|
|
|
const createDcRouterStub = () => {
|
|
const storageManager = new MemoryStorageManager();
|
|
const emailConfig: IUnifiedEmailServerOptions = {
|
|
hostname: 'mail.example.com',
|
|
ports: [25, 587, 465],
|
|
domains: [
|
|
{
|
|
domain: 'example.com',
|
|
dnsMode: 'external-dns',
|
|
},
|
|
],
|
|
routes: [
|
|
{
|
|
name: 'operator-route',
|
|
match: { recipients: 'ops@example.com' },
|
|
action: { type: 'reject', reject: { code: 550, message: 'not here' } },
|
|
},
|
|
],
|
|
auth: {
|
|
users: [{ username: 'operator', password: 'secret' }],
|
|
},
|
|
};
|
|
const dcRouterRef: any = {
|
|
storageManager,
|
|
options: { emailConfig },
|
|
emailServer: {
|
|
updateOptions: (patch: Partial<IUnifiedEmailServerOptions>) => {
|
|
dcRouterRef.options.emailConfig = {
|
|
...dcRouterRef.options.emailConfig,
|
|
...patch,
|
|
};
|
|
},
|
|
},
|
|
updateEmailRoutes: async (routes: IUnifiedEmailServerOptions['routes']) => {
|
|
dcRouterRef.options.emailConfig.routes = routes;
|
|
},
|
|
};
|
|
return { dcRouterRef, storageManager };
|
|
};
|
|
|
|
tap.test('WorkAppMailManager syncs SMTP identity and inbound smartmta route', async () => {
|
|
const { dcRouterRef } = createDcRouterStub();
|
|
const manager = new WorkAppMailManager(dcRouterRef);
|
|
|
|
const createResult = await manager.syncMailIdentity({
|
|
ownership: {
|
|
workHosterType: 'onebox',
|
|
workHosterId: 'box-1',
|
|
workAppId: 'app-1',
|
|
},
|
|
localPart: 'Hello',
|
|
domain: 'Example.com',
|
|
inbound: {
|
|
enabled: true,
|
|
targetHost: '10.0.0.2',
|
|
targetPort: 2525,
|
|
},
|
|
}, 'tester');
|
|
|
|
expect(createResult.success).toEqual(true);
|
|
expect(createResult.action).toEqual('created');
|
|
expect(createResult.identity?.address).toEqual('hello@example.com');
|
|
expect(createResult.identity?.smtp.username.startsWith('workapp-')).toEqual(true);
|
|
expect((createResult.identity as any).smtpPassword).toBeUndefined();
|
|
expect(createResult.smtpCredentials?.password.length).toBeGreaterThan(20);
|
|
|
|
const generatedRoute = dcRouterRef.options.emailConfig.routes.find((route: any) => route.name.startsWith('workapp-mail-'));
|
|
expect(generatedRoute.match.recipients).toEqual('hello@example.com');
|
|
expect(generatedRoute.action.forward.host).toEqual('10.0.0.2');
|
|
expect(generatedRoute.action.forward.port).toEqual(2525);
|
|
expect(generatedRoute.action.forward.addHeaders['X-Dcrouter-WorkApp-Id']).toEqual('app-1');
|
|
expect(dcRouterRef.options.emailConfig.routes.some((route: any) => route.name === 'operator-route')).toEqual(true);
|
|
|
|
const generatedUser = dcRouterRef.options.emailConfig.auth.users.find((user: any) => user.username.startsWith('workapp-'));
|
|
expect(generatedUser.password).toEqual(createResult.smtpCredentials?.password);
|
|
expect(dcRouterRef.options.emailConfig.auth.users.some((user: any) => user.username === 'operator')).toEqual(true);
|
|
|
|
const listResult = await manager.listMailIdentities({ workAppId: 'app-1' });
|
|
expect(listResult.length).toEqual(1);
|
|
expect(listResult[0].address).toEqual('hello@example.com');
|
|
});
|
|
|
|
tap.test('WorkAppMailManager updates, resets credentials, and deletes identities', async () => {
|
|
const { dcRouterRef } = createDcRouterStub();
|
|
const manager = new WorkAppMailManager(dcRouterRef);
|
|
const ownership = {
|
|
workHosterType: 'onebox' as const,
|
|
workHosterId: 'box-1',
|
|
workAppId: 'app-1',
|
|
};
|
|
|
|
const createResult = await manager.syncMailIdentity({
|
|
ownership,
|
|
localPart: 'hello',
|
|
domain: 'example.com',
|
|
inbound: { enabled: true, targetHost: '10.0.0.2', targetPort: 2525 },
|
|
}, 'tester');
|
|
const firstPassword = createResult.smtpCredentials!.password;
|
|
|
|
const updateResult = await manager.syncMailIdentity({
|
|
ownership,
|
|
localPart: 'hello',
|
|
domain: 'example.com',
|
|
inbound: { enabled: true, targetHost: '10.0.0.3', targetPort: 2526 },
|
|
}, 'tester');
|
|
expect(updateResult.action).toEqual('updated');
|
|
expect(updateResult.smtpCredentials).toBeUndefined();
|
|
const generatedUser = dcRouterRef.options.emailConfig.auth.users.find((user: any) => user.username.startsWith('workapp-'));
|
|
expect(generatedUser.password).toEqual(firstPassword);
|
|
const generatedRoute = dcRouterRef.options.emailConfig.routes.find((route: any) => route.name.startsWith('workapp-mail-'));
|
|
expect(generatedRoute.action.forward.host).toEqual('10.0.0.3');
|
|
|
|
const resetResult = await manager.syncMailIdentity({
|
|
ownership,
|
|
localPart: 'hello',
|
|
domain: 'example.com',
|
|
resetSmtpPassword: true,
|
|
}, 'tester');
|
|
expect(resetResult.smtpCredentials?.password !== firstPassword).toEqual(true);
|
|
|
|
const deleteResult = await manager.syncMailIdentity({
|
|
ownership,
|
|
localPart: 'hello',
|
|
domain: 'example.com',
|
|
delete: true,
|
|
}, 'tester');
|
|
expect(deleteResult.action).toEqual('deleted');
|
|
expect(dcRouterRef.options.emailConfig.routes.some((route: any) => route.name.startsWith('workapp-mail-'))).toEqual(false);
|
|
expect(dcRouterRef.options.emailConfig.auth.users.some((user: any) => user.username.startsWith('workapp-'))).toEqual(false);
|
|
expect(dcRouterRef.options.emailConfig.auth.users.some((user: any) => user.username === 'operator')).toEqual(true);
|
|
});
|
|
|
|
tap.test('WorkAppMailManager applies persisted identities to startup email config', async () => {
|
|
const { dcRouterRef } = createDcRouterStub();
|
|
const manager = new WorkAppMailManager(dcRouterRef);
|
|
await manager.syncMailIdentity({
|
|
ownership: {
|
|
workHosterType: 'onebox',
|
|
workHosterId: 'box-1',
|
|
workAppId: 'app-1',
|
|
},
|
|
localPart: 'hello',
|
|
domain: 'example.com',
|
|
inbound: { enabled: true, targetHost: '10.0.0.2', targetPort: 2525 },
|
|
}, 'tester');
|
|
|
|
const baseStartupConfig: IUnifiedEmailServerOptions = {
|
|
hostname: 'mail.example.com',
|
|
ports: [25],
|
|
domains: [{ domain: 'example.com', dnsMode: 'external-dns' }],
|
|
routes: [],
|
|
};
|
|
const startupConfig = await manager.applyStoredIdentitiesToEmailConfig(baseStartupConfig);
|
|
|
|
expect(startupConfig.routes.some((route) => route.name.startsWith('workapp-mail-'))).toEqual(true);
|
|
expect(startupConfig.auth?.users?.some((user) => user.username.startsWith('workapp-'))).toEqual(true);
|
|
});
|
|
|
|
export default tap.start();
|