lucinda/mailing

Very light weight PHP API for email sending and digital signing covering most important parts of RFC-4021 & RFC-6376 specs

v3.0.1 2022-06-13 06:27 UTC

This package is auto-updated.

Last update: 2024-04-13 10:34:27 UTC


README

Very lightweight PHP API covering most important parts of RFC-4021, the worldwide standard at this moment for email sending, along with RFC-6376 for digital signatures.

API requires PHP 8.1+ and comes with just four classes, all belonging to Lucinda\Mail namespace:

  • Address: encapsulates an email address, composed by value of email and name of user associated with it
  • DKIM: creates a DKIM-Signature header using on a heavily refactored version of php-mail-signature classes
  • Exception: encapsulates any logical error that prevents email from being sent
  • Message: encapsulates an email message

The entire logic of email message is encapsulated by class Message via following public methods:

Method Description
__construct Constructs an email message by subject and body
addAttachment Adds an attachment to message body
setFrom Sets message sender's address, as seen in recipients' mail boxes
setSender Sets message sender's address, as seen by recipients' mail server
setReplyTo Adds address message receiver should reply to
addTo Adds address to send mail to (mandatory)
addBCC Adds address to discreetly send a copy of message to (invisible to others)
addCC Adds address to publicly send a copy of message to
setContentType Sets message body content type (strongly recommended)
setDate Sets time message was sent at as date header
setMessageID Sets domain name in order to generate a message ID (strongly recommended)
setSignature Sets a DKIM-Signature header is to be generated (strongly recommended)
addCustomHeader Sets a custom header to send in email message
send Sends message to destination

Simple example:

$message = new \Lucinda\Mail\Message("test subject", "<p>Hello, <strong>world</strong>!</p>");
$message->setMessageID("example.com"); // recommended to prevent message being labeled as spam
$message->setDate(time()); // signals that message was written now
$message->setContentType("text/html", "UTF-8"); // recommended, unless message is ASCII plaintext
$message->addTo(new Address("receiver@asd.com")); // mandatory
$message->setReplyTo(new Address("sender@example.com", "John Doe")); // recommended if message can be replied to
$message->send();

__construct

This method constructs a mail message by following arguments:

Name Type Description
$subject string Subject of email message (mandatory). Must be single-lined!
$body string Body of email message (mandatory). Can be multi-lined!

addAttachment

Adds an attachment to message body based on argument:

Name Type Description
$path string Absolute disk path of file to be attached.

Example:

$message->addAttachment("/foo/bar/baz.jpg");

setFrom

Sets address of message author as seen by recipients (see: from header) based on argument:

Name Type Description
$address Address Address that appears as message author

Usually calling this method is not necessary, unless developer wants a different from address from that default.

Example:

$message->setFrom(new \Lucinda\Mail\Address("sender@example.com", "Example.com Team"));

setSender

Sets address of message author as seen by destination mail server (see: from header) based on argument:

Name Type Description
$address Address Address that appears as message author

Should be same as from address, unless mail server is sending messages on behalf of someone else.

Example:

$message->setSender(new \Lucinda\Mail\Address("sender@example.com", "Example.com Team"));

setReplyTo

Sets address to send message replies to (see: Reply-To header) based on argument:

Name Type Description
$address Address Address to send reply to

Should always be set IF we desire messages to be replied to.

Example:

$message->setReplyTo(new \Lucinda\Mail\Address("sender@example.com", "Example.com Team"));

addTo

Adds an address to send message to (see: To header) based on argument:

Name Type Description
$address Address Address to send message to

At least one address must always be set!

Example:

$message->addTo(new \Lucinda\Mail\Address("destination@server.com"));

addCC

Adds an address to send a copy of message to allowing others to notice (see: Cc header) based on argument:

Name Type Description
$address Address Address to send copy of message to

Example:

$message->addCC(new \Lucinda\Mail\Address("destination@server.com"));

addBCC

Adds an address to send a copy of message to without others to notice (see: Bcc header):

Name Type Description
$address Address Address to send copy of message to

Example:

$message->addBCC(new \Lucinda\Mail\Address("destination@server.com"));

setContentType

Sets message body's content type and character set by following arguments (see: Content-Type header):

Name Type Description
$contentType string Message body content type
$charset string Character set of message body

Example:

$message->setContentType("text/html", "UTF-8");

setDate

Sets custom date message was sent at based on argument (see: Date header):

Name Type Description
$date int UNIX time at which message was written

Usually it is not necessary to send this header unless you want to trick receiver(s) it originated at a different date.

Example:

$message->setDate(time()-1000);

setMessageID

Sets unique ID of message to send based on argument (see: Message-ID header):

Name Type Description
$domainName string Your server's domain name.

It is strongly recommended to send this header in order to prevent having your message labeled as spam by recipient mail servers!

Example:

$message->setMessageID("example.com");

setSignature

Sets a digital signature of message to send based on arguments (see: DKIM-Signature header):

Name Type Description
$rsaPrivateKey string RSA private key to sign messages with
$rsaPassphrase string Password RSA private key was created with, if any (use "" if none)
$domainName string Your server's domain name (same as that used by Message-ID).
$dnsSelector string Name of specific DKIM public key record in your DNS
$signedHeaders array List of headers that participate in signature

In order to prevent having your message labeled as spam by recipient mail servers, setting this header is strongly recommended! To get values for params above, follow this guide:

  • Go to https://tools.socketlabs.com/dkim/generator
    • fill hostname, which will be value of $domainName above (eg: "example.com")
    • write a $dnsSelector "subdomain" (eg: "dkim")
    • hit on GENERATE button
  • Create a DNS TXT record for $selector._domainkey.$domainName. where value is string shown under "Step 2: Create your public DNS record"
  • Store private key shown under "Step 3: Save the private key to your SMTP server" section somewhere. This will become value of $rsaPrivateKey
  • Since you generated a key without a password $rsaPassphrase will always be an empty ""
  • Now finally you must choose list of header names to generate signature from (eg: ["From", "Message-ID", "Content-Type"]) using $signedHeaders. See: recommendations for what should be chosen!

The algorithm used in generating DKIM-Signature header has been taken from php-mail-signature and refactored completely because original was chaotic and poorly programmed. The end result was class DKIM!

Example:

$message->setSignature("-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----", "", "example.com", "dkim", [
    "From",
    "Reply-To",
    "Subject",
    "To"
]);

addCustomHeader

Adds a RFC-4021 header not covered by commands above using following arguments:

Name Type Description
$name string Name of header
$value string Value of header

Example:

$message->addCustomHeader("List-Unsubscribe", "<mailto: unsubscribe@example.com>");

Above command adds a List-Unsubscribe header which allows users to unsubscribe from mailing lists by a button click.

send

Packs message body and headers, compiles latter with DKIM-Signature (if available) and sends mail to destination.

Example:

$message->send();