diff --git a/packages/backend/server/src/__tests__/mocks/mailer.mock.ts b/packages/backend/server/src/__tests__/mocks/mailer.mock.ts index 5cb6291a3a..49632f52fa 100644 --- a/packages/backend/server/src/__tests__/mocks/mailer.mock.ts +++ b/packages/backend/server/src/__tests__/mocks/mailer.mock.ts @@ -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( name: Mail diff --git a/packages/backend/server/src/core/mail/mailer.ts b/packages/backend/server/src/core/mail/mailer.ts index 4abef4b0e5..c1d459342c 100644 --- a/packages/backend/server/src/core/mail/mailer.ts +++ b/packages/backend/server/src/core/mail/mailer.ts @@ -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(); } diff --git a/packages/backend/server/src/core/mail/sender.ts b/packages/backend/server/src/core/mail/sender.ts index b941f8e41e..5567851e4b 100644 --- a/packages/backend/server/src/core/mail/sender.ts +++ b/packages/backend/server/src/core/mail/sender.ts @@ -43,6 +43,10 @@ export class MailSender { return createTransport(configToSMTPOptions(config)); } + get configured() { + return this.smtp !== null; + } + @OnEvent('config.init') onConfigInit() { this.setup(); diff --git a/packages/backend/server/src/core/notification/service.ts b/packages/backend/server/src/core/notification/service.ts index c6057dd8a2..1ce0f23bff 100644 --- a/packages/backend/server/src/core/notification/service.ts +++ b/packages/backend/server/src/core/notification/service.ts @@ -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: { diff --git a/packages/backend/server/src/core/workspaces/event.ts b/packages/backend/server/src/core/workspaces/event.ts index f0a24b38d2..c17c7ba93b 100644 --- a/packages/backend/server/src/core/workspaces/event.ts +++ b/packages/backend/server/src/core/workspaces/event.ts @@ -65,7 +65,7 @@ export class WorkspaceEvents { return; } - await this.mailer.send({ + await this.mailer.trySend({ name: 'MemberRemoved', to: user.email, props: { diff --git a/packages/backend/server/src/core/workspaces/service.ts b/packages/backend/server/src/core/workspaces/service.ts index 37c2799be5..60e1234084 100644 --- a/packages/backend/server/src/core/workspaces/service.ts +++ b/packages/backend/server/src/core/workspaces/service.ts @@ -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: {