enhance: make active email validation configurable

This commit is contained in:
syuilo 2022-07-09 15:05:55 +09:00
parent 522ddba3d7
commit 75d516011b
8 changed files with 61 additions and 8 deletions

View file

@ -9,6 +9,13 @@
You should also include the user name that made the change.
-->
## 12.x.x (unreleased)
### Improvements
- Make active email validation configurable
### Bugfixes
## 12.112.2 (2022/07/08)
### Bugfixes

View file

@ -886,6 +886,7 @@ cannotUploadBecauseNoFreeSpace: "ドライブの空き容量が無いためア
beta: "ベータ"
enableAutoSensitive: "自動NSFW判定"
enableAutoSensitiveDescription: "利用可能な場合は、機械学習を利用して自動でメディアにNSFWフラグを設定します。この機能をオフにしても、インスタンスによっては自動で設定されることがあります。"
activeEmailValidationDescription: "ユーザーのメールアドレスのバリデーションを、捨てアドかどうかや実際に通信可能かどうかなどを判定しより積極的に行います。オフにすると単に文字列として正しいかどうかのみチェックされます。"
_sensitiveMediaDetection:
description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てることができます。サーバーの負荷が少し増えます。"

View file

@ -0,0 +1,11 @@
export class activeEmailValidation1657346559800 {
name = 'activeEmailValidation1657346559800'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "enableActiveEmailValidation" boolean NOT NULL DEFAULT true`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableActiveEmailValidation"`);
}
}

View file

@ -454,4 +454,9 @@ export class Meta {
default: false,
})
public enableIpLogging: boolean;
@Column('boolean', {
default: true,
})
public enableActiveEmailValidation: boolean;
}

View file

@ -324,6 +324,10 @@ export const meta = {
type: 'boolean',
optional: true, nullable: false,
},
enableActiveEmailValidation: {
type: 'boolean',
optional: true, nullable: false,
},
},
},
} as const;
@ -421,5 +425,6 @@ export default define(meta, paramDef, async (ps, me) => {
deeplAuthKey: instance.deeplAuthKey,
deeplIsPro: instance.deeplIsPro,
enableIpLogging: instance.enableIpLogging,
enableActiveEmailValidation: instance.enableActiveEmailValidation,
};
});

View file

@ -101,6 +101,7 @@ export const paramDef = {
objectStorageSetPublicRead: { type: 'boolean' },
objectStorageS3ForcePathStyle: { type: 'boolean' },
enableIpLogging: { type: 'boolean' },
enableActiveEmailValidation: { type: 'boolean' },
},
required: [],
} as const;
@ -421,6 +422,10 @@ export default define(meta, paramDef, async (ps, me) => {
set.enableIpLogging = ps.enableIpLogging;
}
if (ps.enableActiveEmailValidation !== undefined) {
set.enableActiveEmailValidation = ps.enableActiveEmailValidation;
}
await db.transaction(async transactionalEntityManager => {
const metas = await transactionalEntityManager.find(Meta, {
order: {

View file

@ -1,34 +1,37 @@
import { validate as validateEmail } from 'deep-email-validator';
import { UserProfiles } from '@/models/index.js';
import { fetchMeta } from '@/misc/fetch-meta.js';
export async function validateEmailForAccount(emailAddress: string): Promise<{
available: boolean;
reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp';
}> {
const meta = await fetchMeta();
const exist = await UserProfiles.countBy({
emailVerified: true,
email: emailAddress,
});
const validated = await validateEmail({
const validated = meta.enableActiveEmailValidation ? await validateEmail({
email: emailAddress,
validateRegex: true,
validateMx: true,
validateTypo: false, // TLDを見ているみたいだけどclubとか弾かれるので
validateDisposable: true, // 捨てアドかどうかチェック
validateSMTP: false, // 日本だと25ポートが殆どのプロバイダーで塞がれていてタイムアウトになるので
});
}) : { valid: true };
const available = exist === 0 && validated.valid;
return {
available,
reason: available ? null :
exist !== 0 ? 'used' :
validated.reason === 'regex' ? 'format' :
validated.reason === 'disposable' ? 'disposable' :
validated.reason === 'mx' ? 'mx' :
validated.reason === 'smtp' ? 'smtp' :
null,
exist !== 0 ? 'used' :
validated.reason === 'regex' ? 'format' :
validated.reason === 'disposable' ? 'disposable' :
validated.reason === 'mx' ? 'mx' :
validated.reason === 'smtp' ? 'smtp' :
null,
};
}

View file

@ -57,6 +57,19 @@
</div>
</FormFolder>
<FormFolder class="_formBlock">
<template #label>Active Email Validation</template>
<template v-if="enableActiveEmailValidation" #suffix>Enabled</template>
<template v-else #suffix>Disabled</template>
<div class="_formRoot">
<span class="_formBlock">{{ i18n.ts.activeEmailValidationDescription }}</span>
<FormSwitch v-model="enableActiveEmailValidation" class="_formBlock" @update:modelValue="save">
<template #label>Enable</template>
</FormSwitch>
</div>
</FormFolder>
<FormFolder class="_formBlock">
<template #label>Log IP address</template>
<template v-if="enableIpLogging" #suffix>Enabled</template>
@ -112,6 +125,7 @@ let sensitiveMediaDetectionSensitivity: number = $ref(0);
let setSensitiveFlagAutomatically: boolean = $ref(false);
let enableSensitiveMediaDetectionForVideos: boolean = $ref(false);
let enableIpLogging: boolean = $ref(false);
let enableActiveEmailValidation: boolean = $ref(false);
async function init() {
const meta = await os.api('admin/meta');
@ -128,6 +142,7 @@ async function init() {
setSensitiveFlagAutomatically = meta.setSensitiveFlagAutomatically;
enableSensitiveMediaDetectionForVideos = meta.enableSensitiveMediaDetectionForVideos;
enableIpLogging = meta.enableIpLogging;
enableActiveEmailValidation = meta.enableActiveEmailValidation;
}
function save() {
@ -144,6 +159,7 @@ function save() {
setSensitiveFlagAutomatically,
enableSensitiveMediaDetectionForVideos,
enableIpLogging,
enableActiveEmailValidation,
}).then(() => {
fetchInstance();
});