mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-04 07:24:13 +00:00 
			
		
		
		
	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
 | 
						@bindThis
 | 
				
			||||||
	public async validateEmailForAccount(emailAddress: string): Promise<{
 | 
						public async validateEmailForAccount(emailAddress: string): Promise<{
 | 
				
			||||||
		available: boolean;
 | 
							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();
 | 
							const meta = await this.metaService.fetch();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,6 +173,8 @@ export class EmailService {
 | 
				
			||||||
		if (meta.enableActiveEmailValidation) {
 | 
							if (meta.enableActiveEmailValidation) {
 | 
				
			||||||
			if (meta.enableVerifymailApi && meta.verifymailAuthKey != null) {
 | 
								if (meta.enableVerifymailApi && meta.verifymailAuthKey != null) {
 | 
				
			||||||
				validated = await this.verifyMail(emailAddress, meta.verifymailAuthKey);
 | 
									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 {
 | 
								} else {
 | 
				
			||||||
				validated = await validateEmail({
 | 
									validated = await validateEmail({
 | 
				
			||||||
					email: emailAddress,
 | 
										email: emailAddress,
 | 
				
			||||||
| 
						 | 
					@ -201,6 +203,8 @@ export class EmailService {
 | 
				
			||||||
			validated.reason === 'disposable' ? 'disposable' :
 | 
								validated.reason === 'disposable' ? 'disposable' :
 | 
				
			||||||
			validated.reason === 'mx' ? 'mx' :
 | 
								validated.reason === 'mx' ? 'mx' :
 | 
				
			||||||
			validated.reason === 'smtp' ? 'smtp' :
 | 
								validated.reason === 'smtp' ? 'smtp' :
 | 
				
			||||||
 | 
								validated.reason === 'network' ? 'network' :
 | 
				
			||||||
 | 
								validated.reason === 'blacklist' ? 'blacklist' :
 | 
				
			||||||
			null,
 | 
								null,
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -265,4 +269,67 @@ export class EmailService {
 | 
				
			||||||
			reason: null,
 | 
								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;
 | 
						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', {
 | 
						@Column('boolean', {
 | 
				
			||||||
		default: true,
 | 
							default: true,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -284,6 +284,18 @@ export const meta = {
 | 
				
			||||||
				type: 'string',
 | 
									type: 'string',
 | 
				
			||||||
				optional: false, nullable: true,
 | 
									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: {
 | 
								enableChartsForRemoteUser: {
 | 
				
			||||||
				type: 'boolean',
 | 
									type: 'boolean',
 | 
				
			||||||
				optional: false, nullable: false,
 | 
									optional: false, nullable: false,
 | 
				
			||||||
| 
						 | 
					@ -520,6 +532,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 | 
				
			||||||
				enableActiveEmailValidation: instance.enableActiveEmailValidation,
 | 
									enableActiveEmailValidation: instance.enableActiveEmailValidation,
 | 
				
			||||||
				enableVerifymailApi: instance.enableVerifymailApi,
 | 
									enableVerifymailApi: instance.enableVerifymailApi,
 | 
				
			||||||
				verifymailAuthKey: instance.verifymailAuthKey,
 | 
									verifymailAuthKey: instance.verifymailAuthKey,
 | 
				
			||||||
 | 
									enableTruemailApi: instance.enableTruemailApi,
 | 
				
			||||||
 | 
									truemailInstance: instance.truemailInstance,
 | 
				
			||||||
 | 
									truemailAuthKey: instance.truemailAuthKey,
 | 
				
			||||||
				enableChartsForRemoteUser: instance.enableChartsForRemoteUser,
 | 
									enableChartsForRemoteUser: instance.enableChartsForRemoteUser,
 | 
				
			||||||
				enableChartsForFederatedInstances: instance.enableChartsForFederatedInstances,
 | 
									enableChartsForFederatedInstances: instance.enableChartsForFederatedInstances,
 | 
				
			||||||
				enableServerMachineStats: instance.enableServerMachineStats,
 | 
									enableServerMachineStats: instance.enableServerMachineStats,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,6 +116,9 @@ export const paramDef = {
 | 
				
			||||||
		enableActiveEmailValidation: { type: 'boolean' },
 | 
							enableActiveEmailValidation: { type: 'boolean' },
 | 
				
			||||||
		enableVerifymailApi: { type: 'boolean' },
 | 
							enableVerifymailApi: { type: 'boolean' },
 | 
				
			||||||
		verifymailAuthKey: { type: 'string', nullable: true },
 | 
							verifymailAuthKey: { type: 'string', nullable: true },
 | 
				
			||||||
 | 
							enableTruemailApi: { type: 'boolean' },
 | 
				
			||||||
 | 
							truemailInstance: { type: 'string', nullable: true },
 | 
				
			||||||
 | 
							truemailAuthKey: { type: 'string', nullable: true },
 | 
				
			||||||
		enableChartsForRemoteUser: { type: 'boolean' },
 | 
							enableChartsForRemoteUser: { type: 'boolean' },
 | 
				
			||||||
		enableChartsForFederatedInstances: { type: 'boolean' },
 | 
							enableChartsForFederatedInstances: { type: 'boolean' },
 | 
				
			||||||
		enableServerMachineStats: { type: 'boolean' },
 | 
							enableServerMachineStats: { type: 'boolean' },
 | 
				
			||||||
| 
						 | 
					@ -469,6 +472,26 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 | 
				
			||||||
					set.verifymailAuthKey = ps.verifymailAuthKey;
 | 
										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) {
 | 
								if (ps.enableChartsForRemoteUser !== undefined) {
 | 
				
			||||||
				set.enableChartsForRemoteUser = ps.enableChartsForRemoteUser;
 | 
									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 #prefix><i class="ti ti-key"></i></template>
 | 
				
			||||||
							<template #label>Verifymail.io API Auth Key</template>
 | 
												<template #label>Verifymail.io API Auth Key</template>
 | 
				
			||||||
						</MkInput>
 | 
											</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>
 | 
										</div>
 | 
				
			||||||
				</MkFolder>
 | 
									</MkFolder>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -153,6 +164,9 @@ const enableIpLogging = ref<boolean>(false);
 | 
				
			||||||
const enableActiveEmailValidation = ref<boolean>(false);
 | 
					const enableActiveEmailValidation = ref<boolean>(false);
 | 
				
			||||||
const enableVerifymailApi = ref<boolean>(false);
 | 
					const enableVerifymailApi = ref<boolean>(false);
 | 
				
			||||||
const verifymailAuthKey = ref<string | null>(null);
 | 
					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>('');
 | 
					const bannedEmailDomains = ref<string>('');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function init() {
 | 
					async function init() {
 | 
				
			||||||
| 
						 | 
					@ -194,6 +208,9 @@ function save() {
 | 
				
			||||||
		enableActiveEmailValidation: enableActiveEmailValidation.value,
 | 
							enableActiveEmailValidation: enableActiveEmailValidation.value,
 | 
				
			||||||
		enableVerifymailApi: enableVerifymailApi.value,
 | 
							enableVerifymailApi: enableVerifymailApi.value,
 | 
				
			||||||
		verifymailAuthKey: verifymailAuthKey.value,
 | 
							verifymailAuthKey: verifymailAuthKey.value,
 | 
				
			||||||
 | 
							enableTruemailApi: enableTruemailApi.value,
 | 
				
			||||||
 | 
							truemailInstance: truemailInstance.value,
 | 
				
			||||||
 | 
							truemailAuthKey: truemailAuthKey.value,
 | 
				
			||||||
		bannedEmailDomains: bannedEmailDomains.value.split('\n'),
 | 
							bannedEmailDomains: bannedEmailDomains.value.split('\n'),
 | 
				
			||||||
	}).then(() => {
 | 
						}).then(() => {
 | 
				
			||||||
		fetchInstance();
 | 
							fetchInstance();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue