PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.4.5
Fluent Support – Helpdesk & Customer Support Ticket System v2.4.5
2.4.5 2.4.0 2.3.2 2.3.1 2.3.0 2.2.1 2.2.0 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.4.0 1.4.1 1.4.2 1.4.5 1.4.6 1.4.7 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 All 69 releases
← All changes | app/Hooks/Handlers/EmailNotificationHandler.php +66 -19 2.2.0 → 2.4.5 View file →
@@ -2,13 +2,16 @@
2 2
3 3 namespace FluentSupport\App\Hooks\Handlers;
4 4
5 5 use FluentSupport\App\App;
6 +use FluentSupport\App\Models\Agent;
6 7 use FluentSupport\App\Models\Meta;
8 +use FluentSupport\App\Models\Ticket;
7 9 use FluentSupport\App\Services\EmailNotification\Settings;
8 10 use FluentSupport\App\Services\Emogrifier;
9 11 use FluentSupport\App\Services\Helper;
10 12 use FluentSupport\App\Services\Mailer;
13 +use FluentSupport\App\Services\Tickets\AgentTicketAccess;
11 14 use FluentSupport\Framework\Support\Arr;
12 15
13 16 class EmailNotificationHandler
14 17 {
@@ -22,9 +25,11 @@
22 25
23 26 // Let's send welcome email to customer if enabled
24 27 $emailSettings = (new Settings())->getBoxEmailSettings($mailbox, 'ticket_created_email_to_customer');
25 28
26 - if ($this->shouldSendEmail($emailSettings, 'ticket_created_email_to_customer', $ticket, $customer)) {
29 + // Blocked customers get no email; the admin copy below still goes out.
30 + if ($customer && $customer->canReceiveNotifications()
31 + && $this->shouldSendEmail($emailSettings, 'ticket_created_email_to_customer', $ticket, $customer)) {
27 32 $subject = apply_filters('fluent_support/parse_smartcode_data', $emailSettings['email_subject'], [
28 33 'customer' => $customer,
29 34 'business' => $mailbox,
30 35 'ticket' => $ticket
@@ -38,13 +43,14 @@
38 43 'ticket' => $ticket,
39 44 'email_type' => 'ticket_created_email_to_customer'
40 45 ]);
41 46
42 - $headers = $mailbox->getMailerHeader();
47 + $headers = self::automatedHeaders($mailbox->getMailerHeader());
43 48
44 49 $headers = apply_filters('fluent_support/mail_to_customer_header', $headers, [
45 50 'cc_email' => $ticket->getSettingsValue('cc_email', []),
46 - 'hook_type' => 'ticket_created_email_to_customer'
51 + 'hook_type' => 'ticket_created_email_to_customer',
52 + 'ticket' => $ticket
47 53 ]);
48 54
49 55 $attachments = [];
50 56
@@ -90,9 +96,9 @@
90 96 'ticket' => $ticket,
91 97 'email_type' => 'ticket_created_email_to_admin'
92 98 ]);
93 99
94 - $headers = $mailbox->getMailerHeader();
100 + $headers = self::automatedHeaders($mailbox->getMailerHeader());
95 101
96 102 $attachments = [];
97 103
98 104 if ($emailSettings['send_attachments'] == 'yes' && ($files = $ticket->attachments)) {
@@ -131,9 +137,9 @@
131 137
132 138 $ticket->load('customer');
133 139 $customer = $ticket->customer;
134 140
135 - if ($customer->status == 'inactive') {
141 + if (!$customer->canReceiveNotifications()) {
136 142 return false;
137 143 }
138 144
139 145 if (!$this->shouldSendEmail($emailSettings, 'ticket_replied_by_agent_email_to_customer', $ticket, $customer)) {
@@ -159,12 +165,14 @@
159 165 'email_type' => 'ticket_replied_by_agent_email_to_customer'
160 166 ]);
161 167
162 168
163 - $headers = $mailbox->getMailerHeader();
169 + // Written by the agent, so the From name follows the inbox's From name setting.
170 + $headers = $mailbox->getMailerHeader($agent);
164 171 $headers = apply_filters('fluent_support/mail_to_customer_header', $headers, [
165 172 'cc_email' => $response->getSettingsValue('cc_email', []),
166 - 'hook_type' => 'ticket_replied_by_agent_email_to_customer'
173 + 'hook_type' => 'ticket_replied_by_agent_email_to_customer',
174 + 'ticket' => $ticket
167 175 ]);
168 176 $attachments = [];
169 177
170 178 if ($emailSettings['send_attachments'] == 'yes' && ($files = $response->attachments)) {
@@ -197,9 +205,9 @@
197 205
198 206 $ticket->load('customer');
199 207 $customer = $ticket->customer;
200 208
201 - if ($customer->status == 'inactive') {
209 + if (!$customer->canReceiveNotifications()) {
202 210 return false;
203 211 }
204 212
205 213 if (!$this->shouldSendEmail($emailSettings, 'ticket_closed_by_agent_email_to_customer', $ticket, $customer)) {
@@ -222,12 +230,13 @@
222 230 'agent' => $agent,
223 231 'email_type' => 'ticket_closed_by_agent_email_to_customer'
224 232 ]);
225 233
226 - $headers = $mailbox->getMailerHeader();
234 + $headers = self::automatedHeaders($mailbox->getMailerHeader());
227 235 $headers = apply_filters('fluent_support/mail_to_customer_header', $headers, [
228 236 'cc_email' => $ticket->getSettingsValue('cc_email', []),
229 - 'hook_type' => 'ticket_closed_by_agent_email_to_customer'
237 + 'hook_type' => 'ticket_closed_by_agent_email_to_customer',
238 + 'ticket' => $ticket
230 239 ]);
231 240 Mailer::send($customer->email, $subject, $emailBody, $headers);
232 241 }
233 242 }
@@ -273,9 +282,9 @@
273 282 'agent' => $agent,
274 283 'email_type' => 'ticket_replied_by_customer_email_to_admin'
275 284 ]);
276 285
277 - $headers = $mailbox->getMailerHeader();
286 + $headers = self::automatedHeaders($mailbox->getMailerHeader());
278 287 $attachments = [];
279 288
280 289 if ($emailSettings['send_attachments'] == 'yes' && ($files = $response->attachments)) {
281 290 foreach ($files as $file) {
@@ -293,10 +302,18 @@
293 302 Mailer::send($emailTo, $subject, $emailBody, $headers, $attachments);
294 303 }
295 304 }
296 305
297 - public function onAgentAssign($agent, $ticket, $assigner)
306 + public function onAgentAssign(Agent $agent, Ticket $ticket, ?Agent $assigner = null)
298 307 {
308 + if ($agent->status !== 'active' || (int) $ticket->agent_id !== (int) $agent->id) {
309 + return;
310 + }
311 +
312 + if (!(new AgentTicketAccess())->canAccess($agent, $ticket)) {
313 + return;
314 + }
315 +
299 316 $currentUser = Helper::getAgentByUserId();
300 317
301 318 if ($currentUser && $currentUser->user_id == $agent->user_id) {
302 319 return;
@@ -337,9 +354,9 @@
337 354 'assigner' => $assigner,
338 355 'email_type' => 'ticket_agent_on_change'
339 356 ]);
340 357
341 - $headers = $mailbox->getMailerHeader();
358 + $headers = self::automatedHeaders($mailbox->getMailerHeader());
342 359
343 360 Mailer::send($emailTo, $subject, $emailBody, $headers);
344 361 }
345 362 }
@@ -347,9 +364,9 @@
347 364 public function ticketCreatedByAgent($ticket, $customer, $agent)
348 365 {
349 366 $mailbox = $ticket->mailbox;
350 367
351 - if (!$mailbox) {
368 + if (!$mailbox || !$customer || !$customer->canReceiveNotifications()) {
352 369 return;
353 370 }
354 371
355 372 // Let's send welcome email to customer if enabled
@@ -371,9 +388,13 @@
371 388 'ticket' => $ticket,
372 389 'email_type' => 'ticket_created_by_agent_email_to_customer'
373 390 ]);
374 391
375 - $headers = $mailbox->getMailerHeader();
392 + $headers = apply_filters('fluent_support/mail_to_customer_header', self::automatedHeaders($mailbox->getMailerHeader()), [
393 + 'hook_type' => 'ticket_created_by_agent_email_to_customer',
394 + 'cc_email' => [],
395 + 'ticket' => $ticket
396 + ]);
376 397
377 398 $attachments = [];
378 399
379 400 if ($emailSettings['send_attachments'] == 'yes' && ($files = $ticket->attachments)) {
@@ -406,9 +427,9 @@
406 427
407 428 $ticket->load('customer');
408 429 $customer = $ticket->customer;
409 430
410 - if ($customer->status == 'inactive') {
431 + if (!$customer->canReceiveNotifications()) {
411 432 return false;
412 433 }
413 434
414 435 $subject = apply_filters('fluent_support/parse_smartcode_data', $emailSettings['email_subject'], [
@@ -429,9 +450,13 @@
429 450 'response' => $response,
430 451 'email_type' => 'ticket_created_by_agent_on_behalf_email_to_customer'
431 452 ]);
432 453
433 - $headers = $mailbox->getMailerHeader();
454 + $headers = apply_filters('fluent_support/mail_to_customer_header', $mailbox->getMailerHeader($agent), [
455 + 'hook_type' => 'ticket_created_by_agent_on_behalf_email_to_customer',
456 + 'cc_email' => [],
457 + 'ticket' => $ticket
458 + ]);
434 459
435 460 $attachments = [];
436 461
437 462 if ($emailSettings['send_attachments'] == 'yes') {
@@ -476,13 +501,14 @@
476 501 } else {
477 502 $businessName = get_bloginfo('name');
478 503 }
479 504
480 - $footerText = apply_filters('fluent_support/email_footer_credit', 'This email is a service from ' . $businessName . '. Support Plugin is Powered by <a href="https://fluentsupport.com/?utm_source=user&utm_medium=wp&utm_campaign=mail_footer" style="color:#9e9e9e;" target="_new">FluentSupport</a>.');
505 + $footerCreditUrl = Helper::getUpgradeUrl('mail_footer', ['base_url' => 'https://fluentsupport.com/']);
506 + $footerText = apply_filters('fluent_support/email_footer_credit', 'This email is a service from ' . $businessName . '. Support Plugin is Powered by <a href="' . esc_url($footerCreditUrl) . '" style="color:#9e9e9e;" target="_new">FluentSupport</a>.');
481 507
482 508 $data['email_footer'] = $footerText;
483 509
484 - $emailTypeForCustomerFooter = ['ticket_created_email_to_customer', 'ticket_replied_by_agent_email_to_customer', 'ticket_closed_by_agent_email_to_customer'];
510 + $emailTypeForCustomerFooter = ['ticket_created_email_to_customer', 'ticket_replied_by_agent_email_to_customer', 'ticket_closed_by_agent_email_to_customer', 'ticket_created_by_agent_on_behalf_email_to_customer'];
485 511
486 512 if (defined('FLUENTSUPPORTPRO') && in_array($data['email_type'], $emailTypeForCustomerFooter)
487 513 && !is_null($data['business']->email_footer)) {
488 514 $data['email_footer'] = apply_filters('fluent_support/parse_smartcode_data', $data['business']->email_footer, $data);
@@ -500,8 +526,29 @@
500 526 return false;
501 527 }
502 528
503 529 return apply_filters('fluent_support/should_send_notification', true, 'email', $emailType, $ticket, $person);
530 + }
531 +
532 + /**
533 + * Mark a system-generated email (confirmations, closed notices, agent alerts) so
534 + * autoresponders don't answer it (RFC 3834 Auto-Submitted, and Outlook's
535 + * X-Auto-Response-Suppress). An answer would come back through email piping and
536 + * could start a mail loop. Replies an agent writes are not marked.
537 + *
538 + * @param array $headers
539 + * @return array
540 + */
541 + public static function automatedHeaders($headers)
542 + {
543 + if (!apply_filters('fluent_support/mark_automated_emails', true)) {
544 + return $headers;
545 + }
546 +
547 + $headers[] = 'Auto-Submitted: auto-generated';
548 + $headers[] = 'X-Auto-Response-Suppress: All';
549 +
550 + return $headers;
504 551 }
505 552
506 553 public function getMailerHeaderWithCc($headers, $info)
507 554 {