Skip to main content

Mailer Factory

The MailerFactory is responsible for creating mailer instances based on connection strings. It uses a registration pattern that allows you to register which mailer wrappers are available in your application.

Registering Mailers

Before creating a mailer, you need to register the wrapper classes you want to use:

// Register individual wrappers
\ByJG\Mail\MailerFactory::registerMailer(\ByJG\Mail\Wrapper\PHPMailerWrapper::class);
\ByJG\Mail\MailerFactory::registerMailer(\ByJG\Mail\Wrapper\MailgunApiWrapper::class);
\ByJG\Mail\MailerFactory::registerMailer(\ByJG\Mail\Wrapper\AmazonSesWrapper::class);

You only need to register the wrappers you plan to use. This keeps your application lightweight by not loading unnecessary dependencies.

Creating Mailers

Once registered, create a mailer using a connection string:

$mailer = \ByJG\Mail\MailerFactory::create('smtp://username:password@host:587');

The factory automatically selects the appropriate wrapper based on the connection string's scheme.

Using URI Objects

You can also pass a URI object instead of a string:

$uri = new \ByJG\Util\Uri('tls://username:[email protected]:587');
$mailer = \ByJG\Mail\MailerFactory::create($uri);

Creating Mailers Directly

You can bypass the factory and instantiate wrappers directly:

$mailer = new \ByJG\Mail\Wrapper\MailgunApiWrapper(
new \ByJG\Util\Uri('mailgun://YOUR_API_KEY@YOUR_DOMAIN')
);

This approach is useful when:

  • You only use a single mailer type
  • You want to avoid the registration step
  • You need more control over instantiation

Sending Emails

All mailers implement the same interface:

$envelope = new \ByJG\Mail\Envelope(
'[email protected]',
'[email protected]',
'Subject',
'Body content'
);

$result = $mailer->send($envelope);

if ($result->success) {
echo "Email sent! Message ID: " . $result->id;
} else {
echo "Failed to send email";
}

Send Result

The send() method returns a SendResult object with two properties:

class SendResult
{
public readonly bool $success; // true if email was sent
public readonly ?string $id; // Message ID (if available)
}

Example:

$result = $mailer->send($envelope);

if ($result->success) {
// Email was sent successfully
if ($result->id !== null) {
// Some services provide a message ID for tracking
log("Email sent with ID: " . $result->id);
}
}

Exception Handling

The factory may throw exceptions:

use ByJG\Mail\Exception\ProtocolNotRegisteredException;
use ByJG\Mail\Exception\InvalidMailHandlerException;

try {
$mailer = \ByJG\Mail\MailerFactory::create('unknown://host');
} catch (ProtocolNotRegisteredException $e) {
// The scheme 'unknown' hasn't been registered
echo "Protocol not registered: " . $e->getMessage();
}

Best Practices

Configuration Management

Store connection strings in configuration files or environment variables:

// .env file
MAIL_CONNECTION=tls://user:[email protected]:587

// In your application
$mailer = \ByJG\Mail\MailerFactory::create($_ENV['MAIL_CONNECTION']);

Single Registration Point

Register all mailers once during application bootstrap:

// bootstrap.php
$wrappers = [
\ByJG\Mail\Wrapper\PHPMailerWrapper::class,
\ByJG\Mail\Wrapper\MailgunApiWrapper::class,
\ByJG\Mail\Wrapper\AmazonSesWrapper::class,
\ByJG\Mail\Wrapper\SendMailWrapper::class,
];

foreach ($wrappers as $wrapper) {
\ByJG\Mail\MailerFactory::registerMailer($wrapper);
}

Testing

Use FakeSender for testing:

// Test configuration
if ($isTestEnvironment) {
$mailer = \ByJG\Mail\MailerFactory::create('fakesender://localhost');
} else {
$mailer = \ByJG\Mail\MailerFactory::create($productionConnection);
}