## 概要 [Task3310: ユーザー認証完了のお願い [U-114] の実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3310) - ユーザー追加後の認証メール送信について正規のメール文面を出すようにしました。 ## レビューポイント - メールに渡す情報の取得内容で不自然な点はないでしょうか? - メール送信処理に失敗した場合には仮登録したユーザーを削除する処理をそのままにしていますが問題ないでしょうか? ## UIの変更 - なし ## 動作確認状況 - ローカルで確認
873 lines
29 KiB
TypeScript
873 lines
29 KiB
TypeScript
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,
|
||
} from '../../templates/constants';
|
||
|
||
@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 templateEmailVerifyHtml: string;
|
||
private readonly templateEmailVerifyText: string;
|
||
private readonly templateU101Html: string;
|
||
private readonly templateU101Text: 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;
|
||
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 templateU114Html: string;
|
||
private readonly templateU114Text: string;
|
||
private readonly templateU117Html: string;
|
||
private readonly templateU117Text: string;
|
||
|
||
constructor(private readonly configService: ConfigService) {
|
||
this.appDomain = this.configService.getOrThrow<string>('APP_DOMAIN');
|
||
this.mailFrom = this.configService.getOrThrow<string>('MAIL_FROM');
|
||
this.emailConfirmLifetime = this.configService.getOrThrow<number>(
|
||
'EMAIL_CONFIRM_LIFETIME',
|
||
);
|
||
const key = this.configService.getOrThrow<string>('SENDGRID_API_KEY');
|
||
sendgrid.setApiKey(key);
|
||
|
||
// メールテンプレートを読み込む
|
||
{
|
||
this.templateEmailVerifyHtml = readFileSync(
|
||
path.resolve(__dirname, `../../templates/template_email_verify.html`),
|
||
'utf-8',
|
||
);
|
||
this.templateEmailVerifyText = readFileSync(
|
||
path.resolve(__dirname, `../../templates/template_email_verify.txt`),
|
||
'utf-8',
|
||
);
|
||
|
||
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.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.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.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.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',
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Email認証用のメールコンテンツを作成する
|
||
* @param accountId 認証対象のユーザーが所属するアカウントのID
|
||
* @param userId 認証対象のユーザーのID
|
||
* @param email 認証対象のユーザーのメールアドレス
|
||
* @returns メールのサブジェクトとコンテンツ
|
||
*/
|
||
async createMailContentFromEmailConfirm(
|
||
context: Context,
|
||
accountId: number,
|
||
userId: number,
|
||
email: string,
|
||
): Promise<{ subject: string; text: string; html: string }> {
|
||
this.logger.log(
|
||
`[IN] [${context.getTrackingId()}] ${
|
||
this.createMailContentFromEmailConfirm.name
|
||
} | params: { ` +
|
||
`accountId: ${accountId},` +
|
||
`userId: ${userId} };`,
|
||
);
|
||
try {
|
||
const privateKey = getPrivateKey(this.configService);
|
||
const token = sign<{ accountId: number; userId: number; email: string }>(
|
||
{
|
||
accountId,
|
||
userId,
|
||
email,
|
||
},
|
||
this.emailConfirmLifetime,
|
||
privateKey,
|
||
);
|
||
const path = 'mail-confirm/';
|
||
|
||
const html = this.templateEmailVerifyHtml
|
||
.replace('VERIFY_LINK', `${this.appDomain}${path}?verify=${token}`)
|
||
.replace(
|
||
'VERIFY_LINK_TEXT',
|
||
`${this.appDomain}${path}?verify=${token}`,
|
||
);
|
||
const text = this.templateEmailVerifyText
|
||
.replace('VERIFY_LINK', `${this.appDomain}${path}?verify=${token}`)
|
||
.replace(
|
||
'VERIFY_LINK_TEXT',
|
||
`${this.appDomain}${path}?verify=${token}`,
|
||
);
|
||
|
||
return {
|
||
subject: 'Verify your new account',
|
||
text: text,
|
||
html: html,
|
||
};
|
||
} finally {
|
||
this.logger.log(
|
||
`[OUT] [${context.getTrackingId()}] ${
|
||
this.createMailContentFromEmailConfirm.name
|
||
}`,
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Email認証用のメールコンテンツを作成する(一般ユーザ向け)
|
||
* @param accountId 認証対象のユーザーが所属するアカウントのID
|
||
* @param userId 認証対象のユーザーのID
|
||
* @param email 認証対象のユーザーのメールアドレス
|
||
* @returns メールのサブジェクトとコンテンツ
|
||
*/
|
||
//TODO [Task2163] 中身が管理ユーザ向けのままなので、修正の必要あり
|
||
async createMailContentFromEmailConfirmForNormalUser(
|
||
context: Context,
|
||
accountId: number,
|
||
userId: number,
|
||
email: string,
|
||
): Promise<{ subject: string; text: string; html: string }> {
|
||
this.logger.log(
|
||
`[IN] [${context.getTrackingId()}] ${
|
||
this.createMailContentFromEmailConfirmForNormalUser.name
|
||
} | params: { ` +
|
||
`accountId: ${accountId},` +
|
||
`userId: ${userId} };`,
|
||
);
|
||
const privateKey = getPrivateKey(this.configService);
|
||
|
||
const token = sign<{ accountId: number; userId: number; email: string }>(
|
||
{
|
||
accountId,
|
||
userId,
|
||
email,
|
||
},
|
||
this.emailConfirmLifetime,
|
||
privateKey,
|
||
);
|
||
const path = 'mail-confirm/user/';
|
||
|
||
return {
|
||
subject: 'Verify your new account',
|
||
text: `The verification URL. ${this.appDomain}${path}?verify=${token}`,
|
||
html: `<p>The verification URL.<p><a href="${this.appDomain}${path}?verify=${token}">${this.appDomain}${path}?verify=${token}</a>`,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* U-101のテンプレートを使用したメールを送信する
|
||
* @param context
|
||
* @param customerMail アカウント登録を行った管理者ユーザーのメールアドレス
|
||
* @param customerAccountName アカウント登録した会社名
|
||
* @returns mail with u101
|
||
*/
|
||
async sendMailWithU101(
|
||
context: Context,
|
||
customerMail: string,
|
||
customerAccountName: string,
|
||
): Promise<void> {
|
||
this.logger.log(
|
||
`[IN] [${context.getTrackingId()}] ${this.sendMailWithU101.name}`,
|
||
);
|
||
try {
|
||
const subject = 'Account Registered Notification [U-101]';
|
||
const html = this.templateU101Html
|
||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||
.replaceAll(TOP_URL, this.appDomain);
|
||
const text = this.templateU101Text
|
||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||
.replaceAll(TOP_URL, this.appDomain);
|
||
|
||
await this.sendMail(
|
||
context,
|
||
[customerMail],
|
||
[],
|
||
this.mailFrom,
|
||
subject,
|
||
text,
|
||
html,
|
||
);
|
||
} finally {
|
||
this.logger.log(
|
||
`[OUT] [${context.getTrackingId()}] ${this.sendMailWithU101.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<void> {
|
||
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}`);
|
||
|
||
// メールを送信する
|
||
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<void> {
|
||
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}`);
|
||
|
||
// メールを送信する
|
||
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<void> {
|
||
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}`);
|
||
|
||
// メールを送信する
|
||
this.sendMail(
|
||
context,
|
||
customerMails,
|
||
dealerEmails,
|
||
this.mailFrom,
|
||
subject,
|
||
text,
|
||
html,
|
||
);
|
||
} finally {
|
||
this.logger.log(
|
||
`[OUT] [${context.getTrackingId()}] ${this.sendMailWithU107.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<void> {
|
||
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}`);
|
||
|
||
// メールを送信する
|
||
this.sendMail(
|
||
context,
|
||
dealerEmails,
|
||
customerMails,
|
||
this.mailFrom,
|
||
subject,
|
||
text,
|
||
html,
|
||
);
|
||
} finally {
|
||
this.logger.log(
|
||
`[OUT] [${context.getTrackingId()}] ${this.sendMailWithU109.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,
|
||
): Promise<void> {
|
||
this.logger.log(
|
||
`[IN] [${context.getTrackingId()}] ${this.sendMailWithU108.name}`,
|
||
);
|
||
try {
|
||
const subject = 'License Assigned Notification [U-108]';
|
||
|
||
// メールの本文を作成する
|
||
const html = this.templateU108Html
|
||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||
.replaceAll(DEALER_NAME, dealerAccountName)
|
||
.replaceAll(USER_NAME, userName)
|
||
.replaceAll(USER_EMAIL, userMail)
|
||
.replaceAll(TOP_URL, this.appDomain);
|
||
const text = this.templateU108Text
|
||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||
.replaceAll(DEALER_NAME, dealerAccountName)
|
||
.replaceAll(USER_NAME, userName)
|
||
.replaceAll(USER_EMAIL, userMail)
|
||
.replaceAll(TOP_URL, this.appDomain);
|
||
|
||
// メールを送信する
|
||
this.sendMail(
|
||
context,
|
||
[userMail],
|
||
customerAdminMails,
|
||
this.mailFrom,
|
||
subject,
|
||
text,
|
||
html,
|
||
);
|
||
} finally {
|
||
this.logger.log(
|
||
`[OUT] [${context.getTrackingId()}] ${this.sendMailWithU108.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<void> {
|
||
this.logger.log(
|
||
`[IN] [${context.getTrackingId()}] ${this.sendMailWithU111.name}`,
|
||
);
|
||
try {
|
||
const subject = 'Account Deleted Notification [U-111]';
|
||
|
||
// メールの本文を作成する
|
||
const html = this.templateU111Html
|
||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||
.replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName)
|
||
.replaceAll(TOP_URL, this.appDomain);
|
||
|
||
const text = this.templateU111Text
|
||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||
.replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName)
|
||
.replaceAll(TOP_URL, this.appDomain);
|
||
|
||
// メールを送信する
|
||
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<void> {
|
||
this.logger.log(
|
||
`[IN] [${context.getTrackingId()}] ${this.sendMailWithU112.name}`,
|
||
);
|
||
try {
|
||
const subject = 'Account Edit Notification [U-112]';
|
||
|
||
let html: string;
|
||
let text: string;
|
||
|
||
// 親アカウントがない場合は別のテンプレートを使用する
|
||
if (dealerAccountName === null) {
|
||
// メールの本文を作成する
|
||
html = this.templateU112NoParentHtml
|
||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||
.replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName)
|
||
.replaceAll(TOP_URL, this.appDomain);
|
||
text = this.templateU112NoParentText
|
||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||
.replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName)
|
||
.replaceAll(TOP_URL, this.appDomain);
|
||
} else {
|
||
html = this.templateU112Html
|
||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||
.replaceAll(DEALER_NAME, dealerAccountName)
|
||
.replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName)
|
||
.replaceAll(TOP_URL, this.appDomain);
|
||
text = this.templateU112Text
|
||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||
.replaceAll(DEALER_NAME, dealerAccountName)
|
||
.replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName)
|
||
.replaceAll(TOP_URL, this.appDomain);
|
||
}
|
||
|
||
// メールを送信する
|
||
this.sendMail(
|
||
context,
|
||
[primaryAdminMail],
|
||
[],
|
||
this.mailFrom,
|
||
subject,
|
||
text,
|
||
html,
|
||
);
|
||
} finally {
|
||
this.logger.log(
|
||
`[OUT] [${context.getTrackingId()}] ${this.sendMailWithU112.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<void> {
|
||
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 path = 'mail-confirm/user/';
|
||
const verifyLink = `${this.appDomain}${path}?verify=${token}`;
|
||
|
||
const subject = 'User Registration Notification [U-114]';
|
||
|
||
// メールの本文を作成する
|
||
const html = this.templateU114Html
|
||
.replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName)
|
||
.replaceAll(VERIFY_LINK, verifyLink);
|
||
const text = this.templateU114Text
|
||
.replaceAll(PRIMARY_ADMIN_NAME, primaryAdminName)
|
||
.replaceAll(VERIFY_LINK, verifyLink);
|
||
|
||
// メールを送信する
|
||
this.sendMail(
|
||
context,
|
||
[userMail],
|
||
[],
|
||
this.mailFrom,
|
||
subject,
|
||
text,
|
||
html,
|
||
);
|
||
} finally {
|
||
this.logger.log(
|
||
`[OUT] [${context.getTrackingId()}] ${this.sendMailWithU114.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,
|
||
typistEmail: string,
|
||
authorName: string,
|
||
fileName: string,
|
||
typistName: string,
|
||
adminName: string,
|
||
): Promise<void> {
|
||
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);
|
||
|
||
// メールを送信する
|
||
this.sendMail(
|
||
context,
|
||
[authorEmail, typistEmail],
|
||
[],
|
||
this.mailFrom,
|
||
subject,
|
||
text,
|
||
html,
|
||
);
|
||
} finally {
|
||
this.logger.log(
|
||
`[OUT] [${context.getTrackingId()}] ${this.sendMailWithU117.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<void> {
|
||
this.logger.log(`[IN] [${context.getTrackingId()}] ${this.sendMail.name}`);
|
||
try {
|
||
const res = await sendgrid
|
||
.send({
|
||
from: {
|
||
email: from,
|
||
},
|
||
to: to.map((v) => ({ email: v })),
|
||
cc: cc.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}`,
|
||
);
|
||
}
|
||
}
|
||
}
|