summaryrefslogtreecommitdiff
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
parentDeepL TranslationのPro accountトグルスイッチが表示されていな... (diff)
downloadmisskey-0a73973a7c6e6e95a5206bfc5388ff7f7a9ba8ed.tar.gz
misskey-0a73973a7c6e6e95a5206bfc5388ff7f7a9ba8ed.tar.bz2
misskey-0a73973a7c6e6e95a5206bfc5388ff7f7a9ba8ed.zip
メールアドレスの認証にverifymail.ioを使えるようにする。
-rw-r--r--packages/backend/migration/1700303245007-supportVerifyMailApi.js18
-rw-r--r--packages/backend/src/core/EmailService.ts92
-rw-r--r--packages/backend/src/models/Meta.ts11
-rw-r--r--packages/backend/src/server/api/endpoints/admin/update-meta.ts14
-rw-r--r--packages/frontend/src/pages/admin/security.vue13
5 files changed, 140 insertions, 8 deletions
diff --git a/packages/backend/migration/1700303245007-supportVerifyMailApi.js b/packages/backend/migration/1700303245007-supportVerifyMailApi.js
new file mode 100644
index 0000000000..3ac59ec37a
--- /dev/null
+++ b/packages/backend/migration/1700303245007-supportVerifyMailApi.js
@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class SupportVerifyMailApi1700303245007 {
+ name = 'SupportVerifyMailApi1700303245007'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ADD "verifymailAuthKey" character varying(1024)`);
+ await queryRunner.query(`ALTER TABLE "meta" ADD "enableVerifymailApi" boolean NOT NULL DEFAULT false`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableVerifymailApi"`);
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "verifymailAuthKey"`);
+ }
+}
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,
+ };
+ }
}
diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts
index 14a72add1d..83e8962f5d 100644
--- a/packages/backend/src/models/Meta.ts
+++ b/packages/backend/src/models/Meta.ts
@@ -447,6 +447,17 @@ export class MiMeta {
public enableActiveEmailValidation: boolean;
@Column('boolean', {
+ default: false,
+ })
+ public enableVerifymailApi: boolean;
+
+ @Column('varchar', {
+ length: 1024,
+ nullable: true,
+ })
+ public verifymailAuthKey: string | null;
+
+ @Column('boolean', {
default: true,
})
public enableChartsForRemoteUser: boolean;
diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
index da3e5dd9ac..d6f9b2cd94 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -113,6 +113,8 @@ export const paramDef = {
objectStorageS3ForcePathStyle: { type: 'boolean' },
enableIpLogging: { type: 'boolean' },
enableActiveEmailValidation: { type: 'boolean' },
+ enableVerifymailApi: { type: 'boolean' },
+ verifymailAuthKey: { type: 'string', nullable: true },
enableChartsForRemoteUser: { type: 'boolean' },
enableChartsForFederatedInstances: { type: 'boolean' },
enableServerMachineStats: { type: 'boolean' },
@@ -454,6 +456,18 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
set.enableActiveEmailValidation = ps.enableActiveEmailValidation;
}
+ if (ps.enableVerifymailApi !== undefined) {
+ set.enableVerifymailApi = ps.enableVerifymailApi;
+ }
+
+ if (ps.verifymailAuthKey !== undefined) {
+ if (ps.verifymailAuthKey === '') {
+ set.verifymailAuthKey = null;
+ } else {
+ set.verifymailAuthKey = ps.verifymailAuthKey;
+ }
+ }
+
if (ps.enableChartsForRemoteUser !== undefined) {
set.enableChartsForRemoteUser = ps.enableChartsForRemoteUser;
}
diff --git a/packages/frontend/src/pages/admin/security.vue b/packages/frontend/src/pages/admin/security.vue
index a2594ee6c5..f7f76d910a 100644
--- a/packages/frontend/src/pages/admin/security.vue
+++ b/packages/frontend/src/pages/admin/security.vue
@@ -73,6 +73,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSwitch v-model="enableActiveEmailValidation" @update:modelValue="save">
<template #label>Enable</template>
</MkSwitch>
+ <MkSwitch v-model="enableVerifymailApi" @update:modelValue="save">
+ <template #label>Use Verifymail API</template>
+ </MkSwitch>
+ <MkInput v-model="verifymailAuthKey" @update:modelValue="save">
+ <template #prefix><i class="ti ti-key"></i></template>
+ <template #label>Verifymail API Auth Key</template>
+ </MkInput>
</div>
</MkFolder>
@@ -132,6 +139,8 @@ let setSensitiveFlagAutomatically: boolean = $ref(false);
let enableSensitiveMediaDetectionForVideos: boolean = $ref(false);
let enableIpLogging: boolean = $ref(false);
let enableActiveEmailValidation: boolean = $ref(false);
+let enableVerifymailApi: boolean = $ref(false);
+let verifymailAuthKey: string | null = $ref(null);
async function init() {
const meta = await os.api('admin/meta');
@@ -150,6 +159,8 @@ async function init() {
enableSensitiveMediaDetectionForVideos = meta.enableSensitiveMediaDetectionForVideos;
enableIpLogging = meta.enableIpLogging;
enableActiveEmailValidation = meta.enableActiveEmailValidation;
+ enableVerifymailApi = meta.enableVerifymailApi;
+ verifymailAuthKey = meta.verifymailAuthKey;
}
function save() {
@@ -167,6 +178,8 @@ function save() {
enableSensitiveMediaDetectionForVideos,
enableIpLogging,
enableActiveEmailValidation,
+ enableVerifymailApi,
+ verifymailAuthKey,
}).then(() => {
fetchInstance();
});