diff options
Diffstat (limited to 'services/docker/mail-server/aws-sendmail/deliver.ts')
-rw-r--r-- | services/docker/mail-server/aws-sendmail/deliver.ts | 51 |
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, + ); + } +} |