## 概要 [Task3830: デグレ再発防止のため、修正をチェックするテストを作成](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3830) - タスクを100件取得できることを確認するテストを追加 ## レビューポイント - テストでかくにんする項目は足りているか ## UIの変更 - 特になし ## クエリの変更 - 特になし ## 動作確認状況 - ローカルでテストが通ることを確認 ## 補足 - 相談、参考資料などがあれば
969 lines
32 KiB
TypeScript
969 lines
32 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,
|
||
TEMPORARY_PASSWORD,
|
||
} 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 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.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.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',
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 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 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<void> {
|
||
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<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}`);
|
||
|
||
// メールを送信する
|
||
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<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}`);
|
||
|
||
// メールを送信する
|
||
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<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}`);
|
||
|
||
// メールを送信する
|
||
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<void> {
|
||
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<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}`);
|
||
|
||
// メールを送信する
|
||
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<void> {
|
||
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<void> {
|
||
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<void> {
|
||
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<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 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<void> {
|
||
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-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,
|
||
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);
|
||
|
||
// メールを送信する
|
||
await this.sendMail(
|
||
context,
|
||
[authorEmail, typistEmail].filter((x): x is string => x !== null), // authorEmailがnullの場合は除外する
|
||
[],
|
||
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}`,
|
||
);
|
||
}
|
||
}
|
||
}
|