SQLの窓

2017年09月02日


FormData を使用して $.ajax で送信すると、ファイルのアップロードとメール送信(ファイル添付)を一度に行えます

mb_send_mail による メール送信におけるファイル添付の普通のサンプルはこちら

呼び出し
	$( "#base" ).submit(function( event ) {

		event.preventDefault();

		$("#action").prop( "disabled", true );
		$("#action_copy").prop( "disabled", true );
		
		// 新規送信用オブジェクト
		var formData = new FormData();

		// 入力テキスト
		formData.append("fld_to", $("input[name='fld_to']").val() );
		formData.append("fld_subject", $("input[name='fld_subject']").val() );
		formData.append("fld_body", $("textarea[name='fld_body']").val() );
		// ファイルオブジェクト( type="file" )
		formData.append("fld_file", $("input[name='fld_file']").get(0).files[0]);

		$.ajax({
			url: "app-mail.php",
			type: "POST",
			data: formData,
			processData: false,  // jQuery がデータを処理しないよう指定
			contentType: false   // jQuery が contentType を設定しないよう指定
		})
		.done(function( data, textStatus ){
			console.log( "status:" + textStatus );
			console.log( "data:" + JSON.stringify(data, null, "    ") );

			if ( data.status == 0 ) {

				toastr.info("メールが送信されました");

				$("input[name='fld_subject']").val( "" );
				$("textarea[name='fld_body']").val( "" );

			}

			if ( data.status == 1 ) {
				// エラーメッセージを表示
				toastr.error("メール送信に失敗しました");

			}
			
		})
		// 失敗
		.fail(function(jqXHR, textStatus, errorThrown ){
			console.log( "status:" + textStatus );
			console.log( "errorThrown:" + errorThrown );
		})
		// 常に実行
		.always(function() {

			$("#action").prop( "disabled", false );
			$("#action_copy").prop( "disabled", false );

		})
		;		
	
	});

受け側の PHP

$_POST['fld_body'] の中身は UTF-8 ですが、mb_send_mail が変換してくれます。
<?php
// ***************************
// このアプリ特有の定義
// ***************************
require_once("../mail-jquery/app.model");

$GLOBALS["content_type"] = "application/json";
$GLOBALS["upload_dir"] = "./upload";

require_once("{$GLOBALS["common_path"]}common.php");

// type="file" のフィールドの name の値
$fld = "fld_file";

// ******************************************************
// アップロード 処理
// ******************************************************
if ( !$_FILES ) {
	// php.ini の upload_max_filesize を超えて、
	// Apache に制限が無いと $_FILE が空になる
	$_FILES[$fld]['error'] = 5;	// ユーザエラーメッセージ
}

// *************************************
// アップロード処理
// フィールド名 : $fld で固定
// *************************************

// true では実行しない
if ( !$GLOBALS["debug_update"] ) {

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

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


$_POST['files'] = $_FILES;

// *************************************
// メール処理
// *************************************
mb_language("Japanese");
mb_internal_encoding("UTF-8");

$uniqid = uniqid();

$from_header = "From: " . mb_encode_mimeheader( mb_convert_encoding("差出人","iso-2022-jp") );

// このソースを置くサーバから使えるメールアドレス
$from_header .= " <{$GLOBALS["mail"]}>\n";
$from_header .= "Content-Type: multipart/mixed; boundary=\"{$uniqid}\"\n";

$mime = $_FILES['fld_file']['type'];
$fname = $_FILES['fld_file']['name'];

$body  = "--{$uniqid}\n";
$body .= "Content-Type: text/plain; charset=\"ISO-2022-JP\"\n";
$body .= "\n";
$body .= $_POST['fld_body'] . "\n";
$body .= "--{$uniqid}\n";
$body .= "Content-Type: {$mime}; name=\"{$fname}\"\n";
$body .= "Content-Transfer-Encoding: base64\n";
$body .= "Content-Disposition: attachment; filename=\"{$fname}\"\n";
$body .= "\n";

// アップロードされたファイル
$path = $upload;
$data = file_get_contents($path);
$encode = base64_encode($data);

$body .= chunk_split($encode);
$body .= "\n--{$uniqid}--\n";

if ( !$GLOBALS["debug_update"] ) {
	$result = mb_send_mail(
		$_POST["fld_to"],
		$_POST["fld_subject"],
		$body,
		$from_header );
}
if ( $result ) {
	$error = 0;
}
else {
	$error = 1;
}

// アップロードして添付したファイルを削除
unlink($path);


// ***************************
// JSON データ作成
// ***************************
$json = new stdClass;

$json->post = $_POST;			// 行データ
$json->status = $error;		// エラー
if ( !$GLOBALS["debug_update"] ) {
	$json->user = $GLOBALS["mail"];
	$json->debug = $from_header;
}

print json_encode( $json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );

?>

関連する記事

fake sendmail for windows を使って、PHP でごく普通に( mb_send_mail で )メール送信 : Gmail なので ssl(465)




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

ファイルのアップロードからそれを添付してメールを送るテンプレート(スケルトン)



メール送信部分には、『mb_send_mail』を使用しているので、インターネット上のサーバーで、そこからパスワード無しでメールアドレスが利用できる必要があります。

※ fake sendmail for windows でも動作確認しました
※ FormData を使用して送信すると、ファイルのアップロードとメール送信を一度にできます。
( FormData を使用したサンプル )



メールアドレスは、mail.php で、セッション変数にセットして使用しています。

Content-Type の MIME は、ファイルアップロード時に取得した type をセッション変数に保存して使用しています。
<?php
require_once("common.php");

$_SESSION['user'] = "セッションデータを表示する為のダミー";
$_SESSION["mail_from"] = "メールアドレス";

require_once("mail_view.php");
?>
ファイル一覧
  • common.php
  • debug_value.php
  • mail.php
  • mail_view.php
  • form2.php
  • form2_view.php
  • upload1.php
  • html_head.php
  • mail_ex.php
  • style.css ※ ソース全体参照へのリンク
  • メール送信部分の mail_ex.php
    <?php
    require_once("common.php");
    
    require_once("html_head.php");
    
    foreach( $_POST as $Key => $Value ) {
    	$_POST[$Key] = str_replace("\\\\", "\\", $Value );
    	$_POST[$Key] = str_replace("\\'", "'", $_POST[$Key] );
    	$_POST[$Key] = str_replace("\\\"", "\"", $_POST[$Key] );
    }
    
    
    mb_language( "ja" );
    mb_internal_encoding("utf-8");
    
    $from = $_SESSION["mail_from"];
    $fname = $_SESSION["mail_file"];
    $mime = $_SESSION['mime'];
    
    if ( $fname == "" ) {
    	print "ファイルをアップロードして下さい <a href=\"mail.php\">戻る</a><br>";
    	exit();
    }
    
    $uniqid = uniqid();
    
    $headers = "From: {$from}\n";
    $headers .= "Content-Type: multipart/mixed; boundary=\"{$uniqid}\"\n";
    
    $body  = "--{$uniqid}\n";
    $body .= "Content-Type: text/plain; charset=\"ISO-2022-JP\"\n";
    $body .= "\n";
    $body .= $_POST['text'] . "\n";
    $body .= "--{$uniqid}\n";
    $body .= "Content-Type: {$mime}; name=\"{$fname}\"\n";
    $body .= "Content-Transfer-Encoding: base64\n";
    $body .= "Content-Disposition: attachment; filename=\"{$fname}\"\n";
    $body .= "\n";
    
    $path = "upload_file/{$fname}";
    $data = file_get_contents($path);
    $encode = base64_encode($data);
    
    $body .= chunk_split($encode);
    $body .= "\n--{$uniqid}--\n";
    
    $ret = mb_send_mail(
    	$_POST['to_address'],
    	$_POST['subj'],
    	$body,
    	$headers );
    
    // アップロードして添付したファイルを削除
    unlink($path);
    $_SESSION["mail_file"] = "";
    
    if ( $ret === TRUE ) {
    	print "<a href=\"mail.php\">戻る</a> メール送信が終了しました。<br>";
    }
    else {
    	print "<a href=\"mail.php\">戻る</a> メール送信に失敗しました。<br>";
    }
    
    print "</body>";
    print "</html>";
    ?>
    
    
    ファイルのアップロード後、アップロードフォルダのファイルのタイムスタンプが5分以上経過している場合は削除します。(upload1.php)
    
    ファイルアップロードの実行は IFRAME 内の別ページで行っています。さらに、IFRAME 内の IFRAME にアップロード結果を表示している為、アップロード結果の『ファイル名』をメインページに転送する為、JavaScript を PHP で出力しています。
    
    その際、メインページでは jQuery を使用しているので、メインページの jQuery を使用してファイル名をテキストフィールドに転送しています
    
    if ( move_uploaded_file( $_FILES['file_1']['tmp_name'], $upload ) ) {
    	print "アップロードに成功しました<br>";
    	$_SESSION["mail_file"] = $target;
    	print "<script>";
    	print " parent.parent.$('#mail_file').val( \"{$target}\" );";
    	print "</script>";
    }
    else {
    	print "アップロードに失敗しました<br>";
    }
    
    
    関連する記事
    
    fake sendmail for windows を使って、PHP でごく普通に( mb_send_mail で )メール送信 : Gmail なので ssl(465)
    
    
    
    
    posted by lightbox at 2017-09-02 16:33 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    2017年09月01日


    他のアプリケーションを『管理者権限』で実行するコマンドライン

    厳密には、テンポラリフォルダに VBScript のコードを作成しますが、バッチ処理でコマンドを実行する時に『管理者権限』を与えたい場合はこれで対処できると思います。
    
    taskmgr は一例です。taskmgr のところに実行したいアプリケーション( exe ) をセットします。
    
    "taskmgr","" の左の文字列は、実行アプリケーションで、右の文字列は引数の文字列を指定します
    
    Shell.ShellExecute method
    
    cmd "/c echo set o=CreateObject("Shell.Application"):o.ShellExecute "taskmgr","","","runas",1 > %TEMP%\_.vbs & wscript.exe %TEMP%\_.vbs"
    
    Windows7 では、taskmgr.exe が管理者権限で実行されると、新しいタスクの作成ダイアログに『このタスクに管理者特権を付与して作成します』チェックボックスが現れます
    
    
    
    
    
    
    
    
    
    
    posted by lightbox at 2017-09-01 13:09 | コマンド : コマンド | このブログの読者になる | 更新情報をチェックする

    ファイル名を指定して実行と、『管理者権限』

    
    
    このウインドウは、コマンドをタイプまたは参照して実行するものですが、一般的には『スタートメニュー』から表示させます。但し、設定として以下のようにスタートメニーに表示させるようにしている必要があります。
    
    
    
    もし、スタートメニューに無い場合は、『Windows キー + R』で表示する事ができます。しかし、このウインドウに『管理者権限』を持たせると以下、のように表示されます。
    
    
    
    このようにする最も簡単な方法は、『rundll32.exe shell32.dll,#61』と言うコマンドを使ってショートカットを作成し、ショートカットの設定で『管理者として実行する』にチェックする事です。
    
    
    
    この時、ショートカットに『ショートカットキー』を設定しておくとすぐ呼び出す事ができます( ここでは CTRL + SHIFT + G )
    
    また、『ファイル名を指定して実行』ウインドウは、VBScript を使った、たった2行のコードでも開く事ができます
    
    Set obj = CreateObject("Shell.Application")
    obj.FileRun
    
    
    この事を利用すれば、コマンドプロンプトからも開く事ができます。( rundll32.exe shell32.dll,#61 を使えばいいのですが、rundll32.exe はいつ使えなくなるか解らないので )
    
    cmd /c echo Set obj=CreateObject("Shell.Application"):obj.FileRun>%temp%\_.vbs&wscript.exe %temp%\_.vbs
    
    さらに、Windows には、もう一つ『ファイル名を指定して実行』を開く場所があります。それは、タスクマネージャのファイルメニューにある『新しいタスクの実行』です。
    
    
    
    タスクマネージャは、CTRL + SHIFT + ESC か、タスクバーを右クリックして表示されるメニューからか、CTRL + ALT + DEL で画面を切り替えてからメニューから呼び出すというのが一般的ですが、コマンドとして taskmgr を実行してもいいので、スタートメニューの『プログラムとファイルの検索』に入力して、CTRL + SHIFT + ENTER で呼び出すと、『管理者権限』で呼び出されるので、そこから『新しいタスクの実行』を開くと以下のようになります。
    
    
    
    
    
    ※ Windows8 では、最初から管理者権限を選択するチェックボックスが表示されています
    
    ▼ Windows8.1
    
    
    
    
    
    
    
    
    タグ:管理者権限
    posted by lightbox at 2017-09-01 13:06 | Windows | このブログの読者になる | 更新情報をチェックする

    管理者権限でコマンドプロンプトを開く VBScript をエクスプローラの右クリックで開く( そのフォルダで開く )方法

    第一引数にフォルダのパスを指定するようにしています。指定しなければ、カレントフォルダで開きます。
    
    管理者で実行するのは、ShellExecute に、"runas" を渡して実行しているからです。これは、右クリックで表示されるメニューにある『管理者として実行』に相当します
    acmd.vbs
    
    Set obj = CreateObject("Shell.Application")
    Set WshShell = CreateObject( "WScript.Shell" )
    if WScript.Arguments.Count <> 0 then
    	obj.ShellExecute "cmd.exe", "/s /k pushd """ & WScript.Arguments(0) & """", "", "runas", 1
    else
    	obj.ShellExecute "cmd.exe", "/s /k pushd """ & WshShell.CurrentDirectory & """", "", "runas", 1
    end if
    
    
    
    
    
    
    このスクリプトを Windows の system32 フォルダへコピーして、以下のようにレジストリ登録すると、フォルダを右クリックしてその場所で実行可能になります
    ( Windows の system32 フォルダである必要はありません / PC 共通の表現だとこれが間違いないので使用しています  )
    
    ※ 32ビットアプリより system32 にアクセスしようとすると、SysWoW64 にリダイレクトされます
    
    Windows Registry Editor Version 5.00
    
    [HKEY_CLASSES_ROOT\Folder\shell\acmd]
    @="管理者コマンドプロンプト"
    
    [HKEY_CLASSES_ROOT\Folder\shell\acmd\command]
    @="wscript c:\\windows\\system32\\acmd.vbs \"%V\""
    
    
    ※ system32 フォルダへコピーしたスクリプトを編集するには、エディタの実行時に『管理者として実行』する必要があります。
    
    単に管理者としてコマンドプロンプトを開きたい場合は、Windowsキー + S で『ここに入力して検索』内に cmd と入力して CTRL + SHIFT + ENTER すればいいでしょう
    
    あるいは、通常のコマンドプロンプトを起動して、タスクバーのアイコンを Ctrl と Shift キーを押しながらクリックします。
    
    
    
    関連する外部の記事
    
    windows - How to run vbs as administrator from vbs? - Stack Overflow
    
    
    
    
    
    
    
    
    
    posted by lightbox at 2017-09-01 13:03 | VBS + Shell | このブログの読者になる | 更新情報をチェックする
    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 ドロップシャドウの参考デモ
    イラストAC
    ぱくたそ
    写真素材 足成
    フリーフォント一覧
    utf8 文字ツール
    右サイド 終わり
    base 終わり