3

我使用目前正在开发项目 xampp 的 codeigniter 和 imap php。由于某种原因,他们嵌入的图像没有显示。

在我的 getBody() 函数中,我有这个回调

$body = preg_replace_callback(
        '/src="cid:(.*)">/Uims',
        function($m) use($email, $uid){
            //split on @
            $parts = explode('@', $m[1]);
            //replace local path with absolute path
            $img = str_replace($parts[0], '', $parts[0]);
            return "src='$img'>";
       },
    $body);

在此处输入图像描述

在此处输入图像描述

我收到错误

在此处输入图像描述

问题:如何确保它为文本/html 正文等获取正确的图像。

<?php

class Email extends MY_Controller {

    private $enc;
    private $host;
    private $user;
    private $pass;
    private $mailbox;
    private $mbox;

    public function __construct() {
        parent::__construct();

        $this->enc = '/imap/ssl/novalidate-cert';
        $this->host = '****';
        $this->user = '****'; // email
        $this->pass = '****'; // Pass

        $this->mailbox = '{' . $this->host . $this->enc . '}';
        $this->mbox = imap_open($this->mailbox, $this->user, $this->pass);
    }

    public function view() {

        $this->data['message'] = $this->getBody($this->uri->segment(4));

        $this->load->view('template/common/header', $this->data);
        $this->load->view('template/common/nav', $this->data);
        $this->load->view('template/mail/view', $this->data);
        $this->load->view('template/common/footer', $this->data);

        imap_close($this->mbox);
    }

    public function getBody($uid) {
        $body = $this->get_part($uid, "TEXT/HTML");
        // if HTML body is empty, try getting text body
        if ($body == "") {
            $body = $this->get_part($uid, "TEXT/PLAIN");
        }

        $email = $this->user;

        //replace cid with full path to image
        $body = preg_replace_callback(
            '/src="cid:(.*)">/Uims',
            function($m) use($email, $uid){
                //split on @
                $parts = explode('@', $m[1]);
                //replace local path with absolute path
                $img = str_replace($parts[0], '', $parts[0]);
                return "src='$img'>";
           },
        $body);

        return trim(utf8_encode(quoted_printable_decode($body)));
    }    

    private function get_part($uid, $mimetype, $structure = false, $partNumber = false) {
        if (!$structure) {
               $structure = imap_fetchstructure($this->mbox, $uid);
        }
        if ($structure) {
            if ($mimetype == $this->get_mime_type($structure)) {
                if (!$partNumber) {
                    $partNumber = 1;
                }
                $text = imap_fetchbody($this->mbox, $uid, $partNumber, FT_PEEK);
                switch ($structure->encoding) {
                    # 7BIT
                    case 0:
                        return imap_qprint($text);
                    # 8BIT
                    case 1:
                        return imap_8bit($text);
                    # BINARY
                    case 2:
                        return imap_binary($text);
                    # BASE64
                    case 3:
                        return imap_base64($text);
                    # QUOTED-PRINTABLE
                    case 4:
                        return quoted_printable_decode($text);
                    # OTHER
                    case 5:
                        return $text;
                    # UNKNOWN
                    default:
                        return $text;
                }
           }
            // multipart
            if ($structure->type == 1) {
                foreach ($structure->parts as $index => $subStruct) {
                    $prefix = "";
                    if ($partNumber) {
                        $prefix = $partNumber . ".";
                    }
                    $data = $this->get_part($uid, $mimetype, $subStruct, $prefix . ($index + 1));
                    if ($data) {
                        return $data;
                    }
                }
            }
        }
        return false;
    }

    private function get_mime_type($structure) {
        $primaryMimetype = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER");
        if ($structure->subtype) {
           return $primaryMimetype[(int)$structure->type] . "/" . $structure->subtype;
        }
        return "TEXT/PLAIN";
    }

}
4

1 回答 1

1

介绍

您正在尝试将电子邮件转换为 HTML 页面。

一封电子邮件有多个部分:

  1. 标头
  2. 基于文本的电子邮件
  3. 基于 HTML 的电子邮件
  4. 附件

在标题中,您将找到Message-ID以及其他相关元数据。

为了将电子邮件转换为网站,您必须向浏览器公开 HTML 和附件。

每个部分都有自己的标题。当您有一个时,url='cid:Whatever'您必须查找电子邮件的哪一部分具有该Content-Id 标头

将电子邮件作为网页提供

您需要找到包含 HTML 正文的电子邮件部分。解析它并替换http://yourhost/{emailId}您已经实现该部分的 CID URL,因此我不会在此处添加如何操作。

替换 HTML 上的 CID URL - 实现

这是一个可能适合您的原型。

$mailHTML="<html>All your long code here</html>";
$mailId="email.eml";
$generatePartURL=function ($messgeId, $cid) {
    return "http://myhost/".$messgeId."/".$cid; //Adapt this url according to your needs
};
$replace=function ($matches) use ($generatePartURL, $mailId) {
    list($uri, $cid) = $matches;
    return $generatePartURL($mailId, $cid);
};
$mailHTML=preg_replace_callback("/cid:([^'\" \]]*)/", $replace, $mailHTML);

按 CID 查找零件

http://yourhost/{emailId}/{cid}

伪代码:

  • 加载电子邮件
  • 按 CID 查找零件
  • 从使用的 Base64 或其他编码解码(检查 Content-Transfer-Encoding 标头)
  • 将文件作为 HTTP 响应提供

哪个部分有我的 CID 图像?

迭代所有电子邮件部分以查找与您的 CID 值匹配的Content-ID 标头。

--_part_boundery_
Content-Type: image/jpeg; name="filename.jpg"
Content-Description: filename.jpg
Content-Disposition: inline; filename="filename.jpg"; size=39619; creation-date="Thu, 28 Dec 2017 10:53:51 GMT"; modification-date="Thu, 28 Dec 2017 10:53:51 GMT"
Content-ID: <YOUR CID WILL BE HERE>
Content-Transfer-Encoding: base64

解码传输编码并将内容作为常规 http 文件提供。

用 PHP 实现的 Webmail

RoundCube 是一个用 PHP 实现的网络邮件,你可以看看他们是如何做到的:https ://github.com/roundcube/roundcubemail/blob/master/program/lib/Roundcube/rcube_washtml.php

注意:我的代码不基于此解决方案。

于 2017-12-31T18:18:07.840 回答