'use strict'; const express = require('express'); const router = express.Router(); const pool = require('../db'); const { db } = require('../activityDb'); const { sendMail } = require('../utils/mailer'); // ─── SIGNATURES ──────────────────────────────────────────────────────────────── // GET /api/email/signatures — list signatures for a given agent router.get('/signatures', (req, res) => { try { const { agent_id } = req.query; if (!agent_id) return res.status(400).json({ error: 'agent_id è obbligatorio' }); const rows = db.prepare(` SELECT id, name, body_html, is_default, created_at, updated_at FROM email_signatures WHERE agent_id = ? ORDER BY is_default DESC, name ASC `).all(parseInt(agent_id, 10)); res.json(rows); } catch (err) { console.error('[Email] Error listing signatures:', err); res.status(500).json({ error: err.message }); } }); // POST /api/email/signatures — create a new signature router.post('/signatures', (req, res) => { try { const { agent_id, name, body_html, is_default = 0 } = req.body; if (!agent_id || !name) return res.status(400).json({ error: 'agent_id e name sono obbligatori' }); // If new signature is default, reset others for this agent if (is_default) { db.prepare(`UPDATE email_signatures SET is_default = 0 WHERE agent_id = ?`).run(parseInt(agent_id, 10)); } const result = db.prepare(` INSERT INTO email_signatures (agent_id, name, body_html, is_default) VALUES (?, ?, ?, ?) `).run(parseInt(agent_id, 10), name, body_html || '', is_default ? 1 : 0); res.json({ id: result.lastInsertRowid, agent_id, name, body_html, is_default }); } catch (err) { console.error('[Email] Error creating signature:', err); res.status(500).json({ error: err.message }); } }); // PUT /api/email/signatures/:id — update a signature router.put('/signatures/:id', (req, res) => { try { const { id } = req.params; const { agent_id, name, body_html, is_default } = req.body; // If new signature is default, reset others for this agent if (is_default && agent_id) { db.prepare(`UPDATE email_signatures SET is_default = 0 WHERE agent_id = ?`).run(parseInt(agent_id, 10)); } db.prepare(` UPDATE email_signatures SET name = ?, body_html = ?, is_default = ?, updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = ? `).run(name, body_html || '', is_default ? 1 : 0, parseInt(id, 10)); const updated = db.prepare(`SELECT * FROM email_signatures WHERE id = ?`).get(parseInt(id, 10)); res.json(updated); } catch (err) { console.error('[Email] Error updating signature:', err); res.status(500).json({ error: err.message }); } }); // PATCH /api/email/signatures/:id/default — set a signature as default router.patch('/signatures/:id/default', (req, res) => { try { const { id } = req.params; const { agent_id } = req.body; if (agent_id) { db.prepare(`UPDATE email_signatures SET is_default = 0 WHERE agent_id = ?`).run(parseInt(agent_id, 10)); } db.prepare(` UPDATE email_signatures SET is_default = 1, updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = ? `).run(parseInt(id, 10)); res.json({ success: true }); } catch (err) { console.error('[Email] Error setting default signature:', err); res.status(500).json({ error: err.message }); } }); // DELETE /api/email/signatures/:id — delete a signature router.delete('/signatures/:id', (req, res) => { try { const { id } = req.params; db.prepare(`DELETE FROM email_signatures WHERE id = ?`).run(parseInt(id, 10)); res.json({ success: true }); } catch (err) { console.error('[Email] Error deleting signature:', err); res.status(500).json({ error: err.message }); } }); // ─── SEND EMAIL ─────────────────────────────────────────────────────────────── // POST /api/email/send — send an email for a ticket router.post('/send', async (req, res) => { const { ticketId, to, cc = [], subject: customSubject, bodyHtml, attachments = [], inlineImages = [], agentId, agentName = 'Agente', keepHelpdeskCopy = true, } = req.body; if (!ticketId) return res.status(400).json({ error: 'ticketId è obbligatorio' }); if (!to || !to.length) return res.status(400).json({ error: 'Il campo "to" è obbligatorio' }); if (!bodyHtml) return res.status(400).json({ error: 'Il corpo della email è obbligatorio' }); try { // 1. Fetch ticket number and title for subject const ticketResult = await pool.query( `SELECT tn, title FROM ticket WHERE id = $1`, [ticketId] ); if (!ticketResult.rows.length) return res.status(404).json({ error: 'Ticket non trovato' }); const { tn, title } = ticketResult.rows[0]; const subject = customSubject || `Re: [Ticket#${tn}] ${title}`; // 2. Build BCC list (include OTRS system mailbox if keepHelpdeskCopy is true) const bcc = []; if (keepHelpdeskCopy) { const otrsBcc = process.env.OTRS_MAIL_BCC; if (otrsBcc) bcc.push(otrsBcc); } // 3. Send via configured mailer (Graph API or SMTP) await sendMail({ to, cc, bcc, subject, bodyHtml, attachments, inlineImages }); // 4. Log internal note in OTRS ticket via DB (email sent record) try { const now = Math.floor(Date.now() / 1000); const agentLoginResult = agentId ? await pool.query(`SELECT login, first_name, last_name FROM users WHERE id = $1`, [agentId]) : { rows: [] }; const agentUser = agentLoginResult.rows[0]; let agentEmail = 'agent@localhost'; if (agentId) { const prefRes = await pool.query( `SELECT preferences_value FROM user_preferences WHERE user_id = $1 AND preferences_key = 'UserEmail'`, [agentId] ); if (prefRes.rows.length > 0 && prefRes.rows[0].preferences_value) { agentEmail = prefRes.rows[0].preferences_value; } } const aFrom = agentUser ? `"${agentUser.first_name} ${agentUser.last_name}" <${agentEmail}>` : agentName; const toList = to.join(', '); const noteBody = `Email inviata a: ${toList}${cc.length ? `\nCC: ${cc.join(', ')}` : ''}`; // Insert article via DB (internal note to log email dispatch) const artInsert = await pool.query(` INSERT INTO article ( ticket_id, article_sender_type_id, communication_channel_id, is_visible_for_customer, a_from, a_to, a_subject, a_body, content_path, incoming_time, create_time, create_by, change_time, change_by ) VALUES ( $1, 1, 2, 0, $2, $3, $4, $5, '/', $6, NOW(), $7, NOW(), $7 ) RETURNING id`, [ticketId, aFrom, toList, `[Email inviata] ${subject}`, noteBody, now, agentId || 1] ); const articleId = artInsert.rows[0]?.id; if (articleId) { await pool.query(` INSERT INTO article_data_mime (article_id, a_from, a_to, a_cc, a_subject, a_body, a_content_type, incoming_time, create_time, create_by, change_time, change_by) VALUES ($1, $2, $3, $4, $5, $6, 'text/plain; charset=utf-8', $7, NOW(), $8, NOW(), $8)`, [articleId, aFrom, toList, cc.join(', '), subject, noteBody, now, agentId || 1] ); } } catch (noteErr) { console.warn('[Email] Nota interna OTRS non inserita (non bloccante):', noteErr.message); } console.log(`[Email] ✅ Email inviata per ticket #${tn} a: ${to.join(', ')}`); res.json({ success: true, subject, to }); } catch (err) { console.error('[Email] ❌ Errore invio email:', err.message); res.status(500).json({ error: err.message }); } }); module.exports = router;