diff --git a/dictation_server/src/features/users/users.service.spec.ts b/dictation_server/src/features/users/users.service.spec.ts index 8513ca3..4f3897a 100644 --- a/dictation_server/src/features/users/users.service.spec.ts +++ b/dictation_server/src/features/users/users.service.spec.ts @@ -2011,6 +2011,7 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + overrideSendgridService(service, {}); const context = makeContext(`uuidv4`, 'requestId'); expect( @@ -2070,6 +2071,7 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + overrideSendgridService(service, {}); const context = makeContext(`uuidv4`, 'requestId'); expect( @@ -2129,6 +2131,7 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + overrideSendgridService(service, {}); const context = makeContext(`uuidv4`, 'requestId'); expect( @@ -2188,6 +2191,7 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + overrideSendgridService(service, {}); const context = makeContext(`uuidv4`, 'requestId'); expect( @@ -2247,6 +2251,7 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + overrideSendgridService(service, {}); const context = makeContext(`uuidv4`, 'requestId'); expect( @@ -2306,6 +2311,7 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + overrideSendgridService(service, {}); const context = makeContext(`uuidv4`, 'requestId'); await expect( @@ -2355,6 +2361,7 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + overrideSendgridService(service, {}); const context = makeContext(`uuidv4`, 'requestId'); expect( @@ -2414,6 +2421,7 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + overrideSendgridService(service, {}); const context = makeContext(`uuidv4`, 'requestId'); expect( @@ -2473,6 +2481,7 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + overrideSendgridService(service, {}); const context = makeContext(`uuidv4`, 'requestId'); await expect( @@ -2533,6 +2542,7 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + overrideSendgridService(service, {}); const context = makeContext(`uuidv4`, 'requestId'); await expect( diff --git a/dictation_server/src/features/users/users.service.ts b/dictation_server/src/features/users/users.service.ts index d5bb5f2..1e32118 100644 --- a/dictation_server/src/features/users/users.service.ts +++ b/dictation_server/src/features/users/users.service.ts @@ -954,6 +954,51 @@ export class UsersService { encryptionPassword, prompt, ); + + // メール送信処理 + try { + const { adminEmails } = await this.getAccountInformation( + context, + accountId, + ); + + // 変更ユーザー情報を取得 + const { external_id: userExtarnalId } = + await this.usersRepository.findUserById(context, id); + const adb2cUser = await this.adB2cService.getUser( + context, + userExtarnalId, + ); + const { displayName: userName, emailAddress: userEmail } = + getUserNameAndMailAddress(adb2cUser); + + if (userEmail === undefined) { + throw new Error(`userEmail is null. externalId=${extarnalId}`); + } + + // プライマリ管理者を取得 + const { external_id: adminExternalId } = await this.getPrimaryAdminUser( + context, + accountId, + ); + const adb2cAdminUser = await this.adB2cService.getUser( + context, + adminExternalId, + ); + const { displayName: primaryAdminName } = + getUserNameAndMailAddress(adb2cAdminUser); + + await this.sendgridService.sendMailWithU115( + context, + userName, + userEmail, + primaryAdminName, + adminEmails, + ); + } catch (e) { + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + // メール送信に関する例外はログだけ出して握りつぶす + } } catch (e) { this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { @@ -1295,4 +1340,29 @@ export class UsersService { adminEmails: adminEmails, }; } + /** + * アカウントのプライマリ管理者を取得する + * @param context + * @param accountId + * @returns primary admin user + */ + private async getPrimaryAdminUser( + context: Context, + accountId: number, + ): Promise { + const accountInfo = await this.accountsRepository.findAccountById( + context, + accountId, + ); + if (!accountInfo || !accountInfo.primary_admin_user_id) { + throw new Error(`account or primary admin not found. id=${accountId}`); + } + + const primaryAdmin = await this.usersRepository.findUserById( + context, + accountInfo.primary_admin_user_id, + ); + + return primaryAdmin; + } } diff --git a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts index 9455248..46a7274 100644 --- a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts +++ b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts @@ -50,6 +50,8 @@ export class SendGridService { private readonly templateU112NoParentText: string; private readonly templateU114Html: string; private readonly templateU114Text: string; + private readonly templateU115Html: string; + private readonly templateU115Text: string; private readonly templateU117Html: string; private readonly templateU117Text: string; @@ -163,6 +165,14 @@ export class SendGridService { path.resolve(__dirname, `../../templates/template_U_114.txt`), 'utf-8', ); + this.templateU115Html = readFileSync( + path.resolve(__dirname, `../../templates/template_U_115.html`), + 'utf-8', + ); + this.templateU115Text = readFileSync( + path.resolve(__dirname, `../../templates/template_U_115.txt`), + 'utf-8', + ); this.templateU117Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_117.html`), @@ -766,6 +776,56 @@ export class SendGridService { } } + /** + * U-115のテンプレートを使用したメールを送信する + * @param context + * @param userName 情報更新が行われたユーザーの名前 + * @param userMail 情報更新が行われたユーザーのメールアドレス + * @param primaryAdminName 情報更新が行われたユーザーの所属するアカウントの管理者(primary)の名前 + * @param adminMails 情報更新が行われたユーザーの所属するアカウントの管理者(primary/secondary)のメールアドレス + * @returns mail with u115 + */ + async sendMailWithU115( + context: Context, + userName: string, + userMail: string, + primaryAdminName: string, + adminMails: string[], + ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.sendMailWithU115.name}`, + ); + try { + const subject = 'Edit User Notification [U-115]'; + + // メールの本文を作成する + const html = this.templateU115Html + .replaceAll(USER_NAME, userName) + .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName); + const text = this.templateU115Text + .replaceAll(USER_NAME, userName) + .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName); + + // 管理者ユーザーの情報を変更した場合にはTOに管理者のメールアドレスを設定するので、CCには管理者のメールアドレスを設定しない + const ccAdminMails = adminMails.filter((x) => x !== userMail); + + // メールを送信する + this.sendMail( + context, + [userMail], + ccAdminMails, + this.mailFrom, + subject, + text, + html, + ); + } finally { + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU115.name}`, + ); + } + } + /** * U-117のテンプレートを使用したメールを送信する * @param context diff --git a/dictation_server/src/templates/template_U_115.html b/dictation_server/src/templates/template_U_115.html new file mode 100644 index 0000000..851ff7e --- /dev/null +++ b/dictation_server/src/templates/template_U_115.html @@ -0,0 +1,53 @@ + + + Edit User Notification [U-115] + + + +
+

<English>

+

Dear $USER_NAME$,

+

+ Your user information has been edited. Please contact + $PRIMARY_ADMIN_NAME$, if you have any questions concerning your edited + user information. +

+

+ If you have received this e-mail in error, please delete this e-mail + from your system.
+ This is an automatically generated e-mail and this mailbox is not + monitored. Please do not reply. +

+
+
+

<Deutsch>

+

Sehr geehrte(r) $USER_NAME$,

+

+ Ihre Benutzerinformationen wurden bearbeitet. Bitte wenden Sie sich an + $PRIMARY_ADMIN_NAME$ wenn Sie Fragen zu Ihren bearbeiteten + Benutzerinformationen haben. +

+

+ Wenn Sie diese E-Mail fälschlicherweise erhalten haben, löschen Sie + diese E-Mail bitte aus Ihrem System.
+ Dies ist eine automatisch generierte E-Mail und dieses Postfach wird + nicht überwacht. Bitte nicht antworten. +

+
+
+

<Français>

+

Chère/Cher $USER_NAME$,

+

+ Vos informations utilisateur ont été modifiées. Veuillez contacter + $PRIMARY_ADMIN_NAME$ si vous avez des questions concernant vos + informations utilisateur modifiées. +

+

+ Si vous avez reçu cet e-mail par erreur, veuillez supprimer cet e-mail + de votre système.
+ Il s'agit d'un e-mail généré automatiquement et cette boîte aux lettres + n'est pas surveillée. Merci de ne pas répondre. +

+
+ + diff --git a/dictation_server/src/templates/template_U_115.txt b/dictation_server/src/templates/template_U_115.txt new file mode 100644 index 0000000..c0f2b51 --- /dev/null +++ b/dictation_server/src/templates/template_U_115.txt @@ -0,0 +1,26 @@ + + +Dear $USER_NAME$, + +Your user information has been edited. Please contact $PRIMARY_ADMIN_NAME$, if you have any questions concerning your edited user information. + +If you have received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail and this mailbox is not monitored. Please do not reply. + + + +Sehr geehrte(r) $USER_NAME$, + +Ihre Benutzerinformationen wurden bearbeitet. Bitte wenden Sie sich an $PRIMARY_ADMIN_NAME$ wenn Sie Fragen zu Ihren bearbeiteten Benutzerinformationen haben. + +Wenn Sie diese E-Mail fälschlicherweise erhalten haben, löschen Sie diese E-Mail bitte aus Ihrem System. +Dies ist eine automatisch generierte E-Mail und dieses Postfach wird nicht überwacht. Bitte nicht antworten. + + + +Chère/Cher $USER_NAME$, + +Vos informations utilisateur ont été modifiées. Veuillez contacter $PRIMARY_ADMIN_NAME$ si vous avez des questions concernant vos informations utilisateur modifiées. + +Si vous avez reçu cet e-mail par erreur, veuillez supprimer cet e-mail de votre système. +Il s'agit d'un e-mail généré automatiquement et cette boîte aux lettres n'est pas surveillée. Merci de ne pas répondre. \ No newline at end of file