mirror of
https://github.com/certd/certd.git
synced 2026-04-23 11:37:23 +08:00
perf: 支持邮件模版设置
This commit is contained in:
@@ -1,14 +1,10 @@
|
||||
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import { cache, isDev, randomNumber, simpleNanoId } from '@certd/basic';
|
||||
import { SysSettingsService, SysSiteInfo } from '@certd/lib-server';
|
||||
import { SmsServiceFactory } from '../sms/factory.js';
|
||||
import { AccessService, AccessSysGetter, CodeErrorException, SysSettingsService } from '@certd/lib-server';
|
||||
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import { ISmsService } from '../sms/api.js';
|
||||
import { CodeErrorException } from '@certd/lib-server';
|
||||
import { EmailService } from './email-service.js';
|
||||
import { AccessService } from '@certd/lib-server';
|
||||
import { AccessSysGetter } from '@certd/lib-server';
|
||||
import { isComm } from '@certd/plus-core';
|
||||
import { SmsServiceFactory } from '../sms/factory.js';
|
||||
import { CaptchaService } from "./captcha-service.js";
|
||||
import { EmailService } from './email-service.js';
|
||||
|
||||
// {data: '<svg.../svg>', text: 'abcd'}
|
||||
/**
|
||||
@@ -84,8 +80,6 @@ export class CodeService {
|
||||
async sendEmailCode(
|
||||
email: string,
|
||||
opts?: {
|
||||
title?: string,
|
||||
content?: string,
|
||||
duration?: number,
|
||||
verificationType?: string,
|
||||
verificationCodeLength?: number,
|
||||
@@ -96,32 +90,27 @@ export class CodeService {
|
||||
}
|
||||
|
||||
|
||||
let siteTitle = 'Certd';
|
||||
if (isComm()) {
|
||||
const siteInfo = await this.sysSettingsService.getSetting<SysSiteInfo>(SysSiteInfo);
|
||||
if (siteInfo) {
|
||||
siteTitle = siteInfo.title || siteTitle;
|
||||
}
|
||||
}
|
||||
|
||||
const verificationCodeLength = Math.floor(Math.max(Math.min(opts?.verificationCodeLength || 4, 8), 4));
|
||||
const duration = Math.floor(Math.max(Math.min(opts?.duration || 5, 15), 1));
|
||||
|
||||
const code = randomNumber(verificationCodeLength);
|
||||
|
||||
|
||||
const templateData = {
|
||||
code, duration, siteTitle
|
||||
code, duration,
|
||||
title: "验证码",
|
||||
content:`您的验证码是${code},请勿泄露`,
|
||||
notificationType: "registerCode"
|
||||
}
|
||||
|
||||
const titleTemplate = opts?.title?
|
||||
|
||||
const title = `【${siteTitle}】${!!opts?.title ? opts.title : '验证码'}`;
|
||||
const content = !!opts.content ? this.compile(opts.content)(templateData) : `您的验证码是${code},请勿泄露`;
|
||||
|
||||
await this.emailService.send({
|
||||
subject: title,
|
||||
content: content,
|
||||
receivers: [email],
|
||||
if (opts?.verificationType === 'forgotPassword') {
|
||||
templateData.title = '找回密码';
|
||||
templateData.notificationType = "forgotPassword"
|
||||
}
|
||||
await this.emailService.sendByTemplate({
|
||||
type: templateData.notificationType,
|
||||
data: templateData,
|
||||
email:{
|
||||
receivers: [email],
|
||||
},
|
||||
});
|
||||
|
||||
const key = this.buildEmailCodeKey(email,opts?.verificationType);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import type { EmailSend } from '@certd/pipeline';
|
||||
import type { EmailSend, EmailSendByTemplateReq } from '@certd/pipeline';
|
||||
import { IEmailService } from '@certd/pipeline';
|
||||
|
||||
import { logger } from '@certd/basic';
|
||||
@@ -8,9 +8,11 @@ import { isComm, isPlus } from '@certd/plus-core';
|
||||
import nodemailer from 'nodemailer';
|
||||
import { SendMailOptions } from 'nodemailer';
|
||||
import { UserSettingsService } from '../../mine/service/user-settings-service.js';
|
||||
import { PlusService, SysSettingsService, SysSiteInfo } from '@certd/lib-server';
|
||||
import { AddonService, PlusService, SysEmailConf, SysSettingsService, SysSiteInfo } from '@certd/lib-server';
|
||||
import { getEmailSettings } from '../../sys/settings/fix.js';
|
||||
import { UserEmailSetting } from "../../mine/service/models.js";
|
||||
import { AddonGetterService } from '../../pipeline/service/addon-getter-service.js';
|
||||
import { EmailContent, ITemplateProvider } from '../../../plugins/plugin-template/api.js';
|
||||
|
||||
export type EmailConfig = {
|
||||
host: string;
|
||||
@@ -38,6 +40,12 @@ export class EmailService implements IEmailService {
|
||||
@Inject()
|
||||
plusService: PlusService;
|
||||
|
||||
@Inject()
|
||||
addonGetterService: AddonGetterService;
|
||||
@Inject()
|
||||
addonService: AddonService
|
||||
|
||||
|
||||
async sendByPlus(email: EmailSend) {
|
||||
if (!isPlus()) {
|
||||
throw new Error('plus not enabled');
|
||||
@@ -49,7 +57,6 @@ export class EmailService implements IEmailService {
|
||||
* content: string;
|
||||
* receivers: string[];
|
||||
*/
|
||||
|
||||
await this.plusService.sendEmail(email);
|
||||
}
|
||||
|
||||
@@ -62,26 +69,6 @@ export class EmailService implements IEmailService {
|
||||
throw new Error('收件人不能为空');
|
||||
}
|
||||
|
||||
const emailConf = await getEmailSettings(this.sysSettingsService, this.settingsService);
|
||||
|
||||
if (!emailConf.host && emailConf.usePlus == null) {
|
||||
if (isPlus()) {
|
||||
//自动使用plus发邮件
|
||||
return await this.sendByPlus(email);
|
||||
}
|
||||
throw new Error('邮件服务器还未设置');
|
||||
}
|
||||
|
||||
if (emailConf.usePlus && isPlus()) {
|
||||
return await this.sendByPlus(email);
|
||||
}
|
||||
await this.sendByCustom(emailConf, email);
|
||||
logger.info('sendEmail complete: ', email);
|
||||
}
|
||||
|
||||
private async sendByCustom(emailConfig: EmailConfig, email: EmailSend) {
|
||||
const transporter = nodemailer.createTransport(emailConfig);
|
||||
|
||||
let sysTitle = 'Certd';
|
||||
if (isComm()) {
|
||||
const siteInfo = await this.sysSettingsService.getSetting<SysSiteInfo>(SysSiteInfo);
|
||||
@@ -93,10 +80,34 @@ export class EmailService implements IEmailService {
|
||||
if (!subject.includes(`【${sysTitle}】`)) {
|
||||
subject = `【${sysTitle}】${subject}`;
|
||||
}
|
||||
email.subject = subject;
|
||||
|
||||
const emailConf = await getEmailSettings(this.sysSettingsService, this.settingsService);
|
||||
|
||||
if (!emailConf.host && emailConf.usePlus == null) {
|
||||
if (isPlus()) {
|
||||
//自动使用plus发邮件
|
||||
return await this.sendByPlus(email);
|
||||
}
|
||||
throw new Error('邮件服务器还未设置');
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (emailConf.usePlus && isPlus()) {
|
||||
return await this.sendByPlus(email);
|
||||
}
|
||||
await this.sendByCustom(emailConf, email, sysTitle);
|
||||
logger.info('sendEmail complete: ', email);
|
||||
}
|
||||
|
||||
private async sendByCustom(emailConfig: EmailConfig, email: EmailSend, sysTitle: string) {
|
||||
const transporter = nodemailer.createTransport(emailConfig);
|
||||
|
||||
const mailOptions = {
|
||||
from: `${sysTitle} <${emailConfig.sender}>`,
|
||||
to: email.receivers.join(', '), // list of receivers
|
||||
subject: subject,
|
||||
subject: email.subject,
|
||||
text: email.content,
|
||||
html: email.html,
|
||||
attachments: email.attachments,
|
||||
@@ -105,30 +116,72 @@ export class EmailService implements IEmailService {
|
||||
}
|
||||
|
||||
async test(userId: number, receiver: string) {
|
||||
await this.send({
|
||||
receivers: [receiver],
|
||||
subject: '测试邮件,from certd',
|
||||
content: '测试邮件,from certd',
|
||||
await this.sendByTemplate({
|
||||
type:"common",
|
||||
data:{
|
||||
title: '测试邮件,from certd',
|
||||
content: '测试邮件,from certd',
|
||||
},
|
||||
email: {
|
||||
receivers: [receiver],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async list(userId: any) {
|
||||
const userEmailSetting = await this.settingsService.getSetting<UserEmailSetting>(userId,UserEmailSetting)
|
||||
return userEmailSetting.list;
|
||||
const userEmailSetting = await this.settingsService.getSetting<UserEmailSetting>(userId, UserEmailSetting)
|
||||
return userEmailSetting.list;
|
||||
}
|
||||
|
||||
async delete(userId: any, email: string) {
|
||||
const userEmailSetting = await this.settingsService.getSetting<UserEmailSetting>(userId,UserEmailSetting)
|
||||
userEmailSetting.list = userEmailSetting.list.filter(item=>item !== email);
|
||||
await this.settingsService.saveSetting(userId,userEmailSetting)
|
||||
const userEmailSetting = await this.settingsService.getSetting<UserEmailSetting>(userId, UserEmailSetting)
|
||||
userEmailSetting.list = userEmailSetting.list.filter(item => item !== email);
|
||||
await this.settingsService.saveSetting(userId, userEmailSetting)
|
||||
}
|
||||
async add(userId: any, email: string) {
|
||||
const userEmailSetting = await this.settingsService.getSetting<UserEmailSetting>(userId,UserEmailSetting)
|
||||
const userEmailSetting = await this.settingsService.getSetting<UserEmailSetting>(userId, UserEmailSetting)
|
||||
//如果已存在
|
||||
if(userEmailSetting.list.includes(email)){
|
||||
if (userEmailSetting.list.includes(email)) {
|
||||
return
|
||||
}
|
||||
userEmailSetting.list.unshift(email)
|
||||
await this.settingsService.saveSetting(userId,userEmailSetting)
|
||||
await this.settingsService.saveSetting(userId, userEmailSetting)
|
||||
}
|
||||
|
||||
|
||||
async sendByTemplate(req: EmailSendByTemplateReq) {
|
||||
const emailConf = await this.sysSettingsService.getSetting<SysEmailConf>(SysEmailConf);
|
||||
|
||||
const template = emailConf?.templates?.[req.type]
|
||||
let content = null
|
||||
if (template && template.addonId) {
|
||||
const addon: ITemplateProvider<EmailContent> = await this.addonGetterService.getAddonById(template.addonId, true, 0)
|
||||
if (addon) {
|
||||
content = await addon.buildContent({ data: req.data })
|
||||
}
|
||||
}
|
||||
if (!content) {
|
||||
//看看有没有通用模版
|
||||
if (emailConf?.templates?.common && emailConf?.templates?.common.addonId) {
|
||||
const addon: ITemplateProvider<EmailContent> = await this.addonGetterService.getAddonById(emailConf.templates.common.addonId, true, 0)
|
||||
if (addon) {
|
||||
content = await addon.buildContent({ data: req.data })
|
||||
}
|
||||
}
|
||||
}
|
||||
// 没有找到模版,使用默认模版
|
||||
if (!content) {
|
||||
try {
|
||||
const addon: ITemplateProvider<EmailContent> = await this.addonGetterService.getBlank(req.type, "默认")
|
||||
content = await addon.buildDefaultContent({ data: req.data })
|
||||
} catch (e) {
|
||||
const addon: ITemplateProvider<EmailContent> = await this.addonGetterService.getBlank("common", "默认")
|
||||
content = await addon.buildDefaultContent({ data: req.data })
|
||||
}
|
||||
}
|
||||
return await this.send({
|
||||
...req.email,
|
||||
...content
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user