mirror of https://github.com/certd/certd
perf: 通知标题优化
parent
0f051e322e
commit
ff083ce684
|
@ -10,7 +10,8 @@ import { Decorator } from "../decorator/index.js";
|
||||||
import { ICnameProxyService, IEmailService, IPluginConfigService, IUrlService } from "../service/index.js";
|
import { ICnameProxyService, IEmailService, IPluginConfigService, IUrlService } from "../service/index.js";
|
||||||
import { FileStore } from "./file-store.js";
|
import { FileStore } from "./file-store.js";
|
||||||
import { cloneDeep, forEach, merge } from "lodash-es";
|
import { cloneDeep, forEach, merge } from "lodash-es";
|
||||||
import { INotificationService, NotificationBody, NotificationContext, notificationRegistry } from "../notification/index.js";
|
import { INotificationService } from "../notification/index.js";
|
||||||
|
|
||||||
export type SysInfo = {
|
export type SysInfo = {
|
||||||
//系统标题
|
//系统标题
|
||||||
title?: string;
|
title?: string;
|
||||||
|
@ -373,18 +374,17 @@ export class Executor {
|
||||||
let subject = "";
|
let subject = "";
|
||||||
let content = "";
|
let content = "";
|
||||||
const errorMessage = error?.message;
|
const errorMessage = error?.message;
|
||||||
const sysTitle = this.options.sysInfo?.title || "Certd";
|
|
||||||
if (when === "start") {
|
if (when === "start") {
|
||||||
subject = `【${sysTitle}】开始执行,${this.pipeline.title}【${this.pipeline.id}】`;
|
subject = `开始执行,${this.pipeline.title}【${this.pipeline.id}】`;
|
||||||
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`;
|
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`;
|
||||||
} else if (when === "success") {
|
} else if (when === "success") {
|
||||||
subject = `【${sysTitle}】执行成功,${this.pipeline.title}【${this.pipeline.id}】`;
|
subject = `执行成功,${this.pipeline.title}【${this.pipeline.id}】`;
|
||||||
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`;
|
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`;
|
||||||
} else if (when === "turnToSuccess") {
|
} else if (when === "turnToSuccess") {
|
||||||
subject = `【${sysTitle}】执行成功(失败转成功),${this.pipeline.title}【${this.pipeline.id}】`;
|
subject = `执行成功(失败转成功),${this.pipeline.title}【${this.pipeline.id}】`;
|
||||||
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`;
|
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`;
|
||||||
} else if (when === "error") {
|
} else if (when === "error") {
|
||||||
subject = `【${sysTitle}】执行失败,${this.pipeline.title}【${this.pipeline.id}】`;
|
subject = `执行失败,${this.pipeline.title}【${this.pipeline.id}】`;
|
||||||
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}\n错误详情:${error.message}`;
|
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}\n错误详情:${error.message}`;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -407,43 +407,23 @@ export class Executor {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
//构建notification插件,发送通知
|
|
||||||
let notifyConfig: any;
|
|
||||||
if (notification.notificationId === 0) {
|
|
||||||
notifyConfig = await this.options.notificationService.getDefault();
|
|
||||||
} else {
|
|
||||||
notifyConfig = await this.options.notificationService.getById(notification.notificationId);
|
|
||||||
}
|
|
||||||
if (notifyConfig == null) {
|
|
||||||
throw new Error(`通知配置<id:${notification.notificationId}>不存在`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const notificationPlugin = notificationRegistry.get(notifyConfig.type);
|
|
||||||
const notificationCls: any = notificationPlugin.target;
|
|
||||||
const notificationSender = new notificationCls();
|
|
||||||
const notificationCtx: NotificationContext = {
|
|
||||||
http: utils.http,
|
|
||||||
logger,
|
|
||||||
utils,
|
|
||||||
emailService: this.options.emailService,
|
|
||||||
};
|
|
||||||
//设置参数
|
|
||||||
merge(notificationSender, notifyConfig.setting);
|
|
||||||
notificationSender.setCtx(notificationCtx);
|
|
||||||
await notificationSender.onInstance();
|
|
||||||
const body: NotificationBody = {
|
|
||||||
title: subject,
|
|
||||||
content,
|
|
||||||
userId: this.pipeline.userId,
|
|
||||||
pipeline: this.pipeline,
|
|
||||||
result: this.lastRuntime.pipeline.status,
|
|
||||||
pipelineId: this.pipeline.id,
|
|
||||||
historyId: this.runtime.id,
|
|
||||||
errorMessage,
|
|
||||||
url,
|
|
||||||
};
|
|
||||||
//发送通知
|
//发送通知
|
||||||
await notificationSender.send(body);
|
await this.options.notificationService.send({
|
||||||
|
id: notification.notificationId,
|
||||||
|
useDefault: true,
|
||||||
|
useEmail: false,
|
||||||
|
body: {
|
||||||
|
title: subject,
|
||||||
|
content,
|
||||||
|
userId: this.pipeline.userId,
|
||||||
|
pipeline: this.pipeline,
|
||||||
|
result: this.lastRuntime.pipeline.status,
|
||||||
|
pipelineId: this.pipeline.id,
|
||||||
|
historyId: this.runtime.id,
|
||||||
|
errorMessage,
|
||||||
|
url,
|
||||||
|
},
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error("send notification error", e);
|
logger.error("send notification error", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,18 @@ export type NotificationInstanceConfig = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type NotificationSendReq = {
|
||||||
|
id?: number;
|
||||||
|
useDefault?: boolean;
|
||||||
|
useEmail?: boolean;
|
||||||
|
emailAddress?: string;
|
||||||
|
logger?: ILogger;
|
||||||
|
body: NotificationBody;
|
||||||
|
};
|
||||||
export interface INotificationService {
|
export interface INotificationService {
|
||||||
getById(id: number): Promise<NotificationInstanceConfig>;
|
getById(id: number): Promise<NotificationInstanceConfig>;
|
||||||
getDefault(): Promise<NotificationInstanceConfig>;
|
getDefault(): Promise<NotificationInstanceConfig>;
|
||||||
|
send(req: NotificationSendReq): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INotification {
|
export interface INotification {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// src/decorator/memoryCache.decorator.ts
|
// src/decorator/memoryCache.decorator.ts
|
||||||
import { Decorator } from "../decorator/index.js";
|
import { Decorator } from "../decorator/index.js";
|
||||||
import * as _ from "lodash-es";
|
import * as _ from "lodash-es";
|
||||||
|
import { merge } from "lodash-es";
|
||||||
import { notificationRegistry } from "./registry.js";
|
import { notificationRegistry } from "./registry.js";
|
||||||
import { BaseNotification, NotificationBody, NotificationContext, NotificationDefine, NotificationInputDefine, NotificationInstanceConfig } from "./api.js";
|
import { BaseNotification, NotificationBody, NotificationContext, NotificationDefine, NotificationInputDefine, NotificationInstanceConfig } from "./api.js";
|
||||||
import { isPlus } from "@certd/plus-core";
|
|
||||||
|
|
||||||
// 提供一个唯一 key
|
// 提供一个唯一 key
|
||||||
export const NOTIFICATION_CLASS_KEY = "pipeline:notification";
|
export const NOTIFICATION_CLASS_KEY = "pipeline:notification";
|
||||||
|
@ -47,9 +47,7 @@ export async function newNotification(type: string, input: any, ctx: Notificatio
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const plugin = new register.target();
|
const plugin = new register.target();
|
||||||
for (const key in input) {
|
merge(plugin, input);
|
||||||
plugin[key] = input[key];
|
|
||||||
}
|
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
throw new Error("ctx is required");
|
throw new Error("ctx is required");
|
||||||
}
|
}
|
||||||
|
@ -61,8 +59,5 @@ export async function newNotification(type: string, input: any, ctx: Notificatio
|
||||||
|
|
||||||
export async function sendNotification(opts: { config: NotificationInstanceConfig; ctx: NotificationContext; body: NotificationBody }) {
|
export async function sendNotification(opts: { config: NotificationInstanceConfig; ctx: NotificationContext; body: NotificationBody }) {
|
||||||
const notification: BaseNotification = await newNotification(opts.config.type, opts.config.setting, opts.ctx);
|
const notification: BaseNotification = await newNotification(opts.config.type, opts.config.setting, opts.ctx);
|
||||||
if (notification.define.needPlus && !isPlus()) {
|
|
||||||
opts.body.content = `${opts.body.content}\n\n注意:此通知渠道已调整为专业版功能,后续版本将不再支持发送,请尽快修改或升级为专业版`;
|
|
||||||
}
|
|
||||||
await notification.doSend(opts.body);
|
await notification.doSend(opts.body);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { AbstractTaskPlugin, IContext, NotificationBody, sendNotification, Step, TaskInput, TaskOutput } from "@certd/pipeline";
|
import { AbstractTaskPlugin, IContext, NotificationBody, Step, TaskInput, TaskOutput } from "@certd/pipeline";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import type { CertInfo } from "./acme.js";
|
import type { CertInfo } from "./acme.js";
|
||||||
import { CertReader } from "./cert-reader.js";
|
import { CertReader } from "./cert-reader.js";
|
||||||
|
@ -295,7 +295,6 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
||||||
* 检查是否过期,默认提前35天
|
* 检查是否过期,默认提前35天
|
||||||
* @param expires
|
* @param expires
|
||||||
* @param maxDays
|
* @param maxDays
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
*/
|
||||||
isWillExpire(expires: number, maxDays = 20) {
|
isWillExpire(expires: number, maxDays = 20) {
|
||||||
if (expires == null) {
|
if (expires == null) {
|
||||||
|
@ -312,39 +311,19 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
||||||
this.logger.info("发送证书申请成功通知");
|
this.logger.info("发送证书申请成功通知");
|
||||||
const url = await this.ctx.urlService.getPipelineDetailUrl(this.pipeline.id, this.ctx.runtime.id);
|
const url = await this.ctx.urlService.getPipelineDetailUrl(this.pipeline.id, this.ctx.runtime.id);
|
||||||
const body: NotificationBody = {
|
const body: NotificationBody = {
|
||||||
title: `【Certd】证书申请成功【${this.pipeline.title}】`,
|
title: `证书申请成功【${this.pipeline.title}】`,
|
||||||
content: `域名:${this.domains.join(",")}`,
|
content: `域名:${this.domains.join(",")}`,
|
||||||
url: url,
|
url: url,
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const defNotification = await this.ctx.notificationService.getDefault();
|
await this.ctx.notificationService.send({
|
||||||
if (defNotification) {
|
useDefault: true,
|
||||||
this.logger.info(`通知渠道:${defNotification.name}`);
|
useEmail: true,
|
||||||
const notificationCtx = {
|
emailAddress: this.email,
|
||||||
http: this.ctx.http,
|
body,
|
||||||
logger: this.logger,
|
});
|
||||||
utils: this.ctx.utils,
|
|
||||||
emailService: this.ctx.emailService,
|
|
||||||
};
|
|
||||||
await sendNotification({
|
|
||||||
config: defNotification,
|
|
||||||
ctx: notificationCtx,
|
|
||||||
body,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.logger.warn("未配置默认通知,将发送邮件通知");
|
|
||||||
await this.sendSuccessEmail(body);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.error("证书申请成功通知发送失败", e);
|
this.logger.error("证书申请成功通知发送失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async sendSuccessEmail(body: NotificationBody) {
|
|
||||||
this.logger.info("发送邮件通知:" + this.email);
|
|
||||||
await this.ctx.emailService.send({
|
|
||||||
receivers: [this.email],
|
|
||||||
subject: body.title,
|
|
||||||
content: body.content,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,7 @@ function clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function emitValue(value: any) {
|
async function emitValue(value: any) {
|
||||||
|
target.value = optionsDictRef.dataMap[value];
|
||||||
if (value !== 0 && pipeline?.value && target && pipeline.value.userId !== target.value.userId) {
|
if (value !== 0 && pipeline?.value && target && pipeline.value.userId !== target.value.userId) {
|
||||||
message.error("对不起,您不能修改他人流水线的通知");
|
message.error("对不起,您不能修改他人流水线的通知");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -12,10 +12,7 @@ export class EmailController extends BaseController {
|
||||||
emailService: EmailService;
|
emailService: EmailService;
|
||||||
|
|
||||||
@Post('/test', { summary: Constants.per.authOnly })
|
@Post('/test', { summary: Constants.per.authOnly })
|
||||||
public async test(
|
public async test(@Body('receiver') receiver) {
|
||||||
@Body('receiver')
|
|
||||||
receiver
|
|
||||||
) {
|
|
||||||
const userId = super.getUserId();
|
const userId = super.getUserId();
|
||||||
await this.emailService.test(userId, receiver);
|
await this.emailService.test(userId, receiver);
|
||||||
return this.ok({});
|
return this.ok({});
|
||||||
|
|
|
@ -56,18 +56,6 @@ export class HandleController extends BaseController {
|
||||||
@Post('/notification', { summary: Constants.per.authOnly })
|
@Post('/notification', { summary: Constants.per.authOnly })
|
||||||
async notificationRequest(@Body(ALL) body: NotificationRequestHandleReq) {
|
async notificationRequest(@Body(ALL) body: NotificationRequestHandleReq) {
|
||||||
const input = body.input.body;
|
const input = body.input.body;
|
||||||
// if (body.input.id > 0) {
|
|
||||||
// const oldEntity = await this.notificationService.info(body.input.id);
|
|
||||||
// if (oldEntity) {
|
|
||||||
// if (oldEntity.userId !== this.getUserId()) {
|
|
||||||
// throw new Error('notification not found');
|
|
||||||
// }
|
|
||||||
// const param: any = {
|
|
||||||
// type: body.typeName,
|
|
||||||
// setting: JSON.stringify(body.input.access),
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
const notification = await newNotification(body.typeName, input, {
|
const notification = await newNotification(body.typeName, input, {
|
||||||
http,
|
http,
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { Inject, Provide } from '@midwayjs/core';
|
import { Inject, Provide } from '@midwayjs/core';
|
||||||
import { cache, isDev, randomNumber } from '@certd/basic';
|
import { cache, isDev, randomNumber } from '@certd/basic';
|
||||||
import { SysSettingsService } from '@certd/lib-server';
|
import { SysSettingsService, SysSiteInfo } from '@certd/lib-server';
|
||||||
import { SmsServiceFactory } from '../sms/factory.js';
|
import { SmsServiceFactory } from '../sms/factory.js';
|
||||||
import { ISmsService } from '../sms/api.js';
|
import { ISmsService } from '../sms/api.js';
|
||||||
import { CodeErrorException } from '@certd/lib-server/dist/basic/exception/code-error-exception.js';
|
import { CodeErrorException } from '@certd/lib-server/dist/basic/exception/code-error-exception.js';
|
||||||
import { EmailService } from './email-service.js';
|
import { EmailService } from './email-service.js';
|
||||||
import { AccessService } from '../../pipeline/service/access-service.js';
|
import { AccessService } from '../../pipeline/service/access-service.js';
|
||||||
import { AccessSysGetter } from '../../pipeline/service/access-sys-getter.js';
|
import { AccessSysGetter } from '../../pipeline/service/access-sys-getter.js';
|
||||||
|
import { isComm } from '@certd/plus-core';
|
||||||
|
|
||||||
// {data: '<svg.../svg>', text: 'abcd'}
|
// {data: '<svg.../svg>', text: 'abcd'}
|
||||||
/**
|
/**
|
||||||
|
@ -99,9 +100,17 @@ export class CodeService {
|
||||||
throw new Error('randomStr不能为空');
|
throw new Error('randomStr不能为空');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let siteTitle = 'Certd';
|
||||||
|
if (isComm()) {
|
||||||
|
const siteInfo = await this.sysSettingsService.getSetting<SysSiteInfo>(SysSiteInfo);
|
||||||
|
if (siteInfo) {
|
||||||
|
siteTitle = siteInfo.title || siteTitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const code = randomNumber(4);
|
const code = randomNumber(4);
|
||||||
await this.emailService.send({
|
await this.emailService.send({
|
||||||
subject: '【Certd】验证码',
|
subject: `【${siteTitle}】验证码`,
|
||||||
content: `您的验证码是${code},请勿泄露`,
|
content: `您的验证码是${code},请勿泄露`,
|
||||||
receivers: [email],
|
receivers: [email],
|
||||||
});
|
});
|
||||||
|
|
|
@ -91,7 +91,7 @@ export class EmailService implements IEmailService {
|
||||||
const mailOptions = {
|
const mailOptions = {
|
||||||
from: `${sysTitle} <${emailConfig.sender}>`,
|
from: `${sysTitle} <${emailConfig.sender}>`,
|
||||||
to: email.receivers.join(', '), // list of receivers
|
to: email.receivers.join(', '), // list of receivers
|
||||||
subject: email.subject,
|
subject: `【${sysTitle}】${email.subject}`,
|
||||||
text: email.content,
|
text: email.content,
|
||||||
};
|
};
|
||||||
await transporter.sendMail(mailOptions);
|
await transporter.sendMail(mailOptions);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { INotificationService } from '@certd/pipeline';
|
import { INotificationService, NotificationSendReq } from '@certd/pipeline';
|
||||||
import { NotificationService } from './notification-service.js';
|
import { NotificationService } from './notification-service.js';
|
||||||
|
|
||||||
export class NotificationGetter implements INotificationService {
|
export class NotificationGetter implements INotificationService {
|
||||||
|
@ -17,4 +17,8 @@ export class NotificationGetter implements INotificationService {
|
||||||
async getById(id: any) {
|
async getById(id: any) {
|
||||||
return await this.notificationService.getById(id, this.userId);
|
return await this.notificationService.getById(id, this.userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async send(req: NotificationSendReq): Promise<void> {
|
||||||
|
return await this.notificationService.send(req, this.userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||||
import { BaseService, ValidateException } from '@certd/lib-server';
|
import { BaseService, SysSettingsService, SysSiteInfo, ValidateException } from '@certd/lib-server';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { NotificationEntity } from '../entity/notification.js';
|
import { NotificationEntity } from '../entity/notification.js';
|
||||||
import { NotificationInstanceConfig, notificationRegistry } from '@certd/pipeline';
|
import { NotificationInstanceConfig, notificationRegistry, NotificationSendReq, sendNotification } from '@certd/pipeline';
|
||||||
|
import { http, utils } from '@certd/basic';
|
||||||
|
import { EmailService } from '../../basic/service/email-service.js';
|
||||||
|
import { isComm } from '@certd/plus-core';
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Singleton)
|
||||||
|
@ -11,6 +14,12 @@ export class NotificationService extends BaseService<NotificationEntity> {
|
||||||
@InjectEntityModel(NotificationEntity)
|
@InjectEntityModel(NotificationEntity)
|
||||||
repository: Repository<NotificationEntity>;
|
repository: Repository<NotificationEntity>;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
emailService: EmailService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
sysSettingsService: SysSettingsService;
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
getRepository() {
|
getRepository() {
|
||||||
return this.repository;
|
return this.repository;
|
||||||
|
@ -124,4 +133,54 @@ export class NotificationService extends BaseService<NotificationEntity> {
|
||||||
});
|
});
|
||||||
return this.buildNotificationInstanceConfig(res);
|
return this.buildNotificationInstanceConfig(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async send(req: NotificationSendReq, userId?: number) {
|
||||||
|
const logger = req.logger;
|
||||||
|
let notifyConfig: NotificationInstanceConfig = null;
|
||||||
|
if (req.id && req.id > 0) {
|
||||||
|
notifyConfig = await this.getById(req.id, userId);
|
||||||
|
if (!notifyConfig) {
|
||||||
|
logger.warn(`未找到通知配置<${req.id}>`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!notifyConfig) {
|
||||||
|
if (req.id === 0 || req.useDefault) {
|
||||||
|
notifyConfig = await this.getDefault(userId);
|
||||||
|
if (!notifyConfig) {
|
||||||
|
logger.warn(`未找到默认通知配置`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notifyConfig) {
|
||||||
|
//发送通知
|
||||||
|
logger.info('发送通知, 使用通知渠道:' + notifyConfig.name);
|
||||||
|
|
||||||
|
let siteTitle = 'Certd';
|
||||||
|
if (isComm()) {
|
||||||
|
const siteInfo = await this.sysSettingsService.getSetting<SysSiteInfo>(SysSiteInfo);
|
||||||
|
siteTitle = siteInfo?.title || siteTitle;
|
||||||
|
}
|
||||||
|
req.body.title = `【${siteTitle}】${req.body.title}`;
|
||||||
|
await sendNotification({
|
||||||
|
config: notifyConfig,
|
||||||
|
ctx: {
|
||||||
|
http: http,
|
||||||
|
logger: logger,
|
||||||
|
utils: utils,
|
||||||
|
emailService: this.emailService,
|
||||||
|
},
|
||||||
|
body: req.body,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (req.useEmail && req.emailAddress) {
|
||||||
|
logger.info('使用邮件通知');
|
||||||
|
await this.emailService.send({
|
||||||
|
receivers: [req.emailAddress],
|
||||||
|
subject: req.body.title,
|
||||||
|
content: req.body.content,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue