Merged PR 594: [TODO対処] メールの内容について編集しやすくする

## 概要
[Task2163: [TODO対処] メールの内容について編集しやすくする](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2163)

- メール文面をハードコードしない構造を試作

## レビューポイント
- メールテンプレートの定義場所、定義形式、読み込み方法などは問題なさそうか

## 動作確認状況
- ローカルで確認
This commit is contained in:
湯本 開 2023-12-08 05:06:02 +00:00
parent a0da277c05
commit b1f169def5
4 changed files with 68 additions and 22 deletions

View File

@ -1,5 +1,9 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src"
"sourceRoot": "src",
"compilerOptions": {
"assets": ["templates/**/*.html", "templates/**/*.txt"],
"watchAssets": true
}
}

View File

@ -4,12 +4,17 @@ 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';
@Injectable()
export class SendGridService {
private readonly logger = new Logger(SendGridService.name);
private readonly emailConfirmLifetime: number;
private readonly appDomain: string;
private readonly templateEmailVerifyHtml: string;
private readonly templateEmailVerifyText: string;
constructor(private readonly configService: ConfigService) {
this.appDomain = this.configService.getOrThrow<string>('APP_DOMAIN');
this.emailConfirmLifetime = this.configService.getOrThrow<number>(
@ -17,6 +22,18 @@ export class SendGridService {
);
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',
);
}
}
/**
@ -39,29 +56,44 @@ export class SendGridService {
`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 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}`,
);
this.logger.log(
`[OUT] [${context.getTrackingId()}] ${
this.createMailContentFromEmailConfirm.name
}`,
);
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>`,
};
return {
subject: 'Verify your new account',
text: text,
html: html,
};
} finally {
this.logger.log(
`[OUT] [${context.getTrackingId()}] ${
this.createMailContentFromEmailConfirm.name
}`,
);
}
}
/**

View File

@ -0,0 +1,8 @@
<html>
<head>
</head>
<body>
<p>The verification URL.</p>
<a href="VERIFY_LINK">VERIFY_LINK_TEXT</a>
</body>
</html>

View File

@ -0,0 +1,2 @@
The verification URL.
VERIFY_LINK