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);
/*
        }
*/
    }
  













   SQLの窓    create:2006/12/01  update:2018/02/23   管理者用(要ログイン)





フリーフォントツール

SQLの窓ツール

SQLの窓フリーソフト

写真素材

一般ツールリンク

SQLの窓

フリーソフト

JSライブラリ