diff --git a/api/BusinessLogic/Emails/EmailTemplateParser.php b/api/BusinessLogic/Emails/EmailTemplateParser.php index 927a0d00..4fbc3e65 100644 --- a/api/BusinessLogic/Emails/EmailTemplateParser.php +++ b/api/BusinessLogic/Emails/EmailTemplateParser.php @@ -179,7 +179,7 @@ class EmailTemplateParser { $heskSettings['site_title'] = hesk_msgToPlain($heskSettings['site_title'], 1); // Is email required to view ticket (for customers only)? - $heskSettings['e_param'] = $heskSettings['email_view_ticket'] ? '&e=' . rawurlencode($ticket->email) : ''; + $heskSettings['e_param'] = $heskSettings['email_view_ticket'] ? '&e=' . rawurlencode(implode(';', $ticket->email)) : ''; /* Generate the ticket URLs */ $trackingURL = $heskSettings['hesk_url']; @@ -221,7 +221,7 @@ class EmailTemplateParser { $msg = str_replace('%%PRIORITY%%', $priority, $msg); $msg = str_replace('%%OWNER%%', $owner, $msg); $msg = str_replace('%%STATUS%%', $statusName, $msg); - $msg = str_replace('%%EMAIL%%', $ticket->email, $msg); + $msg = str_replace('%%EMAIL%%', implode(';',$ticket->email), $msg); $msg = str_replace('%%CREATED%%', $ticket->dateCreated, $msg); $msg = str_replace('%%UPDATED%%', $ticket->lastChanged, $msg); $msg = str_replace('%%ID%%', $ticket->id, $msg); @@ -252,7 +252,8 @@ class EmailTemplateParser { if (strpos($msg, '%%MESSAGE%%') !== false) { // Replace message if ($html) { - $htmlMessage = nl2br($ticket->message); + $htmlMessage = html_entity_decode($ticket->message); + $htmlMessage = nl2br($htmlMessage); $msg = str_replace('%%MESSAGE%%', $htmlMessage, $msg); } else { $plainTextMessage = $ticket->message; diff --git a/api/BusinessLogic/Exceptions/InternalUseOnlyException.php b/api/BusinessLogic/Exceptions/InternalUseOnlyException.php new file mode 100644 index 00000000..99bbee4d --- /dev/null +++ b/api/BusinessLogic/Exceptions/InternalUseOnlyException.php @@ -0,0 +1,10 @@ +checkForInternalUseOnly(); + + /* @var $ticketRetriever TicketRetriever */ + $ticketRetriever = $applicationContext->get[TicketRetriever::class]; + $ticket = $ticketRetriever->getTicketById($ticketId, $hesk_settings, $userContext); + + /* @var $modsForHeskSettingsGateway ModsForHeskSettingsGateway */ + $modsForHeskSettingsGateway = $applicationContext->get[ModsForHeskSettingsGateway::class]; + $modsForHeskSettings = $modsForHeskSettingsGateway->getAllSettings($hesk_settings); + + /* @var $emailSender EmailSenderHelper */ + $emailSender = $applicationContext->get[EmailSenderHelper::class]; + + $language = $ticket->language; + + if ($language === null) { + $language = $hesk_settings['language']; + } + + if ($ticket === null) { + throw new ApiFriendlyException("Ticket {$ticketId} not found!", "Ticket Not Found", 404); + } + + $reply = null; + $emailTemplate = EmailTemplateRetriever::NEW_TICKET; + if (isset($_GET['replyId'])) { + $replyId = $_GET['replyId']; + $emailTemplate = EmailTemplateRetriever::NEW_REPLY_BY_STAFF; + + foreach ($ticket->replies as $ticketReply) { + if ($ticketReply->id === $replyId) { + $reply = $ticketReply; + break; + } + } + + if ($reply === null) { + throw new ApiFriendlyException("Reply {$replyId} not found on ticket {$ticketId}!", "Reply Not Found", 404); + } + + // Copy over reply properties onto the Ticket + $ticket->lastReplier = $reply->replierName; + $ticket->message = $reply->message; + $ticket->attachments = $reply->attachments; + } + + $addressees = new Addressees(); + $addressees->to = $ticket->email; + + $emailSender->sendEmailForTicket($emailTemplate, $language, $addressees, $ticket, $hesk_settings, $modsForHeskSettings); + + http_response_code(204); + } +} \ No newline at end of file diff --git a/api/index.php b/api/index.php index 079fd851..52a815ee 100644 --- a/api/index.php +++ b/api/index.php @@ -18,8 +18,14 @@ function handle404() { function before() { assertApiIsEnabled(); - $token = \BusinessLogic\Helpers::getHeader('X-AUTH-TOKEN'); - buildUserContext($token); + $internalUse = \BusinessLogic\Helpers::getHeader('X-INTERNAL-CALL'); + + if ($internalUse === 'true') { + buildUserContextFromSession(); + } else { + $token = \BusinessLogic\Helpers::getHeader('X-AUTH-TOKEN'); + buildUserContext($token); + } } function assertApiIsEnabled() { @@ -36,6 +42,19 @@ function assertApiIsEnabled() { return; } +function buildUserContextFromSession() { + global $userContext; + + hesk_session_start(); + + if (!hesk_isLoggedIn(false)) { + throw new \BusinessLogic\Exceptions\SessionNotActiveException(); + } + + /* @var $userContext \BusinessLogic\Security\UserContext */ + $userContext = \BusinessLogic\Security\UserContext::fromDataRow($_SESSION); +} + function buildUserContext($xAuthToken) { global $applicationContext, $userContext, $hesk_settings; @@ -123,6 +142,9 @@ function getLoggingLocation($exception) { $trace = $exception->getTrace(); $lastCall = $trace[0]; $location = basename($lastCall['file'], '.php'); + if ($location === null || trim($location) === '') { + $location = 'N/A'; + } return "REST API: {$location}"; } @@ -161,6 +183,10 @@ Link::all(array( // Settings '/v1/settings' => \Controllers\Settings\SettingsController::class, + /* Internal use only routes */ + // Resend email response + '/v1-internal/staff/tickets/{i}/resend-email' => \Controllers\Tickets\ResendTicketEmailToCustomerController::class, + // Any URL that doesn't match goes to the 404 handler '404' => 'handle404' )); \ No newline at end of file diff --git a/inc/admin_functions.inc.php b/inc/admin_functions.inc.php index 832c5cd4..f2edf27a 100644 --- a/inc/admin_functions.inc.php +++ b/inc/admin_functions.inc.php @@ -460,7 +460,7 @@ function hesk_autoLogin($noredirect = 0) } // END hesk_autoLogin() -function hesk_isLoggedIn() +function hesk_isLoggedIn($redirect_if_not_logged_in = true) { global $hesk_settings; @@ -482,8 +482,13 @@ function hesk_isLoggedIn() } hesk_session_stop(); - header('Location: ' . $url); - exit(); + + if ($redirect_if_not_logged_in) { + header('Location: ' . $url); + exit(); + } else { + return false; + } } else { hesk_session_regenerate_id(); @@ -493,8 +498,13 @@ function hesk_isLoggedIn() // Exit if user not found if (hesk_dbNumRows($res) != 1) { hesk_session_stop(); - header('Location: ' . $url); - exit(); + + if ($redirect_if_not_logged_in) { + header('Location: ' . $url); + exit(); + } else { + return false; + } } // Fetch results from database @@ -503,8 +513,13 @@ function hesk_isLoggedIn() // Verify this session is still valid if (!hesk_activeSessionValidate($me['user'], $me['pass'], $_SESSION['session_verify'])) { hesk_session_stop(); - header('Location: ' . $url); - exit(); + + if ($redirect_if_not_logged_in) { + header('Location: ' . $url); + exit(); + } else { + return false; + } } // Update session variables as needed