@backstage/plugin-notifications-backend-module-email 0.0.1 → 0.0.2-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/index.cjs.js +27 -41
- package/dist/index.cjs.js.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @backstage/plugin-notifications-backend-module-email
|
|
2
2
|
|
|
3
|
+
## 0.0.2-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @backstage/backend-common@0.22.1-next.0
|
|
9
|
+
- @backstage/backend-plugin-api@0.6.19-next.0
|
|
10
|
+
- @backstage/plugin-notifications-node@0.1.5-next.0
|
|
11
|
+
- @backstage/catalog-client@1.6.5
|
|
12
|
+
- @backstage/catalog-model@1.5.0
|
|
13
|
+
- @backstage/config@1.2.0
|
|
14
|
+
- @backstage/integration-aws-node@0.1.12
|
|
15
|
+
- @backstage/types@1.1.1
|
|
16
|
+
- @backstage/plugin-notifications-common@0.0.3
|
|
17
|
+
|
|
3
18
|
## 0.0.1
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -18,26 +18,24 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
|
|
|
18
18
|
var pThrottle__default = /*#__PURE__*/_interopDefaultCompat(pThrottle);
|
|
19
19
|
|
|
20
20
|
const createSmtpTransport = (config) => {
|
|
21
|
-
var _a, _b;
|
|
22
21
|
const username = config.getOptionalString("username");
|
|
23
22
|
const password = config.getOptionalString("password");
|
|
24
23
|
return nodemailer.createTransport({
|
|
25
24
|
host: config.getString("hostname"),
|
|
26
25
|
port: config.getNumber("port"),
|
|
27
|
-
secure:
|
|
28
|
-
requireTLS:
|
|
26
|
+
secure: config.getOptionalBoolean("secure") ?? false,
|
|
27
|
+
requireTLS: config.getOptionalBoolean("requireTls") ?? false,
|
|
29
28
|
auth: username && password ? { user: username, pass: password } : void 0
|
|
30
29
|
});
|
|
31
30
|
};
|
|
32
31
|
|
|
33
32
|
const createSesTransport = async (config, credentialsManager) => {
|
|
34
|
-
var _a;
|
|
35
33
|
const credentials = await credentialsManager.getCredentialProvider({
|
|
36
34
|
accountId: config.getOptionalString("accountId")
|
|
37
35
|
});
|
|
38
36
|
const ses = new clientSes.SES([
|
|
39
37
|
{
|
|
40
|
-
apiVersion:
|
|
38
|
+
apiVersion: config.getOptionalString("apiVersion") ?? "2010-12-01",
|
|
41
39
|
credentials: credentials.sdkCredentialProvider,
|
|
42
40
|
region: config.getOptionalString("region")
|
|
43
41
|
}
|
|
@@ -48,20 +46,13 @@ const createSesTransport = async (config, credentialsManager) => {
|
|
|
48
46
|
};
|
|
49
47
|
|
|
50
48
|
const createSendmailTransport = (config) => {
|
|
51
|
-
var _a, _b;
|
|
52
49
|
return nodemailer.createTransport({
|
|
53
50
|
sendmail: true,
|
|
54
|
-
newline:
|
|
55
|
-
path:
|
|
51
|
+
newline: config.getOptionalString("newline") ?? "unix",
|
|
52
|
+
path: config.getOptionalString("path") ?? "/usr/sbin/sendmail"
|
|
56
53
|
});
|
|
57
54
|
};
|
|
58
55
|
|
|
59
|
-
var __defProp = Object.defineProperty;
|
|
60
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
61
|
-
var __publicField = (obj, key, value) => {
|
|
62
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
63
|
-
return value;
|
|
64
|
-
};
|
|
65
56
|
class NotificationsEmailProcessor {
|
|
66
57
|
constructor(logger, config$1, catalog, auth, cache, templateRenderer) {
|
|
67
58
|
this.logger = logger;
|
|
@@ -70,16 +61,6 @@ class NotificationsEmailProcessor {
|
|
|
70
61
|
this.auth = auth;
|
|
71
62
|
this.cache = cache;
|
|
72
63
|
this.templateRenderer = templateRenderer;
|
|
73
|
-
__publicField(this, "transporter");
|
|
74
|
-
__publicField(this, "broadcastConfig");
|
|
75
|
-
__publicField(this, "transportConfig");
|
|
76
|
-
__publicField(this, "sender");
|
|
77
|
-
__publicField(this, "replyTo");
|
|
78
|
-
__publicField(this, "cacheTtl");
|
|
79
|
-
__publicField(this, "concurrencyLimit");
|
|
80
|
-
__publicField(this, "throttleInterval");
|
|
81
|
-
__publicField(this, "frontendBaseUrl");
|
|
82
|
-
var _a;
|
|
83
64
|
const emailProcessorConfig = config$1.getConfig(
|
|
84
65
|
"notifications.processors.email"
|
|
85
66
|
);
|
|
@@ -87,13 +68,22 @@ class NotificationsEmailProcessor {
|
|
|
87
68
|
this.broadcastConfig = emailProcessorConfig.getOptionalConfig("broadcastConfig");
|
|
88
69
|
this.sender = emailProcessorConfig.getString("sender");
|
|
89
70
|
this.replyTo = emailProcessorConfig.getOptionalString("replyTo");
|
|
90
|
-
this.concurrencyLimit =
|
|
71
|
+
this.concurrencyLimit = emailProcessorConfig.getOptionalNumber("concurrencyLimit") ?? 2;
|
|
91
72
|
const throttleConfig = emailProcessorConfig.getOptionalConfig("throttleInterval");
|
|
92
73
|
this.throttleInterval = throttleConfig ? types.durationToMilliseconds(config.readDurationFromConfig(throttleConfig)) : 100;
|
|
93
74
|
const cacheConfig = emailProcessorConfig.getOptionalConfig("cache.ttl");
|
|
94
75
|
this.cacheTtl = cacheConfig ? types.durationToMilliseconds(config.readDurationFromConfig(cacheConfig)) : 36e5;
|
|
95
76
|
this.frontendBaseUrl = config$1.getString("app.baseUrl");
|
|
96
77
|
}
|
|
78
|
+
transporter;
|
|
79
|
+
broadcastConfig;
|
|
80
|
+
transportConfig;
|
|
81
|
+
sender;
|
|
82
|
+
replyTo;
|
|
83
|
+
cacheTtl;
|
|
84
|
+
concurrencyLimit;
|
|
85
|
+
throttleInterval;
|
|
86
|
+
frontendBaseUrl;
|
|
97
87
|
async getTransporter() {
|
|
98
88
|
if (this.transporter) {
|
|
99
89
|
return this.transporter;
|
|
@@ -120,7 +110,6 @@ class NotificationsEmailProcessor {
|
|
|
120
110
|
return "Email";
|
|
121
111
|
}
|
|
122
112
|
async getBroadcastEmails() {
|
|
123
|
-
var _a, _b, _c;
|
|
124
113
|
if (!this.broadcastConfig) {
|
|
125
114
|
return [];
|
|
126
115
|
}
|
|
@@ -129,10 +118,10 @@ class NotificationsEmailProcessor {
|
|
|
129
118
|
return [];
|
|
130
119
|
}
|
|
131
120
|
if (receiver === "config") {
|
|
132
|
-
return
|
|
121
|
+
return this.broadcastConfig.getOptionalStringArray("receiverEmails") ?? [];
|
|
133
122
|
}
|
|
134
123
|
if (receiver === "users") {
|
|
135
|
-
const cached = await
|
|
124
|
+
const cached = await this.cache?.get("user-emails:all");
|
|
136
125
|
if (cached) {
|
|
137
126
|
return cached;
|
|
138
127
|
}
|
|
@@ -152,21 +141,19 @@ class NotificationsEmailProcessor {
|
|
|
152
141
|
const ret = lodash.compact([
|
|
153
142
|
...new Set(
|
|
154
143
|
entities.items.map((entity) => {
|
|
155
|
-
|
|
156
|
-
return (_a2 = entity == null ? void 0 : entity.spec.profile) == null ? void 0 : _a2.email;
|
|
144
|
+
return entity?.spec.profile?.email;
|
|
157
145
|
})
|
|
158
146
|
)
|
|
159
147
|
]);
|
|
160
|
-
await
|
|
148
|
+
await this.cache?.set("user-emails:all", ret, {
|
|
161
149
|
ttl: this.cacheTtl
|
|
162
|
-
})
|
|
150
|
+
});
|
|
163
151
|
return ret;
|
|
164
152
|
}
|
|
165
153
|
throw new Error(`Unsupported broadcast receiver: ${receiver}`);
|
|
166
154
|
}
|
|
167
155
|
async getUserEmail(entityRef) {
|
|
168
|
-
|
|
169
|
-
const cached = await ((_a = this.cache) == null ? void 0 : _a.get(`user-emails:${entityRef}`));
|
|
156
|
+
const cached = await this.cache?.get(`user-emails:${entityRef}`);
|
|
170
157
|
if (cached) {
|
|
171
158
|
return cached;
|
|
172
159
|
}
|
|
@@ -178,13 +165,13 @@ class NotificationsEmailProcessor {
|
|
|
178
165
|
const ret = [];
|
|
179
166
|
if (entity) {
|
|
180
167
|
const userEntity = entity;
|
|
181
|
-
if (
|
|
168
|
+
if (userEntity.spec.profile?.email) {
|
|
182
169
|
ret.push(userEntity.spec.profile.email);
|
|
183
170
|
}
|
|
184
171
|
}
|
|
185
|
-
await
|
|
172
|
+
await this.cache?.set(`user-emails:${entityRef}`, ret, {
|
|
186
173
|
ttl: this.cacheTtl
|
|
187
|
-
})
|
|
174
|
+
});
|
|
188
175
|
return ret;
|
|
189
176
|
}
|
|
190
177
|
async getRecipientEmails(notification, options) {
|
|
@@ -254,12 +241,11 @@ class NotificationsEmailProcessor {
|
|
|
254
241
|
await this.sendMails(mailOptions, emails);
|
|
255
242
|
}
|
|
256
243
|
async sendTemplateEmail(notification, emails) {
|
|
257
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
258
244
|
const mailOptions = {
|
|
259
245
|
from: this.sender,
|
|
260
|
-
subject:
|
|
261
|
-
html:
|
|
262
|
-
text:
|
|
246
|
+
subject: this.templateRenderer?.getSubject?.(notification) ?? notification.payload.title,
|
|
247
|
+
html: this.templateRenderer?.getHtml?.(notification),
|
|
248
|
+
text: this.templateRenderer?.getText?.(notification),
|
|
263
249
|
replyTo: this.replyTo
|
|
264
250
|
};
|
|
265
251
|
await this.sendMails(mailOptions, emails);
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/processor/transports/smtp.ts","../src/processor/transports/ses.ts","../src/processor/transports/sendmail.ts","../src/processor/NotificationsEmailProcessor.ts","../src/extensions.ts","../src/module.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createTransport } from 'nodemailer';\nimport { Config } from '@backstage/config';\n\nexport const createSmtpTransport = (config: Config) => {\n const username = config.getOptionalString('username');\n const password = config.getOptionalString('password');\n\n return createTransport({\n host: config.getString('hostname'),\n port: config.getNumber('port'),\n secure: config.getOptionalBoolean('secure') ?? false,\n requireTLS: config.getOptionalBoolean('requireTls') ?? false,\n auth: username && password ? { user: username, pass: password } : undefined,\n });\n};\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createTransport } from 'nodemailer';\nimport { SendRawEmailCommand, SES } from '@aws-sdk/client-ses';\nimport { Config } from '@backstage/config';\nimport { AwsCredentialsManager } from '@backstage/integration-aws-node';\n\nexport const createSesTransport = async (\n config: Config,\n credentialsManager: AwsCredentialsManager,\n) => {\n const credentials = await credentialsManager.getCredentialProvider({\n accountId: config.getOptionalString('accountId'),\n });\n const ses = new SES([\n {\n apiVersion: config.getOptionalString('apiVersion') ?? '2010-12-01',\n credentials: credentials.sdkCredentialProvider,\n region: config.getOptionalString('region'),\n },\n ]);\n return createTransport({\n SES: { ses, aws: { SendRawEmailCommand } },\n });\n};\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createTransport } from 'nodemailer';\nimport { Config } from '@backstage/config';\n\nexport const createSendmailTransport = (config: Config) => {\n return createTransport({\n sendmail: true,\n newline: config.getOptionalString('newline') ?? 'unix',\n path: config.getOptionalString('path') ?? '/usr/sbin/sendmail',\n });\n};\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n NotificationProcessor,\n NotificationSendOptions,\n} from '@backstage/plugin-notifications-node';\nimport {\n AuthService,\n CacheService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { durationToMilliseconds } from '@backstage/types';\nimport {\n CATALOG_FILTER_EXISTS,\n CatalogClient,\n} from '@backstage/catalog-client';\nimport { Notification } from '@backstage/plugin-notifications-common';\nimport {\n createSendmailTransport,\n createSesTransport,\n createSmtpTransport,\n} from './transports';\nimport { UserEntity } from '@backstage/catalog-model';\nimport { compact } from 'lodash';\nimport { DefaultAwsCredentialsManager } from '@backstage/integration-aws-node';\nimport { NotificationTemplateRenderer } from '../extensions';\nimport Mail from 'nodemailer/lib/mailer';\nimport pThrottle from 'p-throttle';\n\nexport class NotificationsEmailProcessor implements NotificationProcessor {\n private transporter: any;\n private readonly broadcastConfig?: Config;\n private readonly transportConfig: Config;\n private readonly sender: string;\n private readonly replyTo?: string;\n private readonly cacheTtl: number;\n private readonly concurrencyLimit: number;\n private readonly throttleInterval: number;\n private readonly frontendBaseUrl: string;\n\n constructor(\n private readonly logger: LoggerService,\n private readonly config: Config,\n private readonly catalog: CatalogClient,\n private readonly auth: AuthService,\n private readonly cache?: CacheService,\n private readonly templateRenderer?: NotificationTemplateRenderer,\n ) {\n const emailProcessorConfig = config.getConfig(\n 'notifications.processors.email',\n );\n this.transportConfig = emailProcessorConfig.getConfig('transportConfig');\n this.broadcastConfig =\n emailProcessorConfig.getOptionalConfig('broadcastConfig');\n this.sender = emailProcessorConfig.getString('sender');\n this.replyTo = emailProcessorConfig.getOptionalString('replyTo');\n this.concurrencyLimit =\n emailProcessorConfig.getOptionalNumber('concurrencyLimit') ?? 2;\n const throttleConfig =\n emailProcessorConfig.getOptionalConfig('throttleInterval');\n this.throttleInterval = throttleConfig\n ? durationToMilliseconds(readDurationFromConfig(throttleConfig))\n : 100;\n const cacheConfig = emailProcessorConfig.getOptionalConfig('cache.ttl');\n this.cacheTtl = cacheConfig\n ? durationToMilliseconds(readDurationFromConfig(cacheConfig))\n : 3_600_000;\n this.frontendBaseUrl = config.getString('app.baseUrl');\n }\n\n private async getTransporter() {\n if (this.transporter) {\n return this.transporter;\n }\n const transport = this.transportConfig.getString('transport');\n if (transport === 'smtp') {\n this.transporter = createSmtpTransport(this.transportConfig);\n } else if (transport === 'ses') {\n const awsCredentialsManager = DefaultAwsCredentialsManager.fromConfig(\n this.config,\n );\n this.transporter = await createSesTransport(\n this.transportConfig,\n awsCredentialsManager,\n );\n } else if (transport === 'sendmail') {\n this.transporter = createSendmailTransport(this.transportConfig);\n } else {\n throw new Error(`Unsupported transport: ${transport}`);\n }\n return this.transporter;\n }\n\n getName(): string {\n return 'Email';\n }\n\n private async getBroadcastEmails(): Promise<string[]> {\n if (!this.broadcastConfig) {\n return [];\n }\n\n const receiver = this.broadcastConfig.getString('receiver');\n if (receiver === 'none') {\n return [];\n }\n\n if (receiver === 'config') {\n return (\n this.broadcastConfig.getOptionalStringArray('receiverEmails') ?? []\n );\n }\n\n if (receiver === 'users') {\n const cached = await this.cache?.get<string[]>('user-emails:all');\n if (cached) {\n return cached;\n }\n\n const { token } = await this.auth.getPluginRequestToken({\n onBehalfOf: await this.auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entities = await this.catalog.getEntities(\n {\n filter: [\n { kind: 'user', 'spec.profile.email': CATALOG_FILTER_EXISTS },\n ],\n fields: ['spec.profile.email'],\n },\n { token },\n );\n const ret = compact([\n ...new Set(\n entities.items.map(entity => {\n return (entity as UserEntity)?.spec.profile?.email;\n }),\n ),\n ]);\n\n await this.cache?.set('user-emails:all', ret, {\n ttl: this.cacheTtl,\n });\n return ret;\n }\n\n throw new Error(`Unsupported broadcast receiver: ${receiver}`);\n }\n\n private async getUserEmail(entityRef: string): Promise<string[]> {\n const cached = await this.cache?.get<string[]>(`user-emails:${entityRef}`);\n if (cached) {\n return cached;\n }\n\n const { token } = await this.auth.getPluginRequestToken({\n onBehalfOf: await this.auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await this.catalog.getEntityByRef(entityRef, { token });\n const ret: string[] = [];\n if (entity) {\n const userEntity = entity as UserEntity;\n if (userEntity.spec.profile?.email) {\n ret.push(userEntity.spec.profile.email);\n }\n }\n\n await this.cache?.set(`user-emails:${entityRef}`, ret, {\n ttl: this.cacheTtl,\n });\n\n return ret;\n }\n\n private async getRecipientEmails(\n notification: Notification,\n options: NotificationSendOptions,\n ) {\n if (options.recipients.type === 'broadcast' || notification.user === null) {\n return await this.getBroadcastEmails();\n }\n return await this.getUserEmail(notification.user);\n }\n\n private async sendMail(options: Mail.Options) {\n try {\n await this.transporter.sendMail(options);\n } catch (e) {\n this.logger.error(`Failed to send email to ${options.to}: ${e}`);\n }\n }\n\n private async sendMails(options: Mail.Options, emails: string[]) {\n const throttle = pThrottle({\n limit: this.concurrencyLimit,\n interval: this.throttleInterval,\n });\n\n const throttled = throttle((opts: Mail.Options) => this.sendMail(opts));\n await Promise.all(\n emails.map(email => throttled({ ...options, to: email })),\n );\n }\n\n private getNotificationLink(notification: Notification) {\n if (notification.payload.link) {\n const stripLeadingSlash = (s: string) => s.replace(/^\\//, '');\n const ensureTrailingSlash = (s: string) => s.replace(/\\/?$/, '/');\n\n try {\n const url = new URL(\n stripLeadingSlash(notification.payload.link),\n ensureTrailingSlash(this.frontendBaseUrl),\n );\n return url.toString();\n } catch (_e) {\n // noop: fallback to relative URL\n }\n return notification.payload.link;\n }\n return `${this.frontendBaseUrl}/notifications`;\n }\n\n private getHtmlContent(notification: Notification) {\n const contentParts: string[] = [];\n if (notification.payload.description) {\n contentParts.push(`${notification.payload.description}`);\n }\n const link = this.getNotificationLink(notification);\n contentParts.push(`<a href=\"${link}\">${link}</a>`);\n return `<p>${contentParts.join('<br/>')}</p>`;\n }\n\n private getTextContent(notification: Notification) {\n const contentParts: string[] = [];\n if (notification.payload.description) {\n contentParts.push(notification.payload.description);\n }\n contentParts.push(this.getNotificationLink(notification));\n return contentParts.join('\\n\\n');\n }\n\n private async sendPlainEmail(notification: Notification, emails: string[]) {\n const mailOptions = {\n from: this.sender,\n subject: notification.payload.title,\n html: this.getHtmlContent(notification),\n text: this.getTextContent(notification),\n replyTo: this.replyTo,\n };\n\n await this.sendMails(mailOptions, emails);\n }\n\n private async sendTemplateEmail(\n notification: Notification,\n emails: string[],\n ) {\n const mailOptions = {\n from: this.sender,\n subject:\n this.templateRenderer?.getSubject?.(notification) ??\n notification.payload.title,\n html: this.templateRenderer?.getHtml?.(notification),\n text: this.templateRenderer?.getText?.(notification),\n replyTo: this.replyTo,\n };\n\n await this.sendMails(mailOptions, emails);\n }\n\n async postProcess(\n notification: Notification,\n options: NotificationSendOptions,\n ): Promise<void> {\n this.transporter = await this.getTransporter();\n\n let emails: string[] = [];\n try {\n emails = await this.getRecipientEmails(notification, options);\n } catch (e) {\n this.logger.error(`Failed to resolve recipient emails: ${e}`);\n return;\n }\n\n if (emails.length === 0) {\n this.logger.info(\n `No email recipients found for notification: ${notification.id}, skipping`,\n );\n return;\n }\n\n if (!this.templateRenderer) {\n await this.sendPlainEmail(notification, emails);\n return;\n }\n\n await this.sendTemplateEmail(notification, emails);\n }\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createExtensionPoint } from '@backstage/backend-plugin-api';\nimport { Notification } from '@backstage/plugin-notifications-common';\n\n/**\n * @public\n */\nexport interface NotificationTemplateRenderer {\n getSubject?(notification: Notification): string;\n getText?(notification: Notification): string;\n getHtml?(notification: Notification): string;\n}\n\n/**\n * @public\n */\nexport interface NotificationsEmailTemplateExtensionPoint {\n setTemplateRenderer(renderer: NotificationTemplateRenderer): void;\n}\n\n/**\n * @public\n */\nexport const notificationsEmailTemplateExtensionPoint =\n createExtensionPoint<NotificationsEmailTemplateExtensionPoint>({\n id: 'notifications.email.templates',\n });\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport { notificationsProcessingExtensionPoint } from '@backstage/plugin-notifications-node';\nimport { NotificationsEmailProcessor } from './processor';\nimport {\n notificationsEmailTemplateExtensionPoint,\n NotificationTemplateRenderer,\n} from './extensions';\n\n/**\n * @public\n */\nexport const notificationsModuleEmail = createBackendModule({\n pluginId: 'notifications',\n moduleId: 'email',\n register(reg) {\n let templateRenderer: NotificationTemplateRenderer | undefined;\n reg.registerExtensionPoint(notificationsEmailTemplateExtensionPoint, {\n setTemplateRenderer(renderer) {\n if (templateRenderer) {\n throw new Error(`Email template renderer was already registered`);\n }\n templateRenderer = renderer;\n },\n });\n\n reg.registerInit({\n deps: {\n config: coreServices.rootConfig,\n notifications: notificationsProcessingExtensionPoint,\n discovery: coreServices.discovery,\n logger: coreServices.logger,\n auth: coreServices.auth,\n cache: coreServices.cache,\n },\n async init({ config, notifications, discovery, logger, auth, cache }) {\n const catalogClient = new CatalogClient({\n discoveryApi: discovery,\n });\n\n notifications.addProcessor(\n new NotificationsEmailProcessor(\n logger,\n config,\n catalogClient,\n auth,\n cache,\n templateRenderer,\n ),\n );\n },\n });\n },\n});\n"],"names":["createTransport","SES","SendRawEmailCommand","config","durationToMilliseconds","readDurationFromConfig","DefaultAwsCredentialsManager","CATALOG_FILTER_EXISTS","compact","_a","pThrottle","createExtensionPoint","createBackendModule","coreServices","notificationsProcessingExtensionPoint","catalogClient","CatalogClient"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/processor/transports/smtp.ts","../src/processor/transports/ses.ts","../src/processor/transports/sendmail.ts","../src/processor/NotificationsEmailProcessor.ts","../src/extensions.ts","../src/module.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createTransport } from 'nodemailer';\nimport { Config } from '@backstage/config';\n\nexport const createSmtpTransport = (config: Config) => {\n const username = config.getOptionalString('username');\n const password = config.getOptionalString('password');\n\n return createTransport({\n host: config.getString('hostname'),\n port: config.getNumber('port'),\n secure: config.getOptionalBoolean('secure') ?? false,\n requireTLS: config.getOptionalBoolean('requireTls') ?? false,\n auth: username && password ? { user: username, pass: password } : undefined,\n });\n};\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createTransport } from 'nodemailer';\nimport { SendRawEmailCommand, SES } from '@aws-sdk/client-ses';\nimport { Config } from '@backstage/config';\nimport { AwsCredentialsManager } from '@backstage/integration-aws-node';\n\nexport const createSesTransport = async (\n config: Config,\n credentialsManager: AwsCredentialsManager,\n) => {\n const credentials = await credentialsManager.getCredentialProvider({\n accountId: config.getOptionalString('accountId'),\n });\n const ses = new SES([\n {\n apiVersion: config.getOptionalString('apiVersion') ?? '2010-12-01',\n credentials: credentials.sdkCredentialProvider,\n region: config.getOptionalString('region'),\n },\n ]);\n return createTransport({\n SES: { ses, aws: { SendRawEmailCommand } },\n });\n};\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createTransport } from 'nodemailer';\nimport { Config } from '@backstage/config';\n\nexport const createSendmailTransport = (config: Config) => {\n return createTransport({\n sendmail: true,\n newline: config.getOptionalString('newline') ?? 'unix',\n path: config.getOptionalString('path') ?? '/usr/sbin/sendmail',\n });\n};\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n NotificationProcessor,\n NotificationSendOptions,\n} from '@backstage/plugin-notifications-node';\nimport {\n AuthService,\n CacheService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { durationToMilliseconds } from '@backstage/types';\nimport {\n CATALOG_FILTER_EXISTS,\n CatalogClient,\n} from '@backstage/catalog-client';\nimport { Notification } from '@backstage/plugin-notifications-common';\nimport {\n createSendmailTransport,\n createSesTransport,\n createSmtpTransport,\n} from './transports';\nimport { UserEntity } from '@backstage/catalog-model';\nimport { compact } from 'lodash';\nimport { DefaultAwsCredentialsManager } from '@backstage/integration-aws-node';\nimport { NotificationTemplateRenderer } from '../extensions';\nimport Mail from 'nodemailer/lib/mailer';\nimport pThrottle from 'p-throttle';\n\nexport class NotificationsEmailProcessor implements NotificationProcessor {\n private transporter: any;\n private readonly broadcastConfig?: Config;\n private readonly transportConfig: Config;\n private readonly sender: string;\n private readonly replyTo?: string;\n private readonly cacheTtl: number;\n private readonly concurrencyLimit: number;\n private readonly throttleInterval: number;\n private readonly frontendBaseUrl: string;\n\n constructor(\n private readonly logger: LoggerService,\n private readonly config: Config,\n private readonly catalog: CatalogClient,\n private readonly auth: AuthService,\n private readonly cache?: CacheService,\n private readonly templateRenderer?: NotificationTemplateRenderer,\n ) {\n const emailProcessorConfig = config.getConfig(\n 'notifications.processors.email',\n );\n this.transportConfig = emailProcessorConfig.getConfig('transportConfig');\n this.broadcastConfig =\n emailProcessorConfig.getOptionalConfig('broadcastConfig');\n this.sender = emailProcessorConfig.getString('sender');\n this.replyTo = emailProcessorConfig.getOptionalString('replyTo');\n this.concurrencyLimit =\n emailProcessorConfig.getOptionalNumber('concurrencyLimit') ?? 2;\n const throttleConfig =\n emailProcessorConfig.getOptionalConfig('throttleInterval');\n this.throttleInterval = throttleConfig\n ? durationToMilliseconds(readDurationFromConfig(throttleConfig))\n : 100;\n const cacheConfig = emailProcessorConfig.getOptionalConfig('cache.ttl');\n this.cacheTtl = cacheConfig\n ? durationToMilliseconds(readDurationFromConfig(cacheConfig))\n : 3_600_000;\n this.frontendBaseUrl = config.getString('app.baseUrl');\n }\n\n private async getTransporter() {\n if (this.transporter) {\n return this.transporter;\n }\n const transport = this.transportConfig.getString('transport');\n if (transport === 'smtp') {\n this.transporter = createSmtpTransport(this.transportConfig);\n } else if (transport === 'ses') {\n const awsCredentialsManager = DefaultAwsCredentialsManager.fromConfig(\n this.config,\n );\n this.transporter = await createSesTransport(\n this.transportConfig,\n awsCredentialsManager,\n );\n } else if (transport === 'sendmail') {\n this.transporter = createSendmailTransport(this.transportConfig);\n } else {\n throw new Error(`Unsupported transport: ${transport}`);\n }\n return this.transporter;\n }\n\n getName(): string {\n return 'Email';\n }\n\n private async getBroadcastEmails(): Promise<string[]> {\n if (!this.broadcastConfig) {\n return [];\n }\n\n const receiver = this.broadcastConfig.getString('receiver');\n if (receiver === 'none') {\n return [];\n }\n\n if (receiver === 'config') {\n return (\n this.broadcastConfig.getOptionalStringArray('receiverEmails') ?? []\n );\n }\n\n if (receiver === 'users') {\n const cached = await this.cache?.get<string[]>('user-emails:all');\n if (cached) {\n return cached;\n }\n\n const { token } = await this.auth.getPluginRequestToken({\n onBehalfOf: await this.auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entities = await this.catalog.getEntities(\n {\n filter: [\n { kind: 'user', 'spec.profile.email': CATALOG_FILTER_EXISTS },\n ],\n fields: ['spec.profile.email'],\n },\n { token },\n );\n const ret = compact([\n ...new Set(\n entities.items.map(entity => {\n return (entity as UserEntity)?.spec.profile?.email;\n }),\n ),\n ]);\n\n await this.cache?.set('user-emails:all', ret, {\n ttl: this.cacheTtl,\n });\n return ret;\n }\n\n throw new Error(`Unsupported broadcast receiver: ${receiver}`);\n }\n\n private async getUserEmail(entityRef: string): Promise<string[]> {\n const cached = await this.cache?.get<string[]>(`user-emails:${entityRef}`);\n if (cached) {\n return cached;\n }\n\n const { token } = await this.auth.getPluginRequestToken({\n onBehalfOf: await this.auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await this.catalog.getEntityByRef(entityRef, { token });\n const ret: string[] = [];\n if (entity) {\n const userEntity = entity as UserEntity;\n if (userEntity.spec.profile?.email) {\n ret.push(userEntity.spec.profile.email);\n }\n }\n\n await this.cache?.set(`user-emails:${entityRef}`, ret, {\n ttl: this.cacheTtl,\n });\n\n return ret;\n }\n\n private async getRecipientEmails(\n notification: Notification,\n options: NotificationSendOptions,\n ) {\n if (options.recipients.type === 'broadcast' || notification.user === null) {\n return await this.getBroadcastEmails();\n }\n return await this.getUserEmail(notification.user);\n }\n\n private async sendMail(options: Mail.Options) {\n try {\n await this.transporter.sendMail(options);\n } catch (e) {\n this.logger.error(`Failed to send email to ${options.to}: ${e}`);\n }\n }\n\n private async sendMails(options: Mail.Options, emails: string[]) {\n const throttle = pThrottle({\n limit: this.concurrencyLimit,\n interval: this.throttleInterval,\n });\n\n const throttled = throttle((opts: Mail.Options) => this.sendMail(opts));\n await Promise.all(\n emails.map(email => throttled({ ...options, to: email })),\n );\n }\n\n private getNotificationLink(notification: Notification) {\n if (notification.payload.link) {\n const stripLeadingSlash = (s: string) => s.replace(/^\\//, '');\n const ensureTrailingSlash = (s: string) => s.replace(/\\/?$/, '/');\n\n try {\n const url = new URL(\n stripLeadingSlash(notification.payload.link),\n ensureTrailingSlash(this.frontendBaseUrl),\n );\n return url.toString();\n } catch (_e) {\n // noop: fallback to relative URL\n }\n return notification.payload.link;\n }\n return `${this.frontendBaseUrl}/notifications`;\n }\n\n private getHtmlContent(notification: Notification) {\n const contentParts: string[] = [];\n if (notification.payload.description) {\n contentParts.push(`${notification.payload.description}`);\n }\n const link = this.getNotificationLink(notification);\n contentParts.push(`<a href=\"${link}\">${link}</a>`);\n return `<p>${contentParts.join('<br/>')}</p>`;\n }\n\n private getTextContent(notification: Notification) {\n const contentParts: string[] = [];\n if (notification.payload.description) {\n contentParts.push(notification.payload.description);\n }\n contentParts.push(this.getNotificationLink(notification));\n return contentParts.join('\\n\\n');\n }\n\n private async sendPlainEmail(notification: Notification, emails: string[]) {\n const mailOptions = {\n from: this.sender,\n subject: notification.payload.title,\n html: this.getHtmlContent(notification),\n text: this.getTextContent(notification),\n replyTo: this.replyTo,\n };\n\n await this.sendMails(mailOptions, emails);\n }\n\n private async sendTemplateEmail(\n notification: Notification,\n emails: string[],\n ) {\n const mailOptions = {\n from: this.sender,\n subject:\n this.templateRenderer?.getSubject?.(notification) ??\n notification.payload.title,\n html: this.templateRenderer?.getHtml?.(notification),\n text: this.templateRenderer?.getText?.(notification),\n replyTo: this.replyTo,\n };\n\n await this.sendMails(mailOptions, emails);\n }\n\n async postProcess(\n notification: Notification,\n options: NotificationSendOptions,\n ): Promise<void> {\n this.transporter = await this.getTransporter();\n\n let emails: string[] = [];\n try {\n emails = await this.getRecipientEmails(notification, options);\n } catch (e) {\n this.logger.error(`Failed to resolve recipient emails: ${e}`);\n return;\n }\n\n if (emails.length === 0) {\n this.logger.info(\n `No email recipients found for notification: ${notification.id}, skipping`,\n );\n return;\n }\n\n if (!this.templateRenderer) {\n await this.sendPlainEmail(notification, emails);\n return;\n }\n\n await this.sendTemplateEmail(notification, emails);\n }\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createExtensionPoint } from '@backstage/backend-plugin-api';\nimport { Notification } from '@backstage/plugin-notifications-common';\n\n/**\n * @public\n */\nexport interface NotificationTemplateRenderer {\n getSubject?(notification: Notification): string;\n getText?(notification: Notification): string;\n getHtml?(notification: Notification): string;\n}\n\n/**\n * @public\n */\nexport interface NotificationsEmailTemplateExtensionPoint {\n setTemplateRenderer(renderer: NotificationTemplateRenderer): void;\n}\n\n/**\n * @public\n */\nexport const notificationsEmailTemplateExtensionPoint =\n createExtensionPoint<NotificationsEmailTemplateExtensionPoint>({\n id: 'notifications.email.templates',\n });\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport { notificationsProcessingExtensionPoint } from '@backstage/plugin-notifications-node';\nimport { NotificationsEmailProcessor } from './processor';\nimport {\n notificationsEmailTemplateExtensionPoint,\n NotificationTemplateRenderer,\n} from './extensions';\n\n/**\n * @public\n */\nexport const notificationsModuleEmail = createBackendModule({\n pluginId: 'notifications',\n moduleId: 'email',\n register(reg) {\n let templateRenderer: NotificationTemplateRenderer | undefined;\n reg.registerExtensionPoint(notificationsEmailTemplateExtensionPoint, {\n setTemplateRenderer(renderer) {\n if (templateRenderer) {\n throw new Error(`Email template renderer was already registered`);\n }\n templateRenderer = renderer;\n },\n });\n\n reg.registerInit({\n deps: {\n config: coreServices.rootConfig,\n notifications: notificationsProcessingExtensionPoint,\n discovery: coreServices.discovery,\n logger: coreServices.logger,\n auth: coreServices.auth,\n cache: coreServices.cache,\n },\n async init({ config, notifications, discovery, logger, auth, cache }) {\n const catalogClient = new CatalogClient({\n discoveryApi: discovery,\n });\n\n notifications.addProcessor(\n new NotificationsEmailProcessor(\n logger,\n config,\n catalogClient,\n auth,\n cache,\n templateRenderer,\n ),\n );\n },\n });\n },\n});\n"],"names":["createTransport","SES","SendRawEmailCommand","config","durationToMilliseconds","readDurationFromConfig","DefaultAwsCredentialsManager","CATALOG_FILTER_EXISTS","compact","pThrottle","createExtensionPoint","createBackendModule","coreServices","notificationsProcessingExtensionPoint","catalogClient","CatalogClient"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-notifications-backend-module-email",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2-next.0",
|
|
4
4
|
"description": "The email backend module for the notifications plugin.",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "backend-plugin-module"
|
|
@@ -34,22 +34,22 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@aws-sdk/client-ses": "^3.550.0",
|
|
36
36
|
"@aws-sdk/types": "^3.347.0",
|
|
37
|
-
"@backstage/backend-common": "^0.22.0",
|
|
38
|
-
"@backstage/backend-plugin-api": "^0.6.
|
|
37
|
+
"@backstage/backend-common": "^0.22.1-next.0",
|
|
38
|
+
"@backstage/backend-plugin-api": "^0.6.19-next.0",
|
|
39
39
|
"@backstage/catalog-client": "^1.6.5",
|
|
40
40
|
"@backstage/catalog-model": "^1.5.0",
|
|
41
41
|
"@backstage/config": "^1.2.0",
|
|
42
42
|
"@backstage/integration-aws-node": "^0.1.12",
|
|
43
43
|
"@backstage/plugin-notifications-common": "^0.0.3",
|
|
44
|
-
"@backstage/plugin-notifications-node": "^0.1.
|
|
44
|
+
"@backstage/plugin-notifications-node": "^0.1.5-next.0",
|
|
45
45
|
"@backstage/types": "^1.1.1",
|
|
46
46
|
"lodash": "^4.17.21",
|
|
47
47
|
"nodemailer": "^6.9.13",
|
|
48
48
|
"p-throttle": "^4.1.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@backstage/backend-test-utils": "^0.3.
|
|
52
|
-
"@backstage/cli": "^0.26.
|
|
51
|
+
"@backstage/backend-test-utils": "^0.3.9-next.0",
|
|
52
|
+
"@backstage/cli": "^0.26.6-next.0",
|
|
53
53
|
"@types/nodemailer": "^6.4.14"
|
|
54
54
|
},
|
|
55
55
|
"configSchema": "config.d.ts"
|