I've made this two functions to decode mime headers and so far they are working just fine decoding all headers. Please let me know if you find any error. Hope they are useful for you too.
<?php
function decode_headers($cabecalho){
while (preg_match('/^(.*)=\?([^?]*)\?(Q|B)\?(.*)$/Ui', $cabecalho)){
$cabecalho = preg_replace("/(\t|\r|\n)/", "", $cabecalho);
$cabecalho = preg_replace("/\?(Q|B)\?=/Ui", "?\\1? =", $cabecalho);
$partes_cabecalho = explode("?=", $cabecalho);
$resultado = "";
foreach ($partes_cabecalho as $texto){
$texto = preg_replace("/\?(Q|B)\?\s=/Ui", "?\\1?=", $texto);
$texto = preg_replace("/\?(Q|B)\?/Ui", "=?\\1=?", $texto);
if (preg_match('/^(.*)=\?([^?]*)=\?(Q|B)=\?(.*)$/Ui', $texto)){
$partes_texto = explode ("=?", $texto);
$parte = descodificar_parte($partes_texto[0], $partes_texto[1]);
$parte .= descodificar_parte($partes_texto[3], $partes_texto[2]);
} else {
$parte = $texto;
}
if (strtoupper($partes_texto[1]) == "UTF-8"){ $parte = utf8_decode($parte);}
$resultado .= $parte;
}
$cabecalho = $resultado;
}
return trim($cabecalho);
}
function descodificar_parte($texto, $codificacao){
if (trim($texto) == ""){ return "";}
if (ucfirst($codificacao) == "B"){
$texto = base64_decode($texto);
$texto = htmlspecialchars($texto);
} else if (ucfirst($codificacao) == "Q"){
$texto = str_replace("_", " ", $texto);
$texto = quoted_printable_decode($texto);
}
return $texto;
}
?>
imap_fetchstructure
(PHP 4, PHP 5)
imap_fetchstructure — Read the structure of a particular message
Description
object imap_fetchstructure
( resource $imap_stream
, int $msg_number
[, int $options
] )
Fetches all the structured information for a given message.
Parameters
- imap_stream
-
An IMAP stream returned by imap_open().
- msg_number
-
The message number
- options
-
This optional parameter only has a single option, FT_UID, which tells the function to treat the msg_number argument as a UID.
Return Values
Returns an object includes the envelope, internal date, size, flags and body structure along with a similar object for each mime attachment. The structure of the returned objects is as follows:
| type | Primary body type |
| encoding | Body transfer encoding |
| ifsubtype | TRUE if there is a subtype string |
| subtype | MIME subtype |
| ifdescription | TRUE if there is a description string |
| description | Content description string |
| ifid | TRUE if there is an identification string |
| id | Identification string |
| lines | Number of lines |
| bytes | Number of bytes |
| ifdisposition | TRUE if there is a disposition string |
| disposition | Disposition string |
| ifdparameters | TRUE if the dparameters array exists |
| dparameters | An array of objects where each object has an "attribute" and a "value" property corresponding to the parameters on the Content-disposition MIMEheader. |
| ifparameters | TRUE if the parameters array exists |
| parameters | An array of objects where each object has an "attribute" and a "value" property. |
| parts | An array of objects identical in structure to the top-level object, each of which corresponds to a MIME body part. |
| 0 | text |
| 1 | multipart |
| 2 | message |
| 3 | application |
| 4 | audio |
| 5 | image |
| 6 | video |
| 7 | other |
| 0 | 7BIT |
| 1 | 8BIT |
| 2 | BINARY |
| 3 | BASE64 |
| 4 | QUOTED-PRINTABLE |
| 5 | OTHER |
imap_fetchstructure
Rui Torre rui_sharkye at hotmail dot com
02-Nov-2008 12:34
02-Nov-2008 12:34
Rui Torre rui_sharkye at hotmail dot com
29-Oct-2008 08:38
29-Oct-2008 08:38
I'm programing an webmail program and trying to make the less code possible, so I've made this function to get all mail parts
Hope it helps someone or if you manage to improve this function please post me.
<?php
$caixa_mail = @imap_open ("{localhost:143/notls}INBOX", $user, $password) or die ("It was not possible to establish the imap connection.");
$uid_msg = 1;
$partes_mensagem = obter_partes($caixa_mail, $uid_msg);
function obter_partes($imap, $uid, $estrutura = false, $nparte = 1){
if (!$estrutura){ $estrutura = imap_fetchstructure($imap, $uid, FT_UID);}
//This shows the headers part number (I need to work a little more on this part)
if ($estrutura->parts > 0){
$decimas = explode(".", $nparte);
$decimas[count($decimas)-1] -= 1;
$np = implode(".", $decimas);
} else {
$np = $nparte;
}
//Its a possible message parte (plain or html)
if ($estrutura->type == 0){ print "> mensagem: ";}
print "$np - ".$estrutura->subtype."<br>";
if (count($estrutura->parts) > 0){
foreach ($estrutura->parts as $n => $parte){
if ($n >= 1){
$arr_decimas = explode(".", $nparte);
$arr_decimas[count($arr_decimas)-1] += 1;
$nparte = implode(".", $arr_decimas);
}
if ($parte->type != 1){
if ($parte->type == 0){ print "mensagem: ";}
print "$nparte - ".$parte->subtype."<br>";
}
if (count($parte->parts) > 0){
if ($parte->type == 1){
obter_partes($imap, $uid, $parte, $nparte.".".($n+1));
} else {
foreach ($parte->parts as $idx => $prt){
obter_partes($imap, $uid, $prt, $nparte.".".($idx+1));
}
}
}
}
}
}
?>
david at hundsness dot com
12-Sep-2008 11:00
12-Sep-2008 11:00
[EDITORS: This post corrects mistakes in my previous post, so please delete #85486 on 02-Sep-2008 02:31]
Here is code to parse and decode all types of messages, including attachments. I've been using something like this for a while now, so it's pretty robust.
<?
function getmsg($mbox,$mid) {
// input $mbox = IMAP stream, $mid = message id
// output all the following:
global $htmlmsg,$plainmsg,$charset,$attachments;
// the message may in $htmlmsg, $plainmsg, or both
$htmlmsg = $plainmsg = $charset = '';
$attachments = array();
// HEADER
$h = imap_header($mbox,$mid);
// add code here to get date, from, to, cc, subject...
// BODY
$s = imap_fetchstructure($mbox,$mid);
if (!$s->parts) // not multipart
getpart($mbox,$mid,$s,0); // no part-number, so pass 0
else { // multipart: iterate through each part
foreach ($s->parts as $partno0=>$p)
getpart($mbox,$mid,$p,$partno0+1);
}
}
function getpart($mbox,$mid,$p,$partno) {
// $partno = '1', '2', '2.1', '2.1.3', etc if multipart, 0 if not multipart
global $htmlmsg,$plainmsg,$charset,$attachments;
// DECODE DATA
$data = ($partno)?
imap_fetchbody($mbox,$mid,$partno): // multipart
imap_body($mbox,$mid); // not multipart
// Any part may be encoded, even plain text messages, so check everything.
if ($p->encoding==4)
$data = quoted_printable_decode($data);
elseif ($p->encoding==3)
$data = base64_decode($data);
// no need to decode 7-bit, 8-bit, or binary
// PARAMETERS
// get all parameters, like charset, filenames of attachments, etc.
$params = array();
if ($p->parameters)
foreach ($p->parameters as $x)
$params[ strtolower( $x->attribute ) ] = $x->value;
if ($p->dparameters)
foreach ($p->dparameters as $x)
$params[ strtolower( $x->attribute ) ] = $x->value;
// ATTACHMENT
// Any part with a filename is an attachment,
// so an attached text file (type 0) is not mistaken as the message.
if ($params['filename'] || $params['name']) {
// filename may be given as 'Filename' or 'Name' or both
$filename = ($params['filename'])? $params['filename'] : $params['name'];
// filename may be encoded, so see imap_mime_header_decode()
$attachments[$filename] = $data; // this is a problem if two files have same name
}
// TEXT
elseif ($p->type==0 && $data) {
// Messages may be split in different parts because of inline attachments,
// so append parts together with blank row.
if (strtolower($p->subtype)=='plain')
$plainmsg .= trim($data) ."\n\n";
else
$htmlmsg .= $data ."<br><br>";
$charset = $params['charset']; // assume all parts are same charset
}
// EMBEDDED MESSAGE
// Many bounce notifications embed the original message as type 2,
// but AOL uses type 1 (multipart), which is not handled here.
// There are no PHP functions to parse embedded messages,
// so this just appends the raw source to the main message.
elseif ($p->type==2 && $data) {
$plainmsg .= trim($data) ."\n\n";
}
// SUBPART RECURSION
if ($p->parts) {
foreach ($p->parts as $partno0=>$p2)
getpart($mbox,$mid,$p2,$partno.'.'.($partno0+1)); // 1.2, 1.2.1, etc.
}
}
?>
david at hundsness dot com
02-Sep-2008 12:31
02-Sep-2008 12:31
Here is code to parse and decode all types of messages, including attachments. I've been using something like this for awhile now, so it's pretty robust.
<?
function getmsg($mbox,$mid) {
// input $mbox = IMAP stream, $mid = message id
// output all the following:
global $charset,$htmlmsg,$plainmsg,$attachments;
$htmlmsg = $plainmsg = $charset = '';
$attachments = array();
// HEADER
$h = imap_header($mbox,$mid);
// add code here to get date, from, to, cc, subject...
// BODY
$s = imap_fetchstructure($mbox,$mid);
if (!$s->parts) // simple
getpart($mbox,$mid,$s,0); // pass 0 as part-number
else { // multipart: cycle through each part
foreach ($s->parts as $partno0=>$p)
getpart($mbox,$mid,$p,$partno0+1);
}
}
function getpart($mbox,$mid,$p,$partno) {
// $partno = '1', '2', '2.1', '2.1.3', etc for multipart, 0 if simple
global $htmlmsg,$plainmsg,$charset,$attachments;
// DECODE DATA
$data = ($partno)?
imap_fetchbody($mbox,$mid,$partno): // multipart
imap_body($mbox,$mid); // simple
// Any part may be encoded, even plain text messages, so check everything.
if ($p->encoding==4)
$data = quoted_printable_decode($data);
elseif ($p->encoding==3)
$data = base64_decode($data);
// PARAMETERS
// get all parameters, like charset, filenames of attachments, etc.
$params = array();
if ($p->parameters)
foreach ($p->parameters as $x)
$params[strtolower($x->attribute)] = $x->value;
if ($p->dparameters)
foreach ($p->dparameters as $x)
$params[strtolower($x->attribute)] = $x->value;
// ATTACHMENT
// Any part with a filename is an attachment,
// so an attached text file (type 0) is not mistaken as the message.
if ($params['filename'] || $params['name']) {
// filename may be given as 'Filename' or 'Name' or both
$filename = ($params['filename'])? $params['filename'] : $params['name'];
// filename may be encoded, so see imap_mime_header_decode()
$attachments[$filename] = $data; // this is a problem if two files have same name
}
// TEXT
if ($p->type==0 && $data) {
// Messages may be split in different parts because of inline attachments,
// so append parts together with blank row.
if (strtolower($p->subtype)=='plain')
$plainmsg. = trim($data) ."\n\n";
else
$htmlmsg. = $data ."<br><br>";
$charset = $params['charset']; // assume all parts are same charset
}
// EMBEDDED MESSAGE
// Many bounce notifications embed the original message as type 2,
// but AOL uses type 1 (multipart), which is not handled here.
// There are no PHP functions to parse embedded messages,
// so this just appends the raw source to the main message.
elseif ($p->type==2 && $data) {
$plainmsg. = $data."\n\n";
}
// SUBPART RECURSION
if ($p->parts) {
foreach ($p->parts as $partno0=>$p2)
getpart($mbox,$mid,$p2,$partno.'.'.($partno0+1)); // 1.2, 1.2.1, etc.
}
}
?>
misc at e2007 dot cynergi dot com
21-Oct-2007 05:53
21-Oct-2007 05:53
First of all, for a while now (not sure since which PHP version) a new "primary body type" constant exists: TYPEMODEL (int(7)) and TYPEOTHER became int(8). Furthermore the use of these constants can be misleading. The issue is that "other" MIME-types aren't just ==TYPEOTHER, but rather >=TYPEOTHER. I've added a PHP feature request to help solve this (http://bugs.php.net/43061).
To learn more, read this extract of a conversation I've had with Mark Crispin of IMAP's extension mailing list at UW (e-mail addresses deleted):
----
Mark Crispin:
I certainly understand the frustrations that end users experience with apparent mutual finger-pointing. The way to solve it is through communication.
For what it's worth, here are the current semantics of type codes:
0 TEXT
1 MULTIPART
2 MESSAGE
3 APPLICATION
4 AUDIO
5 IMAGE
6 VIDEO
7 MODEL
8 X-UNKNOWN (or expansion types filed up)
9 first expansion type
...
TYPEMAX last expansion type (currently 15)
On Wed, 17 Oct 2007, Cynergi wrote:
(...)
> -----Original Message-----
> Sent: terça-feira, 16 de Outubro de 2007 17:35
> To: Cynergi
> Subject: Re: [Imap-uw] Apparent bug in imap-2006k.DEV.SNAP-0710121414
> (and older?)
>
> Thank you for your report.
>
> This is not a bug. The c-client library is designed to behave this way.
>
> MIME types and encodings are, by definition in MIME, open-ended. From
> time to time, the IETF defines new MIME types. It is desirable that
> c-client be able to handle these without having to make a source code
> modification to c-client.
>
> To allow applications to support types and encodings that are unknown
> to c-client, c-client will automatically add a (limited) number of
> unknown types and encodings to its tables before resorting to
> TYPEOTHER and ENCOTHER. The names of these added types and encodings
> are available in the body_types[] and body_encodings[] arrays.
>
> Put another way, TYPEOTHER and ENCOTHER are only used if c-client is
> overflowed with unknown types and/or encodings.
>
> If the PHP developers had asked me about this, I would have explained
> this to them. Unfortunately, they have a habit of labelling
> unexpected behaviors as "bugs" rather than seeking answers. I have
> tried to post amended information on the PHP bugzilla in the past, but
> was rewarded with a "you are not authorized to do so" so I've given up.
>
> Hence, a more correct behavior for PHP is not to use type code values,
> but instead to use the body_types[type_code] string.
>
> I hope that this information is helpful.
>
> On Mon, 15 Oct 2007, Cynergi wrote:
>
>> Dear Sirs,
>>
>> I only want to make a bug report. I use PHP for development so I
>> really won't be able to keep up with messages from this list. Please
>> don't take offense if I unsubscribe in a few days after sending this
> message.
>>
>> While developing a Webmail for www.cynergi.com, we started coming
>> upon some
>> (spam) messages with bad MIME types. However PHP (via your c-client
>> library) reported a MIME type code of 9 instead of TYPEOTHER (8).
>>
>> Looking at your library I seem to have found the bug. From a comment
>> in our source code:
>>
>> Unknown MIME-types (such as "25-bit") are returned as int(9) due to
> a
>> bug in c-client's rfc822.c "body_types" array that defines TYPEOTHER
>> as "X-UNKNOWN"; then when imap4r1.c goes to match a MIME-type and
>> can't match any of body_types' strings (including TYPEOTHER's), it
>> returns the next available integer (9).
>> This same bug also seems to apply to ENCOTHER.
>>
>> I am unaware if the body_types array is also used to CREATE
>> MIME-types. If so, deleting "X-UNKNOWN" from there won't be the
>> solution (the solution will then have to be fixing imap4r1.c's code).
>>
>> Thank you for your time, and for such a great open-source library!!
>> :-)
>>
>> Pedro Freire
>> Cynergi
phpnet,a,emailaddress,cjb,net
27-Sep-2007 05:13
27-Sep-2007 05:13
Another comment to inform people about something that should really be in the function description:
imap_fetchstructure() downloads the entire email, attachments and all, rather than just the structure.
I guess it's an undocumented feature, not a bug.
I had assumed that the script would have only downloaded the amount of data that was returned, but my script downloaded a cumulative 2.5gig before i noticed. Hopefully no-one else will have this happen.
oersoep at gmail dot com
30-Jan-2006 09:58
30-Jan-2006 09:58
Please keep in mind that the "parameters" array is a stdClass object when there are no parameters, and NOT a zero-size array.
In PHP5 you'll get this error when iterating structure->parts[x]->parameters if there aren't any parameters for this part:
PHP Fatal error: Cannot use object of type stdClass as array in file.php on line 100
sirber at detritus dot qc dot ca
04-Jan-2006 09:48
04-Jan-2006 09:48
"Primary body type" of "unknown/unknown" will be int(9).
hans at lintoo dot dk
22-Sep-2005 05:07
22-Sep-2005 05:07
To fetch a single part (for example to investigate a charset or something like that)
<?php
class StructureEngine {
private $structureObject;
public function __construct($structureInfo) {
$this->structureObject = $structureInfo;
}
// snip....
public function getPart($partNum) {
$path = split("[.]",$partNum);
$currentPart = $this->structureObject;
foreach ($path as $key => $num) {
$currentPart = $currentPart->parts[$num-1];
}
return $currentPart;
}
}
?>
hans at lintoo dot dk
22-Sep-2005 04:14
22-Sep-2005 04:14
A class for searching through a stucture object.
You can search matching 1-3 parameters or use the methods included.
Feel free to use it, correct it or extend it if you please. Enjoy!
http://lintoo.dk/public/structureengine.class.phps
The code was too wide for this manual, so I hope the link above will do. Here a quick overview instead:
<?php
class StructureEngine {
private $structureObject;
public function __construct($structureInfo) {}
public function locatePlain() {}
public function locateHTML() {}
public function locateAttachments() {}
private function checkParam($part, $type, $value) {}
private function findParts($partsArray, $prefix, $param1Type = 'type', $param1Value = 0, $param2Type = null, ...) {}
}
?>
john at vetsurgeon dot org dot uk
04-Jul-2005 07:07
04-Jul-2005 07:07
A little script I threw together to break a message down and process it into a usable array
<?
//script will fetch an email identified by $msgid, and parse the its parts into an
//array $partsarray
//structure of array:
//$partsarray[<name of part>][<attachment/text>]
//if attachment- subarray is [filename][binary data]
//if text- subarray is [type of text(HTML/PLAIN)][text string]
//i.e.
//$partsarray[3.1][attachment][filename]=filename of attachment in part 3.1
//$partsarray[3.1][attachment][binary]=binary data of attachment in part 3.1
//$partsarray[2][text][type]=type of text in part 2
//$partsarray[2][text][string]=decoded text string in part 2
//$partsarray[not multipart][text][string]=decoded text string in message that isn't multipart
function parsepart($p,$i){
global $link,$msgid,$partsarray;
//where to write file attachments to:
$filestore = '[full/path/to/attachment/store/(chmod777)]';
//fetch part
$part=imap_fetchbody($link,$msgid,$i);
//if type is not text
if ($p->type!=0){
//DECODE PART
//decode if base64
if ($p->encoding==3)$part=base64_decode($part);
//decode if quoted printable
if ($p->encoding==4)$part=quoted_printable_decode($part);
//no need to decode binary or 8bit!
//get filename of attachment if present
$filename='';
// if there are any dparameters present in this part
if (count($p->dparameters)>0){
foreach ($p->dparameters as $dparam){
if ((strtoupper($dparam->attribute)=='NAME') ||(strtoupper($dparam->attribute)=='FILENAME')) $filename=$dparam->value;
}
}
//if no filename found
if ($filename==''){
// if there are any parameters present in this part
if (count($p->parameters)>0){
foreach ($p->parameters as $param){
if ((strtoupper($param->attribute)=='NAME') ||(strtoupper($param->attribute)=='FILENAME')) $filename=$param->value;
}
}
}
//write to disk and set partsarray variable
if ($filename!=''){
$partsarray[$i][attachment] = array('filename'=>$filename,'binary'=>$part);
$fp=fopen($filestore.$filename,"w+");
fwrite($fp,$part);
fclose($fp);
}
//end if type!=0
}
//if part is text
else if($p->type==0){
//decode text
//if QUOTED-PRINTABLE
if ($p->encoding==4) $part=quoted_printable_decode($part);
//if base 64
if ($p->encoding==3) $part=base64_decode($part);
//OPTIONAL PROCESSING e.g. nl2br for plain text
//if plain text
if (strtoupper($p->subtype)=='PLAIN')1;
//if HTML
else if (strtoupper($p->subtype)=='HTML')1;
$partsarray[$i][text] = array('type'=>$p->subtype,'string'=>$part);
}
//if subparts... recurse into function and parse them too!
if (count($p->parts)>0){
foreach ($p->parts as $pno=>$parr){
parsepart($parr,($i.'.'.($pno+1)));
}
}
return;
}
//open resource
$link=imap_open("{localhost:110/pop3}INBOX",'[YOUR USERNAME]','[YOUR PASSWORD]');
//fetch structure of message
$s=imap_fetchstructure($link,$msgid);
//see if there are any parts
if (count($s->parts)>0){
foreach ($s->parts as $partno=>$partarr){
//parse parts of email
parsepart($partarr,$partno+1);
}
}
//for not multipart messages
else{
//get body of message
$text=imap_body($link,$msgid);
//decode if quoted-printable
if ($s->encoding==4) $text=quoted_printable_decode($text);
//OPTIONAL PROCESSING
if (strtoupper($s->subtype)=='PLAIN') $text=$text;
if (strtoupper($s->subtype)=='HTML') $text=$text;
$partsarray['not multipart'][text]=array('type'=>$s->subtype,'string'=>$text);
}
print_r($partsarray);
?>
masterbassist
18-Apr-2005 07:52
18-Apr-2005 07:52
I think the following line (when building attachment information)
>>> "filename" => $parts[$i]->parameters[0]->value
needs to be
>>> "filename" => $parts[$i]->dparameters[0]->value
The first version generated a PHP warning under PHP 5.0.3. The second version actually gets the filename.
spam at emielmols dot info
01-Apr-2005 02:47
01-Apr-2005 02:47
I've created a function which simply extracts basic message content as a string ($content) and attachments as an array ($attachments). I've tested it with messages from Outlook, Outlook Express and Hotmail. Perhaps it's useful to anyone.
<?php
$struct = imap_fetchstructure($mbox, $mid);
$parts = $struct->parts;
$i = 0;
if (!$parts) { /* Simple message, only 1 piece */
$attachment = array(); /* No attachments */
$content = imap_body($mbox, $mid);
} else { /* Complicated message, multiple parts */
$endwhile = false;
$stack = array(); /* Stack while parsing message */
$content = ""; /* Content of message */
$attachment = array(); /* Attachments */
while (!$endwhile) {
if (!$parts[$i]) {
if (count($stack) > 0) {
$parts = $stack[count($stack)-1]["p"];
$i = $stack[count($stack)-1]["i"] + 1;
array_pop($stack);
} else {
$endwhile = true;
}
}
if (!$endwhile) {
/* Create message part first (example '1.2.3') */
$partstring = "";
foreach ($stack as $s) {
$partstring .= ($s["i"]+1) . ".";
}
$partstring .= ($i+1);
if (strtoupper($parts[$i]->disposition) == "ATTACHMENT") { /* Attachment */
$attachment[] = array("filename" => $parts[$i]->parameters[0]->value,
"filedata" => imap_fetchbody($mbox, $mid, $partstring));
} elseif (strtoupper($parts[$i]->subtype) == "PLAIN") { /* Message */
$content .= imap_fetchbody($mbox, $mid, $partstring);
}
}
if ($parts[$i]->parts) {
$stack[] = array("p" => $parts, "i" => $i);
$parts = $parts[$i]->parts;
$i = 0;
} else {
$i++;
}
} /* while */
} /* complicated message */
echo "Analyzed message $mid, result: <br />";
echo "Content: $content<br /><br />";
echo "Attachments:"; print_r ($attachment);
?>
y dot daradkeh at gmail dot com
20-Dec-2004 05:40
20-Dec-2004 05:40
Hey people, get the message attachments with this code:
<?php
$mbox = imap_open("$imap_server".$f,$name,$pass);
// delibertely choose a message with an attachment
$info = imap_fetchstructure($mbox, $mno);
// find out how may parts the object has
$numparts = count($info->parts);
$i=0;
// find if multipart message
if ($numparts >1)
{
echo "<b>More than one part</b><br><br>";
foreach ($info->parts as $part)
{
if ($part->disposition == "INLINE")
printf("Inline message has %s lines<BR>", $part->lines);
elseif ($part->disposition == "attachment")
{
$i++;
echo $i." Attachment/s found!<br>";
echo "Filename: ".$part->dparameters[0]->value."<br><br>";
}
}
}
else
echo "Only one part";
imap_close($mbox);
?>
aperez at informatica dot 24ruedas dot com
16-Jun-2004 10:10
16-Jun-2004 10:10
About above comment and source code I wrote: certainly, plain/html text files are attachments, but I've written my code thinking about web IMAP clients, where text parts are not for downloading, simply they are shown. That's the reason.
Thanks anyway. :)
passeniermaxime at hotmail dot com
15-Jun-2004 06:15
15-Jun-2004 06:15
I have written a code that check's for attachments.
There is a slight problem with the above code;
when you send a mail with a .txt document as attachment
the type will be 0 and so there won't be a attachment found.
I check for the disposition of the body part witch can be inline or attachment.
If this is an attachment he will display it.
You an also mix up both codes by checking on the type and the disposition.
//////////////////////////////////
/// $mbox = connection
/// $a_mails_sort[$i] = message id
$structuur = imap_fetchstructure($mbox,$a_mails_sort[$i]);
$bericht_delen=$structuur->parts;
for($i_delen = 0; $i_delen<=count($bericht_delen);$i_delen++)
{
if($bericht_delen[$i_delen]->disposition == "attachment")
{
$attachment = "OK";
}// end if
}//end for
aperez at informatica dot 24ruedas dot com
25-May-2004 10:12
25-May-2004 10:12
This is my function to check attachments:
<?php
$est=imap_fetchstructure($con,$msg);
if(checkAttachments($est))
{
echo("You have attachment(s)");
}
else
{
echo("You don't have attachment(s)");
}
function checkAttachments($estMsg)
{
if(($estMsg->type!=0) && ($estMsg->type!=1))
{
// Text and multipart parts will not be shown as attachments
return(true);
}
else
{
// If there's no attachments, parts inside will be checked
if($estMsg->parts)
{
$partMsg=$estMsg->parts;
$i=0;
// Parts will be checked while no attachments found or not all of them checked
while(!(checkAttachments($partMsg[$i])) && ($i<sizeof($estMsg->parts)))
{
$i++;
}
// If any 'checkAttachment' calls returned 'true', 'i' should be
// equal to number of parts(after increased in while). So, no
// attachments found
if($i==sizeof($estMsg->parts))
{
return(false);
}
else
{
return(true);
}
}
else
{
// If no parts and text or multipart type, no attachments
return(false);
}
}
}
imap_close($con);
?>
I hope this helps somebody else(if bugs, thanks for your fixes).
richy at smilingsouls dot net
28-Jan-2004 01:08
28-Jan-2004 01:08
After many long hours of pouring over the object returned by imap_fetchstructure() I came up with the solution posted at the following url:
http://p2p.wrox.com/topic.asp?TOPIC_ID=9063
The url above provides an example of how to access variables in the object returned by imap_fetchstructure(). This class creates an object with member variables containing the correct part numbers which are compatible with the imap_fetchbody() function.
The structure returned looks something like this:
0 Raw Headers
$this->pid[$mid][0] = 1 text/plain top level message
$this->pid[$mid][1] = 2 message/rfc822 entire unparsed message
multipart/mixed - part is skipped!
2.0 Raw Headers
$this->pid[$mid][2] = 2.1 multipart/alternative contains unparsed contents of next subpart (text/plain && text/html)
2.1.0 Raw Headers
$this->pid[$mid][3] = 2.1.1 text/plain 2nd level inline embedded message
$this->pid[$mid][4] = 2.1.2 text/html
$this->pid[$mid][5] = 2.2 message/rfc822 entire unparsed message
multipart/mixed - part is skipped!
2.2.0 Raw Headers
$this->pid[$mid][6] = 2.2.1 multipart/alternative
$this->pid[$mid][7] = 2.2.1.1 text/plain 3rd level inline embedded message
$this->pid[$mid][8] = 2.2.1.2 text/html
$this->pid[$mid][9] = 2.2.2 image/jpeg
$this->pid[$mid][10] = 2.2.3 image/jpeg
$this->pid[$mid][11] = 2.2.4 image/jpeg
$this->pid[$mid][12] = 2.2.5 image/gif
Its important to note why multipart/related, multipart/mixed and certain multipart/alternative (if parent part is message/rfc822 && not multipart/mixed) parts are skipped, imap_fetchbody **does not** retreive a message part for these parts. Which isn't a bug, as I have read in other places, these parts exist for the purpose of designing the viewer portion of a mail application. Also, headers aren't assigned part numbers here because they are easy to pick out.
: )
Rich
