PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/laravel/framework/src/Illuminate/Mail/Mailer.php

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