[PHP-users 33326] MIME decodeについて

有)アムス work @ asiams.com
2008年 2月 25日 (月) 16:04:14 JST


こんにちは!

現在メールからサポートチケットに投稿する内容を利用しています。

ところが、日本語のメール名がついていると投稿者メールアドレスが、@しか表
示されないのです。

例えば、佐藤聡<ams @ asiams.com> から support @ andvision.net へ送信する
と、PIPEされて新規投稿する様になっています。しかし、その結果Subjectと本
文は、文字化けしないで正しく表示されます。送信者(投稿者)名は、表示され
ません。また、送信者メールアドレスが@だけに表示されます。

思われるコードは、functions_mime.phpの以下のあたりではないかと思われます。

$output->fromEmail = sprintf('%s@%s', $from[0]->mailbox, $from[0]->host);
			
			$output->fromName  = preg_replace('/^"(.*)"$/u', '$1',
$from[0]->personal);

以下にこのFunctionを追加します。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

	/**
	* Decodes a mail and returns the various parts.
	* Original Function by Richard Heyes, Modified to fix some bugs
	*/
	function decodeMail($input)
	{
		global $decodeMail_output, $_SWIFT, $charset;

		// Declare the additional classes
//		parserDebug("MIME: Initiating Classes");
		$Mail_mimeDecode = new Mail_mimeDecode($input, SWIFT_CRLF);
		$Mail_RFC822 = new Mail_RFC822;

		$output = &$decodeMail_output;
//		parserDebug("MIME: Got Output");

		$decode_params['input'] = $input;
		$decode_params['include_bodies'] = true;
		$decode_params['decode_bodies']  = true;
		$decode_params['decode_headers'] = true;
//		parserDebug("MIME: Input Is\n".$input);
//		parserDebug("MIME: Decoding...");
		$structure = $Mail_mimeDecode->decode($decode_params);
//		parserDebug("MIME: Traversing Structure");
		$this->decodeMail_traverseStructure($structure);
		
		// Sizes
		$output->textSize = jstrlen(@$output->text);
		$output->htmlSize = jstrlen(@$output->html);
//		parserDebug("MIME: Text Size: ".$output->textSize.", HTML Size:
".$output->htmlSize);

		// Headers
		$output->headers = $structure->headers;
		//////////////////////////////////////
		// JcodeConvert($string, 1, 2);
		// Above was modified with JcodeConvert.
		///////////////////////////////////////
		
//		parserDebug("MIME: Got Headers");

		$tofix = array("\(", "\)", "\[", "\]", "\{", "\}");
		$fixres = array("(", ")", "[", "]", "{", "}");

		// From name/email
		if (!empty($output->headers['from'])) {
			
			///////////////////////////////////////////////////////////
			
			// $from = $Mail_RFC822->parseAddressList(str_replace($tofix,
$fixres,
mb_convert_encoding(mb_decode_mimeheader(($output->headers['from'])),"UTF-8","AUTO")),
null, null, false);
			
		// This was modified to change the incoming email to right encoding
		///////////////////////////////////////////////////////////////////
			
		$from = $Mail_RFC822->parseAddressList(str_replace($tofix, $fixres,
$output->headers['from']), null, null, false);
		// Above is the original.
			
			$output->fromEmail = sprintf('%s@%s', $from[0]->mailbox, $from[0]->host);
			// $output->fromName  = preg_replace('/^"(.*)"$/', '\1',
$from[0]->personal);
			// Above is the original.
			$output->fromName  = preg_replace('/^"(.*)"$/u', '$1',
$from[0]->personal);
			// Above /u was added to treat them as UTF-8 characters.
			// Changed from \1 to $1
		}
//		parserDebug("MIME: Parsed From");

		// Reply to
		if (!empty($output->headers['reply-to'])) {
			// $replyto = $Mail_RFC822->parseAddressList(str_replace($tofix,
$fixres, $output->headers['reply-to']), null, null, false);
			// Original is above.
			
			$replyto = $Mail_RFC822->parseAddressList(str_replace($tofix,
$fixres,
mb_convert_encoding(($output->headers['reply-to']),"UTF-8","AUTO")),
null, null, false);
			// Above was replaced for PIPE issue.
			// 2008.2.8
			////////////////////////////////////////
			
			$output->replytoEmail = sprintf('%s@%s', $replyto[0]->mailbox,
$replyto[0]->host);
			$output->replytoName = preg_replace('/^"(.*)"$/u', '$1',
$replyto[0]->personal);
			// Above /u was added to treat them as UTF-8 characters.
			// \1 was changed to $1.
		}
//		parserDebug("MIME: Parsed Reply To");

		// To name/email
		if (!empty($output->headers['to'])) {
			
			$to = $Mail_RFC822->parseAddressList(str_replace($tofix, $fixres,
mb_convert_encoding(mb_decode_mimeheader(($output->headers['to'])),"UTF-8","AUTO")),
null, null, false);
			
			// Above was replaced to properly encode the incoming email.
			////////////////////////////////////////////////////////////
			
			// $to = $Mail_RFC822->parseAddressList(str_replace($tofix, $fixres,
$output->headers['to']), null, null, false);
			
			// Above was replaced with one above.
			////////////////////////////////////////////
			
			// $to = $Mail_RFC822->parseAddressList(str_replace($tofix, $fixres,
mb_convert_encoding($output->headers['to'],"UTF-8","AUTO")), null, null,
false);
			// Now without mb_decode_mimeheader.
			// 2008.2.8
			/////////////////////////////////////////
			
			
			
			if (is_array($output->headers['to'])) {
				$output->toEmail = $output->headers['to'][0];
			} else {
				
				///////////////////////////////////////////////////
				$output->toEmail = sprintf('%s@%s', $to[0]->mailbox, $to[0]->host);
				// %s@%s? What did do?
				///////////////////////////////// This may have some clue
				//////////////////////////////////////////////////////////
				
			}
			$output->toName = preg_replace('/^"(.*)"$/u', '$1', $to[0]->personal);
			// Above /u was added to treat them as UTF-8 characters.
			// \1 was changed to $1
			
			// This has some clue in it.
			// preg_replace can cause the @ email name to be broken.
			// Study: ^ $ は、最初から最後までのことです。
			///////////////////////////////////////////////////////////////
			///////////////////////////////// Potential changes are needed here.
			//////////////////////////////////////////////////////////////////
			
		}
//		parserDebug("MIME: Parsed To");

		// In-Reply-To
		if (!empty($output->headers['in-reply-to'])) {
			// $inreplyto = $Mail_RFC822->parseAddressList(str_replace($tofix,
$fixres, $output->headers['in-reply-to']), null, null, false);
			// Above was the original.
			/////////////////////////////////////////////////////
			
			$inreplyto = $Mail_RFC822->parseAddressList(str_replace($tofix,
$fixres,
mb_convert_encoding(mb_decode_mimeheader(($output->headers['in-reply-to'])),"UTF-8","AUTO")),
null, null, false);
			//////////////////////////////////////////////////////
			// Above was replaced.
			/////////////////////////////////////////////////////////
			
			
			$output->inReplyTo = trim($inreplyto[0]->mailbox);
		}
//		parserDebug("MIME: Parsed In-Reply-To");

		// Return address
		if (!empty($output->headers['reply-to'])) {
			$output->returnAddress = $output->headers['reply-to'];
		} elseif (!empty($output->headers['sender'])) {
			$output->returnAddress = $output->headers['sender'];
		} elseif (!empty($output->headers['from'])) {
			$output->returnAddress = $output->headers['from'];
		} elseif (!empty($output->headers['return-path'])) {
			$output->returnAddress = $output->headers['return-path'];
		}
		if (!empty($output->returnAddress)) {
			// $retAddress = $Mail_RFC822->parseAddressList(str_replace($tofix,
$fixres, $output->returnAddress), null, null, false);
			// Above was original.
			/////////////////////////////////////////////
			
			$retAddress = $Mail_RFC822->parseAddressList(str_replace($tofix,
$fixres,
mb_convert_encoding(mb_decode_mimeheader($output->returnAddress),"UTF-8","AUTO")),
null, null, false);
			//////////////////////////////////////////////////////////
			// Above was replaced.
			////////////////////////////////////////////////////////////
			
			
			
			$output->returnAddressEmail = sprintf('%s@%s',
$retAddress[0]->mailbox, $retAddress[0]->host);
			$output->returnAddressName = preg_replace('/^"(.*)"$/u', '$1',
$retAddress[0]->personal);
			// Above /u was added to treat them as UTF-8 characters.
			// \1 was replaced with $1
		}
//		parserDebug("MIME: Calculated the Return Address:
".$output->returnAddress);

		// Recipient addresses
		$shiftcount = 0;
		foreach (array('to', 'cc', 'x-rcpt-to') as $header) {
			if (!empty($output->headers[$header]) &&
!is_array($output->headers['to'])) {
				// $to = $Mail_RFC822->parseAddressList(str_replace($tofix, $fixres,
$output->headers[$header]), null, null, false);
				///////////////////////////////////////
				// Above was original.
				///////////////////////////////////
				
				$to = $Mail_RFC822->parseAddressList(str_replace($tofix, $fixres,
mb_convert_encoding(mb_decode_mimeheader(($output->headers[$header])),"UTF-8","AUTO")),
null, null, false);
				
				$loopcount = count($to);
				if ($loopcount > 10)
				{
					$loopcount = 10;
				}
				for ($i=0; $i<$loopcount; $i++) {
					if ($to[$i]) {
						$recipientemail = sprintf('%s@%s', $to[$i]->mailbox, $to[$i]->host);
						if ($this->isValidEmail($recipientemail))
						{
							$recipients[] = $recipientemail;
						}
					}
				}
			} else {
				// Most probably this email has multiple to's
				if ($this->isValidEmail($output->headers['to'][0]))
				{
					$recipients[] = $output->headers['to'][0];
				}
			}
			$shiftcount++;

			if ($shiftcount > 50)
			{
				break;
			}
		}

		$output->recipientAddresses = $recipients;
		
		// THe following was replaced
		///////////////////////////////////
		
		$output->subject =
mb_convert_encoding(mb_decode_mimeheader(($output->headers["subject"])),"UTF-8","AUTO");
		
		/// Above was represented to all the changings.
		////////////////////////////////
		
		// $output->subject = $output->headers["subject"];
		// Above is the original
		
		

		//$charset = $structure->ctype_parameters['charset'];
		
		// $subjectUtf8 = $output->headers["subject"];
		// Above is the original.
		////////////////////////////////////////////
		
		$subjectUtf8 =
mb_convert_encoding(mb_decode_mimeheader(($output->headers["subject"])),"UTF-8","AUTO");
		
		if ($_SWIFT["settings"]["pr_conversion"] == 1 &&
extension_loaded("mbstring"))
		{
			if (empty($charset))
			{
				$_emailcharset = mb_detect_encoding($output->headers["subject"]);
			} else {
				$_emailcharset = $charset;
			}

			if (!empty($_emailcharset))
			{
				
				/////////////////////////////////////////////
				//// The following was domified for PIPE.
				///////////////////////////////////////////
				
				//
				
				
				//$subjectUtf8 = @mb_convert_encoding($subjectUtf8,
$_SWIFT["language"]["charset"], $_emailcharset);
				//$_fromName = @mb_convert_encoding($output->fromName,
$_SWIFT["language"]["charset"], $_emailcharset);
				//$_replytoName = @mb_convert_encoding($output->replytoName,
$_SWIFT["language"]["charset"], $_emailcharset);
				//$_toName = @mb_convert_encoding($output->toName,
$_SWIFT["language"]["charset"], $_emailcharset);
				
				//////////////
					
					
				
			    $subjectUtf8 = @mb_convert_encoding($subjectUtf8, "UTF-8",
$_emailcharset);
				$_fromName = @mb_convert_encoding($output->fromName, "UTF-8",
$_emailcharset);
				$_replytoName = @mb_convert_encoding($output->replytoName, "UTF-8",
$_emailcharset);
				$_toName = @mb_convert_encoding($output->toName, "UTF-8",
$_emailcharset);
				
				
				
				///////////////////////////////
				///  Above was modified for PIPE test.
				///////////////////////////////////
				
				$output->fromName = iif(empty($_fromName), $output->fromName,
$_fromName);
				

			  	
				$output->replytoName = iif(empty($_replytoName),
$output->replytoName, $_replytoName);
				
				
				
				$output->toName = iif(empty($_toName), $output->toName, $_toName);
				
				if (empty($subjectUtf8))
				{
					$subjectUtf8 = $output->headers["subject"];
					
					
				}
			}

		} else if ($_SWIFT["language"]["charset"] == "UTF-8") {
			if (!extension_loaded('mbstring') && function_exists("utf8_encode")) {
				if (strtolower($charset) != "utf-8") {
					$subjectUtf8 = utf8_encode($subjectUtf8);
					$output->fromName = utf8_encode($output->fromName);
					$output->replytoName = utf8_encode($output->replytoName);
					$output->toName = utf8_encode($output->toName);
				}
			} else if (extension_loaded("mbstring")) {
				$subjectUtf8 = @mb_convert_encoding($subjectUtf8, "UTF-8", $charset);
				$_fromName = @mb_convert_encoding($output->fromName, "UTF-8", $charset);
				$_replytoName = @mb_convert_encoding($output->replytoName, "UTF-8",
$charset);
				$_toName = @mb_convert_encoding($output->toName, "UTF-8", $charset);
				$output->fromName = iif(empty($_fromName), $output->fromName,
$_fromName);
				$output->replytoName = iif(empty($_replytoName),
$output->replytoName, $_replytoName);
				$output->toName = iif(empty($_toName), $output->toName, $_toName);
				if (empty($subjectUtf8))
				{
					$subjectUtf8 = $output->headers["subject"];
					
				
					
				}
			}
		}
		$output->subject = $subjectUtf8;
		// THis was original.
		
		// $output->subject = @mb_convert_encoding($subjectUtf8,"UTF-8","AUTO");
		////////////////////////////////////////////////////////////////////
		/////////////////// Above was changed for test
		
		
//		parserDebug("MIME: Got the Subject: ".$output->subject);

		return $output;
	}


ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

これの日本語対応をしたいと思いますが、どのようにすればよいのか教えて下さ
いますか?

環境:

アパッチバージョン	2.0.63
PHPバージョン	5.2.5
MySQLバージョン	5.0.45-community
基本設計概念	x86_64
操作システム	Linux

mbstring
Multibyte Support 	enabled
Multibyte string engine 	libmbfl
Multibyte (japanese) regex support 	enabled
Multibyte regex (oniguruma) version 	4.4.4
Multibyte regex (oniguruma) backtrack check 	On

mbstring extension makes use of "streamable kanji code filter and
converter", which is distributed under the GNU Lesser General Public
License version 2.1.

Directive	Local Value	Master Value
mbstring.detect_order	no value	no value
mbstring.encoding_translation	Off	Off
mbstring.func_overload	0	0
mbstring.http_input	pass	pass
mbstring.http_output	pass	pass
mbstring.internal_encoding	ISO-8859-1	no value
mbstring.language	neutral	neutral
mbstring.script_encoding	no value	no value
mbstring.strict_detection	Off	Off
mbstring.substitute_character	no value	no value

使用しているファイル:

http://andvision.net/support/include/functions_mime.php
http://andvision.net/support/include/MIME/mimeDecode.php
http://andvision.net/support/include/MIME/RFC822.php

よろしくお願いします。

アブラハム・リー


PHP-users メーリングリストの案内