Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine part numbers of an email retrieved via PHP IMAP functions?

Tags:

php

imap

To fetch the particular section of the body of a message with imap_fetchbody(), you have to pass the section parameter which relates to the IMAP part number and is defined as follow in the PHP documentation:

It is a string of integers delimited by period which index into a body part list as per the IMAP4 specification

The only clue I have is to use imap_fetchstructure() to read the structure of a particular message. However, I don't know how to deduce the part numbers from it.

EDIT

For those interested in the IMAPv4 specification, here is the paragraph about fetching where part numbers are mentioned. Unfortunately, it does not clearly state how to get or compute them.

like image 808
David Avatar asked Jun 08 '17 17:06

David


1 Answers

You are right, you have to use the result of the imap_fetchstructure() function.

You can get the full listing of parts and subpart of a mail by using the following function :

 function getPartList($struct, $base="") {
    $res=Array();
    if (!property_exists($struct,"parts")) {
            return [$base?:"0"];
    } else {
            $num=1;
            if (count($struct->parts)==1) return getPartList($struct->parts[0], $base);

            foreach ($struct->parts as $p=>$part) {
                    foreach (getPartList($part, $p+1) as $subpart) {
                            $res[]=($base?"$base.":"").$subpart;
                    }
            }
    }
    return $res;
 }

 $struct=imap_fetchstructure($mbox, $i);
 $res=getPartList($struct);
 print_r($res);

 Result:
 Array(
     [0] => 1
     [1] => 2
     [2] => 3.1
     [3] => 3.2
     [4] => 4.1
     [5] => 4.2
 );

EDIT: be aware that your server may not handle RFC822 subpart

For instance on a Dovecot v2.2 server, it returns an empty string

 telnet imapserver.com 143
 a1 LOGIN [email protected] password
 a2 SELECT "Inbox"
 a3 FETCH 522 (BODY[3.1.2])

 // result:

 * 522 FETCH (BODY[3.1.2] {0}
 )
 a3 OK Fetch completed.
 a4 logout

EDIT2 : it seems that subparts with only one part does not count... See modified code

like image 137
Adam Avatar answered Nov 08 '22 05:11

Adam