This commit is contained in:
2022-07-18 08:00:16 +03:00
parent 42dd4c60f2
commit 42a8133706
2387 changed files with 210708 additions and 29 deletions

155
vendor/illuminate/mail/Attachment.php vendored Normal file
View File

@@ -0,0 +1,155 @@
<?php
namespace Illuminate\Mail;
use Closure;
use Illuminate\Container\Container;
use Illuminate\Contracts\Filesystem\Factory as FilesystemFactory;
use Illuminate\Support\Traits\Macroable;
class Attachment
{
use Macroable;
/**
* The attached file's filename.
*
* @var string|null
*/
public $as;
/**
* The attached file's mime type.
*
* @var string|null
*/
public $mime;
/**
* A callback that attaches the attachment to the mail message.
*
* @var \Closure
*/
protected $resolver;
/**
* Create a mail attachment.
*
* @param \Closure $resolver
* @return void
*/
private function __construct(Closure $resolver)
{
$this->resolver = $resolver;
}
/**
* Create a mail attachment from a path.
*
* @param string $path
* @return static
*/
public static function fromPath($path)
{
return new static(fn ($attachment, $pathStrategy) => $pathStrategy($path, $attachment));
}
/**
* Create a mail attachment from in-memory data.
*
* @param \Closure $data
* @param string $name
* @return static
*/
public static function fromData(Closure $data, $name)
{
return (new static(
fn ($attachment, $pathStrategy, $dataStrategy) => $dataStrategy($data, $attachment)
))->as($name);
}
/**
* Create a mail attachment from a file in the default storage disk.
*
* @param string $path
* @return static
*/
public static function fromStorage($path)
{
return static::fromStorageDisk(null, $path);
}
/**
* Create a mail attachment from a file in the specified storage disk.
*
* @param string|null $disk
* @param string $path
* @return static
*/
public static function fromStorageDisk($disk, $path)
{
return new static(function ($attachment, $pathStrategy, $dataStrategy) use ($disk, $path) {
$storage = Container::getInstance()->make(
FilesystemFactory::class
)->disk($disk);
$attachment
->as($attachment->as ?? basename($path))
->withMime($attachment->mime ?? $storage->mimeType($path));
return $dataStrategy(fn () => $storage->get($path), $attachment);
});
}
/**
* Set the attached file's filename.
*
* @param string $name
* @return $this
*/
public function as($name)
{
$this->as = $name;
return $this;
}
/**
* Set the attached file's mime type.
*
* @param string $mime
* @return $this
*/
public function withMime($mime)
{
$this->mime = $mime;
return $this;
}
/**
* Attach the attachment with the given strategies.
*
* @param \Closure $pathStrategy
* @param \Closure $dataStrategy
* @return mixed
*/
public function attachWith(Closure $pathStrategy, Closure $dataStrategy)
{
return ($this->resolver)($this, $pathStrategy, $dataStrategy);
}
/**
* Attach the attachment to a built-in mail type.
*
* @param \Illuminate\Mail\Mailable|\Illuminate\Mail\Message|\Illuminate\Notifications\Messages\MailMessage $mail
* @return mixed
*/
public function attachTo($mail)
{
return $this->attachWith(
fn ($path) => $mail->attach($path, ['as' => $this->as, 'mime' => $this->mime]),
fn ($data) => $mail->attachData($data(), $this->as, ['mime' => $this->mime])
);
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Illuminate\Mail\Events;
use Symfony\Component\Mime\Email;
class MessageSending
{
/**
* The Symfony Email instance.
*
* @var \Symfony\Component\Mime\Email
*/
public $message;
/**
* The message data.
*
* @var array
*/
public $data;
/**
* Create a new event instance.
*
* @param \Symfony\Component\Mime\Email $message
* @param array $data
* @return void
*/
public function __construct(Email $message, array $data = [])
{
$this->data = $data;
$this->message = $message;
}
}

View File

@@ -0,0 +1,93 @@
<?php
namespace Illuminate\Mail\Events;
use Exception;
use Illuminate\Mail\SentMessage;
/**
* @property \Symfony\Component\Mime\Email $message
*/
class MessageSent
{
/**
* The message that was sent.
*
* @var \Illuminate\Mail\SentMessage
*/
public $sent;
/**
* The message data.
*
* @var array
*/
public $data;
/**
* Create a new event instance.
*
* @param \Illuminate\Mail\SentMessage $message
* @param array $data
* @return void
*/
public function __construct(SentMessage $message, array $data = [])
{
$this->sent = $message;
$this->data = $data;
}
/**
* Get the serializable representation of the object.
*
* @return array
*/
public function __serialize()
{
$hasAttachments = collect($this->message->getAttachments())->isNotEmpty();
return $hasAttachments ? [
'sent' => base64_encode(serialize($this->sent)),
'data' => base64_encode(serialize($this->data)),
'hasAttachments' => true,
] : [
'sent' => $this->sent,
'data' => $this->data,
'hasAttachments' => false,
];
}
/**
* Marshal the object from its serialized data.
*
* @param array $data
* @return void
*/
public function __unserialize(array $data)
{
if (isset($data['hasAttachments']) && $data['hasAttachments'] === true) {
$this->sent = unserialize(base64_decode($data['sent']));
$this->data = unserialize(base64_decode($data['data']));
} else {
$this->sent = $data['sent'];
$this->data = $data['data'];
}
}
/**
* Dynamically get the original message.
*
* @param string $key
* @return mixed
*
* @throws \Exception
*/
public function __get($key)
{
if ($key === 'message') {
return $this->sent->getOriginalMessage();
}
throw new Exception('Unable to access undefined property on '.__CLASS__.': '.$key);
}
}

21
vendor/illuminate/mail/LICENSE.md vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Taylor Otwell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

507
vendor/illuminate/mail/MailManager.php vendored Normal file
View File

@@ -0,0 +1,507 @@
<?php
namespace Illuminate\Mail;
use Aws\Ses\SesClient;
use Closure;
use Illuminate\Contracts\Mail\Factory as FactoryContract;
use Illuminate\Log\LogManager;
use Illuminate\Mail\Transport\ArrayTransport;
use Illuminate\Mail\Transport\LogTransport;
use Illuminate\Mail\Transport\SesTransport;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory;
use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory;
use Symfony\Component\Mailer\Transport\Dsn;
use Symfony\Component\Mailer\Transport\FailoverTransport;
use Symfony\Component\Mailer\Transport\SendmailTransport;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory;
use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream;
/**
* @mixin \Illuminate\Mail\Mailer
*/
class MailManager implements FactoryContract
{
/**
* The application instance.
*
* @var \Illuminate\Contracts\Foundation\Application
*/
protected $app;
/**
* The array of resolved mailers.
*
* @var array
*/
protected $mailers = [];
/**
* The registered custom driver creators.
*
* @var array
*/
protected $customCreators = [];
/**
* Create a new Mail manager instance.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return void
*/
public function __construct($app)
{
$this->app = $app;
}
/**
* Get a mailer instance by name.
*
* @param string|null $name
* @return \Illuminate\Contracts\Mail\Mailer
*/
public function mailer($name = null)
{
$name = $name ?: $this->getDefaultDriver();
return $this->mailers[$name] = $this->get($name);
}
/**
* Get a mailer driver instance.
*
* @param string|null $driver
* @return \Illuminate\Mail\Mailer
*/
public function driver($driver = null)
{
return $this->mailer($driver);
}
/**
* Attempt to get the mailer from the local cache.
*
* @param string $name
* @return \Illuminate\Mail\Mailer
*/
protected function get($name)
{
return $this->mailers[$name] ?? $this->resolve($name);
}
/**
* Resolve the given mailer.
*
* @param string $name
* @return \Illuminate\Mail\Mailer
*
* @throws \InvalidArgumentException
*/
protected function resolve($name)
{
$config = $this->getConfig($name);
if (is_null($config)) {
throw new InvalidArgumentException("Mailer [{$name}] is not defined.");
}
// Once we have created the mailer instance we will set a container instance
// on the mailer. This allows us to resolve mailer classes via containers
// for maximum testability on said classes instead of passing Closures.
$mailer = new Mailer(
$name,
$this->app['view'],
$this->createSymfonyTransport($config),
$this->app['events']
);
if ($this->app->bound('queue')) {
$mailer->setQueue($this->app['queue']);
}
// Next we will set all of the global addresses on this mailer, which allows
// for easy unification of all "from" addresses as well as easy debugging
// of sent messages since these will be sent to a single email address.
foreach (['from', 'reply_to', 'to', 'return_path'] as $type) {
$this->setGlobalAddress($mailer, $config, $type);
}
return $mailer;
}
/**
* Create a new transport instance.
*
* @param array $config
* @return \Symfony\Component\Mailer\Transport\TransportInterface
*
* @throws \InvalidArgumentException
*/
public function createSymfonyTransport(array $config)
{
// Here we will check if the "transport" key exists and if it doesn't we will
// assume an application is still using the legacy mail configuration file
// format and use the "mail.driver" configuration option instead for BC.
$transport = $config['transport'] ?? $this->app['config']['mail.driver'];
if (isset($this->customCreators[$transport])) {
return call_user_func($this->customCreators[$transport], $config);
}
if (trim($transport ?? '') === '' || ! method_exists($this, $method = 'create'.ucfirst($transport).'Transport')) {
throw new InvalidArgumentException("Unsupported mail transport [{$transport}].");
}
return $this->{$method}($config);
}
/**
* Create an instance of the Symfony SMTP Transport driver.
*
* @param array $config
* @return \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport
*/
protected function createSmtpTransport(array $config)
{
$factory = new EsmtpTransportFactory;
$transport = $factory->create(new Dsn(
! empty($config['encryption']) && $config['encryption'] === 'tls' ? (($config['port'] == 465) ? 'smtps' : 'smtp') : '',
$config['host'],
$config['username'] ?? null,
$config['password'] ?? null,
$config['port'] ?? null,
$config
));
return $this->configureSmtpTransport($transport, $config);
}
/**
* Configure the additional SMTP driver options.
*
* @param \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport $transport
* @param array $config
* @return \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport
*/
protected function configureSmtpTransport(EsmtpTransport $transport, array $config)
{
$stream = $transport->getStream();
if ($stream instanceof SocketStream) {
if (isset($config['source_ip'])) {
$stream->setSourceIp($config['source_ip']);
}
if (isset($config['timeout'])) {
$stream->setTimeout($config['timeout']);
}
}
return $transport;
}
/**
* Create an instance of the Symfony Sendmail Transport driver.
*
* @param array $config
* @return \Symfony\Component\Mailer\Transport\SendmailTransport
*/
protected function createSendmailTransport(array $config)
{
return new SendmailTransport(
$config['path'] ?? $this->app['config']->get('mail.sendmail')
);
}
/**
* Create an instance of the Symfony Amazon SES Transport driver.
*
* @param array $config
* @return \Symfony\Component\Mailer\Bridge\Amazon\Transport\SesApiAsyncAwsTransport
*/
protected function createSesTransport(array $config)
{
$config = array_merge(
$this->app['config']->get('services.ses', []),
['version' => 'latest', 'service' => 'email'],
$config
);
$config = Arr::except($config, ['transport']);
return new SesTransport(
new SesClient($this->addSesCredentials($config)),
$config['options'] ?? []
);
}
/**
* Add the SES credentials to the configuration array.
*
* @param array $config
* @return array
*/
protected function addSesCredentials(array $config)
{
if (! empty($config['key']) && ! empty($config['secret'])) {
$config['credentials'] = Arr::only($config, ['key', 'secret', 'token']);
}
return $config;
}
/**
* Create an instance of the Symfony Mail Transport driver.
*
* @return \Symfony\Component\Mailer\Transport\SendmailTransport
*/
protected function createMailTransport()
{
return new SendmailTransport;
}
/**
* Create an instance of the Symfony Mailgun Transport driver.
*
* @param array $config
* @return \Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunApiTransport
*/
protected function createMailgunTransport(array $config)
{
$factory = new MailgunTransportFactory();
if (! isset($config['secret'])) {
$config = $this->app['config']->get('services.mailgun', []);
}
return $factory->create(new Dsn(
'mailgun+'.($config['scheme'] ?? 'https'),
$config['endpoint'] ?? 'default',
$config['secret'],
$config['domain']
));
}
/**
* Create an instance of the Symfony Postmark Transport driver.
*
* @param array $config
* @return \Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkApiTransport
*/
protected function createPostmarkTransport(array $config)
{
$factory = new PostmarkTransportFactory();
$options = isset($config['message_stream_id'])
? ['message_stream' => $config['message_stream_id']]
: [];
return $factory->create(new Dsn(
'postmark+api',
'default',
$config['token'] ?? $this->app['config']->get('services.postmark.token'),
null,
null,
$options
));
}
/**
* Create an instance of the Symfony Failover Transport driver.
*
* @param array $config
* @return \Symfony\Component\Mailer\Transport\FailoverTransport
*/
protected function createFailoverTransport(array $config)
{
$transports = [];
foreach ($config['mailers'] as $name) {
$config = $this->getConfig($name);
if (is_null($config)) {
throw new InvalidArgumentException("Mailer [{$name}] is not defined.");
}
// Now, we will check if the "driver" key exists and if it does we will set
// the transport configuration parameter in order to offer compatibility
// with any Laravel <= 6.x application style mail configuration files.
$transports[] = $this->app['config']['mail.driver']
? $this->createSymfonyTransport(array_merge($config, ['transport' => $name]))
: $this->createSymfonyTransport($config);
}
return new FailoverTransport($transports);
}
/**
* Create an instance of the Log Transport driver.
*
* @param array $config
* @return \Illuminate\Mail\Transport\LogTransport
*/
protected function createLogTransport(array $config)
{
$logger = $this->app->make(LoggerInterface::class);
if ($logger instanceof LogManager) {
$logger = $logger->channel(
$config['channel'] ?? $this->app['config']->get('mail.log_channel')
);
}
return new LogTransport($logger);
}
/**
* Create an instance of the Array Transport Driver.
*
* @return \Illuminate\Mail\Transport\ArrayTransport
*/
protected function createArrayTransport()
{
return new ArrayTransport;
}
/**
* Set a global address on the mailer by type.
*
* @param \Illuminate\Mail\Mailer $mailer
* @param array $config
* @param string $type
* @return void
*/
protected function setGlobalAddress($mailer, array $config, string $type)
{
$address = Arr::get($config, $type, $this->app['config']['mail.'.$type]);
if (is_array($address) && isset($address['address'])) {
$mailer->{'always'.Str::studly($type)}($address['address'], $address['name']);
}
}
/**
* Get the mail connection configuration.
*
* @param string $name
* @return array
*/
protected function getConfig(string $name)
{
// Here we will check if the "driver" key exists and if it does we will use
// the entire mail configuration file as the "driver" config in order to
// provide "BC" for any Laravel <= 6.x style mail configuration files.
return $this->app['config']['mail.driver']
? $this->app['config']['mail']
: $this->app['config']["mail.mailers.{$name}"];
}
/**
* Get the default mail driver name.
*
* @return string
*/
public function getDefaultDriver()
{
// Here we will check if the "driver" key exists and if it does we will use
// that as the default driver in order to provide support for old styles
// of the Laravel mail configuration file for backwards compatibility.
return $this->app['config']['mail.driver'] ??
$this->app['config']['mail.default'];
}
/**
* Set the default mail driver name.
*
* @param string $name
* @return void
*/
public function setDefaultDriver(string $name)
{
if ($this->app['config']['mail.driver']) {
$this->app['config']['mail.driver'] = $name;
}
$this->app['config']['mail.default'] = $name;
}
/**
* Disconnect the given mailer and remove from local cache.
*
* @param string|null $name
* @return void
*/
public function purge($name = null)
{
$name = $name ?: $this->getDefaultDriver();
unset($this->mailers[$name]);
}
/**
* Register a custom transport creator Closure.
*
* @param string $driver
* @param \Closure $callback
* @return $this
*/
public function extend($driver, Closure $callback)
{
$this->customCreators[$driver] = $callback;
return $this;
}
/**
* Get the application instance used by the manager.
*
* @return \Illuminate\Contracts\Foundation\Application
*/
public function getApplication()
{
return $this->app;
}
/**
* Set the application instance used by the manager.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return $this
*/
public function setApplication($app)
{
$this->app = $app;
return $this;
}
/**
* Forget all of the resolved mailer instances.
*
* @return $this
*/
public function forgetMailers()
{
$this->mailers = [];
return $this;
}
/**
* Dynamically call the default driver instance.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return $this->mailer()->$method(...$parameters);
}
}

View File

@@ -0,0 +1,73 @@
<?php
namespace Illuminate\Mail;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
class MailServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->registerIlluminateMailer();
$this->registerMarkdownRenderer();
}
/**
* Register the Illuminate mailer instance.
*
* @return void
*/
protected function registerIlluminateMailer()
{
$this->app->singleton('mail.manager', function ($app) {
return new MailManager($app);
});
$this->app->bind('mailer', function ($app) {
return $app->make('mail.manager')->mailer();
});
}
/**
* Register the Markdown renderer instance.
*
* @return void
*/
protected function registerMarkdownRenderer()
{
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__.'/resources/views' => $this->app->resourcePath('views/vendor/mail'),
], 'laravel-mail');
}
$this->app->singleton(Markdown::class, function ($app) {
$config = $app->make('config');
return new Markdown($app->make('view'), [
'theme' => $config->get('mail.markdown.theme', 'default'),
'paths' => $config->get('mail.markdown.paths', []),
]);
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [
'mail.manager',
'mailer',
Markdown::class,
];
}
}

1171
vendor/illuminate/mail/Mailable.php vendored Normal file

File diff suppressed because it is too large Load Diff

604
vendor/illuminate/mail/Mailer.php vendored Normal file
View File

@@ -0,0 +1,604 @@
<?php
namespace Illuminate\Mail;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Mail\Mailable as MailableContract;
use Illuminate\Contracts\Mail\Mailer as MailerContract;
use Illuminate\Contracts\Mail\MailQueue as MailQueueContract;
use Illuminate\Contracts\Queue\Factory as QueueContract;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Contracts\View\Factory;
use Illuminate\Mail\Events\MessageSending;
use Illuminate\Mail\Events\MessageSent;
use Illuminate\Support\HtmlString;
use Illuminate\Support\Traits\Macroable;
use InvalidArgumentException;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Component\Mime\Email;
class Mailer implements MailerContract, MailQueueContract
{
use Macroable;
/**
* The name that is configured for the mailer.
*
* @var string
*/
protected $name;
/**
* The view factory instance.
*
* @var \Illuminate\Contracts\View\Factory
*/
protected $views;
/**
* The Symfony Transport instance.
*
* @var \Symfony\Component\Mailer\Transport\TransportInterface
*/
protected $transport;
/**
* The event dispatcher instance.
*
* @var \Illuminate\Contracts\Events\Dispatcher|null
*/
protected $events;
/**
* The global from address and name.
*
* @var array
*/
protected $from;
/**
* The global reply-to address and name.
*
* @var array
*/
protected $replyTo;
/**
* The global return path address.
*
* @var array
*/
protected $returnPath;
/**
* The global to address and name.
*
* @var array
*/
protected $to;
/**
* The queue factory implementation.
*
* @var \Illuminate\Contracts\Queue\Factory
*/
protected $queue;
/**
* Create a new Mailer instance.
*
* @param string $name
* @param \Illuminate\Contracts\View\Factory $views
* @param \Symfony\Component\Mailer\Transport\TransportInterface $transport
* @param \Illuminate\Contracts\Events\Dispatcher|null $events
* @return void
*/
public function __construct(string $name, Factory $views, TransportInterface $transport, Dispatcher $events = null)
{
$this->name = $name;
$this->views = $views;
$this->events = $events;
$this->transport = $transport;
}
/**
* Set the global from address and name.
*
* @param string $address
* @param string|null $name
* @return void
*/
public function alwaysFrom($address, $name = null)
{
$this->from = compact('address', 'name');
}
/**
* Set the global reply-to address and name.
*
* @param string $address
* @param string|null $name
* @return void
*/
public function alwaysReplyTo($address, $name = null)
{
$this->replyTo = compact('address', 'name');
}
/**
* Set the global return path address.
*
* @param string $address
* @return void
*/
public function alwaysReturnPath($address)
{
$this->returnPath = compact('address');
}
/**
* Set the global to address and name.
*
* @param string $address
* @param string|null $name
* @return void
*/
public function alwaysTo($address, $name = null)
{
$this->to = compact('address', 'name');
}
/**
* Begin the process of mailing a mailable class instance.
*
* @param mixed $users
* @return \Illuminate\Mail\PendingMail
*/
public function to($users)
{
return (new PendingMail($this))->to($users);
}
/**
* Begin the process of mailing a mailable class instance.
*
* @param mixed $users
* @return \Illuminate\Mail\PendingMail
*/
public function cc($users)
{
return (new PendingMail($this))->cc($users);
}
/**
* Begin the process of mailing a mailable class instance.
*
* @param mixed $users
* @return \Illuminate\Mail\PendingMail
*/
public function bcc($users)
{
return (new PendingMail($this))->bcc($users);
}
/**
* Send a new message with only an HTML part.
*
* @param string $html
* @param mixed $callback
* @return \Illuminate\Mail\SentMessage|null
*/
public function html($html, $callback)
{
return $this->send(['html' => new HtmlString($html)], [], $callback);
}
/**
* Send a new message with only a raw text part.
*
* @param string $text
* @param mixed $callback
* @return \Illuminate\Mail\SentMessage|null
*/
public function raw($text, $callback)
{
return $this->send(['raw' => $text], [], $callback);
}
/**
* Send a new message with only a plain part.
*
* @param string $view
* @param array $data
* @param mixed $callback
* @return \Illuminate\Mail\SentMessage|null
*/
public function plain($view, array $data, $callback)
{
return $this->send(['text' => $view], $data, $callback);
}
/**
* Render the given message as a view.
*
* @param string|array $view
* @param array $data
* @return string
*/
public function render($view, array $data = [])
{
// First we need to parse the view, which could either be a string or an array
// containing both an HTML and plain text versions of the view which should
// be used when sending an e-mail. We will extract both of them out here.
[$view, $plain, $raw] = $this->parseView($view);
$data['message'] = $this->createMessage();
return $this->renderView($view ?: $plain, $data);
}
/**
* Send a new message using a view.
*
* @param \Illuminate\Contracts\Mail\Mailable|string|array $view
* @param array $data
* @param \Closure|string|null $callback
* @return \Illuminate\Mail\SentMessage|null
*/
public function send($view, array $data = [], $callback = null)
{
if ($view instanceof MailableContract) {
return $this->sendMailable($view);
}
// First we need to parse the view, which could either be a string or an array
// containing both an HTML and plain text versions of the view which should
// be used when sending an e-mail. We will extract both of them out here.
[$view, $plain, $raw] = $this->parseView($view);
$data['message'] = $message = $this->createMessage();
// Once we have retrieved the view content for the e-mail we will set the body
// of this message using the HTML type, which will provide a simple wrapper
// to creating view based emails that are able to receive arrays of data.
if (! is_null($callback)) {
$callback($message);
}
$this->addContent($message, $view, $plain, $raw, $data);
// If a global "to" address has been set, we will set that address on the mail
// message. This is primarily useful during local development in which each
// message should be delivered into a single mail address for inspection.
if (isset($this->to['address'])) {
$this->setGlobalToAndRemoveCcAndBcc($message);
}
// Next we will determine if the message should be sent. We give the developer
// one final chance to stop this message and then we will send it to all of
// its recipients. We will then fire the sent event for the sent message.
$symfonyMessage = $message->getSymfonyMessage();
if ($this->shouldSendMessage($symfonyMessage, $data)) {
$symfonySentMessage = $this->sendSymfonyMessage($symfonyMessage);
if ($symfonySentMessage) {
$sentMessage = new SentMessage($symfonySentMessage);
$this->dispatchSentEvent($sentMessage, $data);
return $sentMessage;
}
}
}
/**
* Send the given mailable.
*
* @param \Illuminate\Contracts\Mail\Mailable $mailable
* @return \Illuminate\Mail\SentMessage|null
*/
protected function sendMailable(MailableContract $mailable)
{
return $mailable instanceof ShouldQueue
? $mailable->mailer($this->name)->queue($this->queue)
: $mailable->mailer($this->name)->send($this);
}
/**
* Parse the given view name or array.
*
* @param string|array $view
* @return array
*
* @throws \InvalidArgumentException
*/
protected function parseView($view)
{
if (is_string($view)) {
return [$view, null, null];
}
// If the given view is an array with numeric keys, we will just assume that
// both a "pretty" and "plain" view were provided, so we will return this
// array as is, since it should contain both views with numerical keys.
if (is_array($view) && isset($view[0])) {
return [$view[0], $view[1], null];
}
// If this view is an array but doesn't contain numeric keys, we will assume
// the views are being explicitly specified and will extract them via the
// named keys instead, allowing the developers to use one or the other.
if (is_array($view)) {
return [
$view['html'] ?? null,
$view['text'] ?? null,
$view['raw'] ?? null,
];
}
throw new InvalidArgumentException('Invalid view.');
}
/**
* Add the content to a given message.
*
* @param \Illuminate\Mail\Message $message
* @param string $view
* @param string $plain
* @param string $raw
* @param array $data
* @return void
*/
protected function addContent($message, $view, $plain, $raw, $data)
{
if (isset($view)) {
$message->html($this->renderView($view, $data) ?: ' ');
}
if (isset($plain)) {
$message->text($this->renderView($plain, $data) ?: ' ');
}
if (isset($raw)) {
$message->text($raw);
}
}
/**
* Render the given view.
*
* @param string $view
* @param array $data
* @return string
*/
protected function renderView($view, $data)
{
return $view instanceof Htmlable
? $view->toHtml()
: $this->views->make($view, $data)->render();
}
/**
* Set the global "to" address on the given message.
*
* @param \Illuminate\Mail\Message $message
* @return void
*/
protected function setGlobalToAndRemoveCcAndBcc($message)
{
$message->forgetTo();
$message->to($this->to['address'], $this->to['name'], true);
$message->forgetCc();
$message->forgetBcc();
}
/**
* Queue a new e-mail message for sending.
*
* @param \Illuminate\Contracts\Mail\Mailable|string|array $view
* @param string|null $queue
* @return mixed
*
* @throws \InvalidArgumentException
*/
public function queue($view, $queue = null)
{
if (! $view instanceof MailableContract) {
throw new InvalidArgumentException('Only mailables may be queued.');
}
if (is_string($queue)) {
$view->onQueue($queue);
}
return $view->mailer($this->name)->queue($this->queue);
}
/**
* Queue a new e-mail message for sending on the given queue.
*
* @param string $queue
* @param \Illuminate\Contracts\Mail\Mailable $view
* @return mixed
*/
public function onQueue($queue, $view)
{
return $this->queue($view, $queue);
}
/**
* Queue a new e-mail message for sending on the given queue.
*
* This method didn't match rest of framework's "onQueue" phrasing. Added "onQueue".
*
* @param string $queue
* @param \Illuminate\Contracts\Mail\Mailable $view
* @return mixed
*/
public function queueOn($queue, $view)
{
return $this->onQueue($queue, $view);
}
/**
* Queue a new e-mail message for sending after (n) seconds.
*
* @param \DateTimeInterface|\DateInterval|int $delay
* @param \Illuminate\Contracts\Mail\Mailable $view
* @param string|null $queue
* @return mixed
*
* @throws \InvalidArgumentException
*/
public function later($delay, $view, $queue = null)
{
if (! $view instanceof MailableContract) {
throw new InvalidArgumentException('Only mailables may be queued.');
}
return $view->mailer($this->name)->later(
$delay, is_null($queue) ? $this->queue : $queue
);
}
/**
* Queue a new e-mail message for sending after (n) seconds on the given queue.
*
* @param string $queue
* @param \DateTimeInterface|\DateInterval|int $delay
* @param \Illuminate\Contracts\Mail\Mailable $view
* @return mixed
*/
public function laterOn($queue, $delay, $view)
{
return $this->later($delay, $view, $queue);
}
/**
* Create a new message instance.
*
* @return \Illuminate\Mail\Message
*/
protected function createMessage()
{
$message = new Message(new Email());
// If a global from address has been specified we will set it on every message
// instance so the developer does not have to repeat themselves every time
// they create a new message. We'll just go ahead and push this address.
if (! empty($this->from['address'])) {
$message->from($this->from['address'], $this->from['name']);
}
// When a global reply address was specified we will set this on every message
// instance so the developer does not have to repeat themselves every time
// they create a new message. We will just go ahead and push this address.
if (! empty($this->replyTo['address'])) {
$message->replyTo($this->replyTo['address'], $this->replyTo['name']);
}
if (! empty($this->returnPath['address'])) {
$message->returnPath($this->returnPath['address']);
}
return $message;
}
/**
* Send a Symfony Email instance.
*
* @param \Symfony\Component\Mime\Email $message
* @return \Symfony\Component\Mailer\SentMessage|null
*/
protected function sendSymfonyMessage(Email $message)
{
try {
return $this->transport->send($message, Envelope::create($message));
} finally {
//
}
}
/**
* Determines if the email can be sent.
*
* @param \Symfony\Component\Mime\Email $message
* @param array $data
* @return bool
*/
protected function shouldSendMessage($message, $data = [])
{
if (! $this->events) {
return true;
}
return $this->events->until(
new MessageSending($message, $data)
) !== false;
}
/**
* Dispatch the message sent event.
*
* @param \Illuminate\Mail\SentMessage $message
* @param array $data
* @return void
*/
protected function dispatchSentEvent($message, $data = [])
{
if ($this->events) {
$this->events->dispatch(
new MessageSent($message, $data)
);
}
}
/**
* Get the Symfony Transport instance.
*
* @return \Symfony\Component\Mailer\Transport\TransportInterface
*/
public function getSymfonyTransport()
{
return $this->transport;
}
/**
* Get the view factory instance.
*
* @return \Illuminate\Contracts\View\Factory
*/
public function getViewFactory()
{
return $this->views;
}
/**
* Set the Symfony Transport instance.
*
* @param \Symfony\Component\Mailer\Transport\TransportInterface $transport
* @return void
*/
public function setSymfonyTransport(TransportInterface $transport)
{
$this->transport = $transport;
}
/**
* Set the queue manager instance.
*
* @param \Illuminate\Contracts\Queue\Factory $queue
* @return $this
*/
public function setQueue(QueueContract $queue)
{
$this->queue = $queue;
return $this;
}
}

189
vendor/illuminate/mail/Markdown.php vendored Normal file
View File

@@ -0,0 +1,189 @@
<?php
namespace Illuminate\Mail;
use Illuminate\Contracts\View\Factory as ViewFactory;
use Illuminate\Support\HtmlString;
use Illuminate\Support\Str;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\MarkdownConverter;
use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;
class Markdown
{
/**
* The view factory implementation.
*
* @var \Illuminate\Contracts\View\Factory
*/
protected $view;
/**
* The current theme being used when generating emails.
*
* @var string
*/
protected $theme = 'default';
/**
* The registered component paths.
*
* @var array
*/
protected $componentPaths = [];
/**
* Create a new Markdown renderer instance.
*
* @param \Illuminate\Contracts\View\Factory $view
* @param array $options
* @return void
*/
public function __construct(ViewFactory $view, array $options = [])
{
$this->view = $view;
$this->theme = $options['theme'] ?? 'default';
$this->loadComponentsFrom($options['paths'] ?? []);
}
/**
* Render the Markdown template into HTML.
*
* @param string $view
* @param array $data
* @param \TijsVerkoyen\CssToInlineStyles\CssToInlineStyles|null $inliner
* @return \Illuminate\Support\HtmlString
*/
public function render($view, array $data = [], $inliner = null)
{
$this->view->flushFinderCache();
$contents = $this->view->replaceNamespace(
'mail', $this->htmlComponentPaths()
)->make($view, $data)->render();
if ($this->view->exists($customTheme = Str::start($this->theme, 'mail.'))) {
$theme = $customTheme;
} else {
$theme = str_contains($this->theme, '::')
? $this->theme
: 'mail::themes.'.$this->theme;
}
return new HtmlString(($inliner ?: new CssToInlineStyles)->convert(
$contents, $this->view->make($theme, $data)->render()
));
}
/**
* Render the Markdown template into text.
*
* @param string $view
* @param array $data
* @return \Illuminate\Support\HtmlString
*/
public function renderText($view, array $data = [])
{
$this->view->flushFinderCache();
$contents = $this->view->replaceNamespace(
'mail', $this->textComponentPaths()
)->make($view, $data)->render();
return new HtmlString(
html_entity_decode(preg_replace("/[\r\n]{2,}/", "\n\n", $contents), ENT_QUOTES, 'UTF-8')
);
}
/**
* Parse the given Markdown text into HTML.
*
* @param string $text
* @return \Illuminate\Support\HtmlString
*/
public static function parse($text)
{
$environment = new Environment([
'allow_unsafe_links' => false,
]);
$environment->addExtension(new CommonMarkCoreExtension);
$environment->addExtension(new TableExtension);
$converter = new MarkdownConverter($environment);
return new HtmlString($converter->convert($text)->getContent());
}
/**
* Get the HTML component paths.
*
* @return array
*/
public function htmlComponentPaths()
{
return array_map(function ($path) {
return $path.'/html';
}, $this->componentPaths());
}
/**
* Get the text component paths.
*
* @return array
*/
public function textComponentPaths()
{
return array_map(function ($path) {
return $path.'/text';
}, $this->componentPaths());
}
/**
* Get the component paths.
*
* @return array
*/
protected function componentPaths()
{
return array_unique(array_merge($this->componentPaths, [
__DIR__.'/resources/views',
]));
}
/**
* Register new mail component paths.
*
* @param array $paths
* @return void
*/
public function loadComponentsFrom(array $paths = [])
{
$this->componentPaths = $paths;
}
/**
* Set the default theme to be used.
*
* @param string $theme
* @return $this
*/
public function theme($theme)
{
$this->theme = $theme;
return $this;
}
/**
* Get the theme currently being used by the renderer.
*
* @return string
*/
public function getTheme()
{
return $this->theme;
}
}

402
vendor/illuminate/mail/Message.php vendored Normal file
View File

@@ -0,0 +1,402 @@
<?php
namespace Illuminate\Mail;
use Illuminate\Contracts\Mail\Attachable;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\ForwardsCalls;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
/**
* @mixin \Symfony\Component\Mime\Email
*/
class Message
{
use ForwardsCalls;
/**
* The Symfony Email instance.
*
* @var \Symfony\Component\Mime\Email
*/
protected $message;
/**
* CIDs of files embedded in the message.
*
* @deprecated Will be removed in a future Laravel version.
*
* @var array
*/
protected $embeddedFiles = [];
/**
* Create a new message instance.
*
* @param \Symfony\Component\Mime\Email $message
* @return void
*/
public function __construct(Email $message)
{
$this->message = $message;
}
/**
* Add a "from" address to the message.
*
* @param string|array $address
* @param string|null $name
* @return $this
*/
public function from($address, $name = null)
{
is_array($address)
? $this->message->from(...$address)
: $this->message->from(new Address($address, (string) $name));
return $this;
}
/**
* Set the "sender" of the message.
*
* @param string|array $address
* @param string|null $name
* @return $this
*/
public function sender($address, $name = null)
{
is_array($address)
? $this->message->sender(...$address)
: $this->message->sender(new Address($address, (string) $name));
return $this;
}
/**
* Set the "return path" of the message.
*
* @param string $address
* @return $this
*/
public function returnPath($address)
{
$this->message->returnPath($address);
return $this;
}
/**
* Add a recipient to the message.
*
* @param string|array $address
* @param string|null $name
* @param bool $override
* @return $this
*/
public function to($address, $name = null, $override = false)
{
if ($override) {
is_array($address)
? $this->message->to(...$address)
: $this->message->to(new Address($address, (string) $name));
return $this;
}
return $this->addAddresses($address, $name, 'To');
}
/**
* Remove all "to" addresses from the message.
*
* @return $this
*/
public function forgetTo()
{
if ($header = $this->message->getHeaders()->get('To')) {
$this->addAddressDebugHeader('X-To', $this->message->getTo());
$header->setAddresses([]);
}
return $this;
}
/**
* Add a carbon copy to the message.
*
* @param string|array $address
* @param string|null $name
* @param bool $override
* @return $this
*/
public function cc($address, $name = null, $override = false)
{
if ($override) {
is_array($address)
? $this->message->cc(...$address)
: $this->message->cc(new Address($address, (string) $name));
return $this;
}
return $this->addAddresses($address, $name, 'Cc');
}
/**
* Remove all carbon copy addresses from the message.
*
* @return $this
*/
public function forgetCc()
{
if ($header = $this->message->getHeaders()->get('Cc')) {
$this->addAddressDebugHeader('X-Cc', $this->message->getCC());
$header->setAddresses([]);
}
return $this;
}
/**
* Add a blind carbon copy to the message.
*
* @param string|array $address
* @param string|null $name
* @param bool $override
* @return $this
*/
public function bcc($address, $name = null, $override = false)
{
if ($override) {
is_array($address)
? $this->message->bcc(...$address)
: $this->message->bcc(new Address($address, (string) $name));
return $this;
}
return $this->addAddresses($address, $name, 'Bcc');
}
/**
* Remove all of the blind carbon copy addresses from the message.
*
* @return $this
*/
public function forgetBcc()
{
if ($header = $this->message->getHeaders()->get('Bcc')) {
$this->addAddressDebugHeader('X-Bcc', $this->message->getBcc());
$header->setAddresses([]);
}
return $this;
}
/**
* Add a "reply to" address to the message.
*
* @param string|array $address
* @param string|null $name
* @return $this
*/
public function replyTo($address, $name = null)
{
return $this->addAddresses($address, $name, 'ReplyTo');
}
/**
* Add a recipient to the message.
*
* @param string|array $address
* @param string $name
* @param string $type
* @return $this
*/
protected function addAddresses($address, $name, $type)
{
if (is_array($address)) {
$type = lcfirst($type);
$addresses = collect($address)->map(function ($address, $key) {
if (is_string($key) && is_string($address)) {
return new Address($key, $address);
}
if (is_array($address)) {
return new Address($address['email'] ?? $address['address'], $address['name'] ?? null);
}
if (is_null($address)) {
return new Address($key);
}
return $address;
})->all();
$this->message->{"{$type}"}(...$addresses);
} else {
$this->message->{"add{$type}"}(new Address($address, (string) $name));
}
return $this;
}
/**
* Add an address debug header for a list of recipients.
*
* @param string $header
* @param \Symfony\Component\Mime\Address[] $addresses
* @return $this
*/
protected function addAddressDebugHeader(string $header, array $addresses)
{
$this->message->getHeaders()->addTextHeader(
$header,
implode(', ', array_map(fn ($a) => $a->toString(), $addresses)),
);
return $this;
}
/**
* Set the subject of the message.
*
* @param string $subject
* @return $this
*/
public function subject($subject)
{
$this->message->subject($subject);
return $this;
}
/**
* Set the message priority level.
*
* @param int $level
* @return $this
*/
public function priority($level)
{
$this->message->priority($level);
return $this;
}
/**
* Attach a file to the message.
*
* @param string|\Illuminate\Contracts\Mail\Attachable|\Illuminate\Mail\Attachment $file
* @param array $options
* @return $this
*/
public function attach($file, array $options = [])
{
if ($file instanceof Attachable) {
$file = $file->toMailAttachment();
}
if ($file instanceof Attachment) {
return $file->attachTo($this);
}
$this->message->attachFromPath($file, $options['as'] ?? null, $options['mime'] ?? null);
return $this;
}
/**
* Attach in-memory data as an attachment.
*
* @param string $data
* @param string $name
* @param array $options
* @return $this
*/
public function attachData($data, $name, array $options = [])
{
$this->message->attach($data, $name, $options['mime'] ?? null);
return $this;
}
/**
* Embed a file in the message and get the CID.
*
* @param string|\Illuminate\Contracts\Mail\Attachable|\Illuminate\Mail\Attachment $file
* @return string
*/
public function embed($file)
{
if ($file instanceof Attachable) {
$file = $file->toMailAttachment();
}
if ($file instanceof Attachment) {
return $file->attachWith(
function ($path) use ($file) {
$cid = $file->as ?? Str::random();
$this->message->embedFromPath($path, $cid, $file->mime);
return "cid:{$cid}";
},
function ($data) use ($file) {
$this->message->embed($data(), $file->as, $file->mime);
return "cid:{$file->as}";
}
);
}
$cid = Str::random(10);
$this->message->embedFromPath($file, $cid);
return "cid:$cid";
}
/**
* Embed in-memory data in the message and get the CID.
*
* @param string $data
* @param string $name
* @param string|null $contentType
* @return string
*/
public function embedData($data, $name, $contentType = null)
{
$this->message->embed($data, $name, $contentType);
return "cid:$name";
}
/**
* Get the underlying Symfony Email instance.
*
* @return \Symfony\Component\Mime\Email
*/
public function getSymfonyMessage()
{
return $this->message;
}
/**
* Dynamically pass missing methods to the Symfony instance.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return $this->forwardDecoratedCallTo($this->message, $method, $parameters);
}
}

166
vendor/illuminate/mail/PendingMail.php vendored Normal file
View File

@@ -0,0 +1,166 @@
<?php
namespace Illuminate\Mail;
use Illuminate\Contracts\Mail\Mailable as MailableContract;
use Illuminate\Contracts\Mail\Mailer as MailerContract;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Support\Traits\Conditionable;
class PendingMail
{
use Conditionable;
/**
* The mailer instance.
*
* @var \Illuminate\Contracts\Mail\Mailer
*/
protected $mailer;
/**
* The locale of the message.
*
* @var string
*/
protected $locale;
/**
* The "to" recipients of the message.
*
* @var array
*/
protected $to = [];
/**
* The "cc" recipients of the message.
*
* @var array
*/
protected $cc = [];
/**
* The "bcc" recipients of the message.
*
* @var array
*/
protected $bcc = [];
/**
* Create a new mailable mailer instance.
*
* @param \Illuminate\Contracts\Mail\Mailer $mailer
* @return void
*/
public function __construct(MailerContract $mailer)
{
$this->mailer = $mailer;
}
/**
* Set the locale of the message.
*
* @param string $locale
* @return $this
*/
public function locale($locale)
{
$this->locale = $locale;
return $this;
}
/**
* Set the recipients of the message.
*
* @param mixed $users
* @return $this
*/
public function to($users)
{
$this->to = $users;
if (! $this->locale && $users instanceof HasLocalePreference) {
$this->locale($users->preferredLocale());
}
return $this;
}
/**
* Set the recipients of the message.
*
* @param mixed $users
* @return $this
*/
public function cc($users)
{
$this->cc = $users;
return $this;
}
/**
* Set the recipients of the message.
*
* @param mixed $users
* @return $this
*/
public function bcc($users)
{
$this->bcc = $users;
return $this;
}
/**
* Send a new mailable message instance.
*
* @param \Illuminate\Contracts\Mail\Mailable $mailable
* @return \Illuminate\Mail\SentMessage|null
*/
public function send(MailableContract $mailable)
{
return $this->mailer->send($this->fill($mailable));
}
/**
* Push the given mailable onto the queue.
*
* @param \Illuminate\Contracts\Mail\Mailable $mailable
* @return mixed
*/
public function queue(MailableContract $mailable)
{
return $this->mailer->queue($this->fill($mailable));
}
/**
* Deliver the queued message after (n) seconds.
*
* @param \DateTimeInterface|\DateInterval|int $delay
* @param \Illuminate\Contracts\Mail\Mailable $mailable
* @return mixed
*/
public function later($delay, MailableContract $mailable)
{
return $this->mailer->later($delay, $this->fill($mailable));
}
/**
* Populate the mailable with the addresses.
*
* @param \Illuminate\Contracts\Mail\Mailable $mailable
* @return \Illuminate\Mail\Mailable
*/
protected function fill(MailableContract $mailable)
{
return tap($mailable->to($this->to)
->cc($this->cc)
->bcc($this->bcc), function (MailableContract $mailable) {
if ($this->locale) {
$mailable->locale($this->locale);
}
});
}
}

View File

@@ -0,0 +1,128 @@
<?php
namespace Illuminate\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Mail\Factory as MailFactory;
use Illuminate\Contracts\Mail\Mailable as MailableContract;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
class SendQueuedMailable
{
use Queueable;
/**
* The mailable message instance.
*
* @var \Illuminate\Contracts\Mail\Mailable
*/
public $mailable;
/**
* The number of times the job may be attempted.
*
* @var int
*/
public $tries;
/**
* The number of seconds the job can run before timing out.
*
* @var int
*/
public $timeout;
/**
* Indicates if the job should be encrypted.
*
* @var bool
*/
public $shouldBeEncrypted = false;
/**
* Create a new job instance.
*
* @param \Illuminate\Contracts\Mail\Mailable $mailable
* @return void
*/
public function __construct(MailableContract $mailable)
{
$this->mailable = $mailable;
$this->tries = property_exists($mailable, 'tries') ? $mailable->tries : null;
$this->timeout = property_exists($mailable, 'timeout') ? $mailable->timeout : null;
$this->afterCommit = property_exists($mailable, 'afterCommit') ? $mailable->afterCommit : null;
$this->shouldBeEncrypted = $mailable instanceof ShouldBeEncrypted;
}
/**
* Handle the queued job.
*
* @param \Illuminate\Contracts\Mail\Factory $factory
* @return void
*/
public function handle(MailFactory $factory)
{
$this->mailable->send($factory);
}
/**
* Get the number of seconds before a released mailable will be available.
*
* @return mixed
*/
public function backoff()
{
if (! method_exists($this->mailable, 'backoff') && ! isset($this->mailable->backoff)) {
return;
}
return $this->mailable->backoff ?? $this->mailable->backoff();
}
/**
* Determine the time at which the job should timeout.
*
* @return \DateTime|null
*/
public function retryUntil()
{
if (! method_exists($this->mailable, 'retryUntil') && ! isset($this->mailable->retryUntil)) {
return;
}
return $this->mailable->retryUntil ?? $this->mailable->retryUntil();
}
/**
* Call the failed method on the mailable instance.
*
* @param \Throwable $e
* @return void
*/
public function failed($e)
{
if (method_exists($this->mailable, 'failed')) {
$this->mailable->failed($e);
}
}
/**
* Get the display name for the queued job.
*
* @return string
*/
public function displayName()
{
return get_class($this->mailable);
}
/**
* Prepare the instance for cloning.
*
* @return void
*/
public function __clone()
{
$this->mailable = clone $this->mailable;
}
}

54
vendor/illuminate/mail/SentMessage.php vendored Normal file
View File

@@ -0,0 +1,54 @@
<?php
namespace Illuminate\Mail;
use Illuminate\Support\Traits\ForwardsCalls;
use Symfony\Component\Mailer\SentMessage as SymfonySentMessage;
/**
* @mixin \Symfony\Component\Mailer\SentMessage
*/
class SentMessage
{
use ForwardsCalls;
/**
* The Symfony SentMessage instance.
*
* @var \Symfony\Component\Mailer\SentMessage
*/
protected $sentMessage;
/**
* Create a new SentMessage instance.
*
* @param \Symfony\Component\Mailer\SentMessage $sentMessage
* @return void
*/
public function __construct(SymfonySentMessage $sentMessage)
{
$this->sentMessage = $sentMessage;
}
/**
* Get the underlying Symfony Email instance.
*
* @return \Symfony\Component\Mailer\SentMessage
*/
public function getSymfonySentMessage()
{
return $this->sentMessage;
}
/**
* Dynamically pass missing methods to the Symfony instance.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return $this->forwardCallTo($this->sentMessage, $method, $parameters);
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace Illuminate\Mail\Transport;
use Illuminate\Support\Collection;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Component\Mime\RawMessage;
class ArrayTransport implements TransportInterface
{
/**
* The collection of Symfony Messages.
*
* @var \Illuminate\Support\Collection
*/
protected $messages;
/**
* Create a new array transport instance.
*
* @return void
*/
public function __construct()
{
$this->messages = new Collection;
}
/**
* {@inheritdoc}
*/
public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage
{
return $this->messages[] = new SentMessage($message, $envelope ?? Envelope::create($message));
}
/**
* Retrieve the collection of messages.
*
* @return \Illuminate\Support\Collection
*/
public function messages()
{
return $this->messages;
}
/**
* Clear all of the messages from the local collection.
*
* @return \Illuminate\Support\Collection
*/
public function flush()
{
return $this->messages = new Collection;
}
/**
* Get the string representation of the transport.
*
* @return string
*/
public function __toString(): string
{
return 'array';
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace Illuminate\Mail\Transport;
use Psr\Log\LoggerInterface;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Component\Mime\RawMessage;
class LogTransport implements TransportInterface
{
/**
* The Logger instance.
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* Create a new log transport instance.
*
* @param \Psr\Log\LoggerInterface $logger
* @return void
*/
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
/**
* {@inheritdoc}
*/
public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage
{
$this->logger->debug($message->toString());
return new SentMessage($message, $envelope ?? Envelope::create($message));
}
/**
* Get the logger for the LogTransport instance.
*
* @return \Psr\Log\LoggerInterface
*/
public function logger()
{
return $this->logger;
}
/**
* Get the string representation of the transport.
*
* @return string
*/
public function __toString(): string
{
return 'log';
}
}

View File

@@ -0,0 +1,131 @@
<?php
namespace Illuminate\Mail\Transport;
use Aws\Exception\AwsException;
use Aws\Ses\SesClient;
use Exception;
use Symfony\Component\Mailer\Header\MetadataHeader;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\AbstractTransport;
use Symfony\Component\Mime\Message;
class SesTransport extends AbstractTransport
{
/**
* The Amazon SES instance.
*
* @var \Aws\Ses\SesClient
*/
protected $ses;
/**
* The Amazon SES transmission options.
*
* @var array
*/
protected $options = [];
/**
* Create a new SES transport instance.
*
* @param \Aws\Ses\SesClient $ses
* @param array $options
* @return void
*/
public function __construct(SesClient $ses, $options = [])
{
$this->ses = $ses;
$this->options = $options;
parent::__construct();
}
/**
* {@inheritDoc}
*/
protected function doSend(SentMessage $message): void
{
$options = $this->options;
if ($message->getOriginalMessage() instanceof Message) {
foreach ($message->getOriginalMessage()->getHeaders()->all() as $header) {
if ($header instanceof MetadataHeader) {
$options['Tags'][] = ['Name' => $header->getKey(), 'Value' => $header->getValue()];
}
}
}
try {
$result = $this->ses->sendRawEmail(
array_merge(
$options, [
'Source' => $message->getEnvelope()->getSender()->toString(),
'Destinations' => collect($message->getEnvelope()->getRecipients())
->map
->toString()
->values()
->all(),
'RawMessage' => [
'Data' => $message->toString(),
],
]
)
);
} catch (AwsException $e) {
$reason = $e->getAwsErrorMessage() ?? $e->getMessage();
throw new Exception(
sprintf('Request to AWS SES API failed. Reason: %s.', $reason),
is_int($e->getCode()) ? $e->getCode() : 0,
$e
);
}
$messageId = $result->get('MessageId');
$message->getOriginalMessage()->getHeaders()->addHeader('X-Message-ID', $messageId);
$message->getOriginalMessage()->getHeaders()->addHeader('X-SES-Message-ID', $messageId);
}
/**
* Get the string representation of the transport.
*
* @return string
*/
public function __toString(): string
{
return 'ses';
}
/**
* Get the Amazon SES client for the SesTransport instance.
*
* @return \Aws\Ses\SesClient
*/
public function ses()
{
return $this->ses;
}
/**
* Get the transmission options being used by the transport.
*
* @return array
*/
public function getOptions()
{
return $this->options;
}
/**
* Set the transmission options being used by the transport.
*
* @param array $options
* @return array
*/
public function setOptions(array $options)
{
return $this->options = $options;
}
}

49
vendor/illuminate/mail/composer.json vendored Normal file
View File

@@ -0,0 +1,49 @@
{
"name": "illuminate/mail",
"description": "The Illuminate Mail package.",
"license": "MIT",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"require": {
"php": "^8.0.2",
"ext-json": "*",
"illuminate/collections": "^9.0",
"illuminate/container": "^9.0",
"illuminate/contracts": "^9.0",
"illuminate/macroable": "^9.0",
"illuminate/support": "^9.0",
"league/commonmark": "^2.2",
"psr/log": "^1.0|^2.0|^3.0",
"symfony/mailer": "^6.0",
"tijsverkoyen/css-to-inline-styles": "^2.2.2"
},
"autoload": {
"psr-4": {
"Illuminate\\Mail\\": ""
}
},
"extra": {
"branch-alias": {
"dev-master": "9.x-dev"
}
},
"suggest": {
"aws/aws-sdk-php": "Required to use the SES mail driver (^3.198.1).",
"symfony/http-client": "Required to use the Symfony API mail transports (^6.0).",
"symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.0).",
"symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.0)."
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev"
}

View File

@@ -0,0 +1,19 @@
<table class="action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table border="0" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td>
<a href="{{ $url }}" class="button button-{{ $color ?? 'primary' }}" target="_blank" rel="noopener">{{ $slot }}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@@ -0,0 +1,11 @@
<tr>
<td>
<table class="footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td class="content-cell" align="center">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
</td>
</tr>

View File

@@ -0,0 +1,11 @@
<tr>
<td class="header">
<a href="{{ $url }}" style="display: inline-block;">
@if (trim($slot) === 'Laravel')
<img src="https://laravel.com/img/notification-logo.png" class="logo" alt="Laravel Logo">
@else
{{ $slot }}
@endif
</a>
</td>
</tr>

View File

@@ -0,0 +1,56 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="color-scheme" content="light">
<meta name="supported-color-schemes" content="light">
<style>
@media only screen and (max-width: 600px) {
.inner-body {
width: 100% !important;
}
.footer {
width: 100% !important;
}
}
@media only screen and (max-width: 500px) {
.button {
width: 100% !important;
}
}
</style>
</head>
<body>
<table class="wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table class="content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
{{ $header ?? '' }}
<!-- Email Body -->
<tr>
<td class="body" width="100%" cellpadding="0" cellspacing="0">
<table class="inner-body" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
<!-- Body content -->
<tr>
<td class="content-cell">
{{ Illuminate\Mail\Markdown::parse($slot) }}
{{ $subcopy ?? '' }}
</td>
</tr>
</table>
</td>
</tr>
{{ $footer ?? '' }}
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,27 @@
@component('mail::layout')
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ config('app.name') }}
@endcomponent
@endslot
{{-- Body --}}
{{ $slot }}
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
{{ $subcopy }}
@endcomponent
@endslot
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
@endcomponent
@endslot
@endcomponent

View File

@@ -0,0 +1,14 @@
<table class="panel" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td class="panel-content">
<table width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td class="panel-item">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@@ -0,0 +1,7 @@
<table class="subcopy" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td>
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>

View File

@@ -0,0 +1,3 @@
<div class="table">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</div>

View File

@@ -0,0 +1,290 @@
/* Base */
body,
body *:not(html):not(style):not(br):not(tr):not(code) {
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
position: relative;
}
body {
-webkit-text-size-adjust: none;
background-color: #ffffff;
color: #718096;
height: 100%;
line-height: 1.4;
margin: 0;
padding: 0;
width: 100% !important;
}
p,
ul,
ol,
blockquote {
line-height: 1.4;
text-align: left;
}
a {
color: #3869d4;
}
a img {
border: none;
}
/* Typography */
h1 {
color: #3d4852;
font-size: 18px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h2 {
font-size: 16px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h3 {
font-size: 14px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
p {
font-size: 16px;
line-height: 1.5em;
margin-top: 0;
text-align: left;
}
p.sub {
font-size: 12px;
}
img {
max-width: 100%;
}
/* Layout */
.wrapper {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
background-color: #edf2f7;
margin: 0;
padding: 0;
width: 100%;
}
.content {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
margin: 0;
padding: 0;
width: 100%;
}
/* Header */
.header {
padding: 25px 0;
text-align: center;
}
.header a {
color: #3d4852;
font-size: 19px;
font-weight: bold;
text-decoration: none;
}
/* Logo */
.logo {
height: 75px;
max-height: 75px;
width: 75px;
}
/* Body */
.body {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
background-color: #edf2f7;
border-bottom: 1px solid #edf2f7;
border-top: 1px solid #edf2f7;
margin: 0;
padding: 0;
width: 100%;
}
.inner-body {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
background-color: #ffffff;
border-color: #e8e5ef;
border-radius: 2px;
border-width: 1px;
box-shadow: 0 2px 0 rgba(0, 0, 150, 0.025), 2px 4px 0 rgba(0, 0, 150, 0.015);
margin: 0 auto;
padding: 0;
width: 570px;
}
/* Subcopy */
.subcopy {
border-top: 1px solid #e8e5ef;
margin-top: 25px;
padding-top: 25px;
}
.subcopy p {
font-size: 14px;
}
/* Footer */
.footer {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
margin: 0 auto;
padding: 0;
text-align: center;
width: 570px;
}
.footer p {
color: #b0adc5;
font-size: 12px;
text-align: center;
}
.footer a {
color: #b0adc5;
text-decoration: underline;
}
/* Tables */
.table table {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
margin: 30px auto;
width: 100%;
}
.table th {
border-bottom: 1px solid #edeff2;
margin: 0;
padding-bottom: 8px;
}
.table td {
color: #74787e;
font-size: 15px;
line-height: 18px;
margin: 0;
padding: 10px 0;
}
.content-cell {
max-width: 100vw;
padding: 32px;
}
/* Buttons */
.action {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
margin: 30px auto;
padding: 0;
text-align: center;
width: 100%;
}
.button {
-webkit-text-size-adjust: none;
border-radius: 4px;
color: #fff;
display: inline-block;
overflow: hidden;
text-decoration: none;
}
.button-blue,
.button-primary {
background-color: #2d3748;
border-bottom: 8px solid #2d3748;
border-left: 18px solid #2d3748;
border-right: 18px solid #2d3748;
border-top: 8px solid #2d3748;
}
.button-green,
.button-success {
background-color: #48bb78;
border-bottom: 8px solid #48bb78;
border-left: 18px solid #48bb78;
border-right: 18px solid #48bb78;
border-top: 8px solid #48bb78;
}
.button-red,
.button-error {
background-color: #e53e3e;
border-bottom: 8px solid #e53e3e;
border-left: 18px solid #e53e3e;
border-right: 18px solid #e53e3e;
border-top: 8px solid #e53e3e;
}
/* Panels */
.panel {
border-left: #2d3748 solid 4px;
margin: 21px 0;
}
.panel-content {
background-color: #edf2f7;
color: #718096;
padding: 16px;
}
.panel-content p {
color: #718096;
}
.panel-item {
padding: 0;
}
.panel-item p:last-of-type {
margin-bottom: 0;
padding-bottom: 0;
}
/* Utilities */
.break-all {
word-break: break-all;
}

View File

@@ -0,0 +1 @@
{{ $slot }}: {{ $url }}

View File

@@ -0,0 +1 @@
{{ $slot }}

View File

@@ -0,0 +1 @@
[{{ $slot }}]({{ $url }})

View File

@@ -0,0 +1,9 @@
{!! strip_tags($header) !!}
{!! strip_tags($slot) !!}
@isset($subcopy)
{!! strip_tags($subcopy) !!}
@endisset
{!! strip_tags($footer) !!}

View File

@@ -0,0 +1,27 @@
@component('mail::layout')
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ config('app.name') }}
@endcomponent
@endslot
{{-- Body --}}
{{ $slot }}
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
{{ $subcopy }}
@endcomponent
@endslot
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
@endcomponent
@endslot
@endcomponent

View File

@@ -0,0 +1 @@
{{ $slot }}

View File

@@ -0,0 +1 @@
{{ $slot }}

View File

@@ -0,0 +1 @@
{{ $slot }}