feat: Add support for TrueMail (#12850)
Co-authored-by: MarryDream <2190758465@qq.com>
This commit is contained in:
parent
8fb8d7c10c
commit
7948018e6a
6 changed files with 160 additions and 1 deletions
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and other misskey contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export class SupportTrueMailApi1703658526000 {
|
||||
name = 'SupportTrueMailApi1703658526000'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "truemailInstance" character varying(1024)`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "truemailAuthKey" character varying(1024)`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "enableTruemailApi" boolean NOT NULL DEFAULT false`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableTruemailApi"`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "truemailInstance"`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "truemailAuthKey"`);
|
||||
}
|
||||
}
|
|
@ -156,7 +156,7 @@ export class EmailService {
|
|||
@bindThis
|
||||
public async validateEmailForAccount(emailAddress: string): Promise<{
|
||||
available: boolean;
|
||||
reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | 'banned';
|
||||
reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | 'banned' | 'network' | 'blacklist';
|
||||
}> {
|
||||
const meta = await this.metaService.fetch();
|
||||
|
||||
|
@ -173,6 +173,8 @@ export class EmailService {
|
|||
if (meta.enableActiveEmailValidation) {
|
||||
if (meta.enableVerifymailApi && meta.verifymailAuthKey != null) {
|
||||
validated = await this.verifyMail(emailAddress, meta.verifymailAuthKey);
|
||||
} else if (meta.enableTruemailApi && meta.truemailInstance && meta.truemailAuthKey != null) {
|
||||
validated = await this.trueMail(meta.truemailInstance, emailAddress, meta.truemailAuthKey);
|
||||
} else {
|
||||
validated = await validateEmail({
|
||||
email: emailAddress,
|
||||
|
@ -201,6 +203,8 @@ export class EmailService {
|
|||
validated.reason === 'disposable' ? 'disposable' :
|
||||
validated.reason === 'mx' ? 'mx' :
|
||||
validated.reason === 'smtp' ? 'smtp' :
|
||||
validated.reason === 'network' ? 'network' :
|
||||
validated.reason === 'blacklist' ? 'blacklist' :
|
||||
null,
|
||||
};
|
||||
}
|
||||
|
@ -265,4 +269,67 @@ export class EmailService {
|
|||
reason: null,
|
||||
};
|
||||
}
|
||||
|
||||
private async trueMail<T>(truemailInstance: string, emailAddress: string, truemailAuthKey: string): Promise<{
|
||||
valid: boolean;
|
||||
reason: 'used' | 'format' | 'blacklist' | 'mx' | 'smtp' | 'network' | T | null;
|
||||
}> {
|
||||
const endpoint = truemailInstance + '?email=' + emailAddress;
|
||||
try {
|
||||
const res = await this.httpRequestService.send(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
Authorization: truemailAuthKey
|
||||
},
|
||||
});
|
||||
|
||||
const json = (await res.json()) as {
|
||||
email: string;
|
||||
success: boolean;
|
||||
errors?: {
|
||||
list_match?: string;
|
||||
regex?: string;
|
||||
mx?: string;
|
||||
smtp?: string;
|
||||
} | null;
|
||||
};
|
||||
|
||||
if (json.email === undefined || (json.email !== undefined && json.errors?.regex)) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'format',
|
||||
};
|
||||
}
|
||||
if (json.errors?.smtp) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'smtp',
|
||||
};
|
||||
}
|
||||
if (json.errors?.mx) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'mx',
|
||||
};
|
||||
}
|
||||
if (!json.success) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: json.errors?.list_match as T || 'blacklist',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
reason: null,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'network',
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -457,6 +457,23 @@ export class MiMeta {
|
|||
})
|
||||
public verifymailAuthKey: string | null;
|
||||
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
})
|
||||
public enableTruemailApi: boolean;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
nullable: true,
|
||||
})
|
||||
public truemailInstance: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
nullable: true,
|
||||
})
|
||||
public truemailAuthKey: string | null;
|
||||
|
||||
@Column('boolean', {
|
||||
default: true,
|
||||
})
|
||||
|
|
|
@ -284,6 +284,18 @@ export const meta = {
|
|||
type: 'string',
|
||||
optional: false, nullable: true,
|
||||
},
|
||||
enableTruemailApi: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
truemailInstance: {
|
||||
type: 'string',
|
||||
optional: false, nullable: true,
|
||||
},
|
||||
truemailAuthKey: {
|
||||
type: 'string',
|
||||
optional: false, nullable: true,
|
||||
},
|
||||
enableChartsForRemoteUser: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
|
@ -520,6 +532,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
enableActiveEmailValidation: instance.enableActiveEmailValidation,
|
||||
enableVerifymailApi: instance.enableVerifymailApi,
|
||||
verifymailAuthKey: instance.verifymailAuthKey,
|
||||
enableTruemailApi: instance.enableTruemailApi,
|
||||
truemailInstance: instance.truemailInstance,
|
||||
truemailAuthKey: instance.truemailAuthKey,
|
||||
enableChartsForRemoteUser: instance.enableChartsForRemoteUser,
|
||||
enableChartsForFederatedInstances: instance.enableChartsForFederatedInstances,
|
||||
enableServerMachineStats: instance.enableServerMachineStats,
|
||||
|
|
|
@ -116,6 +116,9 @@ export const paramDef = {
|
|||
enableActiveEmailValidation: { type: 'boolean' },
|
||||
enableVerifymailApi: { type: 'boolean' },
|
||||
verifymailAuthKey: { type: 'string', nullable: true },
|
||||
enableTruemailApi: { type: 'boolean' },
|
||||
truemailInstance: { type: 'string', nullable: true },
|
||||
truemailAuthKey: { type: 'string', nullable: true },
|
||||
enableChartsForRemoteUser: { type: 'boolean' },
|
||||
enableChartsForFederatedInstances: { type: 'boolean' },
|
||||
enableServerMachineStats: { type: 'boolean' },
|
||||
|
@ -469,6 +472,26 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
set.verifymailAuthKey = ps.verifymailAuthKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.enableTruemailApi !== undefined) {
|
||||
set.enableTruemailApi = ps.enableTruemailApi;
|
||||
}
|
||||
|
||||
if (ps.truemailInstance !== undefined) {
|
||||
if (ps.truemailInstance === '') {
|
||||
set.truemailInstance = null;
|
||||
} else {
|
||||
set.truemailInstance = ps.truemailInstance;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.truemailAuthKey !== undefined) {
|
||||
if (ps.truemailAuthKey === '') {
|
||||
set.truemailAuthKey = null;
|
||||
} else {
|
||||
set.truemailAuthKey = ps.truemailAuthKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.enableChartsForRemoteUser !== undefined) {
|
||||
set.enableChartsForRemoteUser = ps.enableChartsForRemoteUser;
|
||||
|
|
|
@ -80,6 +80,17 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #prefix><i class="ti ti-key"></i></template>
|
||||
<template #label>Verifymail.io API Auth Key</template>
|
||||
</MkInput>
|
||||
<MkSwitch v-model="enableTruemailApi" @update:modelValue="save">
|
||||
<template #label>Use TrueMail API</template>
|
||||
</MkSwitch>
|
||||
<MkInput v-model="truemailInstance" @update:modelValue="save">
|
||||
<template #prefix><i class="ti ti-key"></i></template>
|
||||
<template #label>TrueMail API Instance</template>
|
||||
</MkInput>
|
||||
<MkInput v-model="truemailAuthKey" @update:modelValue="save">
|
||||
<template #prefix><i class="ti ti-key"></i></template>
|
||||
<template #label>TrueMail API Auth Key</template>
|
||||
</MkInput>
|
||||
</div>
|
||||
</MkFolder>
|
||||
|
||||
|
@ -153,6 +164,9 @@ const enableIpLogging = ref<boolean>(false);
|
|||
const enableActiveEmailValidation = ref<boolean>(false);
|
||||
const enableVerifymailApi = ref<boolean>(false);
|
||||
const verifymailAuthKey = ref<string | null>(null);
|
||||
const enableTruemailApi = ref<boolean>(false);
|
||||
const truemailInstance = ref<string | null>(null);
|
||||
const truemailAuthKey = ref<string | null>(null);
|
||||
const bannedEmailDomains = ref<string>('');
|
||||
|
||||
async function init() {
|
||||
|
@ -194,6 +208,9 @@ function save() {
|
|||
enableActiveEmailValidation: enableActiveEmailValidation.value,
|
||||
enableVerifymailApi: enableVerifymailApi.value,
|
||||
verifymailAuthKey: verifymailAuthKey.value,
|
||||
enableTruemailApi: enableTruemailApi.value,
|
||||
truemailInstance: truemailInstance.value,
|
||||
truemailAuthKey: truemailAuthKey.value,
|
||||
bannedEmailDomains: bannedEmailDomains.value.split('\n'),
|
||||
}).then(() => {
|
||||
fetchInstance();
|
||||
|
|
Loading…
Reference in a new issue