Membangun klien SMTP sendiri di chapter sebelumnya memberi kita pemahaman berharga sekaligus pelajaran: detail MIME, enkripsi TLS, dan penyandian autentikasi adalah beban yang tidak ingin Anda tanggung sendiri di produksi. Library email hadir untuk mengambil alih pekerjaan tersebut. Chapter ini membandingkan tiga pilihan populer — Symfony Mailer, PHPMailer, dan Laminas Mail — lalu berlatih memeriksa dan memilih dependensi dengan tetap bisa diuji tanpa koneksi internet.
Mengapa Library, Bukan Socket Tangan Sendiri #
Library email menyelesaikan pekerjaan yang menyita waktu bila ditulis manual. Daftar berikut merangkum yang mereka urus untuk kita:
- Merakit pesan MIME yang benar, termasuk
multipart/alternativedan lampiran dengan penyandian base64. - Negosiasi TLS, autentikasi SMTP, dan penanganan jawaban error server.
- Header yang rapi — pengodean subjek non-ASCII, alamat berlabel,
Message-ID,Date. - Integrasi transport: SMTP, sendmail, bahkan layanan berbasis API seperti SendGrid atau Mailgun.
- Titik uji yang jelas sehingga logika “pesan apa yang dikirim” dapat diuji tanpa jaringan.
Dengan kata lain, library mengubah tugas tingkat protokol menjadi panggilan method yang deklaratif. Kode Anda menyatakan apa yang dikirim; library yang mengeksekusi bagaimana.
Tiga Kandidat Utama #
| Aspek | Symfony Mailer | PHPMailer | Laminas Mail |
|---|---|---|---|
| Paket Composer | symfony/mailer | phpmailer/phpmailer | laminas/laminas-mail |
| Karakter | komponen modern berbasis DSN | kelas tunggal serba bisa | modular gaya framework Laminas |
| HTML + teks murni | otomatis jadi multipart/alternative | Body + AltBody | dirakit dari objek MIME |
| Transport non-SMTP | dukungan resmi banyak API | terbatas SMTP/sendmail | SMTP via laminas-smtp |
Symfony Mailer adalah generasi terbaru: konfigurasi lewat satu string DSN, API berbasis immutable object, dan dukungan transport API pihak ketiga yang luas. PHPMailer adalah veteran yang paling sering dijumpai di tutorial dan proyek lama; satu kelasnya menampung hampir semua kebutuhan. Laminas Mail meneruskan warisan Zend Mail dengan desain modular khas ekosistem Laminas — kuat bila Anda sudah memakai komponen Laminas lain.
Symfony Mailer #
Instalasi cukup satu perintah Composer:
composer require symfony/mailerBerikut wujud pengiriman lengkap dengan Symfony Mailer. Contoh ini butuh paket terinstal dan server SMTP — pada lingkungan latihan kita, cukup pelajari bentuknya:
<?php
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mime\Email;
require __DIR__ . "/vendor/autoload.php";
$dsn = getenv("MAILER_DSN") ?: "smtp://127.0.0.1:1025";
$mailer = new Mailer(Transport::fromDsn($dsn));
$email = (new Email())
->from("[email protected]")
->to("[email protected]")
->subject("Pesanan #1234 Terkirim")
->text("Halo Budi, pesanan #1234 sudah kami kirim.")
->html("<p>Halo Budi, pesanan <strong>#1234</strong> sudah kami kirim.</p>");
$mailer->send($email);Objek Email dibangun bertahap lewat fluent interface: alamat, subjek, lalu dua versi isi sekaligus — text() dan html(). Saat send() dipanggil, library merakit multipart/alternative secara otomatis, membuka koneksi sesuai DSN, dan menangani seluruh percakapan SMTP yang kita tulis manual di chapter sebelumnya.
Perhatikan string $dsn — ia mengemas skema, kredensial, host, dan port dalam satu URL. Mari kita bedah anatomi DSN dengan parser kecil yang bisa diuji:
<?php
function bacaDsnSmtp(string $dsn): array
{
$bagian = parse_url($dsn);
if ($bagian === false || ($bagian["scheme"] ?? "") !== "smtp") {
throw new InvalidArgumentException("DSN harus diawali smtp://");
}
return [
"host" => $bagian["host"] ?? "",
"port" => $bagian["port"] ?? 25,
"pengguna" => $bagian["user"] ?? null,
];
}
echo json_encode(bacaDsnSmtp("smtp://pengirim:[email protected]:587"), JSON_UNESCAPED_SLASHES) . "\n";
try {
bacaDsnSmtp("http://bukan-smtp.example");
} catch (InvalidArgumentException $e) {
echo "Galat: " . $e->getMessage() . "\n";
}Output yang Dihasilkan:
{"host":"smtp.relay-example.com","port":587,"pengguna":"pengirim"}
Galat: DSN harus diawali smtp://Fungsi bacaDsnSmtp() memakai parse_url() untuk memecah DSN menjadi komponen, memberi nilai bawaan untuk port (25) dan pengguna (null), serta melempar InvalidArgumentException bila skemanya bukan smtp. Inilah pola “nilai hidup dari environment, logika murni dan teruji” yang sama seperti konfigurasi SMTP pada chapter sebelumnya.
PHPMailer #
PHPMailer diinstal dengan cara yang sama:
composer require phpmailer/phpmailerGaya penggunaannya berbasis satu objek dengan banyak property publik. Contoh berikut juga memerlukan paket terinstal dan server SMTP sehingga cukup dipelajari bentuknya:
<?php
use PHPMailer\PHPMailer\PHPMailer;
require __DIR__ . "/vendor/autoload.php";
$mailer = new PHPMailer(true);
$mailer->isSMTP();
$mailer->Host = "smtp.relay-example.com";
$mailer->Port = 587;
$mailer->SMTPAuth = true;
$mailer->Username = "[email protected]";
$mailer->Password = "YOUR_SMTP_PASSWORD";
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mailer->setFrom("[email protected]", "Toko Example");
$mailer->addAddress("[email protected]", "Budi");
$mailer->Subject = "Pesanan #1234 Terkirim";
$mailer->Body = "<p>Halo Budi, pesanan <strong>#1234</strong> sudah kami kirim.</p>";
$mailer->AltBody = "Halo Budi, pesanan #1234 sudah kami kirim.";
$mailer->send();Konfigurasi SMTP diatur sebagai property (Host, Port, SMTPAuth) alih-alih satu string DSN, dan dua versi isi diberi nama Body (HTML) serta AltBody (teks murni). Constructor menerima argumen true agar exception dilempar alih-alih error yang ditelan senyap — selalu pakai bentuk ini agar kegagalan terlihat.
Laminas Mail #
Laminas Mail memakai pendekatan objek terpisah antara pesan dan pengirimannya:
<?php
use Laminas\Mail\Message;
$message = new Message();
$message->setFrom("[email protected]");
$message->addTo("[email protected]");
$message->setSubject("Pesanan #1234 Terkirim");
$message->setBody("Halo Budi, pesanan #1234 sudah kami kirim.");Potongan di atas hanya membangun pesan — pengiriman SMTP membutuhkan transport tambahan dari paket laminas/laminas-smtp, dan pesan multipart dirakit dari objek Mime\Part secara eksplisit. Pendekatan ini lebih bertele-tele, tetapi cocok bila proyek Anda sudah memakai komponen Laminas lain dan menginginkan konsistensi arsitektur.
Memeriksa Dependensi lewat composer.json #
Sebelum menulis kode yang memakai library, kita perlu memastikan paketnya benar-benar terdaftar. Fungsi kecil berikut memeriksa composer.json dalam bentuk string sehingga dapat diuji murni:
<?php
function paketTerpasang(string $composerJson, string $paket): bool
{
$data = json_decode($composerJson, true);
if (!is_array($data)) {
return false;
}
foreach (["require", "require-dev"] as $bagian) {
if (isset($data[$bagian][$paket])) {
return true;
}
}
return false;
}
$composerJson = json_encode(
[
"require" => [
"php" => ">=8.2",
"symfony/mailer" => "^7.3",
],
"require-dev" => [
"phpunit/phpunit" => "^12.0",
],
],
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
);
var_dump(paketTerpasang($composerJson, "symfony/mailer"));
var_dump(paketTerpasang($composerJson, "phpmailer/phpmailer"));
var_dump(paketTerpasang($composerJson, "phpunit/phpunit"));Output yang Dihasilkan:
bool(true)
bool(false)
bool(true)Fungsi paketTerpasang() menguraikan JSON dengan json_decode(..., true) menjadi array asosiatif, menjaga diri dari masukan rusak lewat pemeriksaan is_array(), lalu mencari nama paket di dua bagian: require dan require-dev. Dalam praktik nyata, argumen pertama diisi file_get_contents("composer.json") dari root proyek; hasil false berarti composer require belum pernah dijalankan untuk paket tersebut.
Memilih Library untuk Proyek Anda #
Tiga pertanyaan berikut mempercepat keputusan. Pertama, apakah proyek memakai framework? Aplikasi Symfony/Laravel biasanya cukup memakai Mailer bawaannya (yang berakar pada komponen yang sama). Kedua, seberapa kompleks kebutuhan transport? Bila mengirim lewat API layanan seperti SendGrid atau Mailgun, Symfony Mailer punya dukungan transport resmi terbanyak. Ketiga, seberapa besar ruang lingkup proyek? Untuk skrip kecil yang cukup kirim SMTP sederhana, PHPMailer yang satu-berkas-satu-kelas terasa paling ringan dipegang.
Ringkasan #
Symfony Mailer, PHPMailer, dan Laminas Mail sama-sama menyembunyikan kompleksitas SMTP dan MIME di balik API yang lebih manusiawi, dengan kekuatan berbeda: DSN modern dan transport API di Symfony Mailer, kesederhanaan satu kelas di PHPMailer, modularitas di Laminas Mail. Pemeriksaan dependensi seperti paketTerpasang() menunjukkan pola menguji aspek lingkungan secara murni. Setelah library terpilih, konten email berikutnya yang perlu dikuasai: HTML email yang tampil baik di segala klien.