aboutsummaryrefslogtreecommitdiff
path: root/services/docker/mail-server/aws-sendmail/deliver.ts
diff options
context:
space:
mode:
Diffstat (limited to 'services/docker/mail-server/aws-sendmail/deliver.ts')
-rw-r--r--services/docker/mail-server/aws-sendmail/deliver.ts51
1 files changed, 51 insertions, 0 deletions
diff --git a/services/docker/mail-server/aws-sendmail/deliver.ts b/services/docker/mail-server/aws-sendmail/deliver.ts
new file mode 100644
index 0000000..7035d8c
--- /dev/null
+++ b/services/docker/mail-server/aws-sendmail/deliver.ts
@@ -0,0 +1,51 @@
+class MailDeliverError extends Error {
+ constructor(
+ message: string,
+ options: ErrorOptions,
+ public readonly rawMail: string,
+ ) {
+ super(message, options);
+ }
+}
+
+export class MailDeliverContext {
+ constructor(public rawMail: string) {}
+}
+
+type MailDeliverHook<Context> = (context: Context) => Promise<void>;
+
+export abstract class MailDeliverer<out TContext extends MailDeliverContext = MailDeliverContext> {
+ preHooks: MailDeliverHook<MailDeliverContext>[] = [];
+ postHooks: MailDeliverHook<MailDeliverContext>[] = [];
+
+ constructor(public readonly destination: string) {}
+
+ protected abstract doPrepare(rawMail: string): Promise<TContext>;
+ protected abstract doDeliver(context: TContext): Promise<void>;
+
+ async deliver(rawMail: string): Promise<void> {
+ const context = await this.doPrepare(rawMail);
+
+ for (const hook of this.preHooks) {
+ await hook(context);
+ }
+
+ await this.doDeliver(context);
+
+ for (const hook of this.postHooks) {
+ await hook(context);
+ }
+ }
+
+ protected throwError(
+ reason: string,
+ rawMail: string,
+ cause?: unknown,
+ ): never {
+ throw new MailDeliverError(
+ `Failed to deliver mail to ${this.destination}: ${reason}`,
+ { cause },
+ rawMail,
+ );
+ }
+}