PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Illuminate/Mail/Mailer.php

https://gitlab.com/barrel/framework
PHP | 467 lines | 178 code | 57 blank | 232 comment | 10 complexity | e3c5a278b00498c4e5dda6269b6f48dc MD5 | raw file
  1. <?php namespace Illuminate\Mail;
  2. use Closure;
  3. use Swift_Mailer;
  4. use Swift_Message;
  5. use Illuminate\Log\Writer;
  6. use Illuminate\View\Factory;
  7. use Illuminate\Queue\QueueManager;
  8. use Illuminate\Container\Container;
  9. use Illuminate\Support\SerializableClosure;
  10. class Mailer {
  11. /**
  12. * The view factory instance.
  13. *
  14. * @var \Illuminate\View\Factory
  15. */
  16. protected $views;
  17. /**
  18. * The Swift Mailer instance.
  19. *
  20. * @var \Swift_Mailer
  21. */
  22. protected $swift;
  23. /**
  24. * The global from address and name.
  25. *
  26. * @var array
  27. */
  28. protected $from;
  29. /**
  30. * The log writer instance.
  31. *
  32. * @var \Illuminate\Log\Writer
  33. */
  34. protected $logger;
  35. /**
  36. * The IoC container instance.
  37. *
  38. * @var \Illuminate\Container\Container
  39. */
  40. protected $container;
  41. /**
  42. * Indicates if the actual sending is disabled.
  43. *
  44. * @var bool
  45. */
  46. protected $pretending = false;
  47. /**
  48. * Array of failed recipients.
  49. *
  50. * @var array
  51. */
  52. protected $failedRecipients = array();
  53. /**
  54. * Create a new Mailer instance.
  55. *
  56. * @param \Illuminate\View\Factory $views
  57. * @param \Swift_Mailer $swift
  58. * @return void
  59. */
  60. public function __construct(Factory $views, Swift_Mailer $swift)
  61. {
  62. $this->views = $views;
  63. $this->swift = $swift;
  64. }
  65. /**
  66. * Set the global from address and name.
  67. *
  68. * @param string $address
  69. * @param string $name
  70. * @return void
  71. */
  72. public function alwaysFrom($address, $name = null)
  73. {
  74. $this->from = compact('address', 'name');
  75. }
  76. /**
  77. * Send a new message when only a plain part.
  78. *
  79. * @param string $view
  80. * @param array $data
  81. * @param mixed $callback
  82. * @return int
  83. */
  84. public function plain($view, array $data, $callback)
  85. {
  86. return $this->send(array('text' => $view), $data, $callback);
  87. }
  88. /**
  89. * Send a new message using a view.
  90. *
  91. * @param string|array $view
  92. * @param array $data
  93. * @param Closure|string $callback
  94. * @return int
  95. */
  96. public function send($view, array $data, $callback)
  97. {
  98. // First we need to parse the view, which could either be a string or an array
  99. // containing both an HTML and plain text versions of the view which should
  100. // be used when sending an e-mail. We will extract both of them out here.
  101. list($view, $plain) = $this->parseView($view);
  102. $data['message'] = $message = $this->createMessage();
  103. $this->callMessageBuilder($callback, $message);
  104. // Once we have retrieved the view content for the e-mail we will set the body
  105. // of this message using the HTML type, which will provide a simple wrapper
  106. // to creating view based emails that are able to receive arrays of data.
  107. $this->addContent($message, $view, $plain, $data);
  108. $message = $message->getSwiftMessage();
  109. return $this->sendSwiftMessage($message);
  110. }
  111. /**
  112. * Queue a new e-mail message for sending.
  113. *
  114. * @param string|array $view
  115. * @param array $data
  116. * @param Closure|string $callback
  117. * @param string $queue
  118. * @return void
  119. */
  120. public function queue($view, array $data, $callback, $queue = null)
  121. {
  122. $callback = $this->buildQueueCallable($callback);
  123. $this->queue->push('mailer@handleQueuedMessage', compact('view', 'data', 'callback'), $queue);
  124. }
  125. /**
  126. * Queue a new e-mail message for sending on the given queue.
  127. *
  128. * @param string $queue
  129. * @param string|array $view
  130. * @param array $data
  131. * @param Closure|string $callback
  132. * @return void
  133. */
  134. public function queueOn($queue, $view, array $data, $callback)
  135. {
  136. $this->queue($view, $data, $callback, $queue);
  137. }
  138. /**
  139. * Queue a new e-mail message for sending after (n) seconds.
  140. *
  141. * @param int $delay
  142. * @param string|array $view
  143. * @param array $data
  144. * @param Closure|string $callback
  145. * @param string $queue
  146. * @return void
  147. */
  148. public function later($delay, $view, array $data, $callback, $queue = null)
  149. {
  150. $callback = $this->buildQueueCallable($callback);
  151. $this->queue->later($delay, 'mailer@handleQueuedMessage', compact('view', 'data', 'callback'), $queue);
  152. }
  153. /**
  154. * Queue a new e-mail message for sending after (n) seconds on the given queue.
  155. *
  156. * @param string $queue
  157. * @param int $delay
  158. * @param string|array $view
  159. * @param array $data
  160. * @param Closure|string $callback
  161. * @return void
  162. */
  163. public function laterOn($queue, $delay, $view, array $data, $callback)
  164. {
  165. $this->later($delay, $view, $data, $callback, $queue);
  166. }
  167. /**
  168. * Build the callable for a queued e-mail job.
  169. *
  170. * @param mixed $callback
  171. * @return mixed
  172. */
  173. protected function buildQueueCallable($callback)
  174. {
  175. if ( ! $callback instanceof Closure) return $callback;
  176. return serialize(new SerializableClosure($callback));
  177. }
  178. /**
  179. * Handle a queued e-mail message job.
  180. *
  181. * @param \Illuminate\Queue\Jobs\Job $job
  182. * @param array $data
  183. * @return void
  184. */
  185. public function handleQueuedMessage($job, $data)
  186. {
  187. $this->send($data['view'], $data['data'], $this->getQueuedCallable($data));
  188. $job->delete();
  189. }
  190. /**
  191. * Get the true callable for a queued e-mail message.
  192. *
  193. * @param array $data
  194. * @return mixed
  195. */
  196. protected function getQueuedCallable(array $data)
  197. {
  198. if (str_contains($data['callback'], 'SerializableClosure'))
  199. {
  200. return with(unserialize($data['callback']))->getClosure();
  201. }
  202. return $data['callback'];
  203. }
  204. /**
  205. * Add the content to a given message.
  206. *
  207. * @param \Illuminate\Mail\Message $message
  208. * @param string $view
  209. * @param string $plain
  210. * @param array $data
  211. * @return void
  212. */
  213. protected function addContent($message, $view, $plain, $data)
  214. {
  215. if (isset($view))
  216. {
  217. $message->setBody($this->getView($view, $data), 'text/html');
  218. }
  219. if (isset($plain))
  220. {
  221. $message->addPart($this->getView($plain, $data), 'text/plain');
  222. }
  223. }
  224. /**
  225. * Parse the given view name or array.
  226. *
  227. * @param string|array $view
  228. * @return array
  229. *
  230. * @throws \InvalidArgumentException
  231. */
  232. protected function parseView($view)
  233. {
  234. if (is_string($view)) return array($view, null);
  235. // If the given view is an array with numeric keys, we will just assume that
  236. // both a "pretty" and "plain" view were provided, so we will return this
  237. // array as is, since must should contain both views with numeric keys.
  238. if (is_array($view) && isset($view[0]))
  239. {
  240. return $view;
  241. }
  242. // If the view is an array, but doesn't contain numeric keys, we will assume
  243. // the the views are being explicitly specified and will extract them via
  244. // named keys instead, allowing the developers to use one or the other.
  245. elseif (is_array($view))
  246. {
  247. return array(
  248. array_get($view, 'html'), array_get($view, 'text')
  249. );
  250. }
  251. throw new \InvalidArgumentException("Invalid view.");
  252. }
  253. /**
  254. * Send a Swift Message instance.
  255. *
  256. * @param \Swift_Message $message
  257. * @return int
  258. */
  259. protected function sendSwiftMessage($message)
  260. {
  261. if ( ! $this->pretending)
  262. {
  263. return $this->swift->send($message, $this->failedRecipients);
  264. }
  265. elseif (isset($this->logger))
  266. {
  267. $this->logMessage($message);
  268. return 1;
  269. }
  270. }
  271. /**
  272. * Log that a message was sent.
  273. *
  274. * @param \Swift_Message $message
  275. * @return void
  276. */
  277. protected function logMessage($message)
  278. {
  279. $emails = implode(', ', array_keys((array) $message->getTo()));
  280. $this->logger->info("Pretending to mail message to: {$emails}");
  281. }
  282. /**
  283. * Call the provided message builder.
  284. *
  285. * @param Closure|string $callback
  286. * @param \Illuminate\Mail\Message $message
  287. * @return mixed
  288. *
  289. * @throws \InvalidArgumentException
  290. */
  291. protected function callMessageBuilder($callback, $message)
  292. {
  293. if ($callback instanceof Closure)
  294. {
  295. return call_user_func($callback, $message);
  296. }
  297. elseif (is_string($callback))
  298. {
  299. return $this->container[$callback]->mail($message);
  300. }
  301. throw new \InvalidArgumentException("Callback is not valid.");
  302. }
  303. /**
  304. * Create a new message instance.
  305. *
  306. * @return \Illuminate\Mail\Message
  307. */
  308. protected function createMessage()
  309. {
  310. $message = new Message(new Swift_Message);
  311. // If a global from address has been specified we will set it on every message
  312. // instances so the developer does not have to repeat themselves every time
  313. // they create a new message. We will just go ahead and push the address.
  314. if (isset($this->from['address']))
  315. {
  316. $message->from($this->from['address'], $this->from['name']);
  317. }
  318. return $message;
  319. }
  320. /**
  321. * Render the given view.
  322. *
  323. * @param string $view
  324. * @param array $data
  325. * @return \Illuminate\View\View
  326. */
  327. protected function getView($view, $data)
  328. {
  329. return $this->views->make($view, $data)->render();
  330. }
  331. /**
  332. * Tell the mailer to not really send messages.
  333. *
  334. * @param bool $value
  335. * @return void
  336. */
  337. public function pretend($value = true)
  338. {
  339. $this->pretending = $value;
  340. }
  341. /**
  342. * Get the view factory instance.
  343. *
  344. * @return \Illuminate\View\Factory
  345. */
  346. public function getViewFactory()
  347. {
  348. return $this->views;
  349. }
  350. /**
  351. * Get the Swift Mailer instance.
  352. *
  353. * @return \Swift_Mailer
  354. */
  355. public function getSwiftMailer()
  356. {
  357. return $this->swift;
  358. }
  359. /**
  360. * Get the array of failed recipients.
  361. *
  362. * @return array
  363. */
  364. public function failures()
  365. {
  366. return $this->failedRecipients;
  367. }
  368. /**
  369. * Set the Swift Mailer instance.
  370. *
  371. * @param \Swift_Mailer $swift
  372. * @return void
  373. */
  374. public function setSwiftMailer($swift)
  375. {
  376. $this->swift = $swift;
  377. }
  378. /**
  379. * Set the log writer instance.
  380. *
  381. * @param \Illuminate\Log\Writer $logger
  382. * @return \Illuminate\Mail\Mailer
  383. */
  384. public function setLogger(Writer $logger)
  385. {
  386. $this->logger = $logger;
  387. return $this;
  388. }
  389. /**
  390. * Set the queue manager instance.
  391. *
  392. * @param \Illuminate\Queue\QueueManager $queue
  393. * @return \Illuminate\Mail\Mailer
  394. */
  395. public function setQueue(QueueManager $queue)
  396. {
  397. $this->queue = $queue;
  398. return $this;
  399. }
  400. /**
  401. * Set the IoC container instance.
  402. *
  403. * @param \Illuminate\Container\Container $container
  404. * @return void
  405. */
  406. public function setContainer(Container $container)
  407. {
  408. $this->container = $container;
  409. }
  410. }