Heading


What is php-mail-client/Client?

php-mail-client/Client is PHP library, that can be used for downloading mails from mail server.

Features

Drivers
You can choose, which driver you will use. If you are not friendly with IMAP, use POP3 or plain sockets.
Connecting
You don't have to connect manually or check if connected, php-mail-client/Client solves everything for you.
Lazy emails
Don't be afraid that your mail server will be spammed with tons of commands and you will receive gigabytes of unneeded data just because you want one header. Everything is loaded at the time of first use.
Mailboxes
Operating with mailboxes in plain PHP is hard, when you are for example downloading mails from two mailboxes, you must remember to switch between them every time. php-mail-client/Client switches mailboxes automatically. You can also easily create, rename or delete mailboxes as you want.
Filtering
If you know Nette Framework, you know that there is very nice database layer. Providing fluent interface, you can easily filter rows. I have inspired myself from that and created a very similar-looking layer, that allows you to filter mails like rows in database. No emails are fetched till you request for them.
Mails
If you ever worked with mails, you know, that parsing email body and headers is very robust code. You must find, what encoding is used, decode it, convert charset to UTF-8, etc, etc. With php-mail-client/Client, everything like this collapse in only one line to get header and one line to get body.
Attachments
Getting attachment and saving it to server directory is with php-mail-client/Client as easy as pie. With only one line of code you gain full control of attachments.
Extendable
If you want, you can write your own driver, that for example downloads mails from database and synchronizes them with mail server. Every function, that manipulates with emails, is located in driver.

First steps

We'll start with creating chosen driver. A driver is class implementing greeny\MailLibrary\Drivers\IDriver interface. In this tutorial, i have chosen greeny\MailLibrary\Drivers\ImapDriver.

ImapDriver requires parameters $username, $password, $host and optional parameters $port and $ssl, which, if set to TRUE, secures our connection.

use greeny\MailLibrary\Drivers\ImapDriver;

$driver = new ImapDriver('john', 'doe', 'mail.example.com', 993, TRUE); // John Doe wants secured connection
Now when we have driver, we will create new connection controller. It's class greeny\MailLibrary\Connection and requires one parameter, IDriver. Luckily, we just have one driver created, so creating connection is easy.

use greeny\MailLibrary\Connection;

$connection = new Connection($driver);
And that's all, we have set it up correctly!
Warning! Do not call Driver classes directly, every it's method can and should be called using other classes.

Operating with mailboxes

If you don't know, what mailbox is, it doesn't matter. For standard user, mailbox is like folder to which are mails filtered. Examples of mailboxes are Inbox, Spam, Sent, etc.

With connection already set, we can easily manipulate with mailboxes.
  • $connection->getMailboxes() returns associative array name => mailbox,
  • $mailbox = $connection->getMailbox('INBOX') returns mailbox named 'INBOX',
  • $mailbox = $connection->createMailbox('My mailbox'); creates mailbox 'My mailbox',
  • $connection->renameMailbox('My Mailbox', 'My epic mailbox'); renames mailbox to 'My epic mailbox',
  • $connection->deleteMailbox('My epic mailbox'); deletes mailbox.

Filtering selection

As mentioned above, filtering mails is almost the same as filtering rows in Nette\Database.
We just must have $mailbox variable, that contains required mailbox (instance of greeny\MailLibrary\Mailbox).
We must now create a selection from it - selection is list of mails in one mailbox, which can be filtered, sorted and paginated.
$selection = $mailbox->getMails(); Now we have a $selection variable.

Now we can filter mails from this mailbox:
use greeny\MailLibrary\Mail;

$selection
    ->where(Mail::FROM, 'mom@example.com')
    ->where(Mail::SUBJECT, 'Hello son!')
    ->limit(10)
    ->offset(5)
    ->order(Mail::ORDER_TO);
            
This code will:
  • find all mails from 'mom@example.com' with subject 'Hello son!'
  • fetch only first 10 mails with offset 5 (like in SQL)
  • order mails by 'To' header.
Warning! Ordering mails is released in 3.1.0, so if you have only 3.0.0, it's time to update.
Now the $selection variable contains all these filters, limits, offsets, etc. In next paragraph, we will get mails from it.

Finally, working with mails

You now have $selection variable, possibly filtered (but it's not required) and you want to get mails from it.
The most intuitive way is to use foreach:
foreach($selection as $mail) {
    // do something with $mail
}
If you want, you can also call $mails = $selection->fetchAll(), which returns array where keys are IDs and values are mails.

The third way to get mails is to use $mail = $selection[$id], that returns mail with that ID.

With $mail (instance of greeny\MailLibrary\Mail) we can now access all mail's properties:
  • $mail->getHeader('X-Request-From') gets header
  • $mail->getHeader('xRequestFrom') does the same
  • $mail->xRequestFrom does again the same
  • $mail->getBody() returns HTML body (if not available, returns text body)
  • $mail->getHtmlBody() and $mail->getTextBody() does what they say
  • $mail->getAttachments() - gets array of attachments (will be mentioned later)
Info: The headers with 'contact list' (from, to, cc, bcc, ...) are returned as greeny\MailLibrary\ContactList, which can be iterated using foreach, converted to string or can return contacts as array ($mail->to->getContacts()).
You can also modify mail's parent mailbox:
  • $mail->move($name) or $mail->copy($name), where $name is name of mailbox (you can get it using $mailbox->getName())
  • $mail->delete() deletes mail.
Warning! Do not forget to call $connection->flush() every time after you have moved or deleted mail.
Another feature is setting and getting flags of mail. There are 5 flags, that can be TRUE or FALSE:
  • Mail::FLAG_SEEN
  • Mail::FLAG_FLAGGED
  • Mail::FLAG_ANSWERED
  • Mail::FLAG_DELETED
  • Mail::FLAG_DRAFT
For setting flags, use method $mail->setFlags(array $flags).
The array $flags shall be an associative array with keys as some of the constants mentioned above and values TRUE or FALSE.

Example:
$mail->setFlags(array(Mail::FLAG_SEEN => TRUE, Mail::FLAG_DRAFT => FALSE))
sets flag SEEN to TRUE and DRAFT to FALSE.

For getting flags, use $mail->getFlags(), which returns an associative array with keys again the constants and values TRUE or FALSE

Warning! Do not forget to call $connection->flush() every time after you have modified flags.

Attachments

As always, MailLibrary provides easy access to attachments of mail.

$mail->getAttachments() returns array of greeny\MailLibrary\Attachment, a class which contains some basic methods:
  • getName() - returns original name of attachment
  • getContent() - returns content of the file
  • saveAs($filename) - saves attachment to local file
Simple, easy to use, same as the rest of MailLibrary.

Nette extension

If you use Nette Framework, you can easily use MailLibrary as an Extension. Just add following lines to bootstrap.php:
$configurator->onCompile[] = function($configurator, $compiler) {
	$compiler->addExtension('maillibrary', new \greeny\MailLibrary\Extensions\MailLibraryExtension());
};
And then add your configuration to config.neon or config.local.neon:
maillibrary:
	imap:
		username: john.doe@example.com
		password: top.secret
		host: imap.example.com
		port: 993
		ssl: true
Warning! Nette extension is released in 3.1.0, so if you have only 3.0.0, it's time to update.