From 0a73973a7c6e6e95a5206bfc5388ff7f7a9ba8ed Mon Sep 17 00:00:00 2001 From: Nafu Satsuki Date: Sat, 18 Nov 2023 20:39:48 +0900 Subject: メールアドレスの認証にverifymail.ioを使えるようにする。 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/core/EmailService.ts | 92 ++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 8 deletions(-) (limited to 'packages/backend/src/core/EmailService.ts') 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, + }; + } } -- cgit v1.2.3-freya