PHP使用IMAP接收邮件编码问题

本文详细探讨了在PHP中使用IMAP库接收邮件时遇到的编码问题,包括如何正确解析不同字符集的邮件内容,以及解决乱码的常见方法。通过对邮件头和正文的解析,确保从多种编码格式中提取出正确的信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
	 * 解析结构
	* */
	private function getpart($mid,$p,$partno) {
		// $partno = '1', '2', '2.1', '2.1.3', etc for multipart, 0 if simple
		// type :0 文字 text 1 复合 multipart 2 信息 message 3 程序 application 4 声音 audio 5 图形 image 6 影像 video 7 其它 other

		// 判断数据是否为简单结构,返回数据xi
		$data = ($partno)?
		imap_fetchbody($this->marubox,$mid,$partno):  // multipart
		imap_body($this->marubox,$mid);  // simple

		/**
		 *  解码
		 *  0	7bit	ENC7BIT
            1	8bit	ENC8BIT
            2	Binary	ENCBINARY
            3	Base64	ENCBASE64
            4	Quoted-Printable	ENCQUOTEDPRINTABLE
            5	other	ENCOTHER
		 * */ 
		switch ($p->encoding){
			case 0:
				$data = $this->decode7Bit($data);
				break;
			case 1:
				$data = imap_8bit($data);
				break;
			case 2:
				$data = base64_decode(imap_binary($data));
				break;
			case 3:
				$data = base64_decode($data);
				break;
			case 4:
				$data = quoted_printable_decode($data);
				break;
		}

		// 参数数组
		$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;

		// 附件
		if ($params['filename'] || $params['name']) {

			$temp_filename = ($params['filename'])? $params['filename'] : $params['name'];
			$filename = $this->stringDecode($temp_filename);
			
			//更换名字,防止重复
			$temp_name_arr = explode(".", $filename);
			$tn = count($temp_name_arr);
			$new_name = "ycj-".$mid."-".$partno."-".time().".".$temp_name_arr[$tn-1];
			
			$this->attachments[$new_name] = $data;
		}
		
		//当前邮件的编码
		$charset = $params['charset'];
		
		if ($data){
		    
		    $data = iconv($charset, $this->charset, $data);
		    
		    /**
		     *  0	text	TYPETEXT
		     1	multipart	TYPEMULTIPART
		     2	message	TYPEMESSAGE
		     3	application	TYPEAPPLICATION
		     4	audio	TYPEAUDIO
		     5	image	TYPEIMAGE
		     6	video	TYPEVIDEO
		     7	model	TYPEMODEL
		     8	other	TYPEOTHER
		     * */
		    if ($p->type==0 && $data) {
		        
		        //处理格式
		        if (strtolower($p->subtype)=='plain'){
		            $this->plainmsg .= trim($data) ."\n\n";
		        }else{
		            $this->htmlmsg .= $data ."<br><br>";
		        }
		        	
		        	
		    }elseif ($p->type==2 && $data) {
		        	
		        //转码
		        if (isset($params['charset'])&&$params['charset']!='default'&&$params['charset']!=$this->charset) {
		            $data = iconv($params['charset'], $this->charset, $data);
		        }
		        	
		        $this->plainmsg .= $data."\n\n";
		        	
		    }
		    
		}

		if ($p->parts) {
			foreach ($p->parts as $key=>$p2)
				$this->getpart($mid,$p2,$partno.'.'.($key+1));  // 1.2, 1.2.1, etc.
		}
	}
	
	public function decode7Bit($text) {
	    // If there are no spaces on the first line, assume that the body is
	    // actually base64-encoded, and decode it.
	    $lines = explode("\r\n", $text);
	    $first_line_words = explode(' ', $lines[0]);
	    if ($first_line_words[0] == $lines[0]) {
	        $text = base64_decode($text);
	    }
	
	    // Manually convert common encoded characters into their UTF-8 equivalents.
	    $characters = array(
	        '=20' => ' ', // space.
	        '=E2=80=99' => "'", // single quote.
	        '=0A' => "\r\n", // line break.
	        '=A0' => ' ', // non-breaking space.
	        '=C2=A0' => ' ', // non-breaking space.
	        "=\r\n" => '', // joined line.
	        '=\r' => '',
	        '=\n' => '',
	        '=3D' => '=',
	        '=E2=80=A6' => '…', // ellipsis.
	        '=E2=80=A2' => '•', // bullet.
	    );
	
	    // Loop through the encoded characters and replace any that are found.
	    foreach ($characters as $key => $value) {
	        $text = str_replace($key, $value, $text);
	    }
	
	    return $text;
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值