From c5a13a7580f169a21a4268a8b0f42d1abe25fdb4 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Tue, 28 Sep 2021 10:54:22 -0600 Subject: [PATCH] Update visitor info on email reception based on inbox settings (#23280) Co-authored-by: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> --- app/livechat/server/lib/Helper.js | 6 +++++- app/models/server/models/LivechatRooms.js | 11 ++++++++++ server/features/EmailInbox/EmailInbox.ts | 11 +++++++--- .../EmailInbox/EmailInbox_Incoming.ts | 21 +++++++++++++++++-- server/features/EmailInbox/logger.ts | 3 +++ 5 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 server/features/EmailInbox/logger.ts diff --git a/app/livechat/server/lib/Helper.js b/app/livechat/server/lib/Helper.js index b7a0d2dd92d..5edaee24945 100644 --- a/app/livechat/server/lib/Helper.js +++ b/app/livechat/server/lib/Helper.js @@ -257,8 +257,12 @@ export const dispatchInquiryQueued = (inquiry, agent) => { // Alert only the online agents of the queued request const onlineAgents = Livechat.getOnlineAgents(department, agent); - logger.debug(`Notifying ${ onlineAgents.count() } agents of new inquiry`); + if (!onlineAgents) { + logger.debug('Cannot notify agents of queued inquiry. No online agents found'); + return; + } + logger.debug(`Notifying ${ onlineAgents.count() } agents of new inquiry`); const notificationUserName = v && (v.name || v.username); onlineAgents.forEach((agent) => { diff --git a/app/models/server/models/LivechatRooms.js b/app/models/server/models/LivechatRooms.js index 1d9e29ece77..1d71be35aad 100644 --- a/app/models/server/models/LivechatRooms.js +++ b/app/models/server/models/LivechatRooms.js @@ -193,6 +193,17 @@ export class LivechatRooms extends Base { return this.findOne(query, options); } + findOneByVisitorTokenAndEmailThreadAndDepartment(visitorToken, emailThread, departmentId, options) { + const query = { + t: 'l', + 'v.token': visitorToken, + 'email.thread': emailThread, + ...departmentId && { departmentId }, + }; + + return this.findOne(query, options); + } + findOneOpenByVisitorTokenAndEmailThread(visitorToken, emailThread, options) { const query = { t: 'l', diff --git a/server/features/EmailInbox/EmailInbox.ts b/server/features/EmailInbox/EmailInbox.ts index 5cdab75e3c5..c6f8d683c50 100644 --- a/server/features/EmailInbox/EmailInbox.ts +++ b/server/features/EmailInbox/EmailInbox.ts @@ -6,6 +6,7 @@ import { EmailInbox, EmailMessageHistory } from '../../../app/models/server/raw' import { IMAPInterceptor } from '../../email/IMAPInterceptor'; import { IEmailInbox } from '../../../definition/IEmailInbox'; import { onEmailReceived } from './EmailInbox_Incoming'; +import { logger } from './logger'; export type Inbox = { imap: IMAPInterceptor; @@ -20,6 +21,7 @@ export async function configureEmailInboxes(): Promise { active: true, }); + logger.info('Clearing old email inbox registrations'); for (const { imap } of inboxes.values()) { imap.stop(); } @@ -27,7 +29,7 @@ export async function configureEmailInboxes(): Promise { inboxes.clear(); for await (const emailInboxRecord of emailInboxesCursor) { - console.log('Setting up email interceptor for', emailInboxRecord.email); + logger.info('Setting up email interceptor for', emailInboxRecord.email); const imap = new IMAPInterceptor({ password: emailInboxRecord.imap.password, @@ -38,7 +40,7 @@ export async function configureEmailInboxes(): Promise { tlsOptions: { rejectUnauthorized: false, }, - // debug: (...args: any[]): void => console.log(...args), + // debug: (...args: any[]): void => logger.debug(args), }, { deleteAfterRead: false, filter: [['UNSEEN'], ['SINCE', emailInboxRecord._updatedAt]], @@ -54,8 +56,9 @@ export async function configureEmailInboxes(): Promise { try { await EmailMessageHistory.insertOne({ _id: email.messageId, email: emailInboxRecord.email }); onEmailReceived(email, emailInboxRecord.email, emailInboxRecord.department); - } catch (e) { + } catch (e: any) { // In case the email message history has been received by other instance.. + logger.error(e.message); } })); @@ -73,6 +76,8 @@ export async function configureEmailInboxes(): Promise { inboxes.set(emailInboxRecord.email, { imap, smtp, config: emailInboxRecord }); } + + logger.info(`Configured a total of ${ inboxes.size } inboxes`); } Meteor.startup(() => { diff --git a/server/features/EmailInbox/EmailInbox_Incoming.ts b/server/features/EmailInbox/EmailInbox_Incoming.ts index dffa7f179fd..88eb86c013a 100644 --- a/server/features/EmailInbox/EmailInbox_Incoming.ts +++ b/server/features/EmailInbox/EmailInbox_Incoming.ts @@ -9,6 +9,7 @@ import { LivechatRooms, LivechatVisitors, Messages } from '../../../app/models/s import { FileUpload } from '../../../app/file-upload/server'; import { QueueManager } from '../../../app/livechat/server/lib/QueueManager'; import { settings } from '../../../app/settings/server'; +import { logger } from './logger'; import { OmnichannelSourceType } from '../../../definition/IRoom'; type FileAttachment = { @@ -30,12 +31,20 @@ const language = settings.get('Language') || 'en'; const t = (s: string): string => TAPi18n.__(s, { lng: language }); function getGuestByEmail(email: string, name: string, department?: string): any { + logger.debug(`Attempt to register a guest for ${ email } on department: ${ department }`); const guest = LivechatVisitors.findOneGuestByEmailAddress(email); if (guest) { + logger.debug(`Guest with email ${ email } found with id ${ guest._id }`); + if (guest.department !== department) { + logger.debug(`Switching departments for guest ${ guest._id }. Previous: ${ guest.department } New: ${ department }`); + Livechat.setDepartmentForGuest({ token: guest.token, department }); + return LivechatVisitors.findOneById(guest._id, {}); + } return guest; } + logger.debug(`Creating a new Omnichannel guest for visitor with email ${ email }`); const userId = Livechat.registerGuest({ token: Random.id(), name: name || email, @@ -48,6 +57,7 @@ function getGuestByEmail(email: string, name: string, department?: string): any }); const newGuest = LivechatVisitors.findOneById(userId, {}); + logger.debug(`Guest ${ userId } for visitor ${ email } created`); if (newGuest) { return newGuest; } @@ -103,6 +113,7 @@ async function uploadAttachment(attachment: Attachment, rid: string, visitorToke } export async function onEmailReceived(email: ParsedMail, inbox: string, department?: string): Promise { + logger.debug(`New email conversation received on inbox ${ inbox }. Will be assigned to department ${ department }`); if (!email.from?.value?.[0]?.address) { return; } @@ -111,10 +122,14 @@ export async function onEmailReceived(email: ParsedMail, inbox: string, departme const thread = references?.[0] ?? email.messageId; + logger.debug(`Fetching guest for visitor ${ email.from.value[0].address }`); const guest = getGuestByEmail(email.from.value[0].address, email.from.value[0].name, department); - let room = LivechatRooms.findOneByVisitorTokenAndEmailThread(guest.token, thread, {}); + logger.debug(`Guest ${ guest._id } obtained. Attempting to find or create a room on department ${ department }`); + let room = LivechatRooms.findOneByVisitorTokenAndEmailThreadAndDepartment(guest.token, thread, department, {}); + logger.debug(`Room ${ room?._id } found for guest ${ guest._id }`); if (room?.closedAt) { + logger.debug(`Room ${ room?._id } is closed. Reopening`); room = await QueueManager.unarchiveRoom(room); } @@ -128,6 +143,7 @@ export async function onEmailReceived(email: ParsedMail, inbox: string, departme const rid = room?._id ?? Random.id(); const msgId = Random.id(); + logger.debug(`Sending email message to room ${ rid } for visitor ${ guest._id }. Conversation assigned to department ${ department }`); Livechat.sendMessage({ guest, message: { @@ -205,6 +221,7 @@ export async function onEmailReceived(email: ParsedMail, inbox: string, departme }, }); }).catch((error) => { - Livechat.logger.log('Error receiving Email: %s', error.message); + console.log(error); + Livechat.logger.error('Error receiving Email: %s', error.message); }); } diff --git a/server/features/EmailInbox/logger.ts b/server/features/EmailInbox/logger.ts new file mode 100644 index 00000000000..c27fed8fd97 --- /dev/null +++ b/server/features/EmailInbox/logger.ts @@ -0,0 +1,3 @@ +import { Logger } from '../../lib/logger/Logger'; + +export const logger = new Logger('EmailInbox');