summaryrefslogtreecommitdiff
path: root/packages/backend/src/core/EmailService.ts
diff options
context:
space:
mode:
authorNafu Satsuki <satsuki@nafusoft.dev>2023-11-18 20:39:48 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-11-18 21:01:53 +0900
commit0a73973a7c6e6e95a5206bfc5388ff7f7a9ba8ed (patch)
tree49c87fecae96da7193c8eb253f3cfc9692dbae7e /packages/backend/src/core/EmailService.ts
parentDeepL TranslationのPro accountトグルスイッチが表示されていな... (diff)
downloadsharkey-0a73973a7c6e6e95a5206bfc5388ff7f7a9ba8ed.tar.gz
sharkey-0a73973a7c6e6e95a5206bfc5388ff7f7a9ba8ed.tar.bz2
sharkey-0a73973a7c6e6e95a5206bfc5388ff7f7a9ba8ed.zip
メールアドレスの認証にverifymail.ioを使えるようにする。
Diffstat (limited to 'packages/backend/src/core/EmailService.ts')
-rw-r--r--packages/backend/src/core/EmailService.ts92
1 files changed, 84 insertions, 8 deletions
diff --git a/packages/backend/src/core/EmailService.ts b/packages/backend/src/core/EmailService.ts
index c9da3f77c0..8f28197ebc 100644
--- a/packages/backend/src/core/EmailService.ts
+++ b/packages/backend/src/core/EmailService.ts
@@ -13,6 +13,9 @@ import type Logger from '@/logger.js';
import type { UserProfilesRepository } from '@/models/_.js';
import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js';
+import {URLSearchParams} from "node:url";
+import { HttpRequestService } from '@/core/HttpRequestService.js';
+import {SubOutputFormat} from "deep-email-validator/dist/output/output.js";
@Injectable()
export class EmailService {
@@ -27,6 +30,7 @@ export class EmailService {
private metaService: MetaService,
private loggerService: LoggerService,
+ private httpRequestService: HttpRequestService,
) {
this.logger = this.loggerService.getLogger('email');
}
@@ -160,14 +164,25 @@ export class EmailService {
email: emailAddress,
});
- const validated = meta.enableActiveEmailValidation ? await validateEmail({
- email: emailAddress,
- validateRegex: true,
- validateMx: true,
- validateTypo: false, // TLDを見ているみたいだけどclubとか弾かれるので
- validateDisposable: true, // 捨てアドかどうかチェック
- validateSMTP: false, // 日本だと25ポートが殆どのプロバイダーで塞がれていてタイムアウトになるので
- }) : { valid: true, reason: null };
+ const verifymailApi = meta.enableVerifymailApi && meta.verifymailAuthKey != null;
+ let validated;
+
+ if (meta.enableActiveEmailValidation) {
+ if (verifymailApi) {
+ validated = await this.verifyMail(emailAddress, meta.verifymailAuthKey);
+ } else {
+ validated = meta.enableActiveEmailValidation ? await validateEmail({
+ email: emailAddress,
+ validateRegex: true,
+ validateMx: true,
+ validateTypo: false, // TLDを見ているみたいだけどclubとか弾かれるので
+ validateDisposable: true, // 捨てアドかどうかチェック
+ validateSMTP: false, // 日本だと25ポートが殆どのプロバイダーで塞がれていてタイムアウトになるので
+ }) : { valid: true, reason: null };
+ }
+ } else {
+ validated = { valid: true, reason: null };
+ }
const available = exist === 0 && validated.valid;
@@ -182,4 +197,65 @@ export class EmailService {
null,
};
}
+
+ private async verifyMail(emailAddress: string, verifymailAuthKey: string): Promise<{
+ valid: boolean;
+ reason: 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | null;
+ }> {
+ const endpoint = 'https://verifymail.io/api/' + emailAddress + '?key=' + verifymailAuthKey;
+ const res = await this.httpRequestService.send(endpoint, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ Accept: 'application/json, */*',
+ },
+ });
+
+ const json = (await res.json()) as {
+ block: boolean;
+ catch_all: boolean;
+ deliverable_email: boolean;
+ disposable: boolean;
+ domain: string;
+ email_address: string;
+ email_provider: string;
+ mx: boolean;
+ mx_fallback: boolean;
+ mx_host: string[];
+ mx_ip: string[];
+ mx_priority: { [key: string]: number };
+ privacy: boolean;
+ related_domains: string[];
+ };
+
+ if (json.email_address === undefined) {
+ return {
+ valid: false,
+ reason: 'format',
+ };
+ }
+ if (json.deliverable_email !== undefined && !json.deliverable_email) {
+ return {
+ valid: false,
+ reason: 'smtp',
+ };
+ }
+ if (json.disposable) {
+ return {
+ valid: false,
+ reason: 'disposable',
+ };
+ }
+ if (json.mx !== undefined && !json.mx) {
+ return {
+ valid: false,
+ reason: 'mx',
+ };
+ }
+
+ return {
+ valid: true,
+ reason: null,
+ };
+ }
}