diff --git a/.changeset/curvy-things-call.md b/.changeset/curvy-things-call.md new file mode 100644 index 0000000000..d64f1a14fa --- /dev/null +++ b/.changeset/curvy-things-call.md @@ -0,0 +1,21 @@ +--- +'@backstage/plugin-notifications-backend-module-email': patch +--- + +SES config for the notification email processor now supports utilizing an ARN for the SES identity when sending an email after the SES SDK V2 update. + +The `sesConfig.fromArn` will set the `fromEmailAddressIdentityArn` option for the SES `SendEmailCommand`. The `sesConfig.sourceArn` field is removed since no equivalent option is available in the send email command options. Setting `sesConfig.sourceArn` will have no effect and log a warning. Example changes: + +```diff +notifications: + processors: + email: + transportConfig: + transport: "ses" + region: "us-west-2" + sender: "sender@mycompany.com" + replyTo: "no-reply@mycompany.com" + sesConfig: +- sourceArn: "arn:aws:ses:us-west-2:123456789012:identity/example.com" + fromArn: "arn:aws:ses:us-west-2:123456789012:identity/example.com" +``` diff --git a/plugins/notifications-backend-module-email/README.md b/plugins/notifications-backend-module-email/README.md index c1ead48876..248bb2c501 100644 --- a/plugins/notifications-backend-module-email/README.md +++ b/plugins/notifications-backend-module-email/README.md @@ -81,7 +81,6 @@ notifications: receiver: 'users' # Optional SES config # sesConfig: - # sourceArn: 'arn:aws:ses:us-west-2:123456789012:identity/example.com' # fromArn: 'arn:aws:ses:us-west-2:123456789012:identity/example.com' # configurationSetName: 'custom-config' # How many emails to send concurrently, defaults to 2 diff --git a/plugins/notifications-backend-module-email/config.d.ts b/plugins/notifications-backend-module-email/config.d.ts index 7116826c5d..55a751f8fa 100644 --- a/plugins/notifications-backend-module-email/config.d.ts +++ b/plugins/notifications-backend-module-email/config.d.ts @@ -136,10 +136,6 @@ export interface Config { * Optional SES config for mail options. Allows for delegated sender */ sesConfig?: { - /** - * ARN of the identity to use as the source of the email - */ - sourceArn?: string; /** * ARN of the identity to use for the "From"/sender address of the email */ diff --git a/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.test.ts b/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.test.ts index ebe1b90f35..ad0817521f 100644 --- a/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.test.ts +++ b/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.test.ts @@ -497,9 +497,13 @@ describe('NotificationsEmailProcessor', () => { text: 'https://example.org/notifications', to: 'mock@backstage.io', ses: { - SourceArn: 'arn:aws:ses:us-west-2:123456789012:identity/example.com', - FromArn: 'arn:aws:ses:us-west-2:123456789012:identity/example.com', + FromEmailAddressIdentityArn: + 'arn:aws:ses:us-west-2:123456789012:identity/example.com', }, }); + + expect(logger.warn).toHaveBeenCalledWith( + 'sourceArn is not supported in SESv2 and will be ignored', + ); }); }); diff --git a/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.ts b/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.ts index eadfe7747e..e0e27232c2 100644 --- a/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.ts +++ b/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.ts @@ -45,6 +45,7 @@ import { DefaultAwsCredentialsManager } from '@backstage/integration-aws-node'; import { NotificationTemplateRenderer } from '../extensions'; import Mail from 'nodemailer/lib/mailer'; import pThrottle from 'p-throttle'; +import { SendEmailCommandInput } from '@aws-sdk/client-sesv2'; export class NotificationsEmailProcessor implements NotificationProcessor { private transporter: any; @@ -53,6 +54,7 @@ export class NotificationsEmailProcessor implements NotificationProcessor { private readonly sender: string; private readonly replyTo?: string; private readonly sesConfig?: Config; + private readonly sesOptions?: Partial; private readonly cacheTtl: number; private readonly concurrencyLimit: number; private readonly throttleInterval: number; @@ -91,6 +93,7 @@ export class NotificationsEmailProcessor implements NotificationProcessor { this.sender = emailProcessorConfig.getString('sender'); this.replyTo = emailProcessorConfig.getOptionalString('replyTo'); this.sesConfig = emailProcessorConfig.getOptionalConfig('sesConfig'); + this.sesOptions = this.getSesOptions(); this.concurrencyLimit = emailProcessorConfig.getOptionalNumber('concurrencyLimit') ?? 2; this.throttleInterval = emailProcessorConfig.has('throttleInterval') @@ -307,20 +310,23 @@ export class NotificationsEmailProcessor implements NotificationProcessor { return contentParts.join('\n\n'); } - private async getSesOptions() { + private getSesOptions(): Partial | undefined { if (!this.sesConfig) { return undefined; } - const ses: Record = {}; - const sourceArn = this.sesConfig.getOptionalString('sourceArn'); + const ses: Partial = {}; const fromArn = this.sesConfig.getOptionalString('fromArn'); + const sourceArn = this.sesConfig.getOptionalString('sourceArn'); const configurationSetName = this.sesConfig.getOptionalString( 'configurationSetName', ); - if (sourceArn) ses.SourceArn = sourceArn; - if (fromArn) ses.FromArn = fromArn; + if (fromArn) ses.FromEmailAddressIdentityArn = fromArn; if (configurationSetName) ses.ConfigurationSetName = configurationSetName; + if (sourceArn) + this.logger.warn( + 'sourceArn is not supported in SESv2 and will be ignored', + ); return Object.keys(ses).length > 0 ? ses : undefined; } @@ -332,7 +338,7 @@ export class NotificationsEmailProcessor implements NotificationProcessor { html: this.getHtmlContent(notification), text: this.getTextContent(notification), replyTo: this.replyTo, - ses: await this.getSesOptions(), + ses: this.sesOptions, }; await this.sendMails(mailOptions, emails); @@ -350,7 +356,7 @@ export class NotificationsEmailProcessor implements NotificationProcessor { html: await this.templateRenderer?.getHtml?.(notification), text: await this.templateRenderer?.getText?.(notification), replyTo: this.replyTo, - ses: await this.getSesOptions(), + ses: this.sesOptions, }; await this.sendMails(mailOptions, emails);