feat(core): the e-mail server keeps /mailserver/konten.txt up to date at run time, measured against Java
The account file's writer moves from the export (packages/fls) into the core, so that the export and the running server write the same. The server writes the file at its start and whenever its accounts change. EmailRun now records Java's file as it left it and as Java writes the accounts it ended with; Java leaves the notice to a local sender out until its next write. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -121,7 +121,8 @@ import { EmailServer } from './apps/emailServer.js';
|
||||
import { Terminal } from './apps/terminal.js';
|
||||
import { firewallLogPage, forwardingTablePage, ripTablePage, routerIndexPage } from './apps/routerPages.js';
|
||||
import { applyFirewallSettings, firewallSettingsPage } from './apps/firewallSettings.js';
|
||||
import { VirtualFileSystem } from '../model/virtualFileSystem.js';
|
||||
import { parentPath, VirtualFileSystem } from '../model/virtualFileSystem.js';
|
||||
import { EMAIL_SERVER_ACCOUNTS_FILE, serverAccountsFileText } from './emailAccountsFile.js';
|
||||
import {
|
||||
PRODUCTION_TRACE_RETENTION,
|
||||
type HeaderField,
|
||||
@@ -1181,6 +1182,33 @@ export class NetworkRuntimeEngine {
|
||||
if (server === undefined) return;
|
||||
servers.set(nodeId, { ...server, accounts });
|
||||
this.stateValue.topologySnapshot = withSnapshot(this.stateValue.topologySnapshot, { emailServersByNodeId: servers });
|
||||
this.writeEmailServerAccountsFile(nodeId, server.domain, accounts);
|
||||
}
|
||||
|
||||
/**
|
||||
* The server's account file (EmailServer.kontenSpeichern), written from its
|
||||
* accounts at its start and whenever they change. Java makes it empty at
|
||||
* its start when it is missing (and reads it), and writes it when an
|
||||
* account is made or removed, after a POP3 command, after an SMTP mail was
|
||||
* taken and when it stops — but before the notice to a local sender, which
|
||||
* its file shows only at the next write.
|
||||
*/
|
||||
private writeEmailServerAccountsFile(nodeId: Id, domain: string, accounts: readonly EmailServerAccount[]): void {
|
||||
const files = this.nodeFiles(nodeId);
|
||||
const directory = parentPath(EMAIL_SERVER_ACCOUNTS_FILE);
|
||||
if (!files.contains(directory)) files.createDirectory(directory, true);
|
||||
files.writeTextFile(EMAIL_SERVER_ACCOUNTS_FILE, serverAccountsFileText(domain, accounts));
|
||||
}
|
||||
|
||||
/** The node's files; a node without any gets an empty file system, kept in the snapshot. */
|
||||
private nodeFiles(nodeId: Id): VirtualFileSystem {
|
||||
const existing = this.stateValue.topologySnapshot.fileSystemsByNodeId.get(nodeId);
|
||||
if (existing !== undefined) return existing;
|
||||
const files = new VirtualFileSystem();
|
||||
this.stateValue.topologySnapshot = withSnapshot(this.stateValue.topologySnapshot, {
|
||||
fileSystemsByNodeId: new Map([...this.stateValue.topologySnapshot.fileSystemsByNodeId, [nodeId, files]]),
|
||||
});
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1220,18 +1248,9 @@ export class NetworkRuntimeEngine {
|
||||
this.wallClock,
|
||||
),
|
||||
);
|
||||
this.writeEmailServerAccountsFile(nodeId, emailServer.domain, emailServer.accounts);
|
||||
}
|
||||
if (snapshot.terminalNodeIds.has(node.id)) {
|
||||
let files = snapshot.fileSystemsByNodeId.get(node.id);
|
||||
if (files === undefined) {
|
||||
// A node without files gets an empty file system, kept in the snapshot.
|
||||
files = new VirtualFileSystem();
|
||||
this.stateValue.topologySnapshot = withSnapshot(this.stateValue.topologySnapshot, {
|
||||
fileSystemsByNodeId: new Map([...this.stateValue.topologySnapshot.fileSystemsByNodeId, [node.id, files]]),
|
||||
});
|
||||
}
|
||||
this.terminalsByNodeId.set(node.id, new Terminal(this, node.id, files));
|
||||
}
|
||||
if (snapshot.terminalNodeIds.has(node.id)) this.terminalsByNodeId.set(node.id, new Terminal(this, node.id, this.nodeFiles(node.id)));
|
||||
const emailClient = snapshot.emailClientsByNodeId.get(node.id);
|
||||
if (emailClient !== undefined) {
|
||||
const nodeId = node.id;
|
||||
|
||||
Reference in New Issue
Block a user