Problem Statement
For applications sending many emails (notifications, newsletters, transactional), each message currently requires a full TCP + TLS + AUTH cycle (~200-500ms overhead). There is no way to maintain a pool of ready connections.
Proposed Solution
Add an SMTPConnectionPool class:
$pool = new SMTPConnectionPool($smtpAccount, [
'max_connections' => 5,
'max_messages_per_connection' => 100, // Gmail limit
'idle_timeout' => 300, // seconds before closing idle connections
]);
// Usage
foreach ($emails as $email) {
$email->send($pool->checkout());
$pool->checkin();
}
$pool->closeAll();
Pool responsibilities:
- Maintain N pre-authenticated
SMTPServer instances
- Check out idle connections for sending
- Send
RSET and return connections after use
- Replace dead/stale connections transparently
- Track per-connection message count and cycle when limit reached
- Optionally send
NOOP keep-alive on idle connections
- Enforce rate limits (max messages per second/minute)
Alternatives Considered
- External queue systems (RabbitMQ, Redis) — complementary but don't solve the connection overhead
- Single shared connection — doesn't support concurrency or resilience
Breaking Change
No — new class, no changes to existing API.
Additional Context
Depends on:
Most SMTP providers enforce per-connection message limits:
- Gmail: ~100 messages per connection
- Microsoft 365: ~30 messages per connection
- Amazon SES: ~50 messages per connection
The pool should respect these via the max_messages_per_connection config.
Problem Statement
For applications sending many emails (notifications, newsletters, transactional), each message currently requires a full TCP + TLS + AUTH cycle (~200-500ms overhead). There is no way to maintain a pool of ready connections.
Proposed Solution
Add an
SMTPConnectionPoolclass:Pool responsibilities:
SMTPServerinstancesRSETand return connections after useNOOPkeep-alive on idle connectionsAlternatives Considered
Breaking Change
No — new class, no changes to existing API.
Additional Context
Depends on:
SMTPServer::reset()Email::send()accepting external serverMost SMTP providers enforce per-connection message limits:
The pool should respect these via the
max_messages_per_connectionconfig.