diff options
Diffstat (limited to 'deno/mail-relay/app.ts')
-rw-r--r-- | deno/mail-relay/app.ts | 135 |
1 files changed, 72 insertions, 63 deletions
diff --git a/deno/mail-relay/app.ts b/deno/mail-relay/app.ts index deb72c2..3cac44b 100644 --- a/deno/mail-relay/app.ts +++ b/deno/mail-relay/app.ts @@ -1,81 +1,90 @@ -import { join } from "@std/path"; import { Hono } from "hono"; import { logger as honoLogger } from "hono/logger"; -import log from "./log.ts"; -import config from "./config.ts"; -import { DbService } from "./db.ts"; +import { Logger } from "@crupest/base/log"; + import { AliasRecipientMailHook, FallbackRecipientHook, MailDeliverer, + RecipientFromHeadersHook, } from "./mail.ts"; -import { DovecotMailDeliverer } from "./dovecot/deliver.ts"; -import { CronTask, CronTaskConfig } from "./cron.ts"; +import { DovecotMailDeliverer } from "./dovecot.ts"; import { DumbSmtpServer } from "./dumb-smtp-server.ts"; -export abstract class AppBase { - protected readonly db: DbService; - protected readonly crons: CronTask[] = []; - protected readonly routes: Hono[] = []; - protected readonly inboundDeliverer: MailDeliverer; - protected readonly hono = new Hono(); - - protected abstract readonly outboundDeliverer: MailDeliverer; - - constructor() { - const dataPath = config.get("dataPath"); - Deno.mkdirSync(dataPath, { recursive: true }); - log.path = join(dataPath, "log"); - log.info(config); +export function createInbound( + logger: Logger, + { + fallback, + mailDomain, + aliasFile, + ldaPath, + }: { + fallback: string[]; + mailDomain: string; + aliasFile: string; + ldaPath: string; + }, +) { + const deliverer = new DovecotMailDeliverer(logger, ldaPath); + deliverer.preHooks.push( + new RecipientFromHeadersHook(mailDomain), + new FallbackRecipientHook(new Set(fallback)), + new AliasRecipientMailHook(aliasFile), + ); + return deliverer; +} - this.db = new DbService(join(dataPath, "db.sqlite")); - this.inboundDeliverer = new DovecotMailDeliverer(); - this.inboundDeliverer.preHooks.push( - new FallbackRecipientHook(new Set(config.getList("inboundFallback"))), - new AliasRecipientMailHook(join(dataPath, "aliases.csv")), - ); +export function createHono( + logger: Logger, + outbound: MailDeliverer, + inbound: MailDeliverer, +) { + const hono = new Hono(); - this.hono.onError((err, c) => { - log.error(err); - return c.json({ msg: "Server error, check its log." }, 500); - }); + hono.onError((err, c) => { + logger.error(err); + return c.json({ msg: "Server error, check its log." }, 500); + }); + hono.use(honoLogger()); + hono.post("/send/raw", async (context) => { + const body = await context.req.text(); + if (body.trim().length === 0) { + return context.json({ msg: "Can't send an empty mail." }, 400); + } else { + const result = await outbound.deliverRaw(body); + return context.json({ + awsMessageId: result.awsMessageId, + }); + } + }); + hono.post("/receive/raw", async (context) => { + await inbound.deliverRaw(await context.req.text()); + return context.json({ msg: "Done!" }); + }); - this.hono.use(honoLogger()); - this.hono.post("/send/raw", async (context) => { - const body = await context.req.text(); - if (body.trim().length === 0) { - return context.json({ msg: "Can't send an empty mail." }, 400); - } else { - const result = await this.outboundDeliverer.deliverRaw(body); - return context.json({ - awsMessageId: result.awsMessageId, - }); - } - }); - this.hono.post("/receive/raw", async (context) => { - await this.inboundDeliverer.deliverRaw(await context.req.text()); - return context.json({ "msg": "Done!" }); - }); - } + return hono; +} - createCron(config: CronTaskConfig): CronTask { - const cron = new CronTask(config); - this.crons.push(cron); - return cron; - } +export function createSmtp(logger: Logger, outbound: MailDeliverer) { + return new DumbSmtpServer(logger, outbound); +} - async setup() { - await this.db.migrate() +export async function sendMail(logger: Logger, port: number) { + const decoder = new TextDecoder(); + let text = ""; + for await (const chunk of Deno.stdin.readable) { + text += decoder.decode(chunk); } - serve(): { smtp: DumbSmtpServer; http: Deno.HttpServer } { - const smtp = new DumbSmtpServer(this.outboundDeliverer); - smtp.serve(); - const http = Deno.serve({ - hostname: config.HTTP_HOST, - port: config.HTTP_PORT, - }, this.hono.fetch); - return { smtp, http }; - } + const res = await fetch(`http://127.0.0.1:${port}/send/raw`, { + method: "post", + body: text, + }); + logger.builder(res).setError(!res.ok).write(); + logger + .builder("Body\n" + (await res.text())) + .setError(!res.ok) + .write(); + if (!res.ok) Deno.exit(-1); } |