SQLの窓

2018年02月27日


Windows PHP(Pear)で、Gmail(SSL/465)を使ってメールを送る

2018/02/27 : PMailServer Version 1.91 フリー版 で送信テストをしました。
host : 192.168.1.16, port : 25

関連する記事

PMailServer Version 1.91 フリー版 を Windows10 にインストールして、Windows7 の PHP よりアクセス

Pear の Net_POP3 で、SSL(995) を使って簡単にメール受信
※ 重要 アプリが正しくても、サーバーでログインを拒否されている場合があります。実際問題、WEBブラウザでログインしに行くと、難読文字画像で認証をされられた事が Hotmail ではありました。Google でも同様の事があると他の記事で読んだ事があるので注意して下さい。 Gmail 側で安全性の低いアプリの許可を『有効』にする必要がありました。 Pear なんで、WEBサーバー(Unix等)でも動くと思いますが、その場合はWEBサーバ用のメールアドレスで sendmail が使えると思います。なので、わざわざ Pear を使う必要は無いですが、フリーの WEBサーバだと、sendmail は使え無いのでその時は試してみる価値はあります。 Windows でPHPからメールを送信するには Pear が必要です。( もう一つの選択肢として、CDO.Message を使う事もできます ) あるいは、fake sendmail for windows を使用できます (1) php.ini の OpenSSL を有効にする
extension=php_openssl.dll
(2) php.ini の error_reporting に STRICT エラー用の設定を行う
error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT
※ ソースで error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT); でも可 (3) Pear の関係ファイルをダウンロード Pear
PEAR.php だけでいいです
Mail
Mail フォルダと、Mail.php
Net_SMTP
SMTP.php ( Net ディレクトリ内 )
Net_Socket
Socket.php ( Net ディレクトリ内 )
Net_SMTP の中に以下のようなコメントがあります
     * If you have SSL support in PHP, you can connect to a server
     * over SSL using an 'ssl://' prefix:
     *
     *   // 465 is a common smtps port.
     *   $smtp = new Net_SMTP('ssl://mail.host.com', 465);
     *   $smtp->connect();
send_test.php(UTF-8N で保存)
<?php
error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT);

header( "Content-Type: text/html; Charset=utf-8" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

require_once("Mail.php");

mb_language("ja");
mb_internal_encoding("UTF-8");

// ***********************************************
// 通信のデバッグ表示
// ***********************************************
$debug = true;

// ***********************************************
// SMTP 接続設定
// ***********************************************
$settings = array(
	"host"		=> "ssl://smtp.gmail.com",
	"port"		=> "465",
	"auth"		=> true,
	"username"	=> "ユーザ名@gmail.com",
	"password"	=> "パスワード",
	"debug"		=> $debug
);

// ***********************************************
// メールアドレス
// ***********************************************
$to_address = "宛先メールアドレス";
$from_address = "ユーザ名@gmail.com";

// ***********************************************
// メールヘッダー
// ***********************************************
$subject = "Gmail(SSL/465)を使ってPHPでメールを送る";
$subject = mb_convert_encoding($subject,"iso-2022-jp");
$to_header = mb_convert_encoding("宛先","iso-2022-jp");
$from_header = mb_convert_encoding("差出人","iso-2022-jp");

mb_internal_encoding("iso-2022-jp");

$subject = mb_encode_mimeheader( $subject );
$to_header =  mb_encode_mimeheader( $to_header ) . " <{$to_address}>";
$from_header =  mb_encode_mimeheader( $from_header ) . " <{$from_address}>";

mb_internal_encoding("UTF-8");

$headers = array(
	"To"		=> $to_header,
	"From"		=> $from_header,
	"Subject"	=> $subject
);

// ***********************************************
// 本文
// ***********************************************
$body="本文";
$body = mb_convert_encoding($body,"iso-2022-jp");

// ***********************************************
// SMTP 接続設定をオブジェクトに設定
// ***********************************************
$smtp = Mail::factory("smtp", $settings);

// ***********************************************
// 送信
// ***********************************************
print "<pre>"; 
$result = $smtp->send(
	$to_address,
	$headers,
	$body );
print "</pre>"; 

if ( PEAR::isError($result) ) {
	print "メール送信エラー:" . $result->getMessage();
}

?>
OK

※ Debug フラグを true にしているので、トレースが出力されます

▼ 以下は関数にしたものです
// ***********************************************
// メール送信
// ***********************************************
function send_mail($user,$to,$pass,$message,$subject) {

	global $ErrorMessage;

	error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT);

	// この場合は実行する PHP と同じフォルダに Mail.php があるという前提です
	// それ以外の場合は、
	// set_include_path( get_include_path() . PATH_SEPARATOR . "Mail.phpのあるフォルダ" );
	// を実行します
	require_once("Mail.php");

	mb_language("ja");
	mb_internal_encoding("UTF-8");
	
	// ***********************************************
	// 通信のデバッグ表示
	// ***********************************************
	$debug = false;
	
	// ***********************************************
	// SMTP 接続設定
	// ***********************************************
	$settings = array(
		"host"		=> "ssl://smtp.gmail.com",
		"port"		=> "465",
		"auth"		=> true,
		"username"	=> $user,
		"password"	=> $pass,
		"debug"		=> $debug
	);
	
	// ***********************************************
	// メールアドレス
	// ***********************************************
	$to_address = $to;
	$from_address = $user;
	
	// ***********************************************
	// メールヘッダー
	// ***********************************************
	$subject = mb_encode_mimeheader( mb_convert_encoding($subject,"iso-2022-jp") );
	
	$to_header =  mb_encode_mimeheader( mb_convert_encoding("宛先","iso-2022-jp") ) . " <{$to_address}>";
	$from_header =  mb_encode_mimeheader( mb_convert_encoding("差出人","iso-2022-jp") ) . " <{$from_address}>";
	
	$headers = array(
		"To"		=> $to_header,
		"From"		=> $from_header,
		"Subject"	=> $subject
	);
	
	// ***********************************************
	// 本文
	// ***********************************************
	$body=$message;
	$body = mb_convert_encoding($body,"iso-2022-jp");
	
	// ***********************************************
	// SMTP 接続設定をオブジェクトに設定
	// ***********************************************
	$smtp = Mail::factory("smtp", $settings);
	
	// ***********************************************
	// 送信
	// ***********************************************
	print "<pre>"; 
	$result = $smtp->send(
		$to_address,
		$headers,
		$body );
	print "</pre>"; 
	
	if ( PEAR::isError($result) ) {
		// print "メール送信エラー:" . $result->getMessage();
		$ErrorMessage = "メール送信エラー:" . $result->getMessage();
	}

	

}
PMailServer Version 1.91 フリー版 でのログ
DEBUG: Recv: 220 PMailServer Version 1.91 �t���[�� ESMTP PMailServer [Free Edition] 1.91; Tue, 27 Feb 2018 17:36:11 
DEBUG: Send: EHLO localhost

DEBUG: Recv: 250-ENHANCEDSTATUSCODES
DEBUG: Recv: 250-PIPELINING
DEBUG: Recv: 250-8BITMIME
DEBUG: Recv: 250-AUTH PLAIN LOGIN CRAM-MD5
DEBUG: Recv: 250-AUTH=PLAIN LOGIN CRAM-MD5
DEBUG: Recv: 250-HELP
DEBUG: Recv: 250 OK
DEBUG: Send: AUTH LOGIN

DEBUG: Recv: 334 VXNlcm5hbWU6
DEBUG: Send: bGlnaHRib3g=

DEBUG: Recv: 334 UGFzc3dvcmQ6
DEBUG: Send: cGFzc3dvcmQ=

DEBUG: Recv: 235 2.0.0 Authentication success.
DEBUG: Send: MAIL FROM:

DEBUG: Recv: 250 2.1.0 ... Sender ok
DEBUG: Send: RCPT TO:

DEBUG: Recv: 250 2.1.5 ... Recipient ok
DEBUG: Send: DATA

DEBUG: Recv: 354 Enter mail, end with "." on a line by itself (1)
DEBUG: Send: To: =?ISO-2022-JP?B?GyRCMDhAaBsoQg==?= 
From: =?ISO-2022-JP?B?GyRCOjk9UD9NGyhC?= 
Subject: PMailServer Version 1.91 =?ISO-2022-JP?B?GyRCJVUlaiE8SEcbKEIgGyRCJEsbKEIg?=
 =?ISO-2022-JP?B?UEhQIBskQiRHQXc/LhsoQg==?=


DEBUG: Send: $BK\J8(B
DEBUG: Send: 
.

DEBUG: Recv: 250 2.0.0 yx1S2MGvv2CB7brTdl1Af5fC40k03OJg Message accepted for delivery
DEBUG: Send: QUIT

DEBUG: Recv: 221 2.0.0 PMailServer Version 1.91 �t���[�� closing connection
OK
※ 化けてるのは、PMailServer の登録時に サーバー名に日本語を使用したからです。
posted by lightbox at 2018-02-27 17:57 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

2018年02月22日


Pear の Net_POP3 で、SSL(995) を使って簡単にメール受信

2018/02/21 : PMail Server フリー版を別PCにインストールして受信テストをしてみました。(メ−ルサーバは IP で指定[$ret = $pop3->connect("192.168.10.240",110 )] / "USER" または "APOP" )

( PMail Server フリー版で適当なドメインでテストしているので、外部に対して処理はできません。ローカルネットワークのテスト用です )
2018/02/22 : 久しぶりに Yahoo メールで実行して受信できました。Gmail 受信を確認しましたが、とてもいろいろセキュリティの壁を超えるのが面倒なので使用しないほうがいいと思います。(ローカルで実行したら、socket の connect すらできませんでした / インターネットから接続しようとしたら、『あなたのパスワードを使ってアカウントにログインしようとした人がいます。Google でブロックしましたが、状況をご確認ください。』と言われました)
※ 送信は Windows PHP(Pear)で、Gmail(SSL/465)を使ってメールを送る 後述のサンプルコードでは、ヘッダの一部を取得していますが、本文も取得できます。 ▼ PMail Server フリー版の結果 削除は telnet を使用して以下のように実行するか、$pop3->deleteMsg(番号)を実行します。
>telnet 192.168.1.16 110

USER lightbox
+OK Password required for lightbox.
PASS password
+OK lightbox has 4 visible message (0 hidden) in 2806 octets.
DELE 1
+OK Message 1 has been deleted.
QUIT
+OK Pop server at PMailServer Version 1.91 フリー版 signing off.
ダウンロード Net_POP3 ドキュメント ファイルとしては、Net_Socket も必要で、Pear.php が必要です。また、 OpenSSL を有効にして、error_reporting に STRICT エラー用の設定を行う必要があるかもしれません ▼ Net フォルダ内 関連する記事 Windows PHP(Pear)で、Gmail(SSL/465)を使ってメールを送る ▼ テストは Yahoo メールで行いました。
<?php
header( "Content-Type: text/plain; charset=utf-8" );
header( "Expires: Thu, 19 Nov 1981 08:52:00 GMT" );
header( "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" );
header( "Pragma: no-cache" );

// PEAR( Pear.php が必要 )
require_once('Net/POP3.php');

// 漢字変換用( 内部コード設定 );
mb_language( "ja" );
mb_internal_encoding("utf-8");

// インスタンス作成
$pop3 = new Net_POP3();

// 接続( Yahoo! メールの場合 )
$ret = $pop3->connect ("ssl://pop.mail.yahoo.co.jp", 995 );
if ( $ret === true ) {
	print "接続OK\n";
}
else {
	print "接続できませんでした";
	exit();
}

// ログイン
// Yahoo では、アカウントは @ の前の文字列です
// PMail Server(フリー版) で第三引数に "USER" または "APOP" を指定しています
$ret = $pop3->login( "アカウント", "パスワード", true );
if ( $ret === true ) {
	print "ログインOK\n";
}
else {
	print "ログインできませんでした";
	exit();
}

// メッセージの総件数
$numMsg = $pop3->numMsg();
print "メッセージ件数:$numMsg\n";

// メッセージの総サイズ
$ret = $pop3->getSize();
print "メールボックスのサイズ:$ret\n";

// 欲しい件数
$request_cnt = 10;

// メッセージの一覧
for ( $i = $numMsg; $i > $numMsg - $request_cnt ; $i-- ) {

	if ( $i < 1 ) {
		break;
	}

	print "----------------------------------------------\n";
	$target = $pop3->getListing($i);

	// ヘッダ情報の表示
	$ret2 = $pop3->getParsedHeaders( $i );
	$target[] = array();
	foreach( $ret2 as $key => $value ) {
		if ( $key == "Subject" ) {
			$target[$key] =  mb_decode_mimeheader($value);
		}
		if ( $key == "From" ) {
			$target[$key] =  mb_decode_mimeheader($value);
		}
		if ( $key == "To" ) {
			$target[$key] =  mb_decode_mimeheader($value);
		}
	}

	print "番号:" . $i ."\n";
	print "件名:" . $target['Subject'] ."\n";
	print "差出人:" . $target['From'] ."\n";
	print "宛先:" . $target['To'] ."\n";
	print "サイズ:" . $target['size'] ."\n";

//	print_r($target);

//	# 本文の表示
//	$ret2 = $pop3->getBody( $i );
//	print $ret2 . "\n";

}

// 接続解除
$pop3->disconnect();

?>



ここで使っていない機能

Net_POP3 の冒頭で、@include_once 'Auth/SASL.php'; を実行していますがここでは使用していません。
   /**
    * Constructor. Sets up the object variables, and instantiates
    * the socket object.
    *
    */
    function Net_POP3()
    {
        $this->_timestamp =  ''; // Used for APOP
        $this->_maildrop  =  array();
        $this->_timeout   =  3;
        $this->_state     =  NET_POP3_STATE_DISCONNECTED;
        $this->_socket    = new Net_Socket();
        /*
        * Include the Auth_SASL package.  If the package is not available,
        * we disable the authentication methods that depend upon it.
        */
        @include_once 'Auth/SASL.php';
        if (!class_exists('Auth_SASL')) {
            if ($this->_debug){
                echo "AUTH_SASL NOT PRESENT!\n";
            }
            foreach ($this->supportedSASLAuthMethods as $SASLMethod) {
                $pos = array_search($SASLMethod, $this->supportedAuthMethods);
                if ($this->_debug) {
                    echo "DISABLING METHOD $SASLMethod\n";
                }
                unset($this->supportedAuthMethods[$pos]);
            }
        }
    }



posted by lightbox at 2018-02-22 23:43 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

2018年02月17日


PHP : WEB でもコマンドラインでも HTTP でファイルをダウンロードする 『fget.php』

fopen wrappers が有効の場合、WEB 上で配置するとそのサーバー以外の別のサーバにあるファイルを http 経由でいったん読み込んでからクライアントへ送ります。その際、ファイルサイズが必要になるので、readfile に先立って、cURL で、ファイルサイズだけを取得しています。

readfile は、このような処理に使う為の関数ですが、標準出力へ内容を出力するので、コマンドプロンプトで使う場合は、ファイルへリダイレクトする必要があります。なので、ここでは通常のファイル処理としてファイルを書き込んでいます。

fget.php
<?php
// **************************************************
// 【fget.php】
// http:// で他のサーバのファイルを読み込んでダウンロードします
// 【利用方法】
// WEB : fget.php?target=URLエンコードされたURL
// CMD : php.exe fget.php URL
// **************************************************

// **************************************************
// コマンドラインでも使えるように
// **************************************************
if (substr(php_sapi_name(), 0, 3) == 'cgi') {
	$remoteFile = $_GET['target'];
}
else {
	$remoteFile = $argv[1];
}
$fileName = basename($remoteFile);

// **************************************************
// PHP オンラインマニュアルの投稿データより
// **************************************************
$ch = curl_init($remoteFile);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
if ( substr( $remoteFile, 0, 5 ) == "https" ) {
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
}
$data = curl_exec($ch);
curl_close($ch);
if ($data === false) {
	echo 'cURL failed';
	exit;
}

$contentLength = 'unknown';
$status = 'unknown';
if (preg_match('/^HTTP\/1\.[01] (\d\d\d)/', $data, $matches)) {
	$status = (int)$matches[1];
}
if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
	$contentLength = (int)$matches[1];
}

// **************************************************
// WEB 経由ダウンロード
// **************************************************
if (substr(php_sapi_name(), 0, 3) == 'cgi') {
	header( "Content-Type: application/octet-stream" );
	header( "Content-disposition: attachment; filename={$fileName}" );

	$path = $remoteFile;

	header( "Content-Length: $contentLength" );

	readfile($path);

	exit();
}
// **************************************************
// Windows コマンドライン
// Windows では、fopen()の mode パラメータに 'b' を
// 指定してファイルをオープンする必要があります。
// **************************************************
else {
	$ihandle = fopen($remoteFile, "rb");
	$ohandle = fopen($fileName, "wb");
	if ( $ihandle ) {

		while( !feof($ihandle) ) {
			$ret = fread( $ihandle, 1024 );
			fwrite( $ohandle,  $ret );
		}

		fclose( $ohandle );
		fclose( $ihandle );
	}

	exit();
}

?>


関連する情報

PHP fread

fread の第二引数は、読み込む最大バイトなので、EOF に達すると、それ以内のデータが取得されます。

PHP fwrite

大きなファイルですと、問題が出るという報告もあるので、その場合は以下のように readfile を書き換えるといいかもしれません。
Streaming a large file using PHP

Problem with download of larger files





posted by lightbox at 2018-02-17 16:00 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり