1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
import { Hono } from "hono";
import { logger as honoLogger } from "hono/logger";
import { Logger } from "@crupest/base/log";
import {
AliasRecipientMailHook,
FallbackRecipientHook,
MailDeliverer,
RecipientFromHeadersHook,
} from "./mail.ts";
import { DovecotMailDeliverer } from "./dovecot.ts";
import { DumbSmtpServer } from "./dumb-smtp-server.ts";
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;
}
export function createHono(
logger: Logger,
outbound: MailDeliverer,
inbound: MailDeliverer,
) {
const hono = new Hono();
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!" });
});
return hono;
}
export function createSmtp(logger: Logger, outbound: MailDeliverer) {
return new DumbSmtpServer(logger, outbound);
}
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);
}
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);
}
|