6.0.0-git
2024-10-06
Last Modified 2014-02-27 by Michael Slusarz

Horde/Imap_Client usage examples

Examples

Assumptions

In these examples, $imap is assumed to be a previously configured/created Client object.

Get a list of messages in INBOX, since a certain date:

$query = new Horde_Imap_Client_Search_Query();
$query->dateSearch(
    new Horde_Date($date_string),
    Horde_Imap_Client_Search_Query::DATE_SINCE
);

// $list is an array, containing a single entry: 'match'
$results = $imap->search('INBOX', $query);

// A Horde_Imap_Client_Ids object containing the list of UIDs that matched the query.
var_dump($results['match']);

Using the above message ids, fetch the plaintext body of the first email:

$query = new Horde_Imap_Client_Fetch_Query();
$query->structure();

$uid = new Horde_Imap_Client_Ids($results['match']->ids[0]);

$list = $imap->fetch('INBOX', $query, array(
    'ids' => $uid
));

$part = $list->first()->getStructure();
$id = $part->findBody();
$body = $part->getPart($id);

$query2 = new Horde_Imap_Client_Fetch_Query();
$query2->bodyPart($id, array(
    'decode' => true,
    'peek' => true
));

$list2 = $imap->fetch('INBOX', $query2, array(
    'ids' => $uid
));

$message2 = $list2->first();
$text = $message2->getBodyPart($id);
if (!$message2->getBodyPartDecode($id)) {
    // Quick way to transfer decode contents
    $body->setContents($text);
    $text = $body->getContents();
}

// $text now contains the plaintext body of the message.

TODO (Notes that will eventually be converting to the tutorial)

// Need UIDVALIDITY to pair with UIDs to ensure that future calls are referring
// to the same UID.  We can get the UIDVALIDITY for a mailbox like this:
$status = $client->status('INBOX', Horde_Imap_Client::STATUS_UIDVALIDITY);
$uidvalidity = $status['uidvalidity'];
// UID + UIDVALIDITY = unique 64-bit number for a mailbox on a given server
// See: http://tools.ietf.org/html/rfc3501#section-2.3.1.1

// $results is an array.  The list of UIDs is in the 'match' key.  It is a Horde_Imap_Client_Ids object:
// http://dev.horde.org/api/master/lib/Imap_Client/classes/Horde_Imap_Client_Ids.html

// This object is Traversable (via foreach()).  You can also call count() on the object.
// The raw list of UIDs (in array format) is available via the $ids property.
// i.e. $results['match']->ids gets the list of UIDs.

// Read an attachment from a message.
// From the UIDs result above, pick one of the UIDs.  I will call that $uid.
// First we need to get the structure of that message to determine what parts we want to load.

// To fetch information, we use the Horde_Imap_Client_Fetch_Query class to build the fetch query.
// http://dev.horde.org/api/master/lib/Imap_Client/classes/Horde_Imap_Client_Fetch_Query.html

$query = new Horde_Imap_Client_Fetch_Query();
// This fetches the structure:
$query->structure();

// Now we are ready to fetch() the message info from the server.
// http://dev.horde.org/api/master/lib/Imap_Client/classes/Horde_Imap_Client_Base.html#method_fetch

$results = $client->fetch('INBOX', $query, array(
     // We want to limit results to a single UID (default is ALL UIDs).
     'ids' => new Horde_Imap_Client_Ids($uid)
));

// $results is a Horde_Imap_Client_Fetch_Results object:
// http://dev.horde.org/api/master/lib/Imap_Client/classes/Horde_Imap_Client_Fetch_Results.html

// To get the results for a particular ID, we can use array syntax:
$uid_result = $results[$uid];

// $uid_result now contains the Horde_Imap_Client_Data_Fetch object for UID $uid
// http://dev.horde.org/api/master/lib/Imap_Client/classes/Horde_Imap_Client_Data_Fetch.html

// To retrieve the structure object, we call this:
$structure = $uid_result->getStructure();

// $structure now contains the Horde_Mime_Part object representing the base part of the object.
// http://dev.horde.org/api/master/lib/Mime/classes/Horde_Mime_Part.html
// See also: http://wiki.horde.org/Doc/Dev/MimeH4

// Assuming this structure for the message:
// multipart/related
//   + text/plain
//   + text/html
// To get list of parts in base $structure object:
$parts = $structure->contentTypeMap();

// $parts = array(
//     ['1'] => text/plain
//     ['2'] => text/html
// )

// Consumer (client) code determines we want to view the HTML part, for example (part ID 2).  So we need to grab this data from the
// IMAP server.
$query = new Horde_Imap_Client_Fetch_Query();
$query2->bodyPart('2', array(
     // Set this to true if you don't want the \Seen flag to be set
     'peek' => false
));
$results = $client->fetch('INBOX', $query2, array(
     'ids' => new Horde_Imap_Client_Ids($uid)
));

// This returns the body part data in a stream (recommended to reduce memory usage; if second argument is false,
// data will be returned as string).
$stream = $results[$uid]->getBodyPart('2', true);

// $stream is raw data of part.  It may be transfer-encoded (i.e. base64).
// To decode, we need to add data to Horde_Mime_Part object containing
// structure of this part.  We already have this information - we retrieved it back with the structure data.
$part = $structure['2'];
// $part is now the Horde_Mime_Part object of the text/html (ID 2) part.
$part->setContents($stream, array(
     // This is more efficient; it reuses the $stream from above rather than copying data. It should be used
     // if we know that $stream won't be altered by any other process.
     'usestream' => true
));

// Now, to get the binary data of the part ($html_data is a string).
$html_data = $part->getContents();

// To return $html_data as a stream (more memory efficient):
$html_data = $part->getContents(array(
     'stream' => true
));