SQLの窓

2018年10月18日


PHP の imap 関数で( Windows ローカル )、Yahoo メールのメールをさくらインターネットのメールへコピーする

imap_append でデータを追加しているので、同じメールでも追加されて増えていきます。

メッセージ作成に時間がかかるので、WEB 上の実行の場合は、タイムアウトに注意する必要があります。

imap_utf8_to_mutf7 は、日本語で作成されたフォルダに対して必要です。
<?php
error_reporting( E_ALL & ~E_NOTICE & ~E_STRICT );
session_cache_limiter('nocache');
session_start();

header( "Access-Control-Allow-Origin: *" );
header( "Content-Type: application/json; charset=utf-8" );

# デバッグログの初期化
file_put_contents("debug.log", "開始\n" );

mb_internal_encoding("UTF-8");

xlog("ログの出力");

# ***************************
# IMAP 接続( 送信元 )
# ***************************
$con = @imap_open("{imap.mail.yahoo.co.jp:993/imap/ssl}INBOX", "アカウント", "パスワード");
if ( $con === FALSE ) {
	print imap_last_error();
	xlog(imap_last_error());
	exit();
}

# ***************************
# IMAP 接続( 送信先 )
# ***************************
$folder = imap_utf8_to_mutf7("個人用");
$con2 = @imap_open("{さくらユーザ.sakura.ne.jp:993/imap/ssl}INBOX.{$folder}", "ユーザ@さくらユーザ.sakura.ne.jp", "パスワード");
if ( $con2 === FALSE ) {
	print imap_last_error();
	xlog(imap_last_error());
	exit();
}

# ***************************
// 現在のメールボックスに関する情報を得る
# ***************************
$mbox_info = imap_mailboxmsginfo( $con );
xlog("\n■■■ \$mbox_info 現在のメールボックスに関する情報 -------");
xlog( print_r( $mbox_info ,true ));

if( $mbox_info->Nmsgs == 0 ) {
	xlog( "メールメッセージがありません" );
	exit();
}

// ***************************
// メッセージ件数
// ***************************
$max = $mbox_info->Nmsgs;
xlog("【メッセージ件数:{$max}】" );

// 一番古いものから 30件
if ( $max > 30 ) {
	$max = 30;
}

// ***************************
// $max 〜 1
// 最新から表示
// ***************************
for( $i = 1; $i <= $max; $i++ ) {

	$header = imap_fetchheader( $con, $i );
	$body = imap_body( $con, $i );
	imap_append( $con2, "{さくらユーザ.sakura.ne.jp:993/imap/ssl}INBOX.{$folder}", $header . "\r\n" . $body );

}

// ***************************
// IMAP 接続解除
// ***************************
imap_close($con2);
imap_close($con);

print json_encode($mbox_info, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );

// ***************************
// ログ出力
// ***************************
function xlog($message) {
	file_put_contents("debug.log", "{$message}\n" , FILE_APPEND );
}
?>





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

PHP の imap 関数( Windows のローカル )で、さくらインターネットのメールボックスの情報を取得する

Sylpheed( Windows メールクライアント ) で、INBOX のフォルダの中にさらにフォルダを作成して読み出しています



<?php
error_reporting( E_ALL & ~E_NOTICE & ~E_STRICT );
session_cache_limiter('nocache');
session_start();

header( "Access-Control-Allow-Origin: *" );
header( "Content-Type: application/json; charset=utf-8" );

# デバッグログの初期化
file_put_contents("debug.log", "開始\n" );

mb_internal_encoding("UTF-8");

xlog("ログの出力");

# ***************************
# IMAP 接続
# ***************************
$con = @imap_open("{さくらサーバ:993/imap/ssl}INBOX", "アカウント", "パスワード");
if ( $con === FALSE ) {
	print imap_last_error();
	xlog(imap_last_error());
	exit();
}

// メールボックスのリストを読み込み、各ボックスに関する詳細な情報を返す
$mbox = imap_getmailboxes( $con, "{さくらサーバ}", "*" );
xlog("\n■■■ \$mbox_info 現在のメールボックスに関する情報 -------");
xlog( print_r( $mbox ,true ));

if( $mbox == FALSE ) {
	xlog( "imap_getmailboxes に失敗しました" );
	exit();
}

# ***************************
# デリミタ取得( サーバ依存 )
# ***************************
$delimiter = $mbox[0]->delimiter;

# ***************************
# フォルダ情報の配列
# ***************************
foreach ($mbox as $obj) {

	// サーバー文字列を削除して
	// 日本語を含むフォルダをデコード
	$obj->name = imap_mutf7_to_utf8( str_replace( "{さくらサーバ}", "", $obj->name ) );

	// . が無い場合は、ルートのメールボックス
	if ( strstr($obj->name,".") !== FALSE ) {

		// フォルダパスの分解
		$data = explode( $delimiter, $obj->name );

		// 先頭はメールボックス
		$mailbox = $data[ 0 ];

		// 先頭より下を再度連結する
		$name = "";
		for( $i = 1; $i < count( $data ); $i++ ) {
			if ( $i > 1 ) {
				$name .= ".";
			}
			$name .= $data[ $i ];
		}

		// フォルダのメールボックス以下の階層
		xlog( $mailbox . " のフォルダ名 : " . $name );

	}

}

// ***************************
// IMAP 接続解除
// ***************************
imap_close($con);

// ***************************
// デバッグ用 JSON出力
// ***************************
print json_encode($mbox, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );

// ***************************
// ログ出力
// ***************************
function xlog($message) {
	file_put_contents("debug.log", "{$message}\n" , FILE_APPEND );
}
?>


JSON の内容
[
    {
        "name": "INBOX.メールアイテム格納用.階層テスト",
        "attributes": 64,
        "delimiter": "."
    },
    {
        "name": "INBOX.メールアイテム格納用",
        "attributes": 32,
        "delimiter": "."
    },
    {
        "name": "INBOX.Drafts",
        "attributes": 64,
        "delimiter": "."
    },
    {
        "name": "INBOX.Trash",
        "attributes": 64,
        "delimiter": "."
    },
    {
        "name": "INBOX.spam",
        "attributes": 64,
        "delimiter": "."
    },
    {
        "name": "INBOX.Sent",
        "attributes": 64,
        "delimiter": "."
    },
    {
        "name": "INBOX.Draft",
        "attributes": 64,
        "delimiter": "."
    },
    {
        "name": "INBOX",
        "attributes": 40,
        "delimiter": "."
    }
]
log の内容
開始
ログの出力

■■■ $mbox_info 現在のメールボックスに関する情報 -------
Array
(
    [0] => stdClass Object
        (
            [name] => {さくらサーバ}INBOX.&MOEw,DDrMKIwpDDGMOBoPH0NdSg-.&lo5cZDDGMLkwyA-
            [attributes] => 64
            [delimiter] => .
        )

    [1] => stdClass Object
        (
            [name] => {さくらサーバ}INBOX.&MOEw,DDrMKIwpDDGMOBoPH0NdSg-
            [attributes] => 32
            [delimiter] => .
        )

    [2] => stdClass Object
        (
            [name] => {さくらサーバ}INBOX.Drafts
            [attributes] => 64
            [delimiter] => .
        )

    [3] => stdClass Object
        (
            [name] => {さくらサーバ}INBOX.Trash
            [attributes] => 64
            [delimiter] => .
        )

    [4] => stdClass Object
        (
            [name] => {さくらサーバ}INBOX.spam
            [attributes] => 64
            [delimiter] => .
        )

    [5] => stdClass Object
        (
            [name] => {さくらサーバ}INBOX.Sent
            [attributes] => 64
            [delimiter] => .
        )

    [6] => stdClass Object
        (
            [name] => {さくらサーバ}INBOX.Draft
            [attributes] => 64
            [delimiter] => .
        )

    [7] => stdClass Object
        (
            [name] => {さくらサーバ}INBOX
            [attributes] => 40
            [delimiter] => .
        )

)

INBOX のフォルダ名 : メールアイテム格納用.階層テスト
INBOX のフォルダ名 : メールアイテム格納用
INBOX のフォルダ名 : Drafts
INBOX のフォルダ名 : Trash
INBOX のフォルダ名 : spam
INBOX のフォルダ名 : Sent
INBOX のフォルダ名 : Draft
posted by lightbox at 2018-10-18 11:49 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

2018年10月17日


PHP : IMAP 関数 でまずメールのヘッダ部分を整理してログに出力する / ※ JSON 出力を追加

本文は、マルチパートや添付ファイルなので、頭を切り替えて考える必要があります。とりあえずいろんなメールアカウントから、さくらインターネットのメールに転送してテストしました。

結果はすべて debug.log へ出力します。

データ取得後の管理の為、UID を取得して付加しています。

▼ PHP マニュアルより imap_uid
UID はユニークな ID であり時間が経過しても変わりません
<?php
error_reporting( E_ALL & ~E_NOTICE & ~E_STRICT );
session_cache_limiter('nocache');
session_start();
header( "Content-Type: text/html; charset=utf-8" );

# デバッグログの初期化
file_put_contents("debug.log", "開始\n" );

mb_internal_encoding("UTF-8");

xlog("ログの出力");

# ***************************
# IMAP 接続
# ***************************
$con = @imap_open("{サーバ:993/imap/ssl}INBOX", "ユーザ", "パスワード");
if ( $con === FALSE ) {
	print imap_last_error();
	xlog(imap_last_error());
	exit();
}

// 現在のメールボックスに関する情報を得る
$mbox_info = imap_mailboxmsginfo( $con );
xlog("\n■■■ \$mbox_info 現在のメールボックスに関する情報 -------");
xlog( print_r( $mbox_info ,true ));

if( $mbox_info->Nmsgs == 0 ) {
	xlog( "メールメッセージがありません" );
	exit();
}

// ***************************
// メッセージ件数
// ***************************
$max = $mbox_info->Nmsgs;
xlog("【メッセージ件数:{$max}】" );

if ( $max > 100 ) {
	$max = 100;
}

// メールの主要データの集約
$mail = array();

// ***************************
// $max 〜 1
// 最新から表示
// ***************************
for( $i = $max; $i >= 1; $i-- ) {

	// ***************************
	// 全ヘッダーデータ
	// ***************************
	$mail_head = imap_header($con, $i);
	// アドレス

	xlog( "▼▼▼ \$mail_head このメールのヘッダデータ ({$i}番目) ▼▼▼" );
	// 【UID】を取得して、$mail_head に追加
	$mail["head"][$i]["UID"] = imap_uid( $con, $i );
	$mail["head"][$i]["Msgno"] = $mail_head->Msgno;

	xlog( print_r( $mail_head ,true ) );

	// ***************************
	// from : テキストと メールアドレス( アドレスのみの場合もある )
	// ***************************
	xlog("■■■ fromaddress (decode 前) -------");
	xlog( $mail_head->fromaddress );

	// ***************************
	// ASCII と それ以外で分解
	// ***************************
	$fromaddress = imap_mime_header_decode( $mail_head->fromaddress );
	xlog("■■■ fromaddress (decode 後) -------");
	xlog( print_r( $fromaddress, true ) );

	$mail["head"][$i]["fromaddress"] = "";
	foreach( $fromaddress as $key => $value ) {
		if( $value->charset != 'default' ) {
			$mail["head"][$i]['fromaddress'] .= mb_convert_encoding($value->text,'UTF-8',$value->charset);
		}
		else{
			$mail["head"][$i]['fromaddress'] .= $value->text;
		}
	}
	xlog("■■■ fromaddress (編集後) -------");
	xlog( $mail["head"][$i]['fromaddress'] );
	xlog("");

	// ***************************
	// subject : 件名
	// ***************************
	xlog("■■■ subject (decode 前) -------");
	xlog( $mail_head->subject );

	// ***************************
	// ASCII と それ以外で分解
	// ***************************
	$subject = imap_mime_header_decode( $mail_head->subject );
	xlog("■■■ subject (decode 後) -------");
	xlog( print_r( $subject, true ) );

	$mail["head"][$i]["subject"] = "";
	foreach( $subject as $key => $value ) {
		if( $value->charset != 'default' ) {
			$mail["head"][$i]['subject'] .= mb_convert_encoding($value->text,'UTF-8',$value->charset);
		}
		else{
			$mail["head"][$i]['subject'] .= $value->text;
		}
	}
	xlog("■■■ subject (編集後) -------");
	xlog( $mail["head"][$i]['subject'] );
	xlog("");

	// ***************************
	// 受信日時
	// ***************************
	$data = $mail["head"][$i]['date'] = $mail_head->date;
	$data = $mail["head"][$i]['date_normal'] = date('Y-m-d H:i:s', strtotime($data));

	// ***************************
	// サイズ
	// ***************************
	$data = $mail["head"][$i]['size'] = $mail_head->Size;

	$mail["head"][$i]["mail_head"] = $mail_head;

}

xlog("■■■ 編集後データの一覧 -------");
xlog( print_r( $mail["head"], true ) );


// ***************************
// IMAP 接続解除
// ***************************
imap_close($con);

// ***************************
// ログ出力
// ***************************
function xlog($message) {
	file_put_contents("debug.log", "{$message}\n" , FILE_APPEND );
}
?>
OK



json 文字列を出力して Ajax で使用できるように変更
<?php
error_reporting( E_ALL & ~E_NOTICE & ~E_STRICT );
session_cache_limiter('nocache');
session_start();

header( "Access-Control-Allow-Origin: *" );
header( "Content-Type: application/json; charset=utf-8" );

# デバッグログの初期化
file_put_contents("debug.log", "開始\n" );

mb_internal_encoding("UTF-8");

xlog("ログの出力");

# ***************************
# IMAP 接続
# ***************************
$con = @imap_open("{さくらユーザ.sakura.ne.jp:993/imap/ssl}INBOX", "ユーザ@さくらユーザ.sakura.ne.jp", "パスワード");
if ( $con === FALSE ) {
	print imap_last_error();
	xlog(imap_last_error());
	exit();
}

// 現在のメールボックスに関する情報を得る
$mbox_info = imap_mailboxmsginfo( $con );
xlog("\n■■■ \$mbox_info 現在のメールボックスに関する情報 -------");
xlog( print_r( $mbox_info ,true ));

if( $mbox_info->Nmsgs == 0 ) {
	xlog( "メールメッセージがありません" );
	exit();
}

// ***************************
// メッセージ件数
// ***************************
$max = $mbox_info->Nmsgs;
xlog("【メッセージ件数:{$max}】" );

if ( $max > 100 ) {
	$max = 100;
}

// メールの主要データの集約
$mail = array();

$json = array();

// ***************************
// $max 〜 1
// 最新から表示
// ***************************
for( $i = $max; $i >= 1; $i-- ) {

	$obj = new stdClass();

	// ***************************
	// 全ヘッダーデータ
	// ***************************
	$mail_head = imap_header($con, $i);
	// アドレス

	xlog( "▼▼▼ \$mail_head このメールのヘッダデータ ({$i}番目) ▼▼▼" );
	// 【UID】を取得して、$mail_head に追加
	$mail["head"][$i]["UID"] = imap_uid( $con, $i );
	$mail["head"][$i]["Msgno"] = $mail_head->Msgno;

	xlog( print_r( $mail_head ,true ) );

	// ***************************
	// from : テキストと メールアドレス( アドレスのみの場合もある )
	// ***************************
	xlog("■■■ fromaddress (decode 前) -------");
	xlog( $mail_head->fromaddress );

	// ***************************
	// ASCII と それ以外で分解
	// ***************************
	$fromaddress = imap_mime_header_decode( $mail_head->fromaddress );
	xlog("■■■ fromaddress (decode 後) -------");
	xlog( print_r( $fromaddress, true ) );

	$mail["head"][$i]["fromaddress"] = "";
	foreach( $fromaddress as $key => $value ) {
		if( $value->charset != 'default' ) {
			$mail["head"][$i]['fromaddress'] .= mb_convert_encoding($value->text,'UTF-8',$value->charset);
		}
		else{
			$mail["head"][$i]['fromaddress'] .= $value->text;
		}
	}
	xlog("■■■ fromaddress (編集後) -------");
	xlog( $mail["head"][$i]['fromaddress'] );
	xlog("");

	$obj->fromaddress = $mail["head"][$i]['fromaddress'];


	// ***************************
	// subject : 件名
	// ***************************
	xlog("■■■ subject (decode 前) -------");
	xlog( $mail_head->subject );

	// ***************************
	// ASCII と それ以外で分解
	// ***************************
	$subject = imap_mime_header_decode( $mail_head->subject );
	xlog("■■■ subject (decode 後) -------");
	xlog( print_r( $subject, true ) );

	$mail["head"][$i]["subject"] = "";
	foreach( $subject as $key => $value ) {
		if( $value->charset != 'default' ) {
			$mail["head"][$i]['subject'] .= mb_convert_encoding($value->text,'UTF-8',$value->charset);
		}
		else{
			$mail["head"][$i]['subject'] .= $value->text;
		}
	}
	xlog("■■■ subject (編集後) -------");
	xlog( $mail["head"][$i]['subject'] );
	xlog("");

	$obj->subject = $mail["head"][$i]['subject'];


	// ***************************
	// 受信日時
	// ***************************
	$data = $mail["head"][$i]['date'] = $mail_head->date;
	$data = $mail["head"][$i]['date_normal'] = date('Y-m-d H:i:s', strtotime($data));

	// ***************************
	// サイズ
	// ***************************
	$data = $mail["head"][$i]['size'] = $mail_head->Size;

	$mail["head"][$i]["mail_head"] = $mail_head;

	$json[] = $obj;

}

xlog("■■■ 編集後データの一覧 -------");
xlog( print_r( $mail["head"], true ) );


// ***************************
// IMAP 接続解除
// ***************************
imap_close($con);

print json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );

// ***************************
// ログ出力
// ***************************
function xlog($message) {
	file_put_contents("debug.log", "{$message}\n" , FILE_APPEND );
}
?>




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

2018年08月26日


ファイルを一つアップロード : FORM の target を IFRAME にして、PHP に JavaScript を書き出させて元のページにメッセージを表示させる

昨今、ファイルをアップロードするならば、JavsScript を駆使して UI を作成し、 $.ajax で送信したほうが簡潔になりますが、ベタな FORM の記述のみで送信してそれなりのレスポンスを得ようという処理です。

デモページ


画像をクリックするとデモページへ移動します

当然ですが、デモページで実際のアップロードはできません。しかし、結果を表示するにチェックを入れて送信すると、上の画像のように実際と同じ状態で情報をシミュレートします。

UI の構築を気楽に工夫できるように、twitter-bootstrap の 4.1.3 を組み込んでいます

IFRAME は本来非表示で、ここに JavaScript で右上のメッセージ(toastr.js)を表示するようにしていますが、デバッグ用としても使えるようにしており、その場合は PHP 側の $_FILES の中身が見れるようになっています。

type="file" の name 属性は target で固定して php 側で使用しています。
送信データの制限 データの制限はサーバに対する無意味なアクセスを遮断するアプローチと、アプリから見たデータの制限という二つのアプローチがあります。前者がもっとも重要で、それがなければ php.ini の upload_max_filesize 内であれば結果的にそのサイズまでは送信を許してしまいます。 ※ upload_max_filesize を超えると $_FILES そのものが空になるようです。 後者は、FORM 内の name="MAX_FILE_SIZE" の値で指定できますが、完全な対策ではありません。 そこで、対象ページのあるディレクトリの .htaccess 内に 『LimitRequestBody 102400』のように制限値を設定し、さらに『ErrorDocument 413』 を設定してそのページの中でエラー処理の対応をしています ▼ 413.html
<!DOCTYPE html>
<html lang="ja">
<meta charset="utf-8">
<style>
* {
	font-size: 32px;
}
</style>
<script>

	try {
		parent.$("iframe").show();
		parent.toastr.info( "ファイル のアップロードに失敗しました");
		parent.toastr.info( "エラー内容 : Request Entity Too Large" );
	}
	catch (e) {}

</script>
</head>
<body>

JavaScript の処理用に IFRAME を定義している場合で、
413 Request Entity Too Large が発生した場合にこのページが IFRAME 内に表示されます。

</body>
</html>


file_upload_html.php

$debug 変数で、実際のアップロードの可否を切り替えています。if ( !$_FILES ) { の部分は、upload_max_filesize を超えてしまった状態の対処ですが、ここでは LimitRequestBody 102400 を設定しているので発生する事はありません。
<?php
session_cache_limiter('nocache');
session_start();

header( "Content-Type: text/html; charset=utf-8" );

// *************************************
// 変数初期値
// *************************************
$debug = 0;
$upload_dir = "./upload";
if ( !$_FILES ) {
	// php.ini の upload_max_filesize を超えて、
	// Apache に制限が無いと $_FILE が空になる
	$_FILES['target']['error'] = 5;	// ユーザエラーメッセージ
}

// *************************************
// アップロード処理
// フィールド名 : target で固定
// *************************************
if ( $_SERVER['REQUEST_METHOD'] == "POST" ) {

	// 公開状態では実行しない
	if ( $debug == 1 ) {

		$upload = realpath ( $upload_dir );
		$upload .= ( DIRECTORY_SEPARATOR . $_FILES['target']['name'] );
		if ( move_uploaded_file(
			$_FILES['target']['tmp_name'], $upload ) ) {
			$_POST['result']  = "アップロードに成功しました";
		}
		else {
			if ( !$_FILES ) {
				$_FILES['target']['error'] = 5;	// ユーザエラーメッセージ
			}
			$_POST['result']  = "アップロードに失敗しました";
		}

	}
	else {
		if ( $_FILES['target']['error'] == 0 ) {
			$_POST['result']  = "アップロードに成功しました";
		}
		else {
			$_POST['result']  = "アップロードに失敗しました";
		}
	}

}
else {
	$_POST['result']  = "POST メソッドを使用して下さい";
}

$_POST['files'] = $_FILES;

// *************************************
// この JSON 文字列を HTML 内の json
// オブジェクト定義として埋め込みます
// *************************************
$json = json_encode($_POST, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );


// *************************************
// 画面定義
// *************************************
?>
<!DOCTYPE html>
<html lang="ja">
<style>
/* calc 用 */
html,body {
	height: 100%;
}
body {
	margin: 0;
}

* {
	font-size: 16px;
	font-family: "ヒラギノ角ゴPro W6","Hiragino Kaku Gothic Pro W6","メイリオ",Meiryo,"MS Pゴシック",Verdana,Arial,Helvetica,sans-serif;
}
</style>
<script>
var message = <?php require("error.json.php") ?>
var json = <?= $json ?>;

if ( json.files.target.error == 0 ) {
	parent.toastr.info(json.files.target.name + " がアップロードされました");
	parent.toastr.info("ファイルサイズ : " + json.files.target.size);
}
else {
	parent.toastr.info(json.files.target.name + " のアップロードに失敗しました");
	parent.toastr.info("エラー内容 : " + message.error[json.files.target.error]);
}

<?php if( $_POST["disp_result"] == "1" ) { ?>

	parent.$("iframe[name='upload']")
		.css("border", "1px solid #c0c0c0")
		.show();

<?php } else { ?>

	parent.$("iframe[name='upload']").hide();

<?php } ?>

</script>
</head>
<body>
<?php if( $_POST["disp_result"] == "1" ) { ?>
<textarea style='width:calc(100% - 6px);height:calc(100% - 14px);'><?= $json ?></textarea>

<?php } ?>
</body>
</html>


error.json.php は、PHP のエラーメッセージです。ここでは部品として埋め込んでいますが、$.ajax バージョンでも使用(error.json.php?type=json)しています。

error.json.php
<?php
if ( $_GET["type"] == "json" ) {
	session_cache_limiter('nocache');
	session_start();
	header( "Content-Type: application/json; charset=utf-8" );
}

?>
{
	"error": [
		"0 - 正常終了",
		"1 - アップロードされたファイルは、php.ini の upload_max_filesize ディレクティブの値を超えています",
		"2 - アップロードされたファイルは、HTML フォームで指定された MAX_FILE_SIZE を超えています",
		"3 - アップロードされたファイルは一部のみしかアップロードされていません",
		"4 - ファイルはアップロードされませんでした",
		"5 - 『アップロードに失敗しました』",
		"6 - テンポラリフォルダがありません。PHP 5.0.3 で導入されました",
		"7 - ディスクへの書き込みに失敗しました。PHP 5.1.0 で導入されました",
		"8 - PHP の拡張モジュールがファイルのアップロードを中止しました"
	]
}


upload.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta content="width=device-width initial-scale=1.0 minimum-scale=1.0 maximum-scale=1.0 user-scalable=no" name="viewport">
<title>HTML の FORM のみでファイルを一つアップロードする</title>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link id="link" rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>

<!-- 共通の表示 -->
<link rel="stylesheet" href="common.css">

<!-- CSS の指定 -->
<style>
#top {
	height: 420px;
}
iframe {
	display: block;
	margin-left: auto;
	margin-right: auto;
	width: calc( 100% - 3px );
	height: calc( 100% - 420px - 2px );
}

/* PC 用の表示 */
@media screen and ( min-width:480px ) {
	#content {
		margin: 16px;
	}
}
/* スマホ用の表示 */
@media screen and ( max-width:479px ) {
	#content {
		margin: 0px;
	}
	body {
		width: 100%!important;
		margin: 0px;
	}
	.unit {
		width: 100%;
	}
	.btn {
		margin-top: 7px;
	}
}
</style>
<script>
// 簡易的なスマホチェックを jQuery のプロパティとして登録
jQuery.isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
if ( $.isMobile ) {
	// スマホの場合は表示画面下の中央
	toastr.options.positionClass = "toast-bottom-center";
}

$(function(){

	// このページ自身の QRコードの表示
	$('#qrcode')
		.css({ "margin" : "2px" })
		.qrcode({width: 160,height: 160,text: location.href });
		

});
</script>
</head>
<body>
<div id="top">
	<div id="head">
		<div id="title">
			<a href="./">One File アップロード</a>
		</div>
	</div>

	<div id="content">
		<form target="upload" enctype="multipart/form-data" action="../../php_upload/file_upload_html.php" method="POST">
			<input type="hidden" name="MAX_FILE_SIZE" value="40000">
			<input name="target" type="file" class="btn btn-info">
			<input type="submit" value="ファイルを送信" class="btn btn-success ml-2">

			<p>
				<label for="disp_result">結果を表示する</label>
				<input id="disp_result" type="checkbox" name="disp_result" value="1" class="mt-5" checked>
			</p>
		</form>

		<div id="qrcode"></div>

	</div>

</div>


<iframe src="about:blank" name="upload" style="display:none;border:0px solid #c0c0c0;width:100%;"></iframe>



</body>
</html>


common.css
@charset "UTF-8";

/* calc 用 */
html,body {
	height: 100%;
}
body {
	margin: 0;
}

/* 共通の表示 */
* {
	font-size: 16px;
	font-family: "ヒラギノ角ゴPro W6","Hiragino Kaku Gothic Pro W6","メイリオ",Meiryo,"MS Pゴシック",Verdana,Arial,Helvetica,sans-serif;
}
#head {
	background-color: #404040;
	padding: 10px 0 10px 25px;
}
#head * {
	color: #ffffff;
}



HTML 側のダウンロード



PHP 側のダウンロード





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

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 + 通信 | このブログの読者になる | 更新情報をチェックする
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 終わり