diff --git a/backend/src/services/secret/secret-queue.ts b/backend/src/services/secret/secret-queue.ts index 07cb0923d..50c77da2b 100644 --- a/backend/src/services/secret/secret-queue.ts +++ b/backend/src/services/secret/secret-queue.ts @@ -562,6 +562,30 @@ export const secretQueueFactory = ({ throw new Error("Secret path not found"); } + const sendIntegrationSyncFailedMail = async (integrationId: string, syncMessage: string | null) => { + const appCfg = getConfig(); + + // If smtp is not configured, we can return early without having to fetch the project members. + if (!appCfg.isSmtpConfigured) return; + + const projectMembers = await projectMembershipDAL.findAllProjectMembers(projectId); + const project = await projectDAL.findById(projectId); + + const filteredProjectMembers = + isManual && actorId ? projectMembers.filter((member) => member.userId === actorId) : projectMembers; + + await smtpService.sendMail({ + recipients: filteredProjectMembers.map((member) => member.user.email!), + template: SmtpTemplates.IntegrationSyncFailed, + subjectLine: `Integration Sync Failed`, + substitutions: { + syncMessage, + projectName: project.name, + integrationUrl: `${appCfg.SITE_URL}/integrations/details/${integrationId}` + } + }); + }; + // find all imports made with the given environment and secret path const linkSourceDto = { projectId, @@ -833,6 +857,11 @@ export const secretQueueFactory = ({ syncMessage: response?.syncMessage ?? "", isSynced: response?.isSynced ?? true }); + + // May be undefined, if it's undefined we assume the sync was successful, hence the strict equality type check. + if (response?.isSynced === false) { + await sendIntegrationSyncFailedMail(integration.id, response?.syncMessage); + } } catch (err) { logger.error( err, @@ -863,6 +892,8 @@ export const secretQueueFactory = ({ syncMessage: message, isSynced: false }); + + await sendIntegrationSyncFailedMail(integration.id, message); } } } finally { diff --git a/backend/src/services/smtp/smtp-service.ts b/backend/src/services/smtp/smtp-service.ts index d0e1e0774..823da4cca 100644 --- a/backend/src/services/smtp/smtp-service.ts +++ b/backend/src/services/smtp/smtp-service.ts @@ -33,7 +33,8 @@ export enum SmtpTemplates { SecretLeakIncident = "secretLeakIncident.handlebars", WorkspaceInvite = "workspaceInvitation.handlebars", ScimUserProvisioned = "scimUserProvisioned.handlebars", - PkiExpirationAlert = "pkiExpirationAlert.handlebars" + PkiExpirationAlert = "pkiExpirationAlert.handlebars", + IntegrationSyncFailed = "integrationSyncFailed.handlebars" } export enum SmtpHost { diff --git a/backend/src/services/smtp/templates/integrationSyncFailed.handlebars b/backend/src/services/smtp/templates/integrationSyncFailed.handlebars new file mode 100644 index 000000000..4f5c35014 --- /dev/null +++ b/backend/src/services/smtp/templates/integrationSyncFailed.handlebars @@ -0,0 +1,24 @@ + + + + + + Integration Sync Failed + + + +

Infisical

+

An integration in your project + {{projectName}} + failed to sync secrets.
+ + View integration details. + +

+ + {{#if syncMessage}} +

Reason: {{syncMessage}}

+ {{/if}} + + + \ No newline at end of file