import { SendEmailCommand, SendEmailCommandOutput, AccountSendingPausedException, ConfigurationSetSendingPausedException, ConfigurationSetDoesNotExistException, MailFromDomainNotVerifiedException, MessageRejected, SESServiceException, SESClient } from '@aws-sdk/client-ses'; import { Context, Data, Effect, Layer, Match } from 'effect'; class AccountSendingPausedExceptionError extends Data.TaggedError( 'AccountSendingPausedExceptionError' )<{ message: string; }> {} class ConfigurationSetDoesNotExistExceptionError extends Data.TaggedError( 'ConfigurationSetDoesNotExistExceptionError' )<{ message: string; }> {} class ConfigurationSetSendingPausedExceptionError extends Data.TaggedError( 'ConfigurationSetSendingPausedExceptionError' )<{ message: string; }> {} class MailFromDomainNotVerifiedExceptionError extends Data.TaggedError( 'MailFromDomainNotVerifiedExceptionError' )<{ message: string; }> {} class MessageRejectedError extends Data.TaggedError('MessageRejectedError')<{ message: string; }> {} class SESServiceExceptionError extends Data.TaggedError( 'SESServiceExceptionError' )<{ message: string; }> {} export module Ses { export class SesClient extends Context.Tag('SesClient')< SesClient, { send: ( send: SendEmailCommand | unknown ) => Promise; } >() {} export class SesService extends Context.Tag('SesService')< SesService, { readonly send: ({ sender, receiver, subject, body }: { sender: string; receiver: Array; subject: string; body: string; }) => Effect.Effect< void, | AccountSendingPausedExceptionError | ConfigurationSetDoesNotExistExceptionError | ConfigurationSetSendingPausedExceptionError | MailFromDomainNotVerifiedExceptionError | MessageRejectedError | SESServiceExceptionError >; } >() {} export const SesServiceLive = Layer.effect( SesService, Effect.gen(function* () { const client = yield* SesClient; return { send: ({ sender, receiver, subject, body }) => Effect.gen(function* () { Effect.tryPromise({ try: async () => { const result = await client.send( new SendEmailCommand({ Source: sender, Destination: { ToAddresses: receiver }, Message: { Subject: { Data: subject, Charset: 'utf-8' }, Body: { Html: { Data: body } } } }) ); }, catch: (error) => { Match.value(error).pipe( Match.when( Match.instanceOf(AccountSendingPausedException), (err) => new AccountSendingPausedExceptionError({ message: err.message }) ), Match.when( Match.instanceOf(ConfigurationSetSendingPausedException), (err) => new ConfigurationSetSendingPausedExceptionError({ message: err.message }) ), Match.when( Match.instanceOf(ConfigurationSetDoesNotExistException), (err) => new ConfigurationSetDoesNotExistExceptionError({ message: err.message }) ), Match.when( Match.instanceOf(MailFromDomainNotVerifiedException), (err) => new MailFromDomainNotVerifiedExceptionError({ message: err.message }) ), Match.when( Match.instanceOf(MessageRejected), (err) => new MessageRejectedError({ message: err.message }) ), Match.when( Match.instanceOf(SESServiceException), (err) => new SESServiceExceptionError({ message: err.message }) ) ); } }); }) }; }) ).pipe( Effect.provide(new SESClient({ region: 'us-east-1' })) ); }