Laravel's mail system is transport-agnostic — you write the same Mail::to()->send() code regardless of whether it's actually going out through Gmail's SMTP servers, SendGrid's API, or a local sendmail binary. The differences all live in your .env configuration.
Sending through Gmail SMTP
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=you@gmail.com
MAIL_PASSWORD=your-app-password
MAIL_ENCRYPTION=tls
Gmail requires an App Password here, not your regular account password — generate one from your Google Account's security settings (this requires 2-factor authentication to be enabled first). Using your actual login password will fail authentication.
Sending through a generic SMTP server or local sendmail
MAIL_MAILER=smtp
MAIL_HOST=mail.yourdomain.com
MAIL_PORT=587
MAIL_USERNAME=noreply@yourdomain.com
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=tls
// or, using the local sendmail binary instead of SMTP
MAIL_MAILER=sendmail
MAIL_SENDMAIL_PATH="/usr/sbin/sendmail -bs"
sendmail relies on a mail transfer agent already configured on the server itself — reasonable on a traditional VPS with Postfix or similar installed, but generally not available (or reliable for actual deliverability) on typical shared hosting or serverless platforms.
Sending through SendGrid
MAIL_MAILER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USERNAME=apikey
MAIL_PASSWORD=your-sendgrid-api-key
MAIL_ENCRYPTION=tls
SendGrid's SMTP username is literally the string apikey — the actual API key goes in the password field. A dedicated transactional email provider like SendGrid also generally offers better deliverability and analytics than sending directly through Gmail or a generic SMTP host at any real volume.
Sending to multiple recipients, with CC
Mail::to(['first@example.com', 'second@example.com'])
->cc('manager@example.com')
->send(new OrderShipped($order));
Sending an email with an attachment
class InvoiceMail extends Mailable
{
public function build()
{
return $this->view('emails.invoice')
->attach(storage_path('app/invoices/invoice-123.pdf'), [
'as' => 'invoice.pdf',
'mime' => 'application/pdf',
]);
}
}
The same attach() method works for PDFs, images, or Word documents — Laravel doesn't need a different API per file type, only the correct mime value if you want it set explicitly rather than guessed from the file extension.
Choosing a provider
Gmail SMTP is fine for low-volume personal or small-project sending; a generic SMTP host works when you already have one configured; a dedicated provider like SendGrid (or similar services) is the more reliable choice once an application sends enough transactional email that deliverability and bounce handling genuinely matter.