Merge pull request #3 from neuronapp/send-emails-task

Add email sending functionality
This commit is contained in:
Hakan Shehu
2024-11-09 17:36:17 +01:00
committed by GitHub
7 changed files with 126 additions and 311 deletions

View File

@@ -23,6 +23,7 @@
"@types/express": "^4.17.21",
"@types/multer": "^1.4.12",
"@types/node": "^22.7.7",
"@types/nodemailer": "^6.4.16",
"@types/pg": "^8.11.10",
"@types/ws": "^8.5.12",
"nodemon": "^3.1.7",
@@ -44,6 +45,7 @@
"kafkajs": "^2.2.4",
"kysely": "^0.27.4",
"multer": "^1.4.5-lts.1",
"nodemailer": "^6.9.16",
"pg": "^8.13.0",
"postgres": "^3.4.4",
"redis": "^4.7.0",

View File

@@ -3,6 +3,7 @@ import { initRedis } from '@/data/redis';
import { migrate } from '@/data/database';
import { initEventWorker } from '@/queues/events';
import { initTaskWorker } from '@/queues/tasks';
import { initEmail } from '@/services/email';
import dotenv from 'dotenv';
dotenv.config();
@@ -10,10 +11,11 @@ dotenv.config();
const init = async () => {
await migrate();
await initRedis();
await initEmail();
await initApi();
initEventWorker();
initTaskWorker();
};
init();
init();

View File

@@ -1,7 +1,8 @@
import { database } from '@/data/database';
import { redisConfig } from '@/data/redis';
import { CleanDeviceDataTask, Task } from '@/types/tasks';
import { CleanDeviceDataTask, SendEmailTask, Task } from '@/types/tasks';
import { Job, Queue, Worker } from 'bullmq';
import { sendEmail } from '@/services/email';
const taskQueue = new Queue('tasks', {
connection: {
@@ -36,6 +37,8 @@ const handleTaskJob = async (job: Job) => {
switch (task.type) {
case 'clean_device_data':
return handleCleanDeviceDataTask(task);
case 'send_email':
return handleSendEmailTask(task);
}
};
@@ -58,3 +61,9 @@ const handleCleanDeviceDataTask = async (
.where('device_id', '=', task.deviceId)
.execute();
};
const handleSendEmailTask = async (
task: SendEmailTask
): Promise<void> => {
await sendEmail(task.message);
}

View File

@@ -0,0 +1,43 @@
import nodemailer from 'nodemailer';
import { EmailConfig, EmailMessage } from '@/types/email';
const SMTP_HOST = process.env.SMTP_HOST;
const SMTP_PORT = process.env.SMTP_PORT;
const SMTP_USER = process.env.SMTP_USER;
const SMTP_PASS = process.env.SMTP_PASS;
const EMAIL_FROM = process.env.EMAIL_FROM;
if (!SMTP_HOST || !SMTP_PORT || !SMTP_USER || !SMTP_PASS || !EMAIL_FROM) {
throw new Error('SMTP configuration is missing');
}
let transporter: nodemailer.Transporter;
const emailConfig: EmailConfig = {
from: EMAIL_FROM,
smtp: {
host: SMTP_HOST,
port: parseInt(SMTP_PORT),
secure: true,
auth: {
user: SMTP_USER,
pass: SMTP_PASS,
},
},
};
export const initEmail = async () => {
transporter = nodemailer.createTransport(emailConfig.smtp);
await transporter.verify();
};
export const sendEmail = async (message: EmailMessage): Promise<void> => {
if (!transporter) {
throw new Error('Email service not initialized');
}
await transporter.sendMail({
from: emailConfig.from,
...message,
});
};

View File

@@ -0,0 +1,19 @@
export interface EmailConfig {
from: string;
smtp?: {
host: string;
port: number;
secure: boolean;
auth: {
user: string;
pass: string;
};
};
}
export interface EmailMessage {
to: string | string[];
subject: string;
text?: string;
html?: string;
}

View File

@@ -1,6 +1,13 @@
export type Task = CleanDeviceDataTask;
import { EmailMessage } from '@/types/email';
export type Task = CleanDeviceDataTask | SendEmailTask;
export type CleanDeviceDataTask = {
type: 'clean_device_data';
deviceId: string;
};
export type SendEmailTask = {
type: 'send_email';
message: EmailMessage;
};