PEAR の Mail パッケージによるメール送信


  サンプルコード




以下のソースコードは、Shift_JIS で書かれています

実行テストは、Windows で Pmail Server を使用したこの環境を前提にしています

  

<?php
set_include_path( "C:\php\PEAR" );
include('Mail.php');
include('Mail/mime.php');

# 内部コード指定
mb_language( "ja" );
mb_internal_encoding("UTF-8");

# メール送信環境
$mailServer = "localhost";
$mailPort = 25;
$mailFrom = "lightbox@localhost";
$mailTo = "lightbox@localhost";
$mailUser = "lightbox";
$mailAuth = true;	// true 認証有り、false 認証無し
$mailPass = "password";

print "<PRE>";

# **********************************************************
# 本文( テキスト )
# 30 文字程度で改行を入れて下さい
# **********************************************************
$text = mb_convert_encoding("日本語\n日本語", "JIS", "SJIS" );

# **********************************************************
# 本文( HTML )
# **********************************************************
$html = "<html><body><pre>$text</pre></body></html>";

# **********************************************************
# 添付ファイル( 必要ならば、$file にセットする )
# **********************************************************
#$file = './Book1.xls';
$crlf = "\n";

# **********************************************************
# FROM と TO を設定
# **********************************************************
$from    = mb_convert_encoding( "送信者", "JIS", "SJIS" );
$from    = "=?ISO-2022-JP?B?" . base64_encode($from) . "?= <$mailFrom>";
$to      = mb_convert_encoding( "宛先", "JIS", "SJIS" );
$to      = "=?ISO-2022-JP?B?" . base64_encode($to) . "?= <$mailTo>";

# **********************************************************
# ● 長い件名の処理
# **********************************************************
$subject = "改行する必要のある長い日本語を";
$subject .= "件名にセットしてテストしてみましょう。";
$subject .= "件名に「AあBいC」のように半角が交互に含まれると";
$subject .= "エンコード後の長さが増加するので、";
$subject .= "改行長は短めに設定しています。";

// SJIS として文字数を取得
$len = mb_strlen( $subject, "SJIS" );
// 10 文字以下ならそのまま処理
if ( $len <= 10 ) {
	$subject = mb_convert_encoding( $subject, "JIS", "SJIS" );
	// mime encode
	$sub_str = "=?ISO-2022-JP?B?" . base64_encode($subject) . "?=";
}
// 10 文字以上なら分解して処理
else {
	// 先頭から10文字取得
	$sub_str = mb_substr( $subject, 0, 10, "SJIS" );
	// JIS に変更
	$sub_str = mb_convert_encoding( $sub_str, "JIS", "SJIS" );
	// mime encode
	$sub_str = "=?ISO-2022-JP?B?" . base64_encode($sub_str) . "?=";
	// 次の処理の為に処理済みの文字列を削除
	$sub_work = mb_substr(
		$subject, 10, mb_strlen( $subject,"SJIS" ) - 10, "SJIS" );
	// 処理文字列が存在する間続ける
	while( 1 ) {
		// 改行とスペース
		$sub_str .= "\r\n ";
		// まだ 10 文字より長い場合
		if ( mb_strlen( $sub_work, "SJIS" ) > 10 ) {
			// 先頭から10文字取得
			$sub_left = mb_substr( $sub_work, 0, 10, "SJIS" );
			// JIS に変更
			$sub_left = mb_convert_encoding( $sub_left, "JIS", "SJIS" );
			// mime encode して追加
			$sub_str .=
				"=?ISO-2022-JP?B?" . 
				base64_encode($sub_left) . 
				"?=";
			// 次の処理の為に処理済みの文字列を削除
			$sub_work = mb_substr(
				$sub_work,
				10,
				mb_strlen( $sub_work, "SJIS" ) - 10,
				"SJIS"
			);
		}
		// 10 文字以内の場合
		else {
			// JIS に変更
			$sub_work = mb_convert_encoding( $sub_work, "JIS", "SJIS" );
			// mime encode
			$sub_str .=
				"=?ISO-2022-JP?B?" . 
				base64_encode($sub_work) . 
				"?=";
			// 終了
			break;
		}
	}
}
// 出来上がった文字列を件名として使用する
$subject = $sub_str;

# **********************************************************
# ● 準備された情報を元に、SMTP に渡す MIME 情報を
#    作成する
# **********************************************************
$mime = new Mail_mime($crlf);

# 本文( テキスト )
$mime->setTXTBody($text);
# 本文( HTML )
$mime->setHTMLBody($html);
# 添付ファイル
if ( $file != "" ) {
	$mime->addAttachment($file, 'application/octet-stream');
}
# パーツ別のキャラクタセット指定
$param = 
	array(
		'text_charset' => 'ISO-2022-JP',
		'html_charset' => 'ISO-2022-JP'
	);
# **********************************************************
# ヘッダと本文の作成
# **********************************************************
// ヘッダ情報の整理
$hdrs = 
	array(
		'Date' => date("r"),
		'From'    => $from,
		'To'    => $to,
		'Subject' => $subject
	);

$body = $mime->get( $param );
$hdrs = $mime->headers($hdrs);

# **********************************************************
# SMTP 環境の情報
# **********************************************************
if ( $mailAuth ) {
	$smtp = 
		array(
			'host' => $mailServer,
			'port' => $mailPort,
			'auth' => TRUE,
			'username' => $mailUser,
			'password' => $mailPass,
		);
}
else {
	# 以下は認証なし
	$smtp = 
		array(
			'host' => $mailServer,
			'port' => $mailPort,
			'auth' => FALSE,
			'username' => '',
			'password' => '',
		);
}

# メールオブジェクトを作成
$mail =& Mail::factory('smtp', $smtp );

# **********************************************************
# ● メール送信( ヘッダと本文 を引数として渡す )
# **********************************************************
$ret = $mail->send($mailTo, $hdrs, $body);
if ( $ret !== true ) {
	print $ret->getMessage() . "<br>";
}

print "</PRE>";
?>
Done
  

Mail::factory() の引数によって、sendmail も利用できます
▼ マニュアル
http://pear.php.net/manual/en/package.mail.mail.factory.php

▼ 主なメソッドのマニュアル
http://pear.php.net/manual/en/package.mail.mail-mime.php











  Mail::factory に渡す auth について




以下は、Pear のソースコードのログを取ったものですが、
auth が文字列では無い(true)為、Mail\smtp.php の send メソッドで最初は【送信メソッド】が決定していません。

その後、Net\SMTP.php の auth メソッドが呼ばれ、【送信メソッド】が空なので、_getBestAuthMethodArray
メソッドが呼ばれて、EHLO コマンドで取得済みのデータより、最もセキュリティ性の高いコマンドが選択されます。
( ここでは、CRAM-MD5 )

※ Net\SMTP.php の以下の定義順序で決定される
var $auth_methods = array('DIGEST-MD5', 'CRAM-MD5', 'LOGIN', 'PLAIN');
サーバー側で、DIGEST-MD5 が使用可能な場合 古い Pear だとエラーとなるようなので、
$auth_methods を変更して使用する必要があると思います↓。
var $auth_methods = array('CRAM-MD5', 'LOGIN', 'PLAIN');
最新の Net\SMTP.php では動作確認しました

↓auth に true が設定されている場合のログ
  

●Mail\smtp.php:メソッド決定1:
●Net\SMTP.php:_getBestAuthMethodArray
(
    [ENHANCEDSTATUSCODES] => 
    [PIPELINING] => 
    [8BITMIME] => 
    [AUTH] => PLAIN LOGIN CRAM-MD5
    [AUTH=PLAIN] => LOGIN CRAM-MD5
    [HELP] => 
    [OK] => 
)
●Net\SMTP.php:メソッド決定2:CRAM-MD5
  

よって、auth にセットしておけば、そのメカニズム( CRAM-MD5 等 ) でログイン処理を行えます

  

$smtp = 
	array(
		'host' => $mailServer,
		'port' => $mailPort,
		'auth' => 'CRAM-MD5',
		'username' => $mailUser,
		'password' => $mailPass,
	);
  

↓CRAM-MD5 指定後のログ
  

●Mail\smtp.php:メソッド決定1:CRAM-MD5
●Net\SMTP.php:メソッド決定2:CRAM-MD5
  

  CC、BCC について

PEAR のメール送信は、SMTP プロトコルに沿って作成されているので、
実際にメールを送信するには、RCPT TO コマンドを複数指定する必要があり、

$ret = $mail->send($mailTo, $hdrs, $body);
では、$mailTo で指定する事になります。

$mailTo は、", " で区切られたメールアドレスリストまたは、配列を指定する必要があります。
但し、通常の CC で同等のメールヘッダになるように送信するには、$mailTo は、配列で指定し、
その上で、先頭にメインの送信先を指定します。

また、$mailTo に指定してメールを送信する事と、ヘッダーに Cc: を書き込む事はプログラマ
が自分で行う必要があります。つまり、ヘッダーに何も書き込まなければ Bcc になります

  

# **********************************************************
# ● メール送信( ヘッダと本文 を引数として渡す )
# **********************************************************
$mailTo = array($mailTo);
$mailTo[] = 'cc1@mydomain.com';
$mailTo[] = 'cc2@mydomain.com';

$hdrs['Cc'] = 'cc1@mydomain.com';
$hdrs['Cc'] .= ', cc2@mydomain.com';

$ret = $mail->send($mailTo, $hdrs, $body);
if ( $ret !== true ) {
	print $ret->getMessage() . "<br>";
}
  

  実装する場合のコード

結局関数にして、別ファイルにして Pear のファイルを配置して、OS を考慮して実装する必要があります

配置した pear のサンプルのダウンロード
( 実行コードは以下より作成して下さい )

pear_send_mail の呼び出し
  

<?
header( "Content-Type: text/html; Charset=SHIFT_JIS" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );

$sep = substr( strtoupper( php_uname("s") ), 0, 7 ) == 'WINDOWS' ? ";" : ":";
set_include_path( ".$sep../PEAR" );

include('pear_send_mail.php');

# 内部コード指定
mb_language( "ja" );
mb_internal_encoding("UTF-8");

$cc = array();
$cc[] = 'cc1@mydomain.jp';
$cc[] = 'cc2@mydomain.jp';
$bcc = array();
$bcc[] = 'bcc1@mydomain.jp';
$bcc[] = 'bcc2@mydomain.jp';

$ret= pear_send_mail(
	'SJIS'
	,'me@mydomain.jp'
	,'you@yourdomian.jp'
	,'長い日本語の件名を送る為のテストです'
	,'先日はどうもありがとうございました。
おかげさまで、家族一同大変感謝しております。
つきましては、近いうちにお礼にお伺い致したく思っておりますので、
ご都合の良い日時を教えて頂けないでしょうか。

ご返事をお待ちしております。'
	,"大杉 次郎様"
	,"山田 太郎"
	,$cc
	,$bcc
	,"./test.xls"
);

if ( $ret !== true ) {
	print $ret->getMessage() . "<br>";
}

?>
処理終了。
  

pear_send_mail.php
  

<?
include('Mail.php');
include('Mail/mime.php');

$mailer = 'pear_send_mail';

# メール送信環境
$mailServer = "localhost";
$mailPort = 25;
$mailUser = "lightbox";
$mailPass = "password";

function pear_send_mail(
	$cs
	,$mailTo
	,$mailFrom
	,$subject
	,$body
	,$to=""
	,$from=""
	,$cc=""
	,$bcc=""
	,$file=""
)
{
	$crlf = "\n";

	# **********************************************************
	# 本文( テキスト )
	# 30 文字程度で改行を入れて下さい
	# **********************************************************
	$text = mb_convert_encoding($body, "JIS", $cs );
	
	# **********************************************************
	# FROM と TO を設定
	# **********************************************************
	if ( $from == "" ) {
		$from = "<$mailFrom>";
	}
	else {
		$from = mb_convert_encoding( $from, "JIS", $cs );
		$from = "=?ISO-2022-JP?B?" . base64_encode($from) . "?= <$mailFrom>";
	}
	if ( $to == "" ) {
		$to = "<$mailTo>";
	}
	else {
		$to = mb_convert_encoding( $to, "JIS", $cs );
		$to = "=?ISO-2022-JP?B?" . base64_encode($to) . "?= <$mailTo>";
	}
	
	# **********************************************************
	# ● 長い件名の処理
	# **********************************************************
	// SJIS として文字数を取得
	$len = mb_strlen( $subject, $cs );
	// 10 文字以下ならそのまま処理
	if ( $len <= 10 ) {
		$subject = mb_convert_encoding( $subject, "JIS", $cs );
		// mime encode
		$sub_str = "=?ISO-2022-JP?B?" . base64_encode($subject) . "?=";
	}
	// 10 文字以上なら分解して処理
	else {
		// 先頭から10文字取得
		$sub_str = mb_substr( $subject, 0, 10, $cs );
		// JIS に変更
		$sub_str = mb_convert_encoding( $sub_str, "JIS", $cs );
		// mime encode
		$sub_str = "=?ISO-2022-JP?B?" . base64_encode($sub_str) . "?=";
		// 次の処理の為に処理済みの文字列を削除
		$sub_work = mb_substr(
			$subject, 10, mb_strlen( $subject,$cs ) - 10, $cs );
		// 処理文字列が存在する間続ける
		while( 1 ) {
			// 改行とスペース
			$sub_str .= "\r\n ";
			// まだ 10 文字より長い場合
			if ( mb_strlen( $sub_work, $cs ) > 10 ) {
				// 先頭から10文字取得
				$sub_left = mb_substr( $sub_work, 0, 10, $cs );
				// JIS に変更
				$sub_left = mb_convert_encoding( $sub_left, "JIS", $cs );
				// mime encode して追加
				$sub_str .=
					"=?ISO-2022-JP?B?" . 
					base64_encode($sub_left) . 
					"?=";
				// 次の処理の為に処理済みの文字列を削除
				$sub_work = mb_substr(
					$sub_work,
					10,
					mb_strlen( $sub_work, $cs ) - 10,
					$cs
				);
			}
			// 10 文字以内の場合
			else {
				// JIS に変更
				$sub_work = mb_convert_encoding( $sub_work, "JIS", $cs );
				// mime encode
				$sub_str .=
					"=?ISO-2022-JP?B?" . 
					base64_encode($sub_work) . 
					"?=";
				// 終了
				break;
			}
		}
	}
	// 出来上がった文字列を件名として使用する
	$subject = $sub_str;
	
	# **********************************************************
	# ● 準備された情報を元に、SMTP に渡す MIME 情報を
	#    作成する
	# **********************************************************
	$mime = new Mail_mime($crlf);
	
	# 本文( テキスト )
	$mime->setTXTBody($text);
	# 添付ファイル
	if ( $file != "" ) {
		$mime->addAttachment($file, 'application/octet-stream');
	}
	# パーツ別のキャラクタセット指定
	$param = 
		array(
			'text_charset' => 'ISO-2022-JP'
		);
	# **********************************************************
	# ヘッダと本文の作成
	# **********************************************************
	// ヘッダ情報の整理
	$hdrs = 
		array(
			'Date' => date("r"),
			'From'    => $from,
			'To'    => $to,
			'Subject' => $subject,
			'X-Mailer'=> $GLOBALS['mailer']
		);
	
	$body = $mime->get( $param );
	$hdrs = $mime->headers($hdrs);
	
	# **********************************************************
	# SMTP 環境の情報
	# **********************************************************
	$smtp = 
		array(
			'host' => $GLOBALS['mailServer'],
			'port' => $GLOBALS['mailPort'],
			'auth' => true,
			'username' => $GLOBALS['mailUser'],
			'password' => $GLOBALS['mailPass'],
		);
	
	# メールオブジェクトを作成
	$mail =& Mail::factory('smtp', $smtp );
	
	# **********************************************************
	# ● メール送信( ヘッダと本文 を引数として渡す )
	# **********************************************************
	if ( is_array( $cc ) ) {
		$hdrs['Cc'] = '';
		$mailTo = array($mailTo);
		foreach ($cc as $value) {
			$mailTo[] = $value;
			if ( $hdrs['Cc'] != '' ) {
				$hdrs['Cc'] .= ', ';
			}
			$hdrs['Cc'] .= $value;
		}
	}
	if ( is_array( $bcc ) ) {
		if ( !is_array( $mailTo ) ) {
			$mailTo = array($mailTo);
		}
		foreach ($bcc as $value) {
			$mailTo[] = $value;
		}
	}
	$ret = $mail->send($mailTo, $hdrs, $body);
	return $ret;
}
?>
  

  land.to でテスト

DigestMD5.php で警告が出力されたので、問題部分をコメントにしましたが、
ちゃんと動いているようです。

( ※ sakura のメールアドレスとサーバを使って、ポートは 587 でテストしています )

  

    /**
    * Creates the client nonce for the response
    *
    * @return string  The cnonce value
    * @access private
    */
    function _getCnonce()
    {
/*
        if (file_exists('/dev/urandom') && $fd = @fopen('/dev/urandom', 'r')) {
            return base64_encode(fread($fd, 32));

        } elseif (file_exists('/dev/random') && $fd = @fopen('/dev/random', 'r')) {
            return base64_encode(fread($fd, 32));

        } else {
*/
            $str = '';
            mt_srand((double)microtime()*10000000);
            for ($i=0; $i<32; $i++) {
                $str .= chr(mt_rand(0, 255));
            }
            
            return base64_encode($str);
/*
        }
*/
    }
  




yahoo  google  MSDN  MSDN(us)  WinFAQ  Win Howto  tohoho  ie_DHTML  vector  wdic  辞書  天気 


[phpVarious]
CCBot/2.0 (https://commoncrawl.org/faq/)
24/12/09 05:49:23
InfoBoard Version 1.00 : Language=Perl

1 BatchHelper COMprog CommonSpec Cprog CprogBase CprogSAMPLE CprogSTD CprogSTD2 CprogWinsock Cygwin GameScript HTML HTMLcss InstallShield InstallShieldFunc JScript JScriptSAMPLE Jsfuncs LLINK OldProg OracleGold OracleSilver PRO PRObrowser PROc PROconePOINT PROcontrol PROftpclient PROjscript PROmailer PROperl PROperlCHAT PROphp PROphpLesson PROphpLesson2 PROphpLesson3 PROphpfunction PROphpfunctionArray PROphpfunctionMisc PROphpfunctionString PROsql PROvb PROvbFunction PROvbString PROvbdbmtn PROvbonepoint PROwebapp PROwin1POINT PROwinSYSTEM PROwinYOROZU PROwindows ProjectBoard RealPHP ScriptAPP ScriptMaster VBRealtime Vsfuncs a1root access accreq adsi ajax amazon argus asp aspSample aspVarious aspdotnet aw2kinst cappvariety centura ckeyword classStyle cmaterial cmbin cmdbapp cmenum cmlang cmlistbox cmstd cmstdseed cmtxt cs daz3d db dbCommon dbaccess dnettool dos download flex2 flex3 flex4 framemtn framereq freeWorld freesoft gimp ginpro giodownload google hdml home hta htmlDom ie9svg install java javaSwing javascript jetsql jquery jsp jspTest jspVarious lightbox listasp listmsapi listmsie listmsiis listmsnt listmspatch listmsscript listmsvb listmsvc memo ms msde mysql netbeans oraPlsql oracle oracleWiper oraclehelper orafunc other panoramio pear perl personal pgdojo pgdojo_cal pgdojo_holiday pgdojo_idx pgdojo_ref pgdojo_req php phpVarious phpguide plsql postgres ps r205 realC realwebapp regex rgaki ruby rule sboard sc scprint scquest sdb sdbquest seesaa setup sh_Imagick sh_canvas sh_dotnet sh_google sh_tool sh_web shadowbox shgm shjquery shvbs shweb sjscript skadai skywalker smalltech sperl sqlq src systemdoc tcpip tegaki three toolbox twitter typeface usb useXML vb vbdb vbsfunc vbsguide vbsrc vpc wcsignup webanymind webappgen webclass webparts webtool webwsh win8 winofsql wmi work wp youtube