mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
fix(server): avoid job fail if mail is not configured (#12306)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Improved email notification handling to prevent errors from interrupting other processes when sending emails is not possible. - **Refactor** - Updated internal email sending logic across notifications and workspace features for more robust operation. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -6,6 +6,9 @@ import { MailName } from '../../mails';
|
||||
|
||||
export class MockMailer {
|
||||
send = Sinon.createStubInstance(Mailer).send.resolves(true);
|
||||
trySend(command: Jobs['notification.sendMail']) {
|
||||
return this.send(command, true);
|
||||
}
|
||||
|
||||
last<Mail extends MailName>(
|
||||
name: Mail
|
||||
|
||||
@@ -10,13 +10,20 @@ export class Mailer {
|
||||
private readonly sender: MailSender
|
||||
) {}
|
||||
|
||||
get enabled() {
|
||||
// @ts-expect-error internal api
|
||||
return this.sender.smtp !== null;
|
||||
/**
|
||||
* try to send mail
|
||||
*
|
||||
* @note never throw
|
||||
*/
|
||||
async trySend(command: Jobs['notification.sendMail']) {
|
||||
return this.send(command, true);
|
||||
}
|
||||
|
||||
async send(command: Jobs['notification.sendMail']) {
|
||||
if (!this.enabled) {
|
||||
async send(command: Jobs['notification.sendMail'], suppressError = false) {
|
||||
if (!this.sender.configured) {
|
||||
if (suppressError) {
|
||||
return false;
|
||||
}
|
||||
throw new EmailServiceNotConfigured();
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,10 @@ export class MailSender {
|
||||
return createTransport(configToSMTPOptions(config));
|
||||
}
|
||||
|
||||
get configured() {
|
||||
return this.smtp !== null;
|
||||
}
|
||||
|
||||
@OnEvent('config.init')
|
||||
onConfigInit() {
|
||||
this.setup();
|
||||
|
||||
@@ -65,7 +65,7 @@ export class NotificationService {
|
||||
elementId: input.body.doc.elementId,
|
||||
})
|
||||
);
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'Mention',
|
||||
to: receiver.email,
|
||||
props: {
|
||||
@@ -110,7 +110,7 @@ export class NotificationService {
|
||||
if (!receiver) {
|
||||
return;
|
||||
}
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'MemberInvitation',
|
||||
to: receiver.email,
|
||||
props: {
|
||||
@@ -161,7 +161,7 @@ export class NotificationService {
|
||||
if (!inviter) {
|
||||
return;
|
||||
}
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'MemberAccepted',
|
||||
to: inviter.email,
|
||||
props: {
|
||||
@@ -226,7 +226,7 @@ export class NotificationService {
|
||||
if (!reviewer) {
|
||||
return;
|
||||
}
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'LinkInvitationReviewRequest',
|
||||
to: reviewer.email,
|
||||
props: {
|
||||
@@ -273,7 +273,7 @@ export class NotificationService {
|
||||
if (!receiver) {
|
||||
return;
|
||||
}
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'LinkInvitationApprove',
|
||||
to: receiver.email,
|
||||
props: {
|
||||
@@ -312,7 +312,7 @@ export class NotificationService {
|
||||
if (!receiver) {
|
||||
return;
|
||||
}
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'LinkInvitationDecline',
|
||||
to: receiver.email,
|
||||
props: {
|
||||
|
||||
@@ -65,7 +65,7 @@ export class WorkspaceEvents {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'MemberRemoved',
|
||||
to: user.email,
|
||||
props: {
|
||||
|
||||
@@ -107,7 +107,7 @@ export class WorkspaceService {
|
||||
const admins = await this.models.workspaceUser.getAdmins(workspaceId);
|
||||
|
||||
const link = this.url.link(`/workspace/${workspaceId}`);
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'TeamWorkspaceUpgraded',
|
||||
to: owner.email,
|
||||
props: {
|
||||
@@ -121,7 +121,7 @@ export class WorkspaceService {
|
||||
|
||||
await Promise.allSettled(
|
||||
admins.map(async user => {
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'TeamWorkspaceUpgraded',
|
||||
to: user.email,
|
||||
props: {
|
||||
@@ -188,7 +188,7 @@ export class WorkspaceService {
|
||||
}
|
||||
|
||||
if (ws.role === WorkspaceRole.Admin) {
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'TeamBecomeAdmin',
|
||||
to: user.email,
|
||||
props: {
|
||||
@@ -199,7 +199,7 @@ export class WorkspaceService {
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'TeamBecomeCollaborator',
|
||||
to: user.email,
|
||||
props: {
|
||||
@@ -213,7 +213,7 @@ export class WorkspaceService {
|
||||
}
|
||||
|
||||
async sendOwnershipTransferredEmail(email: string, ws: { id: string }) {
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'OwnershipTransferred',
|
||||
to: email,
|
||||
props: {
|
||||
@@ -225,7 +225,7 @@ export class WorkspaceService {
|
||||
}
|
||||
|
||||
async sendOwnershipReceivedEmail(email: string, ws: { id: string }) {
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'OwnershipReceived',
|
||||
to: email,
|
||||
props: {
|
||||
@@ -238,7 +238,7 @@ export class WorkspaceService {
|
||||
|
||||
async sendLeaveEmail(workspaceId: string, userId: string) {
|
||||
const owner = await this.models.workspaceUser.getOwner(workspaceId);
|
||||
await this.mailer.send({
|
||||
await this.mailer.trySend({
|
||||
name: 'MemberLeave',
|
||||
to: owner.email,
|
||||
props: {
|
||||
|
||||
Reference in New Issue
Block a user