From 0c82e05617f647bdecc19239c0ae813be84e2cfa Mon Sep 17 00:00:00 2001 From: Sergei Date: Wed, 4 Feb 2026 13:03:52 -0800 Subject: [PATCH] Switch email service from Brevo to Legacy API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add sendEmailViaLegacyAPI() function in legacyAPI.js - Update email.js to use Legacy API instead of Brevo - All emails (OTP, password reset, invitations) now go through eluxnetworks.net/function/well-api/api with send_message method - Fix syntax errors in alarm.js, beneficiaries.js, invitations.js (missing console.log statements) Brevo API is no longer used - credentials can be removed from .env 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- backend/src/controllers/alarm.js | 2 +- backend/src/routes/beneficiaries.js | 5 ++++ backend/src/routes/invitations.js | 1 + backend/src/services/email.js | 40 +++++++-------------------- backend/src/services/legacyAPI.js | 43 +++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+), 31 deletions(-) diff --git a/backend/src/controllers/alarm.js b/backend/src/controllers/alarm.js index ef30040..480e2e9 100644 --- a/backend/src/controllers/alarm.js +++ b/backend/src/controllers/alarm.js @@ -94,7 +94,7 @@ exports.sendWalarm = async (req, res) => { try { // TODO: Implement alarm sending (push notifications, SMS, etc.) // For now, log the alarm and return success - + console.log('[ALARM]', { deployment_id, location, method, diff --git a/backend/src/routes/beneficiaries.js b/backend/src/routes/beneficiaries.js index ac67639..15a9885 100644 --- a/backend/src/routes/beneficiaries.js +++ b/backend/src/routes/beneficiaries.js @@ -657,6 +657,7 @@ router.patch('/:id', } beneficiary = updatedBeneficiary; + console.log('[BENEFICIARY] Updated:', { id: beneficiary.id, name: beneficiary.name, phone: beneficiary.phone, @@ -733,6 +734,7 @@ router.delete('/:id', async (req, res) => { .single(); if (accessError || !access || access.role !== 'custodian') { + console.log('[DELETE BENEFICIARY] Access denied:', { userId, beneficiaryId, role: access?.role || 'none' @@ -1001,6 +1003,7 @@ router.post('/:id/activate', async (req, res) => { const normalizedSerial = validation.normalized; const isDemoMode = isDemoSerial(normalizedSerial); + console.log('[ACTIVATE] Serial validation:', { original: serialNumber, normalized: normalizedSerial, format: validation.format, @@ -1038,6 +1041,7 @@ router.post('/:id/activate', async (req, res) => { return res.status(500).json({ error: 'Failed to activate equipment' }); } + console.log('[ACTIVATE] Equipment activated:', { beneficiaryId, equipmentStatus, isDemoMode, @@ -1127,6 +1131,7 @@ router.post('/:id/transfer', async (req, res) => { return res.status(500).json({ error: 'Failed to transfer rights' }); } + console.log('[TRANSFER] Custodian rights transferred:', { from: userId, to: newCustodianId, beneficiaryId diff --git a/backend/src/routes/invitations.js b/backend/src/routes/invitations.js index c4b833c..eb0c08d 100644 --- a/backend/src/routes/invitations.js +++ b/backend/src/routes/invitations.js @@ -290,6 +290,7 @@ router.post('/', .single(); if (accessError || !access || !['custodian', 'guardian'].includes(access.role)) { + console.log('[INVITATIONS] Access denied:', { userId, beneficiaryId, accessError: accessError?.message, diff --git a/backend/src/services/email.js b/backend/src/services/email.js index 240a650..8ae682b 100644 --- a/backend/src/services/email.js +++ b/backend/src/services/email.js @@ -1,42 +1,22 @@ -const BREVO_API_URL = 'https://api.brevo.com/v3/smtp/email'; +const { sendEmailViaLegacyAPI } = require('./legacyAPI'); /** - * Send email via Brevo API + * Send email via Legacy API (eluxnetworks.net) + * Replaces Brevo API with the centralized WellNuo email service */ async function sendEmail({ to, subject, htmlContent, textContent }) { - const apiKey = process.env.BREVO_API_KEY; + // Use HTML content if available, fallback to text + const content = htmlContent || textContent; - if (!apiKey) { - throw new Error('Email service not configured'); + if (!content) { + throw new Error('Email content is required'); } - const payload = { - sender: { - name: process.env.BREVO_SENDER_NAME || 'WellNuo', - email: process.env.BREVO_SENDER_EMAIL || 'noreply@wellnuo.com' - }, - to: [{ email: to }], + return sendEmailViaLegacyAPI({ + to, subject, - htmlContent, - textContent - }; - - const response = await fetch(BREVO_API_URL, { - method: 'POST', - headers: { - 'accept': 'application/json', - 'api-key': apiKey, - 'content-type': 'application/json' - }, - body: JSON.stringify(payload) + content }); - - if (!response.ok) { - const error = await response.text(); - throw new Error('Failed to send email'); - } - - return await response.json(); } /** diff --git a/backend/src/services/legacyAPI.js b/backend/src/services/legacyAPI.js index bbf5e66..813e2fe 100644 --- a/backend/src/services/legacyAPI.js +++ b/backend/src/services/legacyAPI.js @@ -298,6 +298,48 @@ async function findDeploymentByUsername(adminUsername, adminToken, beneficiaryUs } } +/** + * Send email via Legacy API (eluxnetworks.net) + * Uses the send_message function with method=email + * + * @param {object} params - Email parameters + * @param {string} params.to - Recipient email address + * @param {string} params.subject - Email subject + * @param {string} params.content - Email content (HTML supported) + * @returns {Promise} Success status + */ +async function sendEmailViaLegacyAPI({ to, subject, content }) { + const username = process.env.LEGACY_API_USERNAME; + const password = process.env.LEGACY_API_PASSWORD; + + if (!username || !password) { + throw new Error('Legacy API credentials not configured'); + } + + // Get fresh token + const token = await getLegacyToken(username, password); + + const formData = new URLSearchParams({ + function: 'send_message', + token: token, + user_name: username, + user_id_or_recepient: to, + method: 'email', + subject: subject, + content: content + }); + + const response = await axios.post(LEGACY_API_BASE, formData, { + headers: { 'Content-Type': 'application/x-www-form-urlencoded' } + }); + + if (response.data.ok !== true && response.data.status !== '200 OK') { + throw new Error(`Failed to send email via Legacy API: ${JSON.stringify(response.data)}`); + } + + return true; +} + module.exports = { getLegacyToken, createLegacyDeployment, @@ -306,6 +348,7 @@ module.exports = { updateDeviceLocation, getDeploymentDevices, rebootDevice, + sendEmailViaLegacyAPI, ROOM_LOCATIONS, LOCATION_NAMES };