Skip to main content

Mail Wrapper

One interface to send email, whatever the service behind it. Change the provider, or add a new one, without changing your code.

Sponsor Build Status Opensource ByJG Install MCP Server GitHub source GitHub license GitHub release

Why​

SMTP, Amazon SES and Mailgun each have their own SDK, their own message object and their own errors. An application written against one of them is tied to it: switching provider, or sending nothing in a test, means touching every place that sends mail.

Mail Wrapper defines the contract once. You build an Envelope and call send() on a MailWrapperInterface; the provider is chosen by the connection string:

$mailer = MailerFactory::create('smtp://user:[email protected]:587'); // SMTP
$mailer = MailerFactory::create('ses://key:secret@us-east-1'); // Amazon SES
$mailer = MailerFactory::create('fakesender://localhost'); // tests

$mailer->send($envelope);
  • Change the provider without touching the code. The connection string usually lives in configuration, so it is a deploy change, not a code change.
  • Test without sending. FakeSender sends nothing and keeps the envelopes for assertions.
  • Add a provider by implementing one interface. A wrapper is send() and a URI scheme; see Custom Wrappers.

Available Wrappers​

  • SMTP - SMTP with SSL/TLS support
  • AWS SES - Amazon Simple Email Service (using API directly)
  • Mailgun - Mailgun API (using API directly)
  • SendMail - PHP's built-in mail() function
  • FakeSender - For testing (sends nothing, keeps the envelopes for assertions)

Installation​

composer require "byjg/mailwrapper"

Documentation​

Quick Start​

<?php
require "vendor/autoload.php";

// Create the email envelope
$envelope = new \ByJG\Mail\Envelope();
$envelope->setFrom('[email protected]', 'John Doe');
$envelope->addTo('[email protected]');
$envelope->setSubject('Email Subject');
$envelope->setBody('<h1>Hello World</h1>');

// Register available mailers
\ByJG\Mail\MailerFactory::registerMailer(\ByJG\Mail\Wrapper\PHPMailerWrapper::class);
\ByJG\Mail\MailerFactory::registerMailer(\ByJG\Mail\Wrapper\MailgunApiWrapper::class);

// Create mailer from connection string
$mailer = \ByJG\Mail\MailerFactory::create('smtp://username:[email protected]:587');

// Send the email
$result = $mailer->send($envelope);

Architecture​

MailWrapper is organized into three main components:

  • The Envelope: The mail message. Defines the sender, recipients, body, subject, attachments, etc.
  • The Mailer: Responsible for the process of sending the envelope
  • The Factory: Registers and creates the available Mailers in the system

Connection URL Schemes​

SchemeDescriptionURI Pattern
smtpSMTP over insecure connectionsmtp://username:password@host:25
tlsSMTP over secure TLS connectiontls://username:password@host:587
sslSMTP over secure SSL connectionssl://username:password@host:465
sendmailPHP's built-in mail() functionsendmail://localhost
mailgunMailgun APImailgun://YOUR_API_KEY@YOUR_DOMAIN
sesAmazon SES APIses://ACCESS_KEY_ID:SECRET_KEY@REGION
fakesenderTesting (does nothing)fakesender://localhost
fakeAlias of fakesenderfake://localhost

See Connection Strings for detailed configuration examples.

Running Tests​

./vendor/bin/phpunit

Open source ByJG