[dev] Questions about using Horde_Imap_Client

Michael M Slusarz slusarz at horde.org
Mon Jan 2 21:38:57 UTC 2012


Quoting Michael J Rubinsky <mrubinsk at horde.org>:

> Sending to the list, but this question is mostly directed towards Michael:
>
> Anyway, I have tried to get only the plaintext body from the email  
> message like so (simplified from my code):
>
> <code>
> $q = new Horde_Imap_Fetch_Query();
> $q->envelope();
> $q->structure();
> $q->fullText(array('peek' => true));

This is more correct:

$q = new Horde_Imap_Fetch_Query();
// For the example you provided, you don't need envelope, although I  
am guessing you may be using envelope
// information elsewhere...
// $q->envelope();
$q->structure();

You do NOT need fullText() (see below).

> // Obviously $mbox is a Horde_Imap_Client_Mailbox object
> // and $ids is a Horde_Imap_Client_Ids object.
> $list = $client->fetch($mbox, $q, array('ids' => $ids));
>
> $email = array_pop($list);
> $part = $email->getStructure();
> $id = $part->findBody();
> $body = $part->getPart($id);

This is correct so far.  $part contains the Horde_Mime_Part  
representation of the full message.  $body contains the  
Horde_Mime_Part object of the body part.  However, neither of these  
contains the contents of that message/part.  You haven't yet requested  
that information from the server.

> echo $body->getContents(); // <--- Always returns an empty string.

As mentioned above, the empty string is expected here.  Nowhere has  
the contents been added to the MIME part.

> The only way I've been able to do what I want is to parse the entire  
> message text with Horde_Mime_Part::parseMessage();
>
> <code>
>  $msg = Horde_Mime_Part::parseMessage($data->getFullMsg());
>  $id = $msg->findBody();
>  $body = $msg->getPart($id);
>  echo $body->getContents(); // <--- Shows plaintext message body.
> </code>
>
> ..am I missing something, or do I completely misunderstand what I'm doing?

Don't do this.  This is excessive overhead - you will have to download  
the entire source of the original message (which may be many MB, even  
if you only want the several KB text/plain part), and then have to  
parse this entire message on the PHP side.  Instead, you should let  
the IMAP server do the parsing for you, and then only ship the  
information needed.

Thus, after you have determined the body ID (in the above code, it is  
in the $id variable), you just need to request the body part text from  
the IMAP server:

$q2 = new Horde_Imap_Fetch_Query();
$q2->bodyPart($id, array(
     // Attempt to decode server-side if possible.  Falls-back to  
providing unencoded data.
     'decode' => true,
     'peek' => true
));
$list2 = $client->fetch($mbox, $q2, array('ids' => $ids));
$email2 = array_pop($list2);

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

The plaintext representation will now be in $text.

> The EAS client may request to truncate the email body. Is it  
> possible to use the imap library's ability to only return the  
> truncated body data while still being able to parse out only the  
> plaintext portion of the body? i.e., If the IMAP client only returns  
> a portion of the body, I am assuming that it would be impossible to  
> properly parse the body for the different parts, right?  Currently,  
> since I'm parsing the fullMsg anyway, I truncate in the ActiveSync  
> code if needed.

Yes.  Meaning: you grab the structure data, determine the body part  
ID, and then request a portion of the text for a body part ID:

$q2->bodyPart($id, array(
     // Attempt to decode server-side if possible.  Falls-back to  
providing unencoded data.
     'decode' => true,
     'length' => $data_length
     'peek' => true
));

michael

___________________________________
Michael Slusarz [slusarz at horde.org]



More information about the dev mailing list