saito.k 7160e0ee2e Merged PR 804: デグレ再発防止のため、修正をチェックするテストを作成
## 概要
[Task3830: デグレ再発防止のため、修正をチェックするテストを作成](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3830)

- タスクを100件取得できることを確認するテストを追加

## レビューポイント
- テストでかくにんする項目は足りているか

## UIの変更
- 特になし

## クエリの変更
- 特になし

## 動作確認状況
- ローカルでテストが通ることを確認

## 補足
- 相談、参考資料などがあれば
2024-03-06 01:31:10 +00:00

969 lines
32 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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}`,
);
}
}
}