Mail

The documentation is constantly evolving and updated alongside the project's progress. Since it is developed in parallel with the code, some sections may temporarily refer to earlier versions of the system-these are gradually adapted to the current state of the application. If you notice any outdated information, please report it or open an Issue / Pull Request.

Documentation

# Mail

DBM Framework provides a transport-neutral mail API under Dbm\Infrastructure\Mail. Application services depend on MailerInterface; a Mailer delegates message delivery to a MailTransportInterface implementation.

# Compose and send a message

use Dbm\Infrastructure\Mail\Contract\MailerInterface;
use Dbm\Infrastructure\Mail\Dto\EmailAddressDto;
use Dbm\Infrastructure\Mail\Dto\EmailMessageDto;

final class WelcomeEmailService
{
    public function __construct(private readonly MailerInterface $mailer) {}

    public function send(string $email, string $name): bool
    {
        return $this->mailer->send(new EmailMessageDto(
            subject: 'Welcome',
            to: [new EmailAddressDto($email, $name)],
            text: "Hello {$name}",
            html: "<p>Hello {$name}</p>",
        ));
    }
}

EmailMessageDto supports to, cc, bcc, sender and sender name, text and HTML bodies, reply-to, attachments, and custom headers. Recipients are EmailAddressDto values. Attachments use EmailAttachmentDto with a local file path and optional display name and MIME type. The transport builds MIME content; callers do not construct raw mail headers.

# Framework transports and configuration

The built-in MailerFactory supports dbm-mail (PHP's native mail() transport) and dbm-smtp (the framework's SMTP client). MailServiceProvider::register($container) binds MailerInterface as a singleton using the current environment configuration.

MAIL_DRIVER=dbm-smtp
MAIL_HOST=smtp.example.test
MAIL_PORT=587
MAIL_USERNAME=mailer@example.test
MAIL_PASSWORD=replace-with-a-secret
MAIL_SECURE=tls
MAIL_FROM_EMAIL=mailer@example.test
MAIL_FROM_NAME="Example App"

MAIL_DRIVER defaults to dbm-mail. SMTP requires MAIL_HOST; ports 465 and 587 infer SSL and TLS respectively when MAIL_SECURE is omitted. SMTP username and password must be configured together, and authentication requires encryption. Default sender values fall back to APP_EMAIL and APP_NAME. The configured SMTP timeout defaults to 10 seconds.

send() returns the transport result for native mail and returns true on successful SMTP delivery. Configuration or transport failures can raise MailConfigurationException, MailTransportException, or another transport-level exception; handle failures at an appropriate application boundary and log without exposing secrets.

# DBM Platform PHPMailer adapter

DBM Platform adds App\Infrastructure\Mail\PHPMailerTransport, an optional adapter implementing the framework transport contract. Its MailServiceProvider registers the built-in drivers and PHPMailer drivers (phpmailer-mail and phpmailer-smtp) in MailerRegistry, then binds MailerInterface using the configured MAIL_DRIVER. The PHPMailer Composer package must be installed for these platform drivers to work.

This keeps the framework's base implementation free of a PHPMailer dependency. Register the platform provider in the application composition when you want the platform driver set. Do not register the core provider over the platform binding unless that is intentional: the core factory alone handles only dbm-mail and dbm-smtp.

The registry can also be used by an application to add driver factories. Keep transport implementations behind MailTransportInterface so mail-using services remain independent of the selected library.

# Full SMTP test example

This example sends both text and HTML parts, sets a reply-to address, and attaches a local file. The recipient is set to the configured sender address so the message can be used as a self-test; replace it with the intended recipient in normal application code.

use Dbm\Core\Paths;
use Dbm\Infrastructure\Mail\Contract\MailerInterface;
use Dbm\Infrastructure\Mail\Dto\EmailAddressDto;
use Dbm\Infrastructure\Mail\Dto\EmailAttachmentDto;
use Dbm\Infrastructure\Mail\Dto\EmailMessageDto;

final class MailTestService
{
    public function __construct(private readonly MailerInterface $mailer) {}

    private function sendEmail(): bool
    {
        $fromEmail = (string) getenv('MAIL_FROM_EMAIL');
        $fromName = (string) getenv('MAIL_FROM_NAME');

        $html = <<<'HTML'
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>DBM Framework SMTP test</title>
            </head>
            <body>
                <h1>Hello from DBM Framework!</h1>
                <p>SMTP test successful.</p>
                <p><strong>HTML message test.</strong></p>
            </body>
            </html>
            HTML;

        $email = new EmailMessageDto(
            subject: 'DBM Framework SMTP test',
            to: [new EmailAddressDto($fromEmail, $fromName)],
            from: $fromEmail,
            fromName: $fromName,
            text: "Hello from DBM Framework!\n\nSMTP test successful.",
            html: $html,
            replyTo: 'test@example.test',
            replyToName: 'Test User',
            attachments: [
                new EmailAttachmentDto(
                    path: Paths::joinPaths(
                        Paths::basePath(),
                        'data',
                        'attachment',
                        'sample.zip',
                    ),
                ),
            ],
        );

        return $this->mailer->send($email);
    }
}

The configured mail provider must be registered before this service is resolved, and Paths::setBasePath() must have run before building an absolute attachment path. Check that the attachment exists and is readable by PHP. Do not accept an arbitrary attachment path from a request; resolve it from a trusted application-owned location. For a test that sends only HTML, omit text; the built-in MIME builder derives a plain-text alternative from the HTML body.

Older code may reference Dbm\Infrastructure\Sender\MailerInterface; that interface is deprecated. New code should use Dbm\Infrastructure\Mail\Contract\MailerInterface and EmailMessageDto.