aws / aws-sdk-js-v3

Modularized AWS SDK for JavaScript.
Apache License 2.0
2.96k stars 556 forks source link

Add SESv2 Event Notification Type Definitions #6141

Open seanadkinson opened 1 month ago

seanadkinson commented 1 month ago

Describe the feature

Please add types for notification events sent by SES. The structure of the events are documented here, but I can't find any typescript types in the SDK that allow me to code against this structure. Perhaps I am just missing them?

Use Case

I'd like to subscribe to these SESv2 Notifications from Node, and use Typescript to ensure I am only accessing supported properties and fields on the notification event objects.

Proposed Solution

Export a new type, named something like SESEventNotification, which uses a Discriminated Union on the eventType field to determine the object's structure, similar to how this commenter suggested in the v2 SDK

Other Information

No response

Acknowledgements

SDK version used

3.583.0

Environment details (OS name and version, etc.)

Node v20, Typescript v5

seanadkinson commented 1 month ago

My first pass below. Not sure if I got all the optionals correct, but verified against each of the example events here.

type SESEventNotification =
    | SESBounceNotification
    | SESComplaintNotification
    | SESDeliveryNotification
    | SESSendNotification
    | SESRejectNotification
    | SESOpenNotification
    | SESClickNotification
    | SESRenderingFailureNotification
    | SESDeliveryDelayNotification
    | SESSubscriptionNotification;

type SESCommonNotification = {
    mail: {
        timestamp: string,
        messageId: string,
        source: string,
        sourceArn: string,
        sendingAccountId: string,
        destination: string[],
        headersTruncated: boolean,
        headers: { name: string, value: string }[],
        commonHeaders: Record<string, string | string[]>,
        tags: Record<string, string[]>
    }
}

type BounceTypes =
    | { bounceType: 'Undetermined', bounceSubType: 'Undetermined' }
    | { bounceType: 'Permanent', bounceSubType: 'General' | 'NoEmail' | 'Suppressed' | 'OnAccountSuppressionList' }
    | { bounceType: 'Transient', bounceSubType: 'General' | 'MailboxFull' | 'MessageTooLarge' | 'ContentRejected' | 'AttachmentRejected' }

type SESBounceNotification = SESCommonNotification & {
    eventType: 'Bounce'
    bounce: BounceTypes & {
        bouncedRecipients: {
            emailAddress: string,
            action?: string,
            status?: string,
            diagnosticCode?: string
        }[],
        timestamp: string,
        feedbackId: string,
        reportingMTA?: string
    }
}
type SESComplaintNotification = SESCommonNotification & {
    eventType: 'Complaint',
    complaint: {
        complainedRecipients: { emailAddress: string }[],
        timestamp: string,
        feedbackId: string,
        complaintSubType?: string,
        userAgent?: string,
        complaintFeedbackType?: 'abuse' | 'auth-failure' | 'fraud' | 'not-spam' | 'other' | 'virus',
        arrivalDate?: string,
    }
}
type SESDeliveryNotification = SESCommonNotification & {
    eventType: 'Delivery',
    delivery: {
        timestamp: string,
        processingTimeMillis: number,
        recipients: string[],
        smtpResponse: string,
        reportingMTA?: string,
    }
}
type SESSendNotification = SESCommonNotification & {
    eventType: 'Send',
    send: {}
}
type SESRejectNotification = SESCommonNotification & {
    eventType: 'Reject',
    reject: {
        reason: string
    }
}
type SESOpenNotification = SESCommonNotification & {
    eventType: 'Open',
    open: {
        ipAddress: string,
        timestamp: string,
        userAgent: string,
    }
}
type SESClickNotification = SESCommonNotification & {
    eventType: 'Click',
    click: {
        ipAddress: string,
        link: string,
        linkTags: Record<string, string[]>,
        timestamp: string,
        userAgent: string,
    }
}
type SESRenderingFailureNotification = SESCommonNotification & {
    eventType: 'Rendering Failure'
    failure: {
        templateName: string,
        errorMessage: string,
    }
}
type SESDeliveryDelayNotification = SESCommonNotification & {
    eventType: 'DeliveryDelay',
    deliveryDelay: {
        delayType: 'InternalFailure' | 'General' | 'MailboxFull' | 'SpamDetected' | 'RecipientServerError' | 'IPFailure' | 'TransientCommunicationFailure' | 'BYOIPHostNameLookupUnavailable' | 'Undetermined' | 'SendingDeferral',
        delayedRecipients: { emailAddress: string, status: string, diagnosticCode: string }[],
        expirationTime: string,
        reportingMTA?: string,
        timestamp: string,
    }
}
type SESSubscriptionNotification = SESCommonNotification & {
    eventType: 'Subscription',
    subscription: {
        contactList: string,
        timestamp: string,
        source: string,
        newTopicPreferences: TopicPreferences,
        oldTopicPreferences: TopicPreferences
    }
}
type TopicPreferences = {
    unsubscribeAll: boolean,
    topicSubscriptionStatus: {
        topicName: EmailTopic,
        subscriptionStatus: 'OptIn' | 'OptOut'
    }[],
    topicDefaultSubscriptionStatus: {
        topicName: EmailTopic,
        subscriptionStatus: 'OptIn' | 'OptOut'
    }[]
}