EmailAction.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <?php
  2. namespace Drupal\action\Plugin\Action;
  3. use Drupal\Component\Render\PlainTextOutput;
  4. use Drupal\Core\Access\AccessResult;
  5. use Drupal\Core\Action\ConfigurableActionBase;
  6. use Drupal\Core\Entity\EntityManagerInterface;
  7. use Drupal\Core\Form\FormStateInterface;
  8. use Drupal\Core\Language\LanguageManagerInterface;
  9. use Drupal\Core\Mail\MailManagerInterface;
  10. use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
  11. use Drupal\Core\Session\AccountInterface;
  12. use Drupal\Core\Utility\Token;
  13. use Psr\Log\LoggerInterface;
  14. use Egulias\EmailValidator\EmailValidator;
  15. use Symfony\Component\DependencyInjection\ContainerInterface;
  16. /**
  17. * Sends an email message.
  18. *
  19. * @Action(
  20. * id = "action_send_email_action",
  21. * label = @Translation("Send email"),
  22. * type = "system"
  23. * )
  24. */
  25. class EmailAction extends ConfigurableActionBase implements ContainerFactoryPluginInterface {
  26. /**
  27. * The token service.
  28. *
  29. * @var \Drupal\Core\Utility\Token
  30. */
  31. protected $token;
  32. /**
  33. * The user storage.
  34. *
  35. * @var \Drupal\Core\Entity\EntityStorageInterface
  36. */
  37. protected $storage;
  38. /**
  39. * A logger instance.
  40. *
  41. * @var \Psr\Log\LoggerInterface
  42. */
  43. protected $logger;
  44. /**
  45. * The mail manager
  46. *
  47. * @var \Drupal\Core\Mail\MailManagerInterface
  48. */
  49. protected $mailManager;
  50. /**
  51. * The language manager.
  52. *
  53. * @var \Drupal\Core\Language\LanguageManagerInterface
  54. */
  55. protected $languageManager;
  56. /**
  57. * The email validator.
  58. *
  59. * @var \Egulias\EmailValidator\EmailValidator
  60. */
  61. protected $emailValidator;
  62. /**
  63. * Constructs a EmailAction object.
  64. *
  65. * @param array $configuration
  66. * A configuration array containing information about the plugin instance.
  67. * @param string $plugin_id
  68. * The plugin ID for the plugin instance.
  69. * @param mixed $plugin_definition
  70. * The plugin implementation definition.
  71. * @param \Drupal\Core\Utility\Token $token
  72. * The token service.
  73. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
  74. * The entity manager.
  75. * @param \Psr\Log\LoggerInterface $logger
  76. * A logger instance.
  77. * @param \Drupal\Core\Mail\MailManagerInterface $mail_manager
  78. * The mail manager.
  79. * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
  80. * The language manager.
  81. * @param \Egulias\EmailValidator\EmailValidator $email_validator
  82. * The email validator.
  83. */
  84. public function __construct(array $configuration, $plugin_id, $plugin_definition, Token $token, EntityManagerInterface $entity_manager, LoggerInterface $logger, MailManagerInterface $mail_manager, LanguageManagerInterface $language_manager, EmailValidator $email_validator) {
  85. parent::__construct($configuration, $plugin_id, $plugin_definition);
  86. $this->token = $token;
  87. $this->storage = $entity_manager->getStorage('user');
  88. $this->logger = $logger;
  89. $this->mailManager = $mail_manager;
  90. $this->languageManager = $language_manager;
  91. $this->emailValidator = $email_validator;
  92. }
  93. /**
  94. * {@inheritdoc}
  95. */
  96. public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  97. return new static($configuration, $plugin_id, $plugin_definition,
  98. $container->get('token'),
  99. $container->get('entity.manager'),
  100. $container->get('logger.factory')->get('action'),
  101. $container->get('plugin.manager.mail'),
  102. $container->get('language_manager'),
  103. $container->get('email.validator')
  104. );
  105. }
  106. /**
  107. * {@inheritdoc}
  108. */
  109. public function execute($entity = NULL) {
  110. if (empty($this->configuration['node'])) {
  111. $this->configuration['node'] = $entity;
  112. }
  113. $recipient = PlainTextOutput::renderFromHtml($this->token->replace($this->configuration['recipient'], $this->configuration));
  114. // If the recipient is a registered user with a language preference, use
  115. // the recipient's preferred language. Otherwise, use the system default
  116. // language.
  117. $recipient_accounts = $this->storage->loadByProperties(['mail' => $recipient]);
  118. $recipient_account = reset($recipient_accounts);
  119. if ($recipient_account) {
  120. $langcode = $recipient_account->getPreferredLangcode();
  121. }
  122. else {
  123. $langcode = $this->languageManager->getDefaultLanguage()->getId();
  124. }
  125. $params = ['context' => $this->configuration];
  126. $message = $this->mailManager->mail('system', 'action_send_email', $recipient, $langcode, $params);
  127. // Error logging is handled by \Drupal\Core\Mail\MailManager::mail().
  128. if ($message['result']) {
  129. $this->logger->notice('Sent email to %recipient', ['%recipient' => $recipient]);
  130. }
  131. }
  132. /**
  133. * {@inheritdoc}
  134. */
  135. public function defaultConfiguration() {
  136. return [
  137. 'recipient' => '',
  138. 'subject' => '',
  139. 'message' => '',
  140. ];
  141. }
  142. /**
  143. * {@inheritdoc}
  144. */
  145. public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
  146. $form['recipient'] = [
  147. '#type' => 'textfield',
  148. '#title' => t('Recipient email address'),
  149. '#default_value' => $this->configuration['recipient'],
  150. '#maxlength' => '254',
  151. '#description' => t('You may also use tokens: [node:author:mail], [comment:author:mail], etc. Separate recipients with a comma.'),
  152. ];
  153. $form['subject'] = [
  154. '#type' => 'textfield',
  155. '#title' => t('Subject'),
  156. '#default_value' => $this->configuration['subject'],
  157. '#maxlength' => '254',
  158. '#description' => t('The subject of the message.'),
  159. ];
  160. $form['message'] = [
  161. '#type' => 'textarea',
  162. '#title' => t('Message'),
  163. '#default_value' => $this->configuration['message'],
  164. '#cols' => '80',
  165. '#rows' => '20',
  166. '#description' => t('The message that should be sent. You may include placeholders like [node:title], [user:account-name], [user:display-name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
  167. ];
  168. return $form;
  169. }
  170. /**
  171. * {@inheritdoc}
  172. */
  173. public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
  174. if (!$this->emailValidator->isValid($form_state->getValue('recipient')) && strpos($form_state->getValue('recipient'), ':mail') === FALSE) {
  175. // We want the literal %author placeholder to be emphasized in the error message.
  176. $form_state->setErrorByName('recipient', t('Enter a valid email address or use a token email address such as %author.', ['%author' => '[node:author:mail]']));
  177. }
  178. }
  179. /**
  180. * {@inheritdoc}
  181. */
  182. public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
  183. $this->configuration['recipient'] = $form_state->getValue('recipient');
  184. $this->configuration['subject'] = $form_state->getValue('subject');
  185. $this->configuration['message'] = $form_state->getValue('message');
  186. }
  187. /**
  188. * {@inheritdoc}
  189. */
  190. public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
  191. $result = AccessResult::allowed();
  192. return $return_as_object ? $result : $result->isAllowed();
  193. }
  194. }