Email Notifier Update

This commit is contained in:
Rokojori 2026-07-14 15:45:27 +02:00
parent d14c46307f
commit 4b913eb53f
5 changed files with 91 additions and 2 deletions

View File

@ -0,0 +1,4 @@
export interface EmailSender
{
sendEmail( to: string, subject: string, body: string ): Promise<void>;
}

View File

@ -0,0 +1,22 @@
import { EmailSender } from './EmailSender';
import { SMTPEmailSender } from './SMTPEmailSender';
export class EmailService
{
static readonly reportEmail = 'josef@rokojori.com';
private static sender: EmailSender = new SMTPEmailSender(
{
host: process.env.SMTP_HOST ?? '',
port: Number( process.env.SMTP_PORT ?? 587 ),
secure: process.env.SMTP_SECURE === 'true',
user: process.env.SMTP_USER ?? '',
pass: process.env.SMTP_PASS ?? '',
from: process.env.SMTP_FROM ?? ''
} );
static async sendEmail( to: string, subject: string, body: string ): Promise<void>
{
return EmailService.sender.sendEmail( to, subject, body );
}
}

View File

@ -0,0 +1,45 @@
import nodemailer from 'nodemailer';
import { EmailSender } from './EmailSender';
export interface SMTPConfig
{
host: string;
port: number;
secure: boolean;
user: string;
pass: string;
from: string;
}
export class SMTPEmailSender implements EmailSender
{
private transporter: nodemailer.Transporter;
private from: string;
constructor( config: SMTPConfig )
{
this.from = config.from;
this.transporter = nodemailer.createTransport(
{
host: config.host,
port: config.port,
secure: config.secure,
auth:
{
user: config.user,
pass: config.pass
}
} );
}
async sendEmail( to: string, subject: string, body: string ): Promise<void>
{
await this.transporter.sendMail(
{
from: this.from,
to,
subject,
text: body
} );
}
}

View File

@ -11,6 +11,7 @@ import layoutRouter from './routes/layout';
import rojosRouter from './routes/rojos';
import { generateLocales } from './localeGenerator';
import deployRouter from './routes/deploy';
import { EmailService } from './email/EmailService';
generateLocales();
@ -36,7 +37,16 @@ app.get( '/api/auth/me', requireAuth, ( req, res ) => res.json( req.user ) );
app.get( '/', ( _req, res ) => res.redirect( '/dashboard.html' ) );
export function startServer( port: number ): void {
app.listen( port, () => console.log( `Roject running on http://localhost:${port}` ) );
app.listen( port, () =>
{
const time = new Date().toISOString();
console.log( `Roject running on http://localhost:${port}` );
EmailService.sendEmail(
EmailService.reportEmail,
'Roject — server started',
`Server started at ${time} on port ${port}.`
).catch( () => {} );
} );
}
if ( require.main === module ) {

View File

@ -2,6 +2,7 @@ import { Router } from 'express';
import express from 'express';
import { spawn } from 'child_process';
import { createHmac, timingSafeEqual } from 'crypto';
import { EmailService } from '../email/EmailService';
const router = Router();
@ -46,7 +47,14 @@ router.post( '/', express.raw( { type: 'application/json' } ), ( req, res ) => {
return;
}
console.log( `[deploy] triggered by push from ${payload.pusher?.login ?? 'unknown'}` );
const pusher = payload.pusher?.login ?? 'unknown';
const time = new Date().toISOString();
console.log( `[deploy] triggered by push from ${pusher}` );
EmailService.sendEmail(
EmailService.reportEmail,
'Roject — deploy requested',
`Deploy triggered at ${time} by ${pusher}.`
).catch( () => {} );
res.json( { message: 'Deploy triggered' } );
triggerDeploy();
} );