Konfigurasi mail sudah beres di chapter sebelumnya; sekarang saatnya menekan tombol kirim. Laravel menyediakan facade Mail dengan dua gaya pengiriman: closure-based untuk email kilat satu-baris, dan pendekatan berbasis class (Mailable) untuk email yang lebih terstruktur — kita bahas yang pertama di sini. Karena sandbox memakai MAIL_MAILER=log, setiap email yang “terkirim” meninggalkan jejak penuh di storage/logs/laravel.log — header, penerima, subject, sampai isi pesan. Jejak itulah alat bukti kita sepanjang chapter: bukan klaim “sudah terkirim”, melainkan potongan log nyata yang bisa dibaca ulang.
Email Kilat dengan Mail::raw #
Untuk pesan teks sederhana — kode verifikasi, notifikasi singkat — Mail::raw() adalah jalur tercepat. Method ini menerima isi pesan mentah dan sebuah closure yang mengatur amplop pesan:
use Illuminate\Support\Facades\Mail;
Mail::raw('Pesanan Anda sedang diproses.', function ($message) {
$message->to('[email protected]')
->subject('Status Pesanan #123');
});Closure menerima objek $message bertipe Illuminate\Mail\Message. Rantai ->to()->subject() mengisi header tujuan dan judul email sebelum pesan diserahkan ke transport. Setelah baris ini dijalankan di sandbox, kita membuka storage/logs/laravel.log:
Output yang Dihasilkan:
[2026-10-13 19:25:16] local.DEBUG: From: Laravel <[email protected]>
To: [email protected]
Subject: Status Pesanan #123
MIME-Version: 1.0
Date: Tue, 13 Oct 2026 19:25:16 +0000
Message-ID: <[email protected]>
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
Pesanan Anda sedang diproses.Enam baris pertama adalah header MIME yang disusun Symfony Mailer di balik layar. Perhatikan baris From: Laravel <[email protected]> — nilainya diambil otomatis dari konfigurasi mail.from global karena kita tidak menyetel pengirim secara eksplisit. Baris Content-Type: text/plain menegaskan Mail::raw() mengirim teks polos tanpa HTML. Bentuk arrow function juga valid untuk closure pendek:
Mail::raw('Kode verifikasi Anda: 991177', fn ($message) => $message
->to('[email protected]')
->subject('Kode Verifikasi')
);Isi Email dari View Blade #
Teks mentah cepat kaku begitu email perlu format. Mail::send() menerima nama view plus array data, sama seperti view() di controller. Kita buat dulu template di resources/views/emails/sapaan.blade.php:
Halo {{ $nama }},
Terima kasih sudah berbelanja di toko kita.
Salam,
Toko LatihanLalu kirim view tersebut dengan data nama:
Mail::send('emails.sapaan', ['nama' => 'Budi'], function ($message) {
$message->to('[email protected]', 'Budi')
->cc('[email protected]')
->bcc('[email protected]')
->replyTo('[email protected]')
->subject('Terima kasih atas pesanan Anda');
});Argument kedua (['nama' => 'Budi']) tersedia sebagai variabel $nama di dalam view. Closure amplop kini menunjukkan header tambahan: to() dengan nama tampilan, cc() untuk penerima tembusan, bcc() untuk penerima tersembunyi, dan replyTo() agar balasan diarahkan ke alamat support.
Output yang Dihasilkan:
[2026-10-13 19:25:31] local.DEBUG: From: Laravel <[email protected]>
To: Budi <[email protected]>
Cc: [email protected]
Reply-To: [email protected]
Subject: Terima kasih atas pesanan Anda
MIME-Version: 1.0
Date: Tue, 13 Oct 2026 19:25:31 +0000
Message-ID: <[email protected]>
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable
Halo Budi,
Terima kasih sudah berbelanja di toko kita.
Salam,
Toko LatihanDua hal menarik dari log ini. Pertama, To: Budi <[email protected]> — nama tampilan dari argument kedua to() ikut terformat. Kedua, Content-Type: text/html padahal template kita hanya teks: Mail::send() selalu merender view sebagai bagian HTML dari pesan multipart. Baris Bcc: sengaja tidak muncul di header — kalau muncul, penerima utama bisa membaca daftar tersembunyi. Penerima bcc tetap menerima email, hanya dihapus dari header sebelum pesan dikirim.
PendingMail: Rantai to()->send() #
Gaya Mail::to(...)->send(...) adalah alternatif yang lebih mudah dibaca ketika penerima sudah jelas. Method Mail::to() mengembalikan objek Illuminate\Mail\PendingMail yang menyimpan daftar penerima, lalu send() mengeksekusi pengiriman:
use App\Mail\OrderShipped;
use Illuminate\Support\Facades\Mail;
Mail::to('[email protected]')->send(new OrderShipped('123', 'Budi'));Pola ini bersinar saat dipasangkan dengan Mailable — class OrderShipped di atas adalah mailable yang akan kita bangun di chapter berikutnya. Rantainya juga bisa diperpanjang sebelum send():
Mail::to('[email protected]')
->cc('[email protected]')
->bcc('[email protected]')
->send(new OrderShipped('123', 'Budi'));Tabel Ringkas API Pengiriman #
| Method | Peran |
|---|---|
Mail::raw($isi, $closure) | Kirim teks mentah tanpa view |
Mail::send($view, $data, $closure) | Kirim dengan view Blade + data |
Mail::to($penerima) | Mulai rantai penerima (user/string/array) |
$message->to/cc/bcc/replyTo() | Header amplop di dalam closure |
$message->subject($judul) | Judul email |
Mail::mailer('log') | Kirim lewat mailer non-default |
Method to() juga menerima model User secara langsung — Laravel membaca properti email dari notifiable — sehingga Mail::to($user) cukup untuk seluruh aplikasi berbasis user.
Dengan dua gaya pengiriman ini kita sudah bisa mengirim email apa pun. Namana closure yang panjang di controller cepat menumpuk — dan di situlah Mailable masuk: class khusus yang memindahkan seluruh definisi email (amplop, konten, lampiran) keluar dari logic pengiriman.