vendor/uvdesk/core-framework/Services/EmailService.php line 39

Open in your IDE?
  1. <?php
  2. namespace Webkul\UVDesk\CoreFrameworkBundle\Services;
  3. use Doctrine\ORM\EntityManagerInterface;
  4. use Symfony\Component\DependencyInjection\ContainerInterface;
  5. use Symfony\Component\HttpFoundation\RequestStack;
  6. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  7. use Symfony\Component\Mailer\Transport;
  8. use Symfony\Component\Mime\Email;
  9. use Symfony\Component\Mime\Address;
  10. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  11. use Webkul\UVDesk\CoreFrameworkBundle\Entity\EmailTemplates;
  12. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Microsoft\MicrosoftApp;
  13. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Microsoft\MicrosoftAccount;
  14. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Ticket;
  15. use Webkul\UVDesk\CoreFrameworkBundle\Entity\User;
  16. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Website;
  17. use Webkul\UVDesk\CoreFrameworkBundle\Utils\Microsoft\Graph as MicrosoftGraph;
  18. use Webkul\UVDesk\CoreFrameworkBundle\Utils\TokenGenerator;
  19. use Webkul\UVDesk\MailboxBundle\Services\MailboxService;
  20. use Webkul\UVDesk\MailboxBundle\Utils\SMTP\Transport\AppTransportConfigurationInterface;
  21. use Webkul\UVDesk\CoreFrameworkBundle\Services\MicrosoftIntegration;
  22. class EmailService
  23. {
  24. private $request;
  25. private $container;
  26. private $entityManager;
  27. private $session;
  28. private $mailer;
  29. public function __construct(ContainerInterface $container, RequestStack $request, EntityManagerInterface $entityManager, SessionInterface $session, MailboxService $mailboxService, MicrosoftIntegration $microsoftIntegration)
  30. {
  31. $this->request = $request;
  32. $this->container = $container;
  33. $this->entityManager = $entityManager;
  34. $this->session = $session;
  35. $this->mailboxService = $mailboxService;
  36. $this->microsoftIntegration = $microsoftIntegration;
  37. }
  38. public function trans($text)
  39. {
  40. return $this->container->get('translator')->trans($text);
  41. }
  42. public function getEmailPlaceHolders($params)
  43. {
  44. $placeHolders = [];
  45. $allEmailPlaceholders = [];
  46. $template = is_array($params) ? ($params['match'] . 'Note') : (!empty($params) ? $params : 'template');
  47. if ($template == 'template') {
  48. $placeHolders = [
  49. 'ticket' => [
  50. 'id' => [
  51. 'title' => $this->trans('Ticket Id'),
  52. 'info' => $this->trans('ticket.id.placeHolders.info'),
  53. ],
  54. 'subject' => [
  55. 'title' => $this->trans('Ticket Subject'),
  56. 'info' => $this->trans('ticket.subject.placeHolders.info'),
  57. ],
  58. 'message' => [
  59. 'title' => $this->trans('Ticket Message'),
  60. 'info' => $this->trans('ticket.message.placeHolders.info'),
  61. ],
  62. 'attachments' => [
  63. 'title' => $this->trans('Ticket Attachments'),
  64. 'info' => $this->trans('ticket.attachments.placeHolders.info'),
  65. ],
  66. 'threadMessage' => [
  67. 'title' => $this->trans('Ticket Thread Message'),
  68. 'info' => $this->trans('ticket.threadMessage.placeHolders.info'),
  69. ],
  70. 'tags' => [
  71. 'title' => $this->trans('Ticket Tags'),
  72. 'info' => $this->trans('ticket.tags.placeHolders.info'),
  73. ],
  74. 'source' => [
  75. 'title' => $this->trans('Ticket Source'),
  76. 'info' => $this->trans('ticket.source.placeHolders.info'),
  77. ],
  78. 'status' => [
  79. 'title' => $this->trans('Ticket Status'),
  80. 'info' => $this->trans('ticket.status.placeHolders.info'),
  81. ],
  82. 'priority' => [
  83. 'title' => $this->trans('Ticket Priority'),
  84. 'info' => $this->trans('ticket.priority.placeHolders.info'),
  85. ],
  86. 'group' => [
  87. 'title' => $this->trans('Ticket Group'),
  88. 'info' => $this->trans('ticket.group.placeHolders.info'),
  89. ],
  90. 'team' => [
  91. 'title' => $this->trans('Ticket Team'),
  92. 'info' => $this->trans('ticket.team.placeHolders.info'),
  93. ],
  94. 'customerName' => [
  95. 'title' => $this->trans('Ticket Customer Name'),
  96. 'info' => $this->trans('ticket.customerName.placeHolders.info'),
  97. ],
  98. 'customerEmail' => [
  99. 'title' => $this->trans('Ticket Customer Email'),
  100. 'info' => $this->trans('ticket.customerEmail.placeHolders.info'),
  101. ],
  102. 'agentName' => [
  103. 'title' => $this->trans('Ticket Agent Name'),
  104. 'info' => $this->trans('ticket.agentName.placeHolders.info'),
  105. ],
  106. 'agentEmail' => [
  107. 'title' => $this->trans('Ticket Agent Email'),
  108. 'info' => $this->trans('ticket.agentEmail.placeHolders.info'),
  109. ],
  110. 'agentLink' => [
  111. 'title' => $this->trans('Ticket Agent Link'),
  112. 'info' => $this->trans('ticket.link.placeHolders.info'),
  113. ],
  114. 'customerLink' => [
  115. 'title' => $this->trans('Ticket Customer Link'),
  116. 'info' => $this->trans('ticket.link.placeHolders.info'),
  117. ],
  118. 'collaboratorName' => [
  119. 'title' => $this->trans('Last Collaborator Name'),
  120. 'info' => $this->trans('ticket.collaborator.name.placeHolders.info'),
  121. ],
  122. 'collaboratorEmail' => [
  123. 'title' => $this->trans('Last Collaborator Email'),
  124. 'info' => $this->trans('ticket.collaborator.email.placeHolders.info'),
  125. ],
  126. ],
  127. 'user' => [
  128. 'userName' => [
  129. 'title' => $this->trans('Agent/ Customer Name'),
  130. 'info' => $this->trans('user.name.info'),
  131. ],
  132. 'userEmail' => [
  133. 'title' => $this->trans('Email'),
  134. 'info' => $this->trans('user.email.info'),
  135. ],
  136. 'accountValidationLink' => [
  137. 'title' => $this->trans('Account Validation Link'),
  138. 'info' => $this->trans('user.account.validate.link.info'),
  139. ],
  140. 'forgotPasswordLink' => [
  141. 'title' => $this->trans('Password Forgot Link'),
  142. 'info' => $this->trans('user.password.forgot.link.info'),
  143. ],
  144. ],
  145. 'global' => [
  146. 'companyName' => [
  147. 'title' => $this->trans('Company Name'),
  148. 'info' => $this->trans('global.companyName'),
  149. ],
  150. 'companyLogo' => [
  151. 'title' => $this->trans('Company Logo'),
  152. 'info' => $this->trans('global.companyLogo'),
  153. ],
  154. 'companyUrl' => [
  155. 'title' => $this->trans('Company URL'),
  156. 'info' => $this->trans('global.companyUrl'),
  157. ],
  158. ],
  159. ];
  160. } elseif ($template == 'savedReply') {
  161. $placeHolders = [
  162. 'ticket' => [
  163. 'id' => [
  164. 'title' => $this->trans('Ticket Id'),
  165. 'info' => $this->trans('ticket.id.placeHolders.info'),
  166. ],
  167. 'subject' => [
  168. 'title' => $this->trans('Ticket Subject'),
  169. 'info' => $this->trans('ticket.subject.placeHolders.info'),
  170. ],
  171. 'status' => [
  172. 'title' => $this->trans('Ticket Status'),
  173. 'info' => $this->trans('ticket.status.placeHolders.info'),
  174. ],
  175. 'priority' => [
  176. 'title' => $this->trans('Ticket Priority'),
  177. 'info' => $this->trans('ticket.priority.placeHolders.info'),
  178. ],
  179. 'group' => [
  180. 'title' => $this->trans('Ticket Group'),
  181. 'info' => $this->trans('ticket.group.placeHolders.info'),
  182. ],
  183. 'team' => [
  184. 'title' => $this->trans('Ticket Team'),
  185. 'info' => $this->trans('ticket.team.placeHolders.info'),
  186. ],
  187. 'customerName' => [
  188. 'title' => $this->trans('Ticket Customer Name'),
  189. 'info' => $this->trans('ticket.customerName.placeHolders.info'),
  190. ],
  191. 'customerEmail' => [
  192. 'title' => $this->trans('Ticket Customer Email'),
  193. 'info' => $this->trans('ticket.customerEmail.placeHolders.info'),
  194. ],
  195. 'agentName' => [
  196. 'title' => $this->trans('Ticket Agent Name'),
  197. 'info' => $this->trans('ticket.agentName.placeHolders.info'),
  198. ],
  199. 'agentEmail' => [
  200. 'title' => $this->trans('Ticket Agent Email'),
  201. 'info' => $this->trans('ticket.agentEmail.placeHolders.info'),
  202. ],
  203. 'link' => [
  204. 'title' => $this->trans('Ticket Link'),
  205. 'info' => $this->trans('ticket.link.placeHolders.info'),
  206. ],
  207. ],
  208. ];
  209. } elseif ($template == 'ticketNote') {
  210. $placeHolders = [
  211. 'type' => [
  212. 'previousType' => [
  213. 'title' => $this->trans('Previous Type'),
  214. 'info' => $this->trans('type.previous.placeHolders.info'),
  215. ],
  216. 'updatedType' => [
  217. 'title' => $this->trans('Updated Type'),
  218. 'info' => $this->trans('type.updated.placeHolders.info'),
  219. ],
  220. ],
  221. 'status' => [
  222. 'previousStatus' => [
  223. 'title' => $this->trans('Previous Status'),
  224. 'info' => $this->trans('status.previous.placeHolders.info'),
  225. ],
  226. 'updatedStatus' => [
  227. 'title' => $this->trans('Updated Status'),
  228. 'info' => $this->trans('status.updated.placeHolders.info'),
  229. ],
  230. ],
  231. 'group' => [
  232. 'previousGroup' => [
  233. 'title' => $this->trans('Previous Group'),
  234. 'info' => $this->trans('group.previous.placeHolders.info'),
  235. ],
  236. 'updatedGroup' => [
  237. 'title' => $this->trans('Updated Group'),
  238. 'info' => $this->trans('group.updated.placeHolders.info'),
  239. ],
  240. ],
  241. 'team' => [
  242. 'previousTeam' => [
  243. 'title' => $this->trans('Previous Team'),
  244. 'info' => $this->trans('team.previous.placeHolders.info'),
  245. ],
  246. 'updatedTeam' => [
  247. 'title' => $this->trans('Updated Team'),
  248. 'info' => $this->trans('team.updated.placeHolders.info'),
  249. ],
  250. ],
  251. 'priority' => [
  252. 'previousPriority' => [
  253. 'title' => $this->trans('Previous Priority'),
  254. 'info' => $this->trans('priority.previous.placeHolders.info'),
  255. ],
  256. 'updatedPriority' => [
  257. 'title' => $this->trans('Updated Priority'),
  258. 'info' => $this->trans('priority.updated.placeHolders.info'),
  259. ],
  260. ],
  261. 'agent' => [
  262. 'previousAgent' => [
  263. 'title' => $this->trans('Previous Agent'),
  264. 'info' => $this->trans('agent.previous.placeHolders.info'),
  265. ],
  266. 'updatedAgent' => [
  267. 'title' => $this->trans('Updated Agent'),
  268. 'info' => $this->trans('agent.updated.placeHolders.info'),
  269. ],
  270. 'responsePerformingAgent' => [
  271. 'title' => $this->trans('Response Performing Agent'),
  272. 'info' => $this->trans('agent.response.placeHolders.info'),
  273. ],
  274. ],
  275. ];
  276. } elseif($template == 'manualNote') {
  277. $placeHolders = [
  278. 'ticket' => [
  279. 'id' => [
  280. 'title' => $this->trans('Ticket Id'),
  281. 'info' => $this->trans('ticket.id.placeHolders.info'),
  282. ],
  283. 'subject' => [
  284. 'title' => $this->trans('Ticket Subject'),
  285. 'info' => $this->trans('ticket.subject.placeHolders.info'),
  286. ],
  287. 'status' => [
  288. 'title' => $this->trans('Ticket Status'),
  289. 'info' => $this->trans('ticket.status.placeHolders.info'),
  290. ],
  291. 'priority' => [
  292. 'title' => $this->trans('Ticket Priority'),
  293. 'info' => $this->trans('ticket.priority.placeHolders.info'),
  294. ],
  295. 'group' => [
  296. 'title' => $this->trans('Ticket Group'),
  297. 'info' => $this->trans('ticket.group.placeHolders.info'),
  298. ],
  299. 'team' => [
  300. 'title' => $this->trans('Ticket Team'),
  301. 'info' => $this->trans('ticket.team.placeHolders.info'),
  302. ],
  303. 'customerName' => [
  304. 'title' => $this->trans('Ticket Customer Name'),
  305. 'info' => $this->trans('ticket.customerName.placeHolders.info'),
  306. ],
  307. 'customerEmail' => [
  308. 'title' => $this->trans('Ticket Customer Email'),
  309. 'info' => $this->trans('ticket.customerEmail.placeHolders.info'),
  310. ],
  311. 'agentName' => [
  312. 'title' => $this->trans('Ticket Agent Name'),
  313. 'info' => $this->trans('ticket.agentName.placeHolders.info'),
  314. ],
  315. 'agentEmail' => [
  316. 'title' => $this->trans('Ticket Agent Email'),
  317. 'info' => $this->trans('ticket.agentEmail.placeHolders.info'),
  318. ],
  319. ],
  320. ];
  321. }
  322. return $placeHolders;
  323. }
  324. public function getEmailPlaceholderValues(User $user, $userType = 'member')
  325. {
  326. if (null == $user->getVerificationCode()) {
  327. // Set user verification code
  328. $user->setVerificationCode(TokenGenerator::generateToken());
  329. $this->entityManager->persist($user);
  330. $this->entityManager->flush();
  331. }
  332. $router = $this->container->get('router');
  333. $helpdeskWebsite = $this->entityManager->getRepository(Website::class)->findOneByCode('helpdesk');
  334. // Link to company knowledgebase
  335. if (false == array_key_exists('UVDeskSupportCenterBundle', $this->container->getParameter('kernel.bundles'))) {
  336. $companyURL = $this->container->getParameter('uvdesk.site_url');
  337. } else {
  338. $companyURL = $router->generate('helpdesk_knowledgebase', [], UrlGeneratorInterface::ABSOLUTE_URL);
  339. }
  340. // Resolve path to helpdesk brand image
  341. $companyLogoURL = sprintf('http://%s%s', $this->container->getParameter('uvdesk.site_url'), '/bundles/uvdeskcoreframework/images/uv-avatar-uvdesk.png');
  342. $helpdeskKnowledgebaseWebsite = $this->entityManager->getRepository(Website::class)->findOneByCode('knowledgebase');
  343. if (!empty($helpdeskKnowledgebaseWebsite) && null != $helpdeskKnowledgebaseWebsite->getLogo()) {
  344. $companyLogoURL = sprintf('http://%s%s', $this->container->getParameter('uvdesk.site_url'), $helpdeskKnowledgebaseWebsite->getLogo());
  345. }
  346. // Link to update account login credentials
  347. $updateCredentialsURL = $router->generate( 'helpdesk_update_account_credentials', [
  348. 'email' => $user->getEmail(),
  349. 'verificationCode' => $user->getVerificationCode(),
  350. ], UrlGeneratorInterface::ABSOLUTE_URL);
  351. $placeholderParams = [
  352. 'user.userName' => $user->getFullName(),
  353. 'user.userEmail' => $user->getEmail(),
  354. 'user.assignUserEmail' => $user->getEmail(),
  355. 'user.forgotPasswordLink' => "<a href='$updateCredentialsURL'>$updateCredentialsURL</a>",
  356. 'user.accountValidationLink' => "<a href='$updateCredentialsURL'>$updateCredentialsURL</a>",
  357. 'global.companyName' => $helpdeskWebsite->getName(),
  358. 'global.companyLogo' => "<img style='max-height:60px' src='$companyLogoURL'/>",
  359. 'global.companyUrl' => "<a href='$companyURL'>$companyURL</a>",
  360. ];
  361. return $placeholderParams;
  362. }
  363. public function getTicketPlaceholderValues(Ticket $ticket, $type = "")
  364. {
  365. $supportTeam = $ticket->getSupportTeam();
  366. $supportGroup = $ticket->getSupportGroup();
  367. $supportTags = array_map(function ($supportTag) { return $supportTag->getName(); }, $ticket->getSupportTags()->toArray());
  368. $router = $this->container->get('router');
  369. $helpdeskWebsite = $this->entityManager->getRepository(Website::class)->findOneByCode('helpdesk');
  370. // Resolve path to helpdesk brand image
  371. $companyLogoURL = sprintf('http://%s%s', $this->container->getParameter('uvdesk.site_url'), '/bundles/uvdeskcoreframework/images/uv-avatar-uvdesk.png');
  372. $helpdeskKnowledgebaseWebsite = $this->entityManager->getRepository(Website::class)->findOneByCode('knowledgebase');
  373. if (!empty($helpdeskKnowledgebaseWebsite) && null != $helpdeskKnowledgebaseWebsite->getLogo()) {
  374. $companyLogoURL = sprintf('http://%s%s', $this->container->getParameter('uvdesk.site_url'), $helpdeskKnowledgebaseWebsite->getLogo());
  375. }
  376. // Link to company knowledgebase
  377. if (false == array_key_exists('UVDeskSupportCenterBundle', $this->container->getParameter('kernel.bundles'))) {
  378. $companyURL = $this->container->getParameter('uvdesk.site_url');
  379. } else {
  380. $companyURL = $router->generate('helpdesk_knowledgebase', [], UrlGeneratorInterface::ABSOLUTE_URL);
  381. }
  382. $customerPartialDetails = $ticket->getCustomer()->getCustomerInstance()->getPartialDetails();
  383. $agentPartialDetails = $ticket->getAgent() ? $ticket->getAgent()->getAgentInstance()->getPartialDetails() : null;
  384. //Ticket Url and create ticket url for agent
  385. $viewTicketURLAgent = $router->generate('helpdesk_member_ticket', [
  386. 'ticketId' => $ticket->getId(),
  387. ], UrlGeneratorInterface::ABSOLUTE_URL);
  388. $generateTicketURLAgent = $router->generate('helpdesk_member_create_ticket', [], UrlGeneratorInterface::ABSOLUTE_URL);
  389. if (false != array_key_exists('UVDeskSupportCenterBundle', $this->container->getParameter('kernel.bundles'))) {
  390. $viewTicketURL = $router->generate('helpdesk_customer_ticket', [
  391. 'id' => $ticket->getId(),
  392. ], UrlGeneratorInterface::ABSOLUTE_URL);
  393. $generateTicketURLCustomer = $router->generate('helpdesk_customer_create_ticket', [], UrlGeneratorInterface::ABSOLUTE_URL);
  394. } else {
  395. $viewTicketURL = '';
  396. $generateTicketURLCustomer = '';
  397. }
  398. $placeholderParams = [
  399. 'ticket.id' => $ticket->getId(),
  400. 'ticket.subject' => $ticket->getSubject(),
  401. 'ticket.message' => (count($ticket->getThreads())) > 0 ? preg_replace("/<img[^>]+\>/i", "", $ticket->getThreads()->get(0)->getMessage()) : preg_replace("/<img[^>]+\>/i", "", $this->container->get('ticket.service')->getInitialThread($ticket->getId())->getMessage()),
  402. 'ticket.threadMessage' => $this->threadMessage($ticket),
  403. 'ticket.tags' => implode(',', $supportTags),
  404. 'ticket.source' => ucfirst($ticket->getSource()),
  405. 'ticket.status' => $ticket->getStatus()->getDescription(),
  406. 'ticket.priority' => $ticket->getPriority()->getDescription(),
  407. 'ticket.team' => $supportTeam ? $supportTeam->getName() : '',
  408. 'ticket.group' => $supportGroup ? $supportGroup->getName() : '',
  409. 'ticket.customerName' => $customerPartialDetails['name'],
  410. 'ticket.customerEmail' => $customerPartialDetails['email'],
  411. 'ticket.agentName' => !empty($agentPartialDetails) ? $agentPartialDetails['name'] : '',
  412. 'ticket.agentEmail' => !empty($agentPartialDetails) ? $agentPartialDetails['email'] : '',
  413. 'ticket.attachments' => '',
  414. 'ticket.collaboratorName' => $this->getCollaboratorName($ticket),
  415. 'ticket.collaboratorEmail' => $this->getCollaboratorEmail($ticket),
  416. 'ticket.agentLink' => sprintf("<a href='%s'>#%s</a>", $viewTicketURLAgent, $ticket->getId()),
  417. 'ticket.ticketGenerateUrlAgent' => sprintf("<a href='%s'>click here</a>", $generateTicketURLAgent),
  418. 'ticket.customerLink' => sprintf("<a href='%s'>#%s</a>", $viewTicketURL, $ticket->getId()),
  419. 'ticket.ticketGenerateUrlCustomer' => sprintf("<a href='%s'>click here</a>", $generateTicketURLCustomer),
  420. 'global.companyName' => $helpdeskWebsite->getName(),
  421. 'global.companyLogo' => "<img style='max-height:60px' src='$companyLogoURL'/>",
  422. 'global.companyUrl' => "<a href='$companyURL'>$companyURL</a>",
  423. ];
  424. return $placeholderParams;
  425. }
  426. public function threadMessage($ticket)
  427. {
  428. $message = null;
  429. if (isset($ticket->createdThread) && $ticket->createdThread->getThreadType() != "note") {
  430. return preg_replace("/<img[^>]+\>/i", "", $ticket->createdThread->getMessage());
  431. } elseif (isset($ticket->currentThread) && $ticket->currentThread->getThreadType() != "note") {
  432. return preg_replace("/<img[^>]+\>/i", "", $ticket->currentThread->getMessage());
  433. } else {
  434. $messages = $ticket->getThreads();
  435. for ($i = count($messages) - 1 ; $i >= 0 ; $i--) {
  436. if (isset($messages[$i]) && $messages[$i]->getThreadType() != "note") {
  437. return preg_replace("/<img[^>]+\>/i", "", $messages[$i]->getMessage());
  438. }
  439. }
  440. }
  441. return "";
  442. }
  443. public function processEmailSubject($subject, array $emailPlaceholders = [])
  444. {
  445. foreach ($emailPlaceholders as $var => $value) {
  446. $subject = strtr($subject, ["{%$var%}" => $value, "{% $var %}" => $value]);
  447. }
  448. return $subject;
  449. }
  450. public function processEmailContent($content, array $emailPlaceholders = [], $isSavedReply = false)
  451. {
  452. $twigTemplatingEngine = $this->container->get('twig');
  453. $baseEmailTemplate = $this->container->getParameter('uvdesk.default.templates.email');
  454. foreach ($emailPlaceholders as $var => $value) {
  455. $content = strtr($content, ["{%$var%}" => $value, "{% $var %}" => $value]);
  456. }
  457. $content = $isSavedReply ? stripslashes($content) : htmlspecialchars_decode(preg_replace(['#&lt;script&gt;#', '#&lt;/script&gt;#'], ['&amp;lt;script&amp;gt;', '&amp;lt;/script&amp;gt;'], $content));
  458. return $twigTemplatingEngine->render($baseEmailTemplate, ['message' => $content]);
  459. }
  460. public function sendMail($subject, $content, $recipient, array $headers = [], $mailboxEmail = null, array $attachments = [], $cc = [], $bcc = [])
  461. {
  462. $mailer_type = $this->container->getParameter('uvdesk.support_email.mailer_type');
  463. if (empty($mailboxEmail)) {
  464. // Send email on behalf of support helpdesk
  465. $supportEmail = $this->container->getParameter('uvdesk.support_email.id');
  466. $supportEmailName = $this->container->getParameter('uvdesk.support_email.name');
  467. $mailerID = $this->container->getParameter('uvdesk.support_email.mailer_id');
  468. } else {
  469. // Register automations conditionally if AutomationBundle has been added as an dependency.
  470. if (!array_key_exists('UVDeskMailboxBundle', $this->container->getParameter('kernel.bundles'))) {
  471. return;
  472. } else {
  473. // Send email on behalf of configured mailbox
  474. try {
  475. $mailbox = $this->container->get('uvdesk.mailbox')->getMailboxByEmail($mailboxEmail);
  476. if (true === $mailbox['enabled']) {
  477. if ($mailer_type == 'swiftmailer_id') {
  478. $supportEmail = $mailbox['email'];
  479. $supportEmailName = $mailbox['name'];
  480. $mailerID = $mailbox['smtp_swift_mailer_server']['mailer_id'];
  481. } else {
  482. $supportEmail = $mailbox['email'];
  483. $supportEmailName = $mailbox['name'];
  484. $mailerID = $this->container->getParameter('uvdesk.support_email.mailer_id');
  485. }
  486. } else {
  487. return;
  488. }
  489. } catch (\Exception $e) {
  490. // @TODO: Log exception - Mailbox not found
  491. return;
  492. }
  493. }
  494. }
  495. // Send emails only if any mailer configuration is available
  496. $mailer = null;
  497. $mailboxConfigurations = $this->mailboxService->parseMailboxConfigurations();
  498. if ($mailer_type != 'swiftmailer_id') {
  499. $mailbox = $mailboxConfigurations->getMailboxById($mailerID);
  500. if (!$mailbox) {
  501. return;
  502. }
  503. $mailboxSmtpConfiguration = $mailbox?->getSmtpConfiguration();
  504. }
  505. if ($mailer_type == 'swiftmailer_id') {
  506. // Retrieve mailer to be used for sending emails
  507. try {
  508. $mailer = $this->container->get('swiftmailer.mailer' . (('default' == $mailerID) ? '' : ".$mailerID"));
  509. $mailer->getTransport()->setPassword(base64_decode($mailer->getTransport()->getPassword()));
  510. } catch (\Exception $e) {
  511. // @TODO: Log exception - Mailer not found
  512. return;
  513. }
  514. // Format email address collections
  515. $ccAddresses = [];
  516. foreach ($cc as $_emailAddress) {
  517. if (strpos($_emailAddress, "<") !== false && strpos($_emailAddress, ">") !== false) {
  518. $_recipientName = trim(substr($_emailAddress, 0, strpos($_emailAddress, "<")));
  519. $_recipientAddress = substr($_emailAddress, strpos($_emailAddress, "<") + 1);
  520. $_recipientAddress = substr($_recipientAddress, 0, strpos($_recipientAddress, ">"));
  521. $ccAddresses[$_recipientAddress] = $_recipientName;
  522. } else {
  523. $ccAddresses[] = $_emailAddress;
  524. }
  525. }
  526. $bccAddresses = [];
  527. foreach ($bcc as $_emailAddress) {
  528. if (strpos($_emailAddress, "<") !== false && strpos($_emailAddress, ">") !== false) {
  529. $_recipientName = trim(substr($_emailAddress, 0, strpos($_emailAddress, "<")));
  530. $_recipientAddress = substr($_emailAddress, strpos($_emailAddress, "<") + 1);
  531. $_recipientAddress = substr($_recipientAddress, 0, strpos($_recipientAddress, ">"));
  532. $bccAddresses[$_recipientAddress] = $_recipientName;
  533. } else {
  534. $bccAddresses[] = $_emailAddress;
  535. }
  536. }
  537. // Create a message
  538. $message = (new \Swift_Message($subject))
  539. ->setFrom([$supportEmail => $supportEmailName])
  540. ->setTo($recipient)
  541. ->setBcc($bccAddresses)
  542. ->setCc($ccAddresses)
  543. ->setBody($content, 'text/html')
  544. ->addPart(strip_tags($content), 'text/plain')
  545. ;
  546. foreach ($attachments as $attachment) {
  547. if (!empty($attachment['path']) && !empty($attachment['name'])) {
  548. $message->attach(\Swift_Attachment::fromPath($attachment['path'])->setFilename($attachment['name']));
  549. continue;
  550. }
  551. $message->attach(\Swift_Attachment::fromPath($attachment));
  552. }
  553. $messageHeaders = $message->getHeaders();
  554. foreach ($headers as $headerName => $headerValue) {
  555. if (is_array($headerValue) && !empty($headerValue['messageId'])) {
  556. $headerValue = $headerValue['messageId'];
  557. }
  558. if (is_array($headerValue) || empty($headerValue)) {
  559. continue; // Skip arrays that don't have a 'messageId'.
  560. }
  561. $messageHeaders->addTextHeader($headerName, $headerValue);
  562. }
  563. try {
  564. $messageId = $message->getId();
  565. $mailer->send($message);
  566. return "<$messageId>";
  567. } catch (\Exception $e) {
  568. // @TODO: Log exception
  569. $this->session->getFlashBag()->add('warning', $this->trans('Warning! Swiftmailer not working. An error has occurred while sending emails!'));
  570. }
  571. return null;
  572. } else {
  573. // Prepare email
  574. $email = new Email();
  575. $email
  576. ->from(new Address($supportEmail, $supportEmailName))
  577. ->subject($subject)
  578. ->text(strip_tags($content))
  579. ->html($content)
  580. ;
  581. // Manage email recipients
  582. if (!empty($recipient)) {
  583. $email->to($recipient);
  584. }
  585. foreach ($cc as $emailAddress) {
  586. $email->addCc($emailAddress);
  587. }
  588. foreach ($bcc as $emailAddress) {
  589. $email->addBcc($emailAddress);
  590. }
  591. // Manage email attachments
  592. foreach ($attachments as $attachment) {
  593. if (!empty($attachment['path']) && !empty($attachment['name'])) {
  594. $email->attachFromPath($attachment['path'], $attachment['name']);
  595. continue;
  596. }
  597. $email->attachFromPath($attachment);
  598. }
  599. // Configure email headers
  600. $emailHeaders = $email->getHeaders();
  601. foreach ($headers as $name => $value) {
  602. if (is_array($value) && ! empty($value['messageId'])) {
  603. $value = $value['messageId'];
  604. }
  605. if (is_array($value) || empty($value)) {
  606. continue; // Skip arrays that don't have a 'messageId'.
  607. }
  608. $emailHeaders->addTextHeader($name, $value);
  609. }
  610. // Send email
  611. $messageId = null;
  612. try {
  613. if ($mailboxSmtpConfiguration instanceof AppTransportConfigurationInterface) {
  614. $microsoftApp = $this->entityManager->getRepository(MicrosoftApp::class)->findOneByClientId($mailboxSmtpConfiguration->getClient());
  615. if (empty($microsoftApp)) {
  616. $this->session->getFlashBag()->add('warning', $this->trans('An unexpected error occurred while trying to send email. Please try again later.'));
  617. $this->session->getFlashBag()->add('warning', $this->trans('No associated microsoft apps were found for configured mailbox.'));
  618. return null;
  619. }
  620. $microsoftAccount = $this->entityManager->getRepository(MicrosoftAccount::class)->findOneBy([
  621. 'email' => $mailboxSmtpConfiguration->getUsername(),
  622. 'microsoftApp' => $microsoftApp,
  623. ]);
  624. if (empty($microsoftAccount)) {
  625. $this->session->getFlashBag()->add('warning', $this->trans('An unexpected error occurred while trying to send email. Please try again later.'));
  626. $this->session->getFlashBag()->add('warning', $this->trans('No associated microsoft account was found for configured mailbox.'));
  627. return null;
  628. }
  629. $credentials = json_decode($microsoftAccount->getCredentials(), true);
  630. $emailParams = [
  631. 'subject' => $subject,
  632. 'body' => [
  633. 'contentType' => 'HTML',
  634. 'content' => $content,
  635. ],
  636. 'toRecipients' => [
  637. [
  638. 'emailAddress' => [
  639. 'address' => $recipient,
  640. ],
  641. ],
  642. ],
  643. ];
  644. foreach ($headers as $name => $value) {
  645. if ($name == 'X-Transport' || empty($value)) {
  646. continue;
  647. }
  648. if (is_array($value)) {
  649. $value = $value['messageId'];
  650. }
  651. $emailParams['internetMessageHeaders'][] = [
  652. 'name' => "x-$name",
  653. 'value' => $value,
  654. ];
  655. }
  656. $graphResponse = MicrosoftGraph\Me::sendMail($credentials['access_token'], $emailParams);
  657. // Refresh access token if expired
  658. if (!empty($graphResponse['error'])) {
  659. if (!empty($graphResponse['error']['code']) && $graphResponse['error']['code'] == 'InvalidAuthenticationToken') {
  660. $tokenResponse = $this->microsoftIntegration->refreshAccessToken($microsoftApp, $credentials['refresh_token']);
  661. if (!empty($tokenResponse['access_token'])) {
  662. $microsoftAccount
  663. ->setCredentials(json_encode($tokenResponse))
  664. ;
  665. $this->entityManager->persist($microsoftAccount);
  666. $this->entityManager->flush();
  667. $credentials = json_decode($microsoftAccount->getCredentials(), true);
  668. $graphResponse = MicrosoftGraph\Me::sendMail($credentials['access_token'], $emailParams);
  669. }
  670. }
  671. }
  672. } else {
  673. $dsn = strtr("smtp://{email}:{password}@{host}:{port}", [
  674. "{email}" => $mailboxSmtpConfiguration->getUsername(),
  675. "{password}" => $mailboxSmtpConfiguration->getPassword(),
  676. "{host}" => $mailboxSmtpConfiguration->getHost(),
  677. "{port}" => $mailboxSmtpConfiguration->getPort(),
  678. ]);
  679. if (false == $mailbox->getIsStrictModeEnabled()) {
  680. $dsn .= "?verify_peer=0";
  681. }
  682. $transport = Transport::fromDsn($dsn);
  683. $sentMessage = $transport->send($email);
  684. if (!empty($sentMessage)) {
  685. $messageId = $sentMessage->getMessageId();
  686. }
  687. }
  688. } catch (\Exception $e) {
  689. // @TODO: Log exception
  690. $this->session->getFlashBag()->add('warning', $this->trans('An unexpected error occurred while trying to send email. Please try again later.'));
  691. $this->session->getFlashBag()->add('warning', $this->trans($e->getMessage()));
  692. return null;
  693. }
  694. return !empty($messageId) ? "<$messageId>" : null;
  695. }
  696. }
  697. public function getCollaboratorName($ticket)
  698. {
  699. $name = null;
  700. $ticket->lastCollaborator = null;
  701. if ($ticket->getCollaborators() != null && count($ticket->getCollaborators()) > 0) {
  702. try {
  703. $ticket->lastCollaborator = $ticket->getCollaborators()[ -1 + count($ticket->getCollaborators()) ];
  704. } catch(\Exception $e) {
  705. }
  706. }
  707. if ($ticket->lastCollaborator != null) {
  708. $name = $ticket->lastCollaborator->getFirstName()." ".$ticket->lastCollaborator->getLastName();
  709. }
  710. return $name != null ? $name : '';
  711. }
  712. public function getCollaboratorEmail($ticket)
  713. {
  714. $email = null;
  715. $ticket->lastCollaborator = null;
  716. if ($ticket->getCollaborators() != null && count($ticket->getCollaborators()) > 0) {
  717. try {
  718. $ticket->lastCollaborator = $ticket->getCollaborators()[ -1 + count($ticket->getCollaborators()) ];
  719. } catch(\Exception $e) {
  720. }
  721. }
  722. if ($ticket->lastCollaborator != null) {
  723. $email = $ticket->lastCollaborator->getEmail();
  724. }
  725. return $email != null ? $email : '';;
  726. }
  727. }