View source
<?php
namespace Drupal\easy_email\Service;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Render\PlainTextOutput;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Mail\MailManagerInterface;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\RendererInterface;
use Drupal\easy_email\Entity\EasyEmailInterface;
use Drupal\easy_email\Event\EasyEmailEvent;
use Drupal\easy_email\Event\EasyEmailEvents;
use Html2Text\Html2Text;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class EmailHandler implements EmailHandlerInterface {
protected $languageManager;
protected $mailManager;
protected $renderer;
protected $entityTypeManager;
protected $emailStorage;
protected $emailTypeStorage;
protected $emailViewBuilder;
protected $time;
protected $tokenEvaluator;
protected $userEvaluator;
protected $attachmentEvaluator;
protected $renderedPreviews;
protected $eventDispatcher;
public function __construct(EntityTypeManagerInterface $entityTypeManager, MailManagerInterface $mailManager, LanguageManagerInterface $languageManager, RendererInterface $renderer, TimeInterface $time, EmailTokenEvaluatorInterface $tokenEvaluator, EmailUserEvaluatorInterface $userEvaluator, EmailAttachmentEvaluatorInterface $attachmentEvaluator, EventDispatcherInterface $eventDispatcher) {
$this->languageManager = $languageManager;
$this->mailManager = $mailManager;
$this->renderer = $renderer;
$this->entityTypeManager = $entityTypeManager;
$this->emailStorage = $entityTypeManager
->getStorage('easy_email');
$this->emailViewBuilder = $entityTypeManager
->getViewBuilder('easy_email');
$this->emailTypeStorage = $entityTypeManager
->getStorage('easy_email_type');
$this->time = $time;
$this->tokenEvaluator = $tokenEvaluator;
$this->userEvaluator = $userEvaluator;
$this->attachmentEvaluator = $attachmentEvaluator;
$this->renderedPreviews = [];
$this->eventDispatcher = $eventDispatcher;
}
public function createEmail($values = []) {
return $this->emailStorage
->create($values);
}
public function duplicateExists(EasyEmailInterface $email) {
if ($email
->hasField('key') && ($key = $email
->getKey())) {
$email = $email
->createDuplicate();
$this->userEvaluator
->evaluateUsers($email);
$key = $this->tokenEvaluator
->replaceTokens($email, $key);
$result = $this->emailStorage
->getQuery()
->condition('key', $key)
->exists('sent')
->range(0, 1)
->execute();
if (!empty($result)) {
return TRUE;
}
}
return FALSE;
}
public function sendEmail(EasyEmailInterface $email, $params = [], $send_duplicate = FALSE) {
if ($email
->isSent()) {
return FALSE;
}
if (!$send_duplicate && $this
->duplicateExists($email)) {
return FALSE;
}
$this->renderer
->executeInRenderContext(new RenderContext(), function () use ($email) {
return $this->tokenEvaluator
->evaluateTokens($email);
});
$this->userEvaluator
->evaluateUsers($email);
$params = $this
->generateEmailParams($email, $params);
$email_type = $this->emailTypeStorage
->load($email
->bundle());
$save_attachments_to = FALSE;
if ($email_type
->getSaveAttachment()) {
$save_attachments_to = $email_type
->getAttachmentScheme() . '://' . $this->tokenEvaluator
->replaceTokens($email, $email_type
->getAttachmentDirectory());
}
$this->attachmentEvaluator
->evaluateAttachments($email, $save_attachments_to);
$params['files'] = $email
->getEvaluatedAttachments();
$reply = $email
->getReplyToAddress();
$recipient_emails = $email
->getRecipientAddresses();
$default_langcode = $this->languageManager
->getDefaultLanguage()
->getId();
if ($this->tokenEvaluator
->containsUnsafeTokens($email)) {
$emails_to_send = $this
->createUnsafeEmailsForRecipients($email, $params);
}
else {
$emails_to_send = [
[
'to' => implode(', ', $recipient_emails),
'email' => $email,
'params' => $params,
],
];
}
foreach ($emails_to_send as $email_info) {
if (!empty($email_info['to'])) {
$this->eventDispatcher
->dispatch(EasyEmailEvents::EMAIL_PRESEND, new EasyEmailEvent($email));
$message = $this->mailManager
->mail('easy_email', $email_info['email']
->bundle(), $email_info['to'], $default_langcode, $email_info['params'], $reply, TRUE);
}
if (!empty($message['result'])) {
$this->eventDispatcher
->dispatch(EasyEmailEvents::EMAIL_SENT, new EasyEmailEvent($email));
$email_info['email']
->setSentTime($this->time
->getCurrentTime())
->save();
}
}
return !empty($message['result']) ? $message['result'] : FALSE;
}
protected function createUnsafeEmailsForRecipients(EasyEmailInterface $email, array $params) {
$emails = [];
$recipients = $email
->getRecipients();
foreach ($recipients as $recipient) {
if (empty($emails)) {
$user_email = $email;
}
else {
$user_email = $email
->createDuplicate();
}
$user_email
->setRecipientIds([
$recipient
->id(),
]);
$user_email
->setRecipientAddresses([
$recipient
->getEmail(),
]);
$user_email
->setCCIds(NULL);
$user_email
->setCCAddresses(NULL);
$user_email
->setBCCIds(NULL);
$user_email
->setBCCAddresses(NULL);
$user_params = $params;
if (isset($user_params['headers']['Cc'])) {
unset($user_params['headers']['Cc']);
}
if (isset($user_params['headers']['Bcc'])) {
unset($user_params['headers']['Bcc']);
}
$unsafe_user_email = $user_email
->createDuplicate();
$html_body = $user_email
->getHtmlBody();
if (!empty($html_body)) {
$unsafe_user_email
->setHtmlBody($this->tokenEvaluator
->replaceUnsafeTokens($html_body['value'], $recipient), $html_body['format']);
$user_params['body'] = $this
->buildHtmlBody($unsafe_user_email);
}
$plain_body = $user_email
->getPlainBody();
if (!empty($plain_body)) {
$unsafe_user_email
->setPlainBody($this->tokenEvaluator
->replaceUnsafeTokens($plain_body, $recipient));
$user_params['plain'] = $this
->buildPlainBody($unsafe_user_email);
}
$emails[] = [
'to' => $recipient
->getEmail(),
'email' => $user_email,
'params' => $user_params,
];
}
return $emails;
}
public function preview(EasyEmailInterface $email, $params = []) {
$message = NULL;
if (!$email
->isNew() && isset($this->renderedPreviews[$email
->id()])) {
$message = $this->renderedPreviews[$email
->id()];
}
if (empty($message)) {
$this->tokenEvaluator
->evaluateTokens($email);
$params = $this
->generateEmailParams($email, $params);
$reply = $email
->getReplyToAddress();
$recipient_emails = $email
->getRecipientAddresses();
$default_langcode = $this->languageManager
->getDefaultLanguage()
->getId();
$to = implode(', ', $recipient_emails);
$message = $this->mailManager
->mail('easy_email', $email
->bundle(), $to, $default_langcode, $params, $reply, FALSE);
if (!$email
->isNew()) {
$this->renderedPreviews[$email
->id()] = $message;
}
}
return $message;
}
protected function generateEmailParams(EasyEmailInterface $email, $params = []) {
$headers = [
'Content-Transfer-Encoding' => '8Bit',
];
$from = $email
->getFromAddress();
if (!empty($from) && !empty($email
->getFromName())) {
$from = $email
->getFromName() . ' <' . $from . '>';
}
if (!empty($from)) {
$headers += [
'From' => $from,
];
}
if ($email
->hasField('body_html') && $email
->hasField('body_plain')) {
$headers['Content-Type'] = 'text/html; charset=UTF-8;';
if ($this
->shouldGeneratePlainBody($email)) {
$body = $this
->buildHtmlBody($email);
$params['body'] = $body;
$params['convert'] = TRUE;
}
else {
$params['body'] = $this
->buildHtmlBody($email);
$params['plain'] = $this
->buildPlainBody($email);
}
}
elseif ($email
->hasField('body_html')) {
$headers['Content-Type'] = 'text/html; charset=UTF-8;';
$params['body'] = $this
->buildHtmlBody($email);
}
elseif ($email
->hasField('body_plain')) {
$headers['Content-Type'] = 'text/plain; charset=UTF-8';
$params['body'] = $this
->buildPlainBody($email);
}
else {
}
$cc = $email
->getCCAddresses();
if (!empty($cc)) {
$headers['Cc'] = implode(', ', $cc);
}
$bcc = $email
->getBCCAddresses();
if (!empty($bcc)) {
$headers['Bcc'] = implode(', ', $bcc);
}
if (!empty($params['headers'])) {
$headers += $params['headers'];
}
$params += [
'headers' => $headers,
'subject' => $email
->getSubject(),
];
$params['easy_email'] = TRUE;
return $params;
}
protected function hasHTMLBody(EasyEmailInterface $email) {
return $email
->hasField('body_html') && !empty($email
->getHtmlBody()) && !empty($email
->getHtmlBody()['value']);
}
protected function hasPlainBody(EasyEmailInterface $email) {
return $email
->hasField('body_plain') && !empty($email
->getPlainBody());
}
protected function hasInboxPreview(EasyEmailInterface $email) {
return $email
->hasField('inbox_preview') && !empty($email
->getInboxPreview());
}
protected function buildHtmlBody(EasyEmailInterface $email) {
$body = [
'body' => [
'#theme' => 'easy_email_body_html',
'#easy_email' => $email,
],
];
if ($this
->hasInboxPreview($email)) {
$body['inbox_preview'] = [
'#theme' => 'easy_email_body_inbox_preview',
'#easy_email' => $email,
'#weight' => -100,
];
}
return $body;
}
protected function renderInNewContext($build, $plain_text = FALSE) {
return $this->renderer
->executeInRenderContext(new RenderContext(), function () use ($build, $plain_text) {
if ($plain_text) {
return PlainTextOutput::renderFromHtml($this->renderer
->renderPlain($build));
}
return $this->renderer
->render($build);
});
}
protected function buildPlainBody(EasyEmailInterface $email) {
return [
'#theme' => 'easy_email_body_plain',
'#easy_email' => $email,
];
}
protected function shouldGeneratePlainBody(EasyEmailInterface $email) {
$email_type = $this->emailTypeStorage
->load($email
->bundle());
return $email_type
->getGenerateBodyPlain();
}
}