From afc27c804d7d7c4942fc0081bc347b45006b904b Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Wed, 4 Mar 2026 17:32:50 +0000 Subject: [PATCH] email --- .../service/infrastructure/emailService.ts | 8 ++- .../notificationProviders/email.ts | 51 ++++++++++++------- .../notificationProviders/matrix.ts | 12 ++--- .../notificationProviders/utils.ts | 5 +- server/src/types/alert.ts | 7 +-- 5 files changed, 50 insertions(+), 33 deletions(-) diff --git a/server/src/service/infrastructure/emailService.ts b/server/src/service/infrastructure/emailService.ts index 26e3e3e6d..9de3999a4 100755 --- a/server/src/service/infrastructure/emailService.ts +++ b/server/src/service/infrastructure/emailService.ts @@ -7,7 +7,13 @@ const __dirname = path.dirname(__filename); const SERVICE_NAME = "EmailService"; -class EmailService { +export interface IEmailService { + init(): void; + buildEmail(template: string, context: Record): Promise; + sendEmail(to: string, subject: string, html: string, transportConfig?: EmailTransportConfig): Promise; +} + +class EmailService implements IEmailService { static SERVICE_NAME = SERVICE_NAME; private settingsService: any; diff --git a/server/src/service/infrastructure/notificationProviders/email.ts b/server/src/service/infrastructure/notificationProviders/email.ts index effd94946..c14d59a85 100644 --- a/server/src/service/infrastructure/notificationProviders/email.ts +++ b/server/src/service/infrastructure/notificationProviders/email.ts @@ -1,15 +1,15 @@ const SERVICE_NAME = "EmailProvider"; -import type { Monitor, Notification, MonitorStatusResponse } from "@/types/index.js"; +import type { Notification } from "@/types/index.js"; import { INotificationProvider } from "@/service/index.js"; -import type { MonitorActionDecision } from "@/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js"; import { buildTestEmail } from "@/service/infrastructure/notificationProviders/utils.js"; import type { NotificationMessage } from "@/types/notificationMessage.js"; - +import type { ILogger } from "@/utils/logger.js"; +import { IEmailService } from "@/service/infrastructure/emailService.js"; export class EmailProvider implements INotificationProvider { - private emailService: any; - private logger: any; + private emailService: IEmailService; + private logger: ILogger; - constructor(emailService: any, logger: any) { + constructor(emailService: IEmailService, logger: ILogger) { this.emailService = emailService; this.logger = logger; } @@ -18,6 +18,24 @@ export class EmailProvider implements INotificationProvider { const subject = "Test notification"; const html = await buildTestEmail(this.emailService); + if (!notification.address) { + this.logger.warn({ + message: "Missing address", + service: SERVICE_NAME, + method: "sendTestAlert", + }); + return false; + } + + if (!html) { + this.logger.warn({ + message: "Failed to build test email content", + service: SERVICE_NAME, + method: "sendTestAlert", + }); + return false; + } + const messageId = await this.emailService.sendEmail(notification.address, subject, html); if (!messageId) { this.logger.warn({ @@ -38,6 +56,15 @@ export class EmailProvider implements INotificationProvider { const subject = this.buildSubject(message); const html = await this.buildEmailFromMessage(message); + if (!html) { + this.logger.warn({ + message: "Failed to build email content", + service: SERVICE_NAME, + method: "sendMessage", + }); + return false; + } + const messageId = await this.emailService.sendEmail(notification.address, subject, html); if (!messageId) { this.logger.warn({ @@ -65,7 +92,7 @@ export class EmailProvider implements INotificationProvider { } } - private async buildEmailFromMessage(message: NotificationMessage): Promise { + private async buildEmailFromMessage(message: NotificationMessage): Promise { const context = { title: message.content.title, summary: message.content.summary, @@ -88,16 +115,6 @@ export class EmailProvider implements INotificationProvider { const html = await this.emailService.buildEmail("unifiedNotificationTemplate", context); - this.logger.info({ - message: "[DEBUG] Email HTML generated", - service: SERVICE_NAME, - method: "buildEmailFromMessage", - details: { - htmlLength: html?.length || 0, - htmlPreview: html?.substring(0, 200), - }, - }); - return html; } diff --git a/server/src/service/infrastructure/notificationProviders/matrix.ts b/server/src/service/infrastructure/notificationProviders/matrix.ts index 8d58e6ead..ce53215bd 100644 --- a/server/src/service/infrastructure/notificationProviders/matrix.ts +++ b/server/src/service/infrastructure/notificationProviders/matrix.ts @@ -1,14 +1,15 @@ const SERVICE_NAME = "MatrixProvider"; import got from "got"; import type { INotificationProvider } from "@/service/index.js"; -import type { Notification } from "@/types/index.js"; +import type { AlertMatrixPayload, Notification } from "@/types/index.js"; import type { NotificationMessage } from "@/types/notificationMessage.js"; import { getTestMessage } from "@/service/infrastructure/notificationProviders/utils.js"; +import { ILogger } from "@/utils/logger.js"; export class MatrixProvider implements INotificationProvider { - private logger: any; + private logger: ILogger; - constructor(logger: any) { + constructor(logger: ILogger) { this.logger = logger; } @@ -42,9 +43,6 @@ export class MatrixProvider implements INotificationProvider { } }; - /** - * New unified message format - builds Matrix HTML message from NotificationMessage - */ sendMessage = async (notification: Notification, message: NotificationMessage): Promise => { const { homeserverUrl, accessToken, roomId } = notification; @@ -87,7 +85,7 @@ export class MatrixProvider implements INotificationProvider { * Returns both plain text and HTML formatted versions * Matrix supports HTML subset for rich formatting */ - private buildMatrixMessage(message: NotificationMessage): { plainText: string; htmlText: string } { + private buildMatrixMessage(message: NotificationMessage): AlertMatrixPayload { const plainLines: string[] = []; const htmlLines: string[] = []; diff --git a/server/src/service/infrastructure/notificationProviders/utils.ts b/server/src/service/infrastructure/notificationProviders/utils.ts index 8d4e08171..454df1963 100644 --- a/server/src/service/infrastructure/notificationProviders/utils.ts +++ b/server/src/service/infrastructure/notificationProviders/utils.ts @@ -1,6 +1,5 @@ -import EmailService from "@/service/infrastructure/emailService.js"; -// Test notification helpers - used by all providers for test alerts -export const buildTestEmail = async (emailService: EmailService) => { +import { IEmailService } from "@/service/infrastructure/emailService.js"; +export const buildTestEmail = async (emailService: IEmailService) => { const context = { testName: "Monitoring System" }; const html = await emailService.buildEmail("testEmailTemplate", context); return html; diff --git a/server/src/types/alert.ts b/server/src/types/alert.ts index 03e88fe6a..8f5bf509e 100644 --- a/server/src/types/alert.ts +++ b/server/src/types/alert.ts @@ -11,11 +11,8 @@ export interface AlertPagerDutyPayload { } export interface AlertMatrixPayload { - friendlyName?: string; - homeserverUrl: string; - accessToken: string; - roomId: string; - monitorName: string; + plainText: string; + htmlText: string; } export interface Alert {