import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { sign } from '../../common/jwt'; import sendgrid from '@sendgrid/mail'; import { getPrivateKey } from '../../common/jwt/jwt'; import { Context } from '../../common/log'; import { readFileSync } from 'node:fs'; import path from 'node:path'; import { PRIMARY_ADMIN_NAME, AUTHOR_NAME, CUSTOMER_NAME, DEALER_NAME, FILE_NAME, LICENSE_QUANTITY, PO_NUMBER, TOP_URL, USER_EMAIL, USER_NAME, TYPIST_NAME, VERIFY_LINK, TEMPORARY_PASSWORD, EMAIL_DUPLICATION_EN, AUTHOR_ID_DUPLICATION_EN, UNEXPECTED_ERROR_EN, EMAIL_DUPLICATION_DE, AUTHOR_ID_DUPLICATION_DE, UNEXPECTED_ERROR_DE, EMAIL_DUPLICATION_FR, AUTHOR_ID_DUPLICATION_FR, UNEXPECTED_ERROR_FR, REQUEST_TIME, NO_ERROR_MESSAGE_EN, NO_ERROR_MESSAGE_DE, NO_ERROR_MESSAGE_FR, } from '../../templates/constants'; import { URL } from 'node:url'; @Injectable() export class SendGridService { private readonly logger = new Logger(SendGridService.name); private readonly emailConfirmLifetime: number; private readonly appDomain: string; private readonly mailFrom: string; private readonly templateU101Html: string; private readonly templateU101Text: string; private readonly templateU102Html: string; private readonly templateU102Text: string; private readonly templateU105Html: string; private readonly templateU105Text: string; private readonly templateU106Html: string; private readonly templateU106Text: string; private readonly templateU107Html: string; private readonly templateU107Text: string; private readonly templateU108Html: string; private readonly templateU108Text: string; // U-108のテンプレート差分(親アカウントがない場合) private readonly templateU108NoParentHtml: string; private readonly templateU108NoParentText: string; private readonly templateU109Html: string; private readonly templateU109Text: string; private readonly templateU111Html: string; private readonly templateU111Text: string; private readonly templateU112Html: string; private readonly templateU112Text: string; // U-112のテンプレート差分(親アカウントがない場合) private readonly templateU112NoParentHtml: string; private readonly templateU112NoParentText: string; private readonly templateU113Html: string; private readonly templateU113Text: string; private readonly templateU114Html: string; private readonly templateU114Text: string; private readonly templateU115Html: string; private readonly templateU115Text: string; private readonly templateU116Html: string; private readonly templateU116Text: string; private readonly templateU117Html: string; private readonly templateU117Text: string; private readonly templateU118Html: string; private readonly templateU118Text: string; private readonly templateU118NoParentHtml: string; private readonly templateU118NoParentText: string; private readonly templateU119Html: string; private readonly templateU119Text: string; private readonly templateU119NoParentHtml: string; private readonly templateU119NoParentText: string; private readonly templateU120Html: string; private readonly templateU120Text: string; private readonly templateU120NoParentHtml: string; private readonly templateU120NoParentText: string; private readonly templateU121Html: string; private readonly templateU121Text: string; private readonly templateU121NoParentHtml: string; private readonly templateU121NoParentText: string; private readonly templateU122Html: string; private readonly templateU122Text: string; private readonly templateU122NoParentHtml: string; private readonly templateU122NoParentText: string; private readonly templateU123Html: string; private readonly templateU123Text: string; private readonly templateU124Html: string; private readonly templateU124Text: string; constructor(private readonly configService: ConfigService) { this.appDomain = this.configService.getOrThrow('APP_DOMAIN'); this.mailFrom = this.configService.getOrThrow('MAIL_FROM'); this.emailConfirmLifetime = this.configService.getOrThrow( 'EMAIL_CONFIRM_LIFETIME', ); const key = this.configService.getOrThrow('SENDGRID_API_KEY'); sendgrid.setApiKey(key); // メールテンプレートを読み込む { this.templateU101Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_101.html`), 'utf-8', ); this.templateU101Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_101.txt`), 'utf-8', ); this.templateU102Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_102.html`), 'utf-8', ); this.templateU102Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_102.txt`), 'utf-8', ); this.templateU105Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_105.html`), 'utf-8', ); this.templateU105Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_105.txt`), 'utf-8', ); this.templateU106Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_106.html`), 'utf-8', ); this.templateU106Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_106.txt`), 'utf-8', ); this.templateU107Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_107.html`), 'utf-8', ); this.templateU107Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_107.txt`), 'utf-8', ); this.templateU108Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_108.html`), 'utf-8', ); this.templateU108Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_108.txt`), 'utf-8', ); this.templateU108NoParentHtml = readFileSync( path.resolve( __dirname, `../../templates/template_U_108_no_parent.html`, ), 'utf-8', ); this.templateU108NoParentText = readFileSync( path.resolve(__dirname, `../../templates/template_U_108_no_parent.txt`), 'utf-8', ); this.templateU109Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_109.html`), 'utf-8', ); this.templateU109Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_109.txt`), 'utf-8', ); this.templateU111Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_111.html`), 'utf-8', ); this.templateU111Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_111.txt`), 'utf-8', ); this.templateU112Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_112.html`), 'utf-8', ); this.templateU112Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_112.txt`), 'utf-8', ); this.templateU112NoParentHtml = readFileSync( path.resolve( __dirname, `../../templates/template_U_112_no_parent.html`, ), 'utf-8', ); this.templateU112NoParentText = readFileSync( path.resolve(__dirname, `../../templates/template_U_112_no_parent.txt`), 'utf-8', ); this.templateU113Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_113.html`), 'utf-8', ); this.templateU113Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_113.txt`), 'utf-8', ); this.templateU114Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_114.html`), 'utf-8', ); this.templateU114Text = readFileSync( 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.templateU116Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_116.html`), 'utf-8', ); this.templateU116Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_116.txt`), 'utf-8', ); this.templateU117Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_117.html`), 'utf-8', ); this.templateU117Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_117.txt`), 'utf-8', ); this.templateU118Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_118.html`), 'utf-8', ); this.templateU118Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_118.txt`), 'utf-8', ); this.templateU118NoParentHtml = readFileSync( path.resolve( __dirname, `../../templates/template_U_118_no_parent.html`, ), 'utf-8', ); this.templateU118NoParentText = readFileSync( path.resolve(__dirname, `../../templates/template_U_118_no_parent.txt`), 'utf-8', ); this.templateU119Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_119.html`), 'utf-8', ); this.templateU119Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_119.txt`), 'utf-8', ); this.templateU119NoParentHtml = readFileSync( path.resolve( __dirname, `../../templates/template_U_119_no_parent.html`, ), 'utf-8', ); this.templateU119NoParentText = readFileSync( path.resolve(__dirname, `../../templates/template_U_119_no_parent.txt`), 'utf-8', ); this.templateU120Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_120.html`), 'utf-8', ); this.templateU120Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_120.txt`), 'utf-8', ); this.templateU120NoParentHtml = readFileSync( path.resolve( __dirname, `../../templates/template_U_120_no_parent.html`, ), 'utf-8', ); this.templateU120NoParentText = readFileSync( path.resolve(__dirname, `../../templates/template_U_120_no_parent.txt`), 'utf-8', ); this.templateU121Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_121.html`), 'utf-8', ); this.templateU121Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_121.txt`), 'utf-8', ); this.templateU121NoParentHtml = readFileSync( path.resolve( __dirname, `../../templates/template_U_121_no_parent.html`, ), 'utf-8', ); this.templateU121NoParentText = readFileSync( path.resolve(__dirname, `../../templates/template_U_121_no_parent.txt`), 'utf-8', ); this.templateU122Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_122.html`), 'utf-8', ); this.templateU122Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_122.txt`), 'utf-8', ); this.templateU122NoParentHtml = readFileSync( path.resolve( __dirname, `../../templates/template_U_122_no_parent.html`, ), 'utf-8', ); this.templateU122NoParentText = readFileSync( path.resolve(__dirname, `../../templates/template_U_122_no_parent.txt`), 'utf-8', ); this.templateU123Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_123.html`), 'utf-8', ); this.templateU123Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_123.txt`), 'utf-8', ); this.templateU124Html = readFileSync( path.resolve(__dirname, `../../templates/template_U_124.html`), 'utf-8', ); this.templateU124Text = readFileSync( path.resolve(__dirname, `../../templates/template_U_124.txt`), 'utf-8', ); } } /** * U-101のテンプレートを使用したメールを送信する * @param context * @param customerMail アカウント登録を行った管理者ユーザーのメールアドレス * @param customerAccountName アカウント登録した会社名 * @returns mail with u101 */ async sendMailWithU101( context: Context, customerMail: string, customerAccountName: string, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU101.name}`, ); try { const subject = 'Account Registered Notification [U-101]'; const url = new URL(this.appDomain).href; const html = this.templateU101Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(TOP_URL, url); const text = this.templateU101Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(TOP_URL, url); await this.sendMail( context, [customerMail], [], this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU101.name}`, ); } } /** * U-102のテンプレートを使用したメールを送信する * @param context * @param adminEmail 登録したアカウントの管理者(primary)のメールアドレス * @param accountId 登録したアカウントのID * @param userId 登録したユーザーのID * @returns mail with u102 */ async sendMailWithU102( context: Context, adminEmail: string, accountId: number, userId: number, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU102.name}`, ); try { const privateKey = getPrivateKey(this.configService); const token = sign<{ accountId: number; userId: number; email: string }>( { accountId, userId, email: adminEmail, }, this.emailConfirmLifetime, privateKey, ); const paths = path.join('mail-confirm'); const url = new URL(paths, this.appDomain).href; const verifyUrl = `${url}?verify=${token}`; const subject = 'User Registration Notification [U-102]'; const html = this.templateU102Html.replaceAll(VERIFY_LINK, verifyUrl); const text = this.templateU102Text.replaceAll(VERIFY_LINK, verifyUrl); await this.sendMail( context, [adminEmail], [], this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU102.name}`, ); } } /** * U-105のテンプレートを使用したメールを送信する * @param context * @param customerMails 注文を行ったアカウントの管理者(primary/secondary)のメールアドレス * @param customerAccountName 送信対象の企業名 * @param lisenceCount 注文を行った対象の注文の内容(ライセンス数) * @param poNumber 注文を行った対象の注文の内容(PO番号) * @param dealerEmails 問題発生時に問い合わせする先の上位のディーラーの管理者(primary/secondary)のメールアドレス * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) * @returns mail with u105 */ async sendMailWithU105( context: Context, customerMails: string[], customerAccountName: string, lisenceCount: number, poNumber: string, dealerEmails: string[], dealerAccountName: string, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU105.name}`, ); try { const subject = 'License Requested Notification [U-105]'; // メールの本文を作成する const html = this.templateU105Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(PO_NUMBER, poNumber) .replaceAll(LICENSE_QUANTITY, `${lisenceCount}`); const text = this.templateU105Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(PO_NUMBER, poNumber) .replaceAll(LICENSE_QUANTITY, `${lisenceCount}`); // メールを送信する await this.sendMail( context, customerMails, dealerEmails, this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU105.name}`, ); } } /** * U-106のテンプレートを使用したメールを送信する * @param context * @param cancelUserEmailAddress 注文キャンセルを行ったアカウントの管理者(primary/secondary)のメールアドレス * @param customerAccountName 送信対象の企業名 * @param lisenceCount 注文キャンセルを行った対象の注文の内容(ライセンス数) * @param poNumber 注文キャンセルを行った対象の注文の内容(PO番号) * @param dealerEmails 問題発生時に問い合わせする先の上位のディーラーの管理者(primary/secondary)のメールアドレス * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) * @returns mail with u106 */ async sendMailWithU106( context: Context, customerMails: string[], customerAccountName: string, lisenceCount: number, poNumber: string, dealerEmails: string[], dealerAccountName: string, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU106.name}`, ); try { const subject = 'Cancelled License Order Notification [U-106]'; // メールの本文を作成する const html = this.templateU106Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(PO_NUMBER, poNumber) .replaceAll(LICENSE_QUANTITY, `${lisenceCount}`); const text = this.templateU106Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(PO_NUMBER, poNumber) .replaceAll(LICENSE_QUANTITY, `${lisenceCount}`); // メールを送信する await this.sendMail( context, customerMails, dealerEmails, this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU106.name}`, ); } } /** * U-107のテンプレートを使用したメールを送信する * @param context * @param cancelUserEmailAddress ライセンス発行をされたアカウントの管理者(primary/secondary)のメールアドレス * @param customerAccountName 送信対象の企業名 * @param lisenceCount ライセンス発行を行った対象の注文の内容(ライセンス数) * @param poNumber ライセンス発行を行った対象の注文の内容(PO番号) * @param dealerEmails 問題発生時に問い合わせする先の上位のディーラーの管理者(primary/secondary)のメールアドレス * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) * @returns mail with u107 */ async sendMailWithU107( context: Context, customerMails: string[], customerAccountName: string, lisenceCount: number, poNumber: string, dealerEmails: string[], dealerAccountName: string, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU107.name}`, ); try { const subject = 'License Issued Notification [U-107]'; // メールの本文を作成する const html = this.templateU107Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(PO_NUMBER, poNumber) .replaceAll(LICENSE_QUANTITY, `${lisenceCount}`); const text = this.templateU107Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(PO_NUMBER, poNumber) .replaceAll(LICENSE_QUANTITY, `${lisenceCount}`); // メールを送信する await this.sendMail( context, customerMails, dealerEmails, this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU107.name}`, ); } } /** * U-108のテンプレートを使用したメールを送信する * @param context * @param userName ライセンス割り当てされたユーザーの名前 * @param userMail ライセンス割り当てされたユーザーのメールアドレス * @param customerAdminMails ライセンス割り当てされたユーザーの所属するアカウントの管理者(primary/secondary)のメールアドレス * @param customerAccountName ライセンス割り当てされたユーザーの所属するアカウントの名前 * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) * @returns mail with u108 */ async sendMailWithU108( context: Context, userName: string, userMail: string, customerAdminMails: string[], customerAccountName: string, dealerAccountName: string | null, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU108.name}`, ); try { const subject = 'License Assigned Notification [U-108]'; const url = new URL(this.appDomain).href; let html: string; let text: string; if (dealerAccountName === null) { html = this.templateU108NoParentHtml .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(USER_NAME, userName) .replaceAll(USER_EMAIL, userMail) .replaceAll(TOP_URL, url); text = this.templateU108NoParentText .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(USER_NAME, userName) .replaceAll(USER_EMAIL, userMail) .replaceAll(TOP_URL, url); } else { html = this.templateU108Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(USER_NAME, userName) .replaceAll(USER_EMAIL, userMail) .replaceAll(TOP_URL, url); text = this.templateU108Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(USER_NAME, userName) .replaceAll(USER_EMAIL, userMail) .replaceAll(TOP_URL, url); } const ccAddress = customerAdminMails.includes(userMail) ? [] : [userMail]; // メールを送信する await this.sendMail( context, customerAdminMails, ccAddress, this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU108.name}`, ); } } /** * U-109のテンプレートを使用したメールを送信する * @param context context * @param dealerEmails ライセンス発行をキャンセルした上位アカウントの管理者(primary/secondary)のメールアドレス * @param dealerAccountName ライセンス発行をキャンセルした上位アカウントの会社名 * @param lisenceCount ライセンス発行をキャンセルした対象の注文の内容(ライセンス数) * @param poNumber ライセンス発行をキャンセルした対象の注文の内容(PO番号) * @param customerMails ライセンス発行をキャンセルされたアカウントの管理者(primary/secondary)のメールアドレス * @param customerAccountName ライセンス発行をキャンセルされたアカウントの会社名 * @returns */ async sendMailWithU109( context: Context, dealerEmails: string[], dealerAccountName: string, lisenceCount: number, poNumber: string, customerMails: string[], customerAccountName: string, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU109.name}`, ); try { const subject = 'License Returned Notification [U-109]'; // メールの本文を作成する const html = this.templateU109Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(PO_NUMBER, poNumber) .replaceAll(LICENSE_QUANTITY, `${lisenceCount}`); const text = this.templateU109Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(PO_NUMBER, poNumber) .replaceAll(LICENSE_QUANTITY, `${lisenceCount}`); // メールを送信する await this.sendMail( context, dealerEmails, customerMails, this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU109.name}`, ); } } /** * U-111のテンプレートを使用したメールを送信する * @param context * @param primaryAdminName 削除されたアカウントの管理者(primary)の名前 * @param primaryAdminMail 削除されたアカウントの管理者(primary)のメールアドレス * @param customerAccountName 削除されたアカウントの会社名 * @returns mail with u111 */ async sendMailWithU111( context: Context, primaryAdminName: string, primaryAdminMail: string, customerAccountName: string, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU111.name}`, ); try { const subject = 'Account Deleted Notification [U-111]'; const url = new URL(this.appDomain).href; // メールの本文を作成する const html = this.templateU111Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName) .replaceAll(TOP_URL, url); const text = this.templateU111Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName) .replaceAll(TOP_URL, url); // メールを送信する await this.sendMail( context, [primaryAdminMail], [], this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU111.name}`, ); } } /** * U-112のテンプレートを使用したメールを送信する * @param context * @param primaryAdminName 情報変更を行ったアカウントの管理者(primary)の名前 * @param primaryAdminMail 情報変更を行ったアカウントの管理者(primary)のメールアドレス * @param customerAccountName 情報変更を行ったアカウントの名前 * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) * @returns mail with u112 */ async sendMailWithU112( context: Context, primaryAdminName: string, primaryAdminMail: string, customerAccountName: string, dealerAccountName: string | null, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU112.name}`, ); try { const subject = 'Account Edit Notification [U-112]'; let html: string; let text: string; const url = new URL(this.appDomain).href; // 親アカウントがない場合は別のテンプレートを使用する if (dealerAccountName === null) { // メールの本文を作成する html = this.templateU112NoParentHtml .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName) .replaceAll(TOP_URL, url); text = this.templateU112NoParentText .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName) .replaceAll(TOP_URL, url); } else { html = this.templateU112Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName) .replaceAll(TOP_URL, url); text = this.templateU112Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName) .replaceAll(TOP_URL, url); } // メールを送信する await this.sendMail( context, [primaryAdminMail], [], this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU112.name}`, ); } } /** * U-113のテンプレートを使用したメールを送信する * @param context * @param userMail 認証済みユーザーのメールアドレス * @param primaryAdminName 認証済みユーザーが所属するアカウントの管理者(primary)の名前 * @param temporaryPassword 認証済みユーザーの一時パスワード * @returns mail with u113 */ async sendMailWithU113( context: Context, userMail: string, primaryAdminName: string, temporaryPassword: string, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU113.name}`, ); try { const subject = 'Temporary password [U-113]'; // メールの本文を作成する const html = this.templateU113Html .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName) .replaceAll(TEMPORARY_PASSWORD, temporaryPassword); const text = this.templateU113Text .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName) .replaceAll(TEMPORARY_PASSWORD, temporaryPassword); // メールを送信する await this.sendMail( context, [userMail], [], this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU113.name}`, ); } } /** * U-114のテンプレートを使用したメールを送信する * @param context * @param accountId 認証対象のユーザーが所属するアカウントのID * @param userId 認証対象のユーザーのID * @param userMail 認証対象のユーザーのメールアドレス * @param primaryAdminName 認証対象のユーザーが所属するアカウントの管理者(primary)の名前 * @returns mail with u114 */ async sendMailWithU114( context: Context, accountId: number, userId: number, userMail: string, primaryAdminName: string, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU114.name}`, ); try { // ユーザー認証用のトークンを作成する const privateKey = getPrivateKey(this.configService); const token = sign<{ accountId: number; userId: number; email: string }>( { accountId, userId, email: userMail, }, this.emailConfirmLifetime, privateKey, ); const paths = path.join('mail-confirm', '/user'); const url = new URL(paths, this.appDomain); const verifyUrl = `${url}?verify=${token}`; const subject = 'User Registration Notification [U-114]'; // メールの本文を作成する const html = this.templateU114Html .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName) .replaceAll(VERIFY_LINK, verifyUrl); const text = this.templateU114Text .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName) .replaceAll(VERIFY_LINK, verifyUrl); // メールを送信する await this.sendMail( context, [userMail], [], this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU114.name}`, ); } } /** * 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); // メールを送信する await this.sendMail( context, [userMail], ccAdminMails, this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU115.name}`, ); } } /** * U-116のテンプレートを使用したメールを送信する * @param context * @param userName 削除されたユーザーの名前 * @param userMail 削除されたユーザーのメールアドレス * @param primaryAdminName 削除されたユーザーの所属するアカウントの管理者(primary)の名前 * @param adminMails 削除されたユーザーの所属するアカウントの管理者(primary/secondary)のメールアドレス * @returns mail with u116 */ async sendMailWithU116( context: Context, userName: string, userMail: string, primaryAdminName: string, adminMails: string[], ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU116.name}`, ); try { const subject = 'User Deleted Notification [U-116]'; // メールの本文を作成する const html = this.templateU116Html .replaceAll(USER_NAME, userName) .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName); const text = this.templateU116Text .replaceAll(USER_NAME, userName) .replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName); // メールを送信する await this.sendMail( context, [userMail], adminMails, this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU116.name}`, ); } } /** * U-117のテンプレートを使用したメールを送信する * @param context * @param authorEmail 文字起こしファイルのAuthorのメールアドレス * @param typistEmail 文字起こしを行ったTypistのメールアドレス * @param authorName 文字起こしファイルのAuthorの名前 * @param fileName 文字起こしファイルのファイル名 * @param typistName 文字起こしを行ったTypistの名前 * @param adminName アカウント管理者の名前(プライマリ) * @returns mail with u117 */ async sendMailWithU117( context: Context, authorEmail: string | null, authorName: string, fileName: string, typistName: string, adminName: string, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU117.name}`, ); try { const subject = 'Transcription Completion Notification [U-117]'; // メールの本文を作成する const html = this.templateU117Html .replaceAll(AUTHOR_NAME, authorName) .replaceAll(FILE_NAME, fileName) .replaceAll(TYPIST_NAME, typistName) .replaceAll(PRIMARY_ADMIN_NAME, adminName); const text = this.templateU117Text .replaceAll(AUTHOR_NAME, authorName) .replaceAll(FILE_NAME, fileName) .replaceAll(TYPIST_NAME, typistName) .replaceAll(PRIMARY_ADMIN_NAME, adminName); // OMDS_IS-380 Dictation Workflow完了通知 [U-117]  をTypistには送信しないようにしたいの対応のため送信先からtypistEmailを削除 2024年8月7日 const to = [authorEmail].filter((x): x is string => x !== null); if (to.length === 0) { this.logger.log('There is no email recipient.'); return; } // メールを送信する await this.sendMail(context, to, [], this.mailFrom, subject, text, html); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU117.name}`, ); } } /** * U-118のテンプレートを使用したメールを送信する * @param context * @param customerAdminMails アカウントの管理者(primary/secondary)のメールアドレス * @param customerAccountName アカウントの名前 * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) * @returns mail with u118 */ async sendMailWithU118( context: Context, customerAdminMails: string[], customerAccountName: string, dealerAccountName: string | null, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU118.name}`, ); try { const subject = 'Storage Usage Worning Notification [U-118]'; let html: string; let text: string; if (!dealerAccountName) { html = this.templateU118NoParentHtml.replaceAll( CUSTOMER_NAME, customerAccountName, ); text = this.templateU118NoParentText.replaceAll( CUSTOMER_NAME, customerAccountName, ); } else { html = this.templateU118Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName); text = this.templateU118Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName); } // メールを送信する await this.sendMail( context, customerAdminMails, [], this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU118.name}`, ); } } /** * U-119のテンプレートを使用したメールを送信する * @param context * @param customerAdminMails アカウントの管理者(primary/secondary)のメールアドレス * @param customerAccountName アカウントの名前 * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) * @param tire1AdminMails 第一階層の管理者(primary/secondary)のメールアドレス * @returns mail with u119 */ async sendMailWithU119( context: Context, customerAdminMails: string[], customerAccountName: string, dealerAccountName: string | null, tire1AdminMails: string[], ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU119.name}`, ); try { const subject = 'Storage Usage Exceeded Notification [U-119]'; let html: string; let text: string; if (!dealerAccountName) { html = this.templateU119NoParentHtml.replaceAll( CUSTOMER_NAME, customerAccountName, ); text = this.templateU119NoParentText.replaceAll( CUSTOMER_NAME, customerAccountName, ); } else { html = this.templateU119Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName); text = this.templateU119Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName); } // メールを送信する await this.sendMail( context, customerAdminMails, tire1AdminMails, this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU119.name}`, ); } } /** * U-120のテンプレートを使用したメールを送信する * @param context * @param customerAdminMails アカウントの管理者(primary/secondary)のメールアドレス * @param customerAccountName アカウントの名前 * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) * @param tire1AdminMails 第一階層の管理者(primary/secondary)のメールアドレス * @returns mail with u119 */ async sendMailWithU120( context: Context, customerAdminMails: string[], customerAccountName: string, dealerAccountName: string | null, requestTime: string, fileName: string, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU120.name}`, ); try { const subject = 'User Bulk Registration Received Notification [U-120]'; let html: string; let text: string; console.log(dealerAccountName); if (!dealerAccountName) { html = this.templateU120NoParentHtml .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(REQUEST_TIME, requestTime) .replaceAll(FILE_NAME, fileName); text = this.templateU120NoParentText .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(REQUEST_TIME, requestTime) .replaceAll(FILE_NAME, fileName); } else { html = this.templateU120Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(REQUEST_TIME, requestTime) .replaceAll(FILE_NAME, fileName); text = this.templateU120Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(REQUEST_TIME, requestTime) .replaceAll(FILE_NAME, fileName); } // メールを送信する await this.sendMail( context, customerAdminMails, [], this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU120.name}`, ); } } /** * U-121のテンプレートを使用したメールを送信する * @param context * @param customerAdminMails アカウントの管理者(primary/secondary)のメールアドレス * @param customerAccountName アカウントの名前 * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) * @param requestTime ユーザー一括登録のリクエストを受け付けた日時 * @param fileName ユーザー一括登録で使用されたファイル名 * @returns mail with u121 */ async sendMailWithU121( context: Context, customerAdminMails: string[], customerAccountName: string, dealerAccountName: string | null, requestTime: string, fileName: string, ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU121.name}`, ); try { const subject = 'User Bulk Registration Completed Notification [U-121]'; let html: string; let text: string; if (!dealerAccountName) { html = this.templateU121NoParentHtml .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(REQUEST_TIME, requestTime) .replaceAll(FILE_NAME, fileName); text = this.templateU121NoParentText .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(REQUEST_TIME, requestTime) .replaceAll(FILE_NAME, fileName); } else { html = this.templateU121Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(REQUEST_TIME, requestTime) .replaceAll(FILE_NAME, fileName); text = this.templateU121Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(REQUEST_TIME, requestTime) .replaceAll(FILE_NAME, fileName); } // メールを送信する await this.sendMail( context, customerAdminMails, [], this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU121.name}`, ); } } /** * U-122のテンプレートを使用したメールを送信する * @param context * @param customerAdminMails アカウントの管理者(primary/secondary)のメールアドレス * @param customerAccountName アカウントの名前 * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) * @param duplicateEmails メールアドレスの重複エラーのある行番号 * @param duplicateAuthorIds AuthorIdの重複エラーのある行番号 * @param otherErrors その他のエラーのある行番号 * @returns mail with u122 */ async sendMailWithU122( context: Context, customerAdminMails: string[], customerAccountName: string, dealerAccountName: string | null, duplicateEmails: number[], duplicateAuthorIds: number[], otherErrors: number[], ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU122.name}`, ); try { let duplicateEmailsMsgEn = NO_ERROR_MESSAGE_EN; let duplicateAuthorIdsMsgEn = NO_ERROR_MESSAGE_EN; let otherErrorsMsgEn = NO_ERROR_MESSAGE_EN; let duplicateEmailsMsgDe = NO_ERROR_MESSAGE_DE; let duplicateAuthorIdsMsgDe = NO_ERROR_MESSAGE_DE; let otherErrorsMsgDe = NO_ERROR_MESSAGE_DE; let duplicateEmailsMsgFr = NO_ERROR_MESSAGE_FR; let duplicateAuthorIdsMsgFr = NO_ERROR_MESSAGE_FR; let otherErrorsMsgFr = NO_ERROR_MESSAGE_FR; if (duplicateEmails.length !== 0) { duplicateEmailsMsgEn = duplicateEmails.map((x) => `L${x}`).join(', '); duplicateEmailsMsgDe = duplicateEmails.map((x) => `L${x}`).join(', '); duplicateEmailsMsgFr = duplicateEmails.map((x) => `L${x}`).join(', '); } if (duplicateAuthorIds.length !== 0) { duplicateAuthorIdsMsgEn = duplicateAuthorIds .map((x) => `L${x}`) .join(', '); duplicateAuthorIdsMsgDe = duplicateAuthorIds .map((x) => `L${x}`) .join(', '); duplicateAuthorIdsMsgFr = duplicateAuthorIds .map((x) => `L${x}`) .join(', '); } if (otherErrors.length !== 0) { otherErrorsMsgEn = otherErrors.map((x) => `L${x}`).join(', '); otherErrorsMsgDe = otherErrors.map((x) => `L${x}`).join(', '); otherErrorsMsgFr = otherErrors.map((x) => `L${x}`).join(', '); } const subject = 'User Bulk Registration Failed Notification [U-122]'; let html: string; let text: string; if (!dealerAccountName) { html = this.templateU122NoParentHtml .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(EMAIL_DUPLICATION_EN, duplicateEmailsMsgEn) .replaceAll(EMAIL_DUPLICATION_DE, duplicateEmailsMsgDe) .replaceAll(EMAIL_DUPLICATION_FR, duplicateEmailsMsgFr) .replaceAll(AUTHOR_ID_DUPLICATION_EN, duplicateAuthorIdsMsgEn) .replaceAll(AUTHOR_ID_DUPLICATION_DE, duplicateAuthorIdsMsgDe) .replaceAll(AUTHOR_ID_DUPLICATION_FR, duplicateAuthorIdsMsgFr) .replaceAll(UNEXPECTED_ERROR_EN, otherErrorsMsgEn) .replaceAll(UNEXPECTED_ERROR_DE, otherErrorsMsgDe) .replaceAll(UNEXPECTED_ERROR_FR, otherErrorsMsgFr); text = this.templateU122NoParentText .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(EMAIL_DUPLICATION_EN, duplicateEmailsMsgEn) .replaceAll(EMAIL_DUPLICATION_DE, duplicateEmailsMsgDe) .replaceAll(EMAIL_DUPLICATION_FR, duplicateEmailsMsgFr) .replaceAll(AUTHOR_ID_DUPLICATION_EN, duplicateAuthorIdsMsgEn) .replaceAll(AUTHOR_ID_DUPLICATION_DE, duplicateAuthorIdsMsgDe) .replaceAll(AUTHOR_ID_DUPLICATION_FR, duplicateAuthorIdsMsgFr) .replaceAll(UNEXPECTED_ERROR_EN, otherErrorsMsgEn) .replaceAll(UNEXPECTED_ERROR_DE, otherErrorsMsgDe) .replaceAll(UNEXPECTED_ERROR_FR, otherErrorsMsgFr); } else { html = this.templateU122Html .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(EMAIL_DUPLICATION_EN, duplicateEmailsMsgEn) .replaceAll(EMAIL_DUPLICATION_DE, duplicateEmailsMsgDe) .replaceAll(EMAIL_DUPLICATION_FR, duplicateEmailsMsgFr) .replaceAll(AUTHOR_ID_DUPLICATION_EN, duplicateAuthorIdsMsgEn) .replaceAll(AUTHOR_ID_DUPLICATION_DE, duplicateAuthorIdsMsgDe) .replaceAll(AUTHOR_ID_DUPLICATION_FR, duplicateAuthorIdsMsgFr) .replaceAll(UNEXPECTED_ERROR_EN, otherErrorsMsgEn) .replaceAll(UNEXPECTED_ERROR_DE, otherErrorsMsgDe) .replaceAll(UNEXPECTED_ERROR_FR, otherErrorsMsgFr); text = this.templateU122Text .replaceAll(CUSTOMER_NAME, customerAccountName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(EMAIL_DUPLICATION_EN, duplicateEmailsMsgEn) .replaceAll(EMAIL_DUPLICATION_DE, duplicateEmailsMsgDe) .replaceAll(EMAIL_DUPLICATION_FR, duplicateEmailsMsgFr) .replaceAll(AUTHOR_ID_DUPLICATION_EN, duplicateAuthorIdsMsgEn) .replaceAll(AUTHOR_ID_DUPLICATION_DE, duplicateAuthorIdsMsgDe) .replaceAll(AUTHOR_ID_DUPLICATION_FR, duplicateAuthorIdsMsgFr) .replaceAll(UNEXPECTED_ERROR_EN, otherErrorsMsgEn) .replaceAll(UNEXPECTED_ERROR_DE, otherErrorsMsgDe) .replaceAll(UNEXPECTED_ERROR_FR, otherErrorsMsgFr); } // メールを送信する await this.sendMail( context, customerAdminMails, [], this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU122.name}`, ); } } /** * U-123のテンプレートを使用したメールを送信する * @param context * @param partnerAccountName * @param partnerPrimaryName * @param partnerPrimaryMail * @param dealerAccountName * @param dealerEmails * @returns mail with u123 */ async sendMailWithU123( context: Context, partnerAccountName: string, partnerPrimaryName: string, partnerPrimaryMail: string, dealerAccountName: string, dealerEmails: string[], ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU123.name}`, ); try { const subject = 'Partner Account Deleted Notification [U-123]'; const html = this.templateU123Html .replaceAll(CUSTOMER_NAME, partnerAccountName) .replaceAll(PRIMARY_ADMIN_NAME, partnerPrimaryName) .replaceAll(DEALER_NAME, dealerAccountName); const text = this.templateU123Text .replaceAll(CUSTOMER_NAME, partnerAccountName) .replaceAll(PRIMARY_ADMIN_NAME, partnerPrimaryName) .replaceAll(DEALER_NAME, dealerAccountName); // メールを送信する await this.sendMail( context, [partnerPrimaryMail], dealerEmails, this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU123.name}`, ); } } /** * U-124のテンプレートを使用したメールを送信する * @param context * @param partnerAccountName * @param partnerPrimaryName * @param partnerPrimaryMail * @param dealerAccountName * @param dealerEmails * @returns mail with u124 */ async sendMailWithU124( context: Context, partnerAccountName: string, partnerPrimaryName: string, partnerPrimaryMail: string, dealerAccountName: string, dealerEmails: string[], ): Promise { this.logger.log( `[IN] [${context.getTrackingId()}] ${this.sendMailWithU124.name}`, ); try { const subject = 'Partner Account Edit Notification [U-124]'; const url = new URL(this.appDomain).href; const html = this.templateU124Html .replaceAll(CUSTOMER_NAME, partnerAccountName) .replaceAll(PRIMARY_ADMIN_NAME, partnerPrimaryName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(TOP_URL, url); const text = this.templateU124Text .replaceAll(CUSTOMER_NAME, partnerAccountName) .replaceAll(PRIMARY_ADMIN_NAME, partnerPrimaryName) .replaceAll(DEALER_NAME, dealerAccountName) .replaceAll(TOP_URL, url); // メールを送信する await this.sendMail( context, [partnerPrimaryMail], dealerEmails, this.mailFrom, subject, text, html, ); } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU124.name}`, ); } } /** * メールを送信する * @param context * @param to * @param cc * @param from * @param subject * @param text * @param html * @returns mail */ async sendMail( context: Context, to: string[], cc: string[], from: string, subject: string, text: string, html: string, ): Promise { this.logger.log(`[IN] [${context.getTrackingId()}] ${this.sendMail.name}`); try { // toの重複を削除 const uniqueTo = [...new Set(to)]; // ccの重複を削除 let uniqueCc = [...new Set(cc)]; // toとccの重複を削除(cc側から削除) uniqueCc = uniqueCc.filter((email) => !uniqueTo.includes(email)); const res = await sendgrid .send({ from: { email: from, }, to: uniqueTo.map((v) => ({ email: v })), cc: uniqueCc.map((v) => ({ email: v })), subject: subject, text: text, html: html, }) .then((v) => v[0]); this.logger.log( `[${context.getTrackingId()}] status code: ${ res.statusCode } body: ${JSON.stringify(res.body)}`, ); } catch (e) { this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { this.logger.log( `[OUT] [${context.getTrackingId()}] ${this.sendMail.name}`, ); } } }