Object-oriented IMAP for PHP

Object-oriented IMAP for PHP

README

Build Status
Code Coverage
Scrutinizer Code Quality
Latest Stable Version
Total Downloads

A PHP 7.1+ library to read and process e-mails over IMAP.

This library requires IMAP,
iconv and
Multibyte String extensions installed.

Table of Contents

  1. Feature Requests
  2. Installation
  3. Usage

    1. Connect and Authenticate
    2. Mailboxes
    3. Messages

      1. Searching for Messages
      2. Unknown search criterion: OR
      3. Message Properties and Operations
    4. Message Attachments
    5. Embedded Messages
    6. Timeouts
  4. Mock the library
  5. Running the Tests

    1. Running Tests using Docker

Feature Requests

Feature Requests

Installation

The recommended way to install the IMAP library is through Composer:

$ composer require ddeboer/imap

This command requires you to have Composer installed globally, as explained
in the installation chapter
of the Composer documentation.

Usage

Connect and Authenticate

use DdeboerImapServer;

$server = new Server('imap.gmail.com');

// $connection is instance of DdeboerImapConnection
$connection = $server->authenticate('my_username', 'my_password');

You can specify port, flags and parameters
to the server:

$server = new Server(
    $hostname, // required
    $port,     // defaults to '993'
    $flags,    // defaults to '/imap/ssl/validate-cert'
    $parameters
);

Mailboxes

Retrieve mailboxes (also known as mail folders) from the mail server and iterate
over them:

$mailboxes = $connection->getMailboxes();

foreach ($mailboxes as $mailbox) {
    // Skip container-only mailboxes
    // @see https://secure.php.net/manual/en/function.imap-getmailboxes.php
    if ($mailbox->getAttributes() & LATT_NOSELECT) {
        continue;
    }

    // $mailbox is instance of DdeboerImapMailbox
    printf('Mailbox "%s" has %s messages', $mailbox->getName(), $mailbox->count());
}

Or retrieve a specific mailbox:

$mailbox = $connection->getMailbox('INBOX');

Delete a mailbox:

$connection->deleteMailbox($mailbox);

You can bulk set, or clear, any flag of mailbox messages (by UIDs):

$mailbox->setFlag('\Seen \Flagged', ['1:5', '7', '9']);
$mailbox->setFlag('\Seen', '1,3,5,6:8');

$mailbox->clearFlag('\Flagged', '1,3');

WARNING You must retrieve new Message instances in case of bulk modify flags to refresh the single Messages flags.

Messages

Retrieve messages (e-mails) from a mailbox and iterate over them:

$messages = $mailbox->getMessages();

foreach ($messages as $message) {
    // $message is instance of DdeboerImapMessage
}

To insert a new message (that just has been sent) into the Sent mailbox and flag it as seen:

$mailbox = $connection->getMailbox('Sent');
$mailbox->addMessage($messageMIME, '\Seen');

Note that the message should be a string at MIME format (as described in the RFC2045).

Searching for Messages

use DdeboerImapSearchExpression;
use DdeboerImapSearchEmailTo;
use DdeboerImapSearchTextBody;

$search = new SearchExpression();
$search->addCondition(new To('[email protected]'));
$search->addCondition(new Body('contents'));

$messages = $mailbox->getMessages($search);

WARNING We are currently unable to have both spaces and double-quotes
escaped together. Only spaces are currently escaped correctly.
You can use DdeboerImapSearchRawExpression to write the complete search
condition by yourself.

Messages can also be retrieved sorted as per imap_sort
function:

$today = new DateTimeImmutable();
$lastMonth = $today->sub(new DateInterval('P30D'));

$messages = $mailbox->getMessages(
    new DdeboerImapSearchDateSince($lastMonth),
    SORTDATE, // Sort criteria
    true // Descending order
);

Unknown search criterion: OR

Note that PHP imap library relies on the c-client library available at https://www.washington.edu/imap/
which doesn’t fully support some IMAP4 search criteria like OR. If you want those unsupported criteria,
you need to manually patch the latest version (imap-2007f of 23-Jul-2011 at the time of this commit)
and recompile PHP onto your patched c-client library.

By the way most of the common search criteria are available and functioning, browse them in ./src/Search.

References:

  1. https://stackoverflow.com/questions/36356715/imap-search-unknown-search-criterion-or
  2. imap-2007f.tar.gz: ./src/c-client/mail.c and ./docs/internal.txt

Message Properties and Operations

Get message number and unique message id
in the form <…>:

$message->getNumber();
$message->getId();

Get other message properties:

$message->getSubject();
$message->getFrom();    // MessageEmailAddress
$message->getTo();      // array of MessageEmailAddress
$message->getDate();    // DateTimeImmutable
$message->isAnswered();
$message->isDeleted();
$message->isDraft();
$message->isSeen();

Get message headers as a DdeboerImapMessageHeaders object:

$message->getHeaders();

Get message body as HTML or plain text:

$message->getBodyHtml();    // Content of text/html part, if present
$message->getBodyText();    // Content of text/plain part, if present

Reading the message body keeps the message as unseen.
If you want to mark the message as seen:

$message->markAsSeen();

Or you can set, or clear, any flag:

$message->setFlag('\Seen \Flagged');
$message->clearFlag('\Flagged');

Move a message to another mailbox:

$mailbox = $connection->getMailbox('another-mailbox');
$message->move($mailbox);
$connection->expunge();

Deleting messages:

$mailbox->getMessage(1)->delete();
$mailbox->getMessage(2)->delete();
$connection->expunge();

Message Attachments

Get message attachments (both inline and attached) and iterate over them:

$attachments = $message->getAttachments();

foreach ($attachments as $attachment) {
    // $attachment is instance of DdeboerImapMessageAttachment
}

Download a message attachment to a local file:

// getDecodedContent() decodes the attachment’s contents automatically:
file_put_contents(
    '/my/local/dir/' . $attachment->getFilename(),
    $attachment->getDecodedContent()
);

Embedded Messages

Check if attachment is embedded message and get it:

$attachments = $message->getAttachments();

foreach ($attachments as $attachment) {
    if ($attachment->isEmbeddedMessage()) {
        $embeddedMessage = $attachment->getEmbeddedMessage();
        // $embeddedMessage is instance of DdeboerImapMessageEmbeddedMessage
    }
}

An EmbeddedMessage has the same API as a normal Message, apart from flags
and operations like copy, move or delete.

Timeouts

The IMAP extension provides the imap_timeout
function to adjust the timeout seconds for various operations.

However the extension’s implementation doesn’t link the functionality to a
specific context or connection, instead they are global. So in order to not
affect functionalities outside this library, we had to choose whether wrap
every imap_* call around an optional user-provided timeout or leave this
task to the user.

Because of the heterogeneous world of IMAP servers and the high complexity
burden cost for such a little gain of the former, we chose the latter.

Mock the library

Mockability is granted by interfaces present for each API.
Dig into MockabilityTest for an example of a
mocked workflow.

Running the Tests

This library is functionally tested on Travis CI
against a local Dovecot server.

If you have your own IMAP (test) account, you can run the tests locally by
providing your IMAP credentials:

$ composer install
$ IMAP_SERVER_NAME="my.imap.server.com" IMAP_SERVER_PORT="60993" IMAP_USERNAME="johndoe" IMAP_PASSWORD="p4ssword" vendor/bin/phpunit

You can also copy phpunit.xml.dist file to a custom phpunit.xml and put
these environment variables in it:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit
    bootstrap="./vendor/autoload.php"
    colors="true"
    verbose="true"
>
    <testsuites>
        <testsuite name="ddeboer/imap">
            <directory>./tests/</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory suffix=".php">./src</directory>
        </whitelist>
    </filter>
    <php>
        <env name="IMAP_SERVER_NAME" value="my.imap.server.com" />
        <env name="IMAP_SERVER_PORT" value="60993" />
        <env name="IMAP_USERNAME" value="johndoe" />
        <env name="IMAP_PASSWORD" value="p4ssword" />
    </php>
</phpunit>

WARNING Tests create new mailboxes without removing them.

Running Tests using Docker

If you have Docker installed you can run the tests locally with the following command:

$ docker-compose run tests

Source

Tags:, ,

Add a Comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *