diff --git a/public/js/views/emailCompose.js b/public/js/views/emailCompose.js index b3fcf08..5f39df0 100644 --- a/public/js/views/emailCompose.js +++ b/public/js/views/emailCompose.js @@ -324,9 +324,10 @@ const EmailCompose = (() => { document.body.appendChild(overlay); // Init tag inputs - const initialTo = options.customerEmail ? [options.customerEmail] : []; + const initialTo = options.initialTo || (options.customerEmail ? [options.customerEmail] : []); + const initialCc = options.initialCc || []; const toTagsCtrl = makeTagInput('ec-to-container', initialTo); - const ccTagsCtrl = makeTagInput('ec-cc-container', []); + const ccTagsCtrl = makeTagInput('ec-cc-container', initialCc); // Subject const subjectEl = document.getElementById('ec-subject'); diff --git a/public/js/views/ticketDetail.js b/public/js/views/ticketDetail.js index a999ef1..6dcc623 100644 --- a/public/js/views/ticketDetail.js +++ b/public/js/views/ticketDetail.js @@ -756,18 +756,46 @@ const TicketDetailView = {


`; - // Extract sender email if possible for CC/To - let customerEmail = ticket.customer_email || ''; - const matchEmail = (article.a_from || '').match(/<([^>]+)>/) || (article.a_from || '').match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/); - if (matchEmail) { - customerEmail = matchEmail[1]; + // Helper to extract email addresses from headers + const parseEmails = (str) => { + if (!str) return []; + return (str.match(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g) || []) + .map(email => email.toLowerCase().trim()); + }; + + const fromEmails = parseEmails(article.a_from); + const toEmails = parseEmails(article.a_to); + const ccEmails = parseEmails(article.a_cc); + + // Exclude list (helpdesk and active agent) + const config = App.lookups.config || {}; + const helpdeskEmail = (config.helpdeskEmail || 'helpdesk@pharmaidea.com').toLowerCase(); + const agentEmail = (config.agentEmail || '').toLowerCase(); + const excludeEmails = [helpdeskEmail, agentEmail].filter(Boolean); + + const initialToSet = new Set(); + fromEmails.forEach(e => { + if (!excludeEmails.includes(e) && !e.includes('helpdesk')) { + initialToSet.add(e); + } + }); + if (initialToSet.size === 0 && ticket.customer_email) { + initialToSet.add(ticket.customer_email.toLowerCase()); } + const initialCcSet = new Set(); + [...toEmails, ...ccEmails].forEach(e => { + if (!excludeEmails.includes(e) && !e.includes('helpdesk') && !initialToSet.has(e)) { + initialCcSet.add(e); + } + }); + EmailCompose.open({ ticketId: ticket.id, ticketTn: ticket.tn, ticketTitle: ticket.title, - customerEmail: customerEmail, + initialTo: Array.from(initialToSet), + initialCc: Array.from(initialCcSet), initialBodyHtml: initialBodyHtml, }); } else { diff --git a/routes/lookups.js b/routes/lookups.js index 4c62af7..7f3e07c 100644 --- a/routes/lookups.js +++ b/routes/lookups.js @@ -132,12 +132,26 @@ router.get('/users', async (req, res) => { }); // GET /api/config — Application config -router.get('/config', (req, res) => { +router.get('/config', async (req, res) => { + const agentId = parseInt(req.headers['x-agent-id'], 10) || 1; + let agentEmail = ''; + try { + 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) { + agentEmail = prefRes.rows[0].preferences_value || ''; + } + } catch (_) {} + res.json({ defaultAgentLogin: process.env.OTRS_API_USER || '', dailyTargetTime: parseInt(process.env.DAILY_TARGET_TIME, 10) || 480, phraseThreshold: parseInt(process.env.PHRASE_THRESHOLD, 10) || 70, - autoTimeMinHour: process.env.AUTO_TIME_MIN_HOUR || '18:00' + autoTimeMinHour: process.env.AUTO_TIME_MIN_HOUR || '18:00', + helpdeskEmail: process.env.OTRS_MAIL_BCC || '', + agentEmail: agentEmail }); });