Simple services for sending UTF-8 e-mail.
See UPGRADING.md for upgrade instructions.
Some features are delibarely outside the scope of this project:
Support for arbitrary character sets is omitted - all modern mail clients support UTF-8.
No support for mail()
as a transport method, as this function has constraints that conflict with our
objectives - mainly, it does not support streams, which means the entire message has to fit in memory,
which leads to unpredictable performance and memory usage.
Mail service implementations are abstracted behind the MailService
interface, which depends
on the Message
model to define the actual content.
To send mail, simply create an instance of Message
, populate it with new instances of Address
and Attachment
models by calling various public set/add-methods, then call MailService::send()
.
The model permits any combination of UTF-8 text and HTML message bodies with any number of attachments.
The following example assumes a MailService
instance named $service
is in scope - subsequent sections
will explain how to configure an e-mail service.
Here's an example of sending a plain-text e-mail with an attachment:
$message = new Message(
new Address($email), // recipient
new Address("me@test.org"), // sender
"Hello, Person!", // subject
$text // plain text message body
);
$message->addAttachment(Attachment::fromFile(__DIR__ . "/awsum/unicorns.gif"));
$service->send($message);
Refer to the Message
model to learn about additional message properties.
The SMTPMailService
implementation connects directly to an SMTP server via sockets.
To bootstrap an SMTP mail service, you need to select your Connector
and Authenticator
implementations - for example:
$service = new SMTPMailService(
new SocketConnector("localhost", 25),
new LoginAuthenticator("user", "super_secret_pa55w0rd"),
"test.org"
);
Note the third argument, which is the local host-name - this is used in the handshake (EHLO
) message
send to the SMTP server when the client connects.
SMTP protocol-level logging is supported for diagnostic purposes, and can be enabled by injecting
a PSR-3 Logger into SMTPClient
via SMTPClient::setLogger()
-
this may be useful if you have connection issues, as it will write a debug
-level entry for every
SMTP command sent, and every response received.
Unlike SMTP protocol-level logging described above, a more general logging facility is also available -
this will write a single log-entry on success or failure to send a message, and is more generally
applicable to any MailService
implementation, including of course the SMTP service.
To write a log-entry to a PSR-3 Logger, use the MailSeviceLogger
implementation, which acts as a decorator for any other MailService
implementation - for example:
$service = new MailServiceLogger($psr_logger, new SMTPMailService(...));
See inline documentation for MailServiceLogger
for details on customizing the message template and log-level.
A passive implementation of MailService
is available, which does nothing.
You can use this during testing/development to disable any outgoing Messages.
This is typically most useful in conjunction with the MailServiceLogger
described above, to bootstrap
a fake mail-service for testing and development, enabling you to see Messages that would have been sent.
To run the integration tests, you will need to set up a local SMTP server for testing.
To make sure SecureSocketCest
passes your SMTP server also needs to have TLS support with a SSL certificate.
It is recommended to use smtp4dev since it has cross-platform support and can generate its own self-signed SSL certificate.
When configuring smtp4dev make sure to set TlsMode
to StartTls
, this ensures that TLS is only used when the client asks for it, setting it to ImplicitTls
will likely make all non-TLS tests fail.
When starting the smtp4dev server it should tell you where the generated certificate is stored, you'll need to add this to your systems trusted CA store.
You may need to copy integration.suite.dist.yml
to integration.suite.yml
to customize the
SMTP host-name, port-number, etc.
This library has a number of stated design objectives: