从嵌套的imap零件获取附件

时间:2018-09-17 07:28:41

标签: php imap

我正在使用以下功能从现有imap连接($ imap)上的电子邮件(索引为$ m)获取附件

function parse_parts(&$structure, &$attachments, &$imap, $m, $par){
if(isset($structure->parts) && count($structure->parts) ) {
    for($i = 0; $i < count($structure->parts); $i++) {
        $attachments[] = array(
            'is_attachment' => false,
            'filename' => '',
            'name' => '',
            'attachment' => ''
        );
        $lstk= array_keys($attachments);  $j=end($lstk); // use this instead of $i to avoid overlapping indices when there's sub-parts and recursion

        if($structure->parts[$i]->ifdparameters) {
            foreach($structure->parts[$i]->dparameters as $object) {
                if(strtolower($object->attribute) == 'filename') {
                    $attachments[$j]['is_attachment'] = true;
                    $attachments[$j]['filename'] = $object->value;
                }
            }
        }
        if($structure->parts[$i]->ifparameters) {
            foreach($structure->parts[$i]->parameters as $object) {
                if(strtolower($object->attribute) == 'name') {
                    $attachments[$j]['is_attachment'] = true;
                    $attachments[$j]['filename'] = imap_utf8($object->value);
                }
            }
        }
        if($attachments[$j]['is_attachment']) {
            if($par==''){
                $attachments[$j]['attachment'] = imap_fetchbody($imap, $m,  $i+1);
            }else{
                $attachments[$j]['attachment'] = imap_fetchbody($imap, $m,  $par . $i+1);
            }
            if($structure->parts[$i]->encoding == 3) { // 3 = BASE64
                $attachments[$j]['attachment'] = base64_decode($attachments[$j]['attachment']);
            }
            elseif($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
                $attachments[$j]['attachment'] = quoted_printable_decode($attachments[$j]['attachment']);
            }else{echo "encod:". $structure->parts[$i]->encoding . PHP_EOL; }
        } 
        if(isset($structure->parts[$i]->parts) && count($structure->parts[$i]->parts)){ //if the part contains its own parts, recurse
             $prnt = $i;
             $prnt = $prnt . '.';
             parse_parts($structure->parts[$i], $attachments, $imap, $m, $prnt );    
        }
    }
}

}

稍后调用此函数的函数如下:

$structure = imap_fetchstructure($imap, $m);
$attachments = array();
parse_parts($structure, $attachments, $imap, $m, '');

标准函数可以正常工作,但是当它必须递归时(即有嵌套的部分),虽然看起来确实是正确的大小,但生成的文件不可读。知道我在做什么错吗? 我尝试将$ prnt更改为

$prnt = $i+1 .'.';

但是,它只是输出一个空文件。 我注意到其他人在这里也有类似的问题: imap - get attached file

但他们的解决方案似乎不适用于此电子邮件/代码。

2 个答案:

答案 0 :(得分:0)

感谢IVO GELOV发现我的错误。最终工作功能:

function parse_parts(&$structure, &$attachments, &$imap, $m, $par){
if(isset($structure->parts) && count($structure->parts) ) {
    for($i = 0; $i < count($structure->parts); $i++) {
        $attachments[] = array(
            'is_attachment' => false,
            'filename' => '',
            'name' => '',
            'attachment' => ''
        );
        $lstk= array_keys($attachments);  $j=end($lstk); // use this instead of $i to avoid overlapping indices when there's sub-parts and recursion

        if($structure->parts[$i]->ifdparameters) {
            foreach($structure->parts[$i]->dparameters as $object) {
                if(strtolower($object->attribute) == 'filename') {
                    $attachments[$j]['is_attachment'] = true;
                    $attachments[$j]['filename'] = $object->value;
                }
            }
        }
        if($structure->parts[$i]->ifparameters) {
            foreach($structure->parts[$i]->parameters as $object) {
                if(strtolower($object->attribute) == 'name') {
                    $attachments[$j]['is_attachment'] = true;
                    $attachments[$j]['filename'] = imap_utf8($object->value);
                }
            }
        }
        if($attachments[$j]['is_attachment']) {
            if($par==''){
                $attachments[$j]['attachment'] = imap_fetchbody($imap, $m,  ($i+1));
            }else{
                $attachments[$j]['attachment'] = imap_fetchbody($imap, $m,  $par . ($i+1));
            }
            if($structure->parts[$i]->encoding == 3) { // 3 = BASE64
                $attachments[$j]['attachment'] = base64_decode($attachments[$j]['attachment']);
            }
            elseif($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
                $attachments[$j]['attachment'] = quoted_printable_decode($attachments[$j]['attachment']);
            }else{echo "encod:". $structure->parts[$i]->encoding . PHP_EOL; }
        } 
        if(isset($structure->parts[$i]->parts) && count($structure->parts[$i]->parts)){ //if the part contains its own parts, recurse
             $prnt = $i+1;
             $prnt = $prnt . '.';
             parse_parts($structure->parts[$i], $attachments, $imap, $m, $prnt );    
        }
    }
}

}

答案 1 :(得分:0)

附件也可以是内联文件或外部文件。

所以我们必须同时获得两种附件。

$structure = imap_fetchstructure($this->imap, $id);
    $fileName = $attachments = array();
    /* if any attachments found... */
    if (isset($structure->parts) && count($structure->parts)) {
        $n = 0;
        for($i = 0; $i < count($structure->parts); $i++){
            if(isset($structure->parts[$i]->parts) && !empty($structure->parts[$i]->parts) && count($structure->parts[$i]->parts)>0){
                for($y = 0; $y < count($structure->parts[$i]->parts); $y++) 
                {
                    $attachments[$n] = array('is_attachment' => false,'filename' => '','name' => '','attachment' => '','size' => '','cid' => 0);
                    if($structure->parts[$i]->parts[$y]->ifdparameters==1) {
                        foreach($structure->parts[$i]->parts[$y]->dparameters as $object){
                            if(strtolower($object->attribute) == 'filename'){
                                $attachments[$n]['is_attachment'] = true; 
                                $fileName[0] = $object->value;
                                $filename = $this->filterFileName($fileName);                               
                                $attachments[$n]['filename'] = $filename;
                                $attachments[$n]['name'] = $filename;
                            }
                        }
                    }
                    if($structure->parts[$i]->parts[$y]->ifparameters){
                        foreach($structure->parts[$i]->parts[$y]->parameters as $object){
                            if(strtolower($object->attribute) == 'name'){
                                $attachments[$n]['is_attachment'] = true;
                                $fileName[0] = $object->value;
                                $filename = $this->filterFileName($fileName);
                                $attachments[$n]['name'] = $filename;
                                $attachments[$n]['filename'] = $filename;
                            }
                        }
                    }
                    if($attachments[$n]['is_attachment']){
                        $attachments[$n]['attachment'] = imap_fetchbody($this->imap, $id, ($i+1).'.'.($y+1));                            
                        if($structure->parts[$i]->parts[$y]->encoding == 3){ /* 4 = QUOTED-PRINTABLE encoding */
                            $attachments[$n]['attachment'] = base64_decode($attachments[$n]['attachment']);
                        }                            
                        elseif($structure->parts[$i]->parts[$y]->encoding == 4){ /* 3 = BASE64 encoding */
                            $attachments[$n]['attachment'] = quoted_printable_decode($attachments[$n]['attachment']);
                        }
                        $attachments[$n]['size'] = $structure->parts[$i]->parts[$y]->bytes;
                        $attachments[$n]['cid'] = ($structure->parts[$i]->parts[$y]->ifid) ? str_replace(array('<', '>'), '', $structure->parts[$i]->parts[$y]->id) : 0;                            
                    }
                    $email['attachments'][] = $attachments[$n];$n++;
                }
            }else{
                $attachments[$n] = array('is_attachment' => false,'filename' => '','name' => '','attachment' => '','size' => '','cid' => 0);
                if($structure->parts[$i]->ifdparameters==1){
                    foreach($structure->parts[$i]->dparameters as $object){
                        if(strtolower($object->attribute) == 'filename'){
                            $attachments[$n]['is_attachment'] = true;
                            $fileName[0] = $object->value;
                            $filename = $this->filterFileName($fileName);
                            $attachments[$n]['filename'] = $filename;
                            $attachments[$n]['name'] = $filename;
                        }
                    }
                }
                if($structure->parts[$i]->ifparameters){
                    foreach($structure->parts[$i]->parameters as $object){
                        if(strtolower($object->attribute) == 'name'){
                            $attachments[$n]['is_attachment'] = true;
                            $fileName[0] = $object->value;
                            $filename = $this->filterFileName($fileName);
                            $attachments[$n]['name'] = $filename;
                            $attachments[$n]['filename'] = $filename;
                        }
                    }
                }
                if($attachments[$n]['is_attachment']){
                    $attachments[$n]['attachment'] = imap_fetchbody($this->imap, $id, $i+1);                        
                    if($structure->parts[$i]->encoding == 3){/* 4 = QUOTED-PRINTABLE encoding */ 
                        $attachments[$n]['attachment'] = base64_decode($attachments[$n]['attachment']);
                    }elseif($structure->parts[$i]->encoding == 4){ /* 3 = BASE64 encoding */
                        $attachments[$n]['attachment'] = quoted_printable_decode($attachments[$n]['attachment']);
                    }
                    $attachments[$n]['size'] = $structure->parts[$i]->bytes;
                    $attachments[$n]['cid'] = ($structure->parts[$i]->ifid) ? str_replace(array('<', '>'), '', $structure->parts[$i]->id) : 0;                        
                }
                $email['attachments'][] = $attachments[$n];$n++;
            }
        }            
    }
public function filterFileName($fileName) {
    $newstr = preg_replace('/[^a-zA-Z0-9\-\.\']/', '_', $fileName[0]);
    $fileName = str_replace("'", '', $newstr);
    return $fileName;       
}

之后,您必须存储此附件