VOOZH about

URL: https://deepwiki.com/hypervel/mail/4.3-transport-system-overview

⇱ Transport System Overview | hypervel/mail | DeepWiki


Loading...
Menu

Transport System Overview

This document explains the transport abstraction layer in the hypervel/mail package, which provides a pluggable mechanism for dispatching emails through various delivery backends. The transport system decouples email preparation (handled by Mailer) from the actual sending mechanism, enabling support for SMTP, cloud services (SES, Mailgun, Postmark), logging, testing, and composite strategies.

For documentation on individual transport driver implementations (SMTP, SES, Mailgun, etc.), see Transport Drivers. For information on how the MailManager creates and configures these transports, see Mail Manager and Factory Pattern.

Purpose and Scope

The transport system provides:

  • A unified interface (TransportInterface) for all email delivery mechanisms
  • Factory methods in MailManager for creating configured transport instances
  • Custom transport registration via the extend() method
  • Connection pooling for performance optimization via TransportPoolProxy
  • Support for composite transports (Failover, RoundRobin) that wrap other transports

Transport Abstraction

The transport layer is built on Symfony Mailer's TransportInterface, which defines a single method for sending messages:


All transport implementations in hypervel/mail implement this interface, whether they are native Symfony transports (SMTP, Sendmail), custom transports (SES, SES V2, Log, Array), or composite transports (Failover, RoundRobin).

The Mailer class dispatches email messages to a TransportInterface instance without knowledge of the underlying delivery mechanism. This abstraction enables:

  • Swapping transports via configuration without code changes
  • Testing with ArrayTransport or LogTransport
  • High availability via FailoverTransport
  • Load balancing via RoundRobinTransport

Sources: src/MailManager.php38 Diagram 3 from architecture overview

Transport Creation Architecture

The MailManager class serves as the transport factory, creating instances based on configuration through the createSymfonyTransport() method:


Sources: src/MailManager.php155-188

Transport Type Resolution

The createSymfonyTransport() method resolves the transport type through a three-step process:

  1. Custom Creator Lookup - Checks if a custom creator was registered via extend() for the transport name src/MailManager.php162-171
  2. Method Name Construction - Builds method name create{TransportName}Transport using camel-case conversion src/MailManager.php173-177
  3. Method Invocation - Calls the constructed method with configuration array src/MailManager.php187

Sources: src/MailManager.php155-188 src/MailManager.php71-73

Poolable Transports

The MailManager maintains a list of transport types that support connection pooling:

Transport TypePoolableFactory Method
smtpYescreateSmtpTransport
sendmailYescreateSendmailTransport
mailgunYescreateMailgunTransport
sesYescreateSesTransport
ses_v2YescreateSesV2Transport
postmarkYescreatePostmarkTransport
resendYes(via custom creator)
failoverYescreateFailoverTransport
roundrobinYescreateRoundrobinTransport
logNocreateLogTransport
arrayNocreateArrayTransport

Poolable transports are automatically wrapped in a TransportPoolProxy when a pool name is provided, enabling connection reuse across multiple sends.

Sources: src/MailManager.php71-73 src/MailManager.php179-185

Transport Factory Methods

The MailManager implements specific factory methods for each built-in transport type. Each method follows a consistent pattern:


Example: SMTP Transport Creation

The SMTP transport factory demonstrates the typical creation flow src/MailManager.php193-216:

  1. Factory Instantiation - Creates EsmtpTransportFactory from Symfony
  2. Scheme Resolution - Determines protocol scheme (smtp/smtps) from encryption settings
  3. DSN Construction - Builds Symfony DSN with host, credentials, port
  4. Transport Creation - Factory creates EsmtpTransport instance
  5. Configuration - Applies additional settings (source IP, timeout) via configureSmtpTransport()

Example: SES Transport Creation

The SES transport factory shows configuration merging src/MailManager.php251-265:

  1. Config Merging - Combines services.ses config with mailer-specific config
  2. Credential Addition - Adds AWS credentials via addSesCredentials()
  3. Client Creation - Instantiates SesClient from AWS SDK
  4. Transport Instantiation - Creates SesTransport with client and options

Sources: src/MailManager.php193-265

Custom Transport Registration

Applications can register custom transport implementations using the extend() method:


The registration process:


The callback receives the configuration array and must return a TransportInterface instance. The $poolable parameter indicates whether the transport should support connection pooling.

When createSymfonyTransport() is called with a custom transport name, it checks the customCreators array first src/MailManager.php162-171 invoking the registered callback before attempting to resolve a built-in transport method.

Sources: src/MailManager.php516-525 src/MailManager.php162-171

Transport Pooling System

The TransportPoolProxy class wraps transport instances in an object pool to optimize connection reuse:


TransportPoolProxy Implementation

The proxy implements both TransportInterface and Stringable, delegating method calls to pooled instances:

MethodDescriptionDelegation
send(RawMessage, ?Envelope)Sends message via pooled transport__call() to pool
__toString()Returns transport string representation__call() to pool

The proxy extends PoolProxy from hypervel/object-pool, which handles connection borrowing, returning, and lifecycle management. When send() is called, the proxy:

  1. Borrows an idle transport from the pool
  2. Delegates the send() call to the borrowed instance
  3. Returns the transport to the pool for reuse

Sources: src/TransportPoolProxy.php1-29 src/MailManager.php66

Pool Configuration

Pool behavior is configured via the pool key in mailer configuration:


The MailManager passes this configuration when creating the pool proxy src/MailManager.php167 src/MailManager.php183

Sources: src/MailManager.php163-168 src/MailManager.php179-185

Transport Resolution in Mailer Creation

The transport creation occurs during mailer resolution in the resolve() method:


The process:

  1. Configuration Retrieval - Gets mailer config via getConfig() src/MailManager.php117
  2. Transport Type Extraction - Reads transport key or falls back to mail.driver src/MailManager.php123
  3. Poolability Check - Determines if transport type is in poolables array src/MailManager.php124
  4. Transport Creation - Calls createSymfonyTransport() with pool name if poolable src/MailManager.php132
  5. Mailer Instantiation - Creates Mailer with transport instance src/MailManager.php129-134

Sources: src/MailManager.php115-148 src/MailManager.php123-132

Configuration-Driven Transport Selection

Transport selection is driven by the transport key in mailer configuration:


The getConfig() method supports both modern (mail.mailers.{name}) and legacy (mail.driver) configuration formats src/MailManager.php459-475 When a URL configuration is provided, it's parsed via ConfigurationUrlParser and the driver is extracted to transport src/MailManager.php468-472

Sources: src/MailManager.php459-475 src/MailManager.php123 src/MailManager.php160

Transport Interface Integration

The transport system integrates with the broader mail architecture:


The Mailer receives a TransportInterface during construction and uses it to dispatch prepared messages. The transport implementation handles protocol-specific details, API calls, authentication, and error handling without exposing these concerns to the Mailer.

Sources: src/MailManager.php129-134 Diagram 1 from architecture overview


This transport system architecture provides flexibility, testability, and extensibility while maintaining a clean separation between message preparation and delivery. The factory pattern in MailManager, combined with the TransportInterface abstraction and optional pooling, enables sophisticated email delivery strategies with minimal configuration.