VOOZH about

URL: https://deepwiki.com/hypervel/mail/4.1-mail-manager-and-factory-pattern

⇱ Mail Manager and Factory Pattern | hypervel/mail | DeepWiki


Loading...
Menu

Mail Manager and Factory Pattern

The MailManager class implements the Factory pattern to provide a centralized point for creating and managing Mailer instances with their configured transports. It serves as the primary entry point for the mail system, resolving configuration, creating transport instances, and maintaining a registry of mailer instances.

As a factory, MailManager abstracts the complexity of transport creation, connection pooling, and configuration parsing. Application code interacts with named mailers (e.g., "smtp", "ses") without needing to understand the underlying transport instantiation details.

This document covers the factory pattern implementation, transport creation mechanisms, mailer resolution, and configuration handling. For information about individual mailer instances and their sending operations, see page 4.2. For transport-specific details, see pages 4.3 and 4.4.

Factory Pattern Implementation

The MailManager class implements the Hypervel\Mail\Contracts\Factory interface, providing a standard factory pattern for creating mailer instances. The factory maintains an internal registry to cache created instances and supports lazy initialization.

Factory Responsibilities

ResponsibilityImplementationCode Reference
Instance RegistryMaintains $mailers array cachesrc/MailManager.php56
Configuration ResolutionParses mail.php config via getConfig()src/MailManager.php458-474
Transport CreationFactory methods for each transport typesrc/MailManager.php155-423
Custom ExtensionsRegistry of custom transport creators in $customCreatorssrc/MailManager.php60
Connection PoolingWraps transports in TransportPoolProxysrc/MailManager.php66-73
Default Driver ManagementTracks and resolves default mailersrc/MailManager.php479-498

Sources: src/MailManager.php44-82

Class Structure

MailManager Core Architecture


Sources: src/MailManager.php44-82 src/MailManager.php115-148

Mailer Resolution Process

The factory pattern in MailManager follows a three-tier resolution strategy: check cache, resolve configuration, and construct instance.

Resolution Flow

Mailer Instance Resolution


Sources: src/MailManager.php84-92 src/MailManager.php105-108 src/MailManager.php115-148

Factory Method Pattern for Transport Creation

The MailManager uses convention-based method dispatch to create transport instances. For a transport named "smtp", it calls createSmtpTransport(). This follows the Factory Method pattern where the factory class delegates to specialized creation methods.

Transport Factory Method Dispatch


Sources: src/MailManager.php155-188 src/MailManager.php173-177

Transport Creation Methods

The MailManager provides dedicated factory methods for each supported transport type. Each method creates a TransportInterface implementation configured according to the provided configuration array.

Supported Transport Types

TransportFactory MethodImplementation ClassPool SupportConfig Key
SMTPcreateSmtpTransport()Symfony\...\EsmtpTransportYessmtp
SendmailcreateSendmailTransport()Symfony\...\SendmailTransportYessendmail
SEScreateSesTransport()Hypervel\Mail\Transport\SesTransportYesses
SES V2createSesV2Transport()Hypervel\Mail\Transport\SesV2TransportYesses_v2
MailguncreateMailgunTransport()Symfony\...\MailgunTransportYesmailgun
PostmarkcreatePostmarkTransport()Symfony\...\PostmarkTransportYespostmark
LogcreateLogTransport()Hypervel\Mail\Transport\LogTransportNolog
ArraycreateArrayTransport()Hypervel\Mail\Transport\ArrayTransportNoarray
FailovercreateFailoverTransport()Symfony\...\FailoverTransportYesfailover
Round RobincreateRoundrobinTransport()Symfony\...\RoundRobinTransportYesroundrobin

Sources: src/MailManager.php71-73 src/MailManager.php193-423

Transport Factory Method Examples

SMTP Transport Creation

The createSmtpTransport() method uses EsmtpTransportFactory to construct a Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport instance with DSN-based configuration.

createSmtpTransport(config) →
 EsmtpTransportFactory.create(Dsn) →
 EsmtpTransport configured with:
 - scheme (smtp/smtps based on encryption/port)
 - host, username, password, port
 - optional source_ip, timeout via SocketStream

Sources: src/MailManager.php193-215 src/MailManager.php220-235

AWS SES Transport Creation

The createSesTransport() and createSesV2Transport() methods create AWS SDK clients and wrap them in transport adapters.

createSesTransport(config) →
 merge config with services.ses
 addSesCredentials(config)
 new SesClient(config)
 new SesTransport(SesClient, options)

Sources: src/MailManager.php250-264 src/MailManager.php269-283 src/MailManager.php288-295

Composite Transport Creation

The createFailoverTransport() and createRoundrobinTransport() methods recursively create multiple child transports.

createFailoverTransport(config) →
 foreach config['mailers'] as name:
 childConfig = getConfig(name)
 childTransport = createSymfonyTransport(childConfig)
 transports[] = childTransport
 new FailoverTransport(transports)

Sources: src/MailManager.php354-374 src/MailManager.php379-399

Transport Configuration Sequence

SMTP Transport Creation Flow


Sources: src/MailManager.php193-215 src/MailManager.php220-235

Connection Pooling Integration

The MailManager integrates with hypervel/object-pool to provide connection pooling for long-lived transports. This optimization reduces connection overhead for SMTP and API-based transports by reusing connections across multiple send operations.

Pool Proxy Architecture

The HasPoolProxy trait provides the createPoolProxy() method, which wraps transport instances in a TransportPoolProxy. This proxy implements TransportInterface and delegates to pooled transport instances managed by the object pool system.

Pool Proxy Class Structure


Sources: src/MailManager.php46 src/MailManager.php66 src/MailManager.php71-73

Poolable Transports

The $poolables array defines which transport types support pooling:


Log and array transports are excluded because they do not maintain connections requiring pooling.

Sources: src/MailManager.php71-73

Pool Proxy Creation Logic

When creating a transport, if a $poolName is provided and the transport type is in $poolables, the transport is wrapped:

if poolName != null:
 createPoolProxy(poolName, fn() => transport, config['pool'] ?? [])
else:
 return transport

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

Configuration Management

The MailManager resolves mailer configurations from the mail.php configuration file, supporting both modern multi-mailer setups and legacy single-mailer configurations.

Configuration Resolution Strategy

Configuration Loading Flow


Sources: src/MailManager.php458-474

Configuration Structure

The getConfig() method returns an array with the following structure:

KeyTypePurpose
transportstringTransport driver name (smtp, ses, etc.)
hoststringServer hostname (SMTP)
portintServer port (SMTP)
usernamestringAuthentication username
passwordstringAuthentication password
encryptionstringEncryption method (tls, ssl)
fromarrayGlobal from address ['address' => '...', 'name' => '...']
reply_toarrayGlobal reply-to address
toarrayGlobal to address (testing)
return_patharrayGlobal return-path address
poolarrayPool configuration ['min' => 1, 'max' => 10]
urlstringDSN-style configuration URL (alternative format)

Sources: src/MailManager.php458-474

URL-Based Configuration Parsing

When config['url'] is present, the ConfigurationUrlParser extracts connection parameters from DSN-style URLs:

smtp://username:password@host:port?encryption=tls

The parsed parameters are merged with the configuration array, and the driver key is moved to transport.

Sources: src/MailManager.php467-471

Global Address Application

After creating a Mailer instance, the factory applies global addresses from configuration:

foreach ['from', 'reply_to', 'to', 'return_path'] as $type:
 setGlobalAddress(mailer, config, type)

The setGlobalAddress() method checks both mailer-specific config and global mail.* config:

address = config[type] ?? config.get('mail.' + type)
if is_array(address) && isset(address['address']):
 mailer->always{Type}(address['address'], address['name'])

Sources: src/MailManager.php143-145 src/MailManager.php446-453

Public API

Factory Methods

The primary public interface for obtaining Mailer instances:

MethodParametersReturnDescription
mailer()?string $name = nullMailerContractGet or create named mailer (uses default if name is null)
driver()?string $driver = nullMailerContractAlias for mailer() method

Sources: src/MailManager.php87-100

Transport Creation API

MethodParametersReturnDescription
createSymfonyTransport()array $config, ?string $poolName = nullTransportInterfaceCreate transport instance from config array

This method is typically used internally but can be called directly for custom transport creation scenarios.

Sources: src/MailManager.php155-188

Configuration Methods

MethodParametersReturnDescription
getDefaultDriver()nonestringRetrieve default mailer name from config
setDefaultDriver()string $namevoidUpdate default mailer name in config

Sources: src/MailManager.php479-498

Cache Management Methods

MethodParametersReturnDescription
purge()?string $name = nullvoidRemove mailer from cache (uses default if name is null)
forgetMailers()nonestaticClear all cached mailer instances

Sources: src/MailManager.php503-508 src/MailManager.php547-552

Extension Methods

MethodParametersReturnDescription
extend()string $driver, Closure $callback, bool $poolable = falsestaticRegister custom transport creator

Sources: src/MailManager.php515-524

Container Access Methods

MethodParametersReturnDescription
getApplication()noneContainerInterfaceGet container instance
setApplication()ContainerInterface $appstaticSet container instance

Sources: src/MailManager.php529-542

Magic Method Delegation

The __call() method delegates undefined method calls to the default mailer instance:


This allows MailManager to act as a transparent proxy:


Sources: src/MailManager.php557-560

Custom Transport Extension

Registering Custom Transports

The extend() method allows registration of custom transport creators:


Sources: src/MailManager.php515-524

Custom Creator Integration

Custom transport creators integrate seamlessly with the pooling system when marked as poolable during registration.

Sources: src/MailManager.php162-171

Refresh this wiki

On this page