Laravel のメールの仕組みの多くは大がかりです。例えば、通知の一形態としてのメールならば Eloquent に通知可能を示す trait を use させて、通知クラスを作って、メール用の Blade を作って、となりますし、\Mail::send メソッドもすぐにメールを飛ばせると思いきやメール内容定義用の別ファイルが必要になります。
次の三行ですぐにメールを飛ばせます(Laravel 6.18 で確認)。
\Mail::raw('これは本文です', function (\Illuminate\Mail\Message $message) {
$message->to('hoge@example.com')->subject('これは件名です');
});
これを次の様に tmp という名の Artisan Command にすれば、php artisan tmp と打つだけで Laravel としてのメール設定テストが行えます。
<?php
namespace App\Console\Commands;
class Tmp extends \Illuminate\Console\Command
{
protected $name = 'tmp';
public function handle()
{
\Mail::raw('これは本文です', function (\Illuminate\Mail\Message $message) {
$message->to('hoge@example.com')->subject('これは件名です');
});
}
}
以下関連する Laravel ソースコードへのコメントによる簡易な解説です。
\Mail ファサードは \Illuminate\Mail\Mailer を Laravel 内の設定に従ってインスタンス化した状態でよく使うメソッドをすぐ呼び出せるようにしているファサードです。これによって \Illuminate\Mail\Mailer::raw を呼び出します。 raw メソッドは生の平文メールを送信するメソッドで、次が raw メソッドの中身によって簡単な平文メールが構築されて、送信メソッドを呼び出される部分のソースコードです。
\Illuminate\Mail\Mailer::raw 関連部のソースコード
// \Illuminate\Mail\Mailer::raw
/**
* Send a new message with only a raw text part.
*
* @param string $text
* @param mixed $callback
* @return void
*/
public function raw($text, $callback)
{
// send メソッドのラッパーメソッド
return $this->send(['raw' => $text], [], $callback);
}
/**
* Send a new message using a view.
*
* @param \Illuminate\Contracts\Mail\Mailable|string|array $view
* @param array $data
* @param \Closure|string|null $callback
* @return void
*/
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.
// ここで引数を解釈して[null, null, $raw]になる
[$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.
// ここでメールのメタ情報(from, to, subject など)を構築
// $message instanceof \Illuminate\Mail\Message な $message に受け渡された処理である 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.
// ここでメール送信を実行
$swiftMessage = $message->getSwiftMessage();
if ($this->shouldSendMessage($swiftMessage, $data)) {
$this->sendSwiftMessage($swiftMessage);
$this->dispatchSentEvent($message, $data);
}
}
/**
* 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)
{
// $view には null が入るので無視
if (isset($view)) {
$message->setBody($this->renderView($view, $data), 'text/html');
}
// $plain には null が入るので無視
if (isset($plain)) {
$method = isset($view) ? 'addPart' : 'setBody';
$message->$method($this->renderView($plain, $data) ?: ' ', 'text/plain');
}
// $raw のみあるでこの if 文内のみが実行されて簡易な平文メールとして構築されます
if (isset($raw)) {
$method = (isset($view) || isset($plain)) ? 'addPart' : 'setBody';
$message->$method($raw, 'text/plain');
}
}