import { Logger } from "../logger.ts"; import { MailDeliverContext, MailDeliverer } from "../deliver.ts"; export class DovecotMailDeliverer extends MailDeliverer { constructor(private readonly logger: Logger) { super("dovecot"); } readonly ldaBin = "dovecot-lda"; protected override doPrepare( rawMail: string, ): Promise { return Promise.resolve(new MailDeliverContext(rawMail)); } protected override async doDeliver( context: MailDeliverContext, ): Promise { const { logger, ldaBin } = this; const { rawMail } = context; let status; try { const utf8Encoder = new TextEncoder(); // TODO: A problem here is if mail is VERY long, this will block for a long time. // Maybe some task queue can be used. const utf8Stream = utf8Encoder.encode(rawMail); const ldaCommand = new Deno.Command(ldaBin, { stdin: "piped", stdout: "piped", stderr: "piped", }); const ldaProcess = ldaCommand.spawn(); logger.logProgramOutput(ldaProcess, ldaBin); const stdinWriter = ldaProcess.stdin.getWriter(); await stdinWriter.ready; await stdinWriter.write(utf8Stream); await stdinWriter.ready; status = await ldaProcess.status; } catch (cause) { this.throwError( "external error.", rawMail, cause, ); } if (!status.success) { this.throwError(`${ldaBin} exited with non-zero.`, rawMail); } } }