携帯メールでFlash世界に写真出現!
携帯メールでFlash世界に写真出現!
携帯で画像添付メールを指定されたアドレスに送るとFlashの箱から画像が出てきます。
こんな感じ。
http://moeten.info/flex/20081201_mail2present/bin-release/main.html
#ほかの方がアップしてたりすると勝手に反応しちゃうので、なんとなく使用してない時間帯くらいに試してみてください。
動作ムービーはこちら
簡単な説明
キューブの作成@Flash10
<mx:Canvas id="myCanvas" x="300" y="300"> <mx:Image id="myImage01" source="01.jpg"/> <mx:Image id="myImage02" source="01.jpg" rotationX="90"/> <mx:Image id="myImage03" source="01.jpg" rotationY="90" z="200"/> <mx:Image id="myImage04" source="01.jpg" rotationZ="90" x="200" z="200"/> <mx:Image id="myImage05" source="01.jpg" rotationX="90" rotationY="90" x="0" y="200" z="200"/> <mx:Image id="myImage06" source="01.jpg" rotationX="90" rotationY="90" rotationZ="90" x="200" y="0" z="200"/> </mx:Canvas>
メールが来てないか、タイマークラスを用いてメールをチェック
//初期化。タイマー作成 private var timer:Timer; private function creationCompleteHandler(e:Event):void{ timer = new Timer( 3000 ); timer.addEventListener(TimerEvent.TIMER , myTimer ); timer.start(); } //タイマーイベント private function myTimer(e:Event):void{ hts.send(); }
毎回httpserviceで問い合わせしているのでナンセンスですが、とりあえずのものってことで今回はごり押しで作成してます(^^;
メールのチェックプログラムはレッツPHP!さんの写メール BBSが大変便利です(^−^)
サーバー(PHP)にメール問い合わせをしてメールがあったら画像を作成してステージに追加
//httpレザルトイベント private function onResult():void{ if( hts.lastResult.image != "" ){ //メール発見 addImage(); timer.removeEventListener(TimerEvent.TIMER , myTimer ); } } //画像を作成してステージに配置 [Bindable]private var myImage07:Image; private function addImage():void{ var loader:URLLoader = new URLLoader(new URLRequest( hts.lastResult.image ) ); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE , function():void{ SimpleZSorter.sortClips( myCanvas , true); myImage07 = new Image(); myImage07.width = 180; myImage07.height = 180; myImage07.source = loader.data; myCanvas.addChild(myImage07); }); loader.load(new URLRequest( hts.lastResult.image ) ); }
あと、小ネタたとして、Flexの意外と知られていないクラス「AnimateProperty」の紹介。
このAnimatePropertyは好きな値をTweenすることができます。
<mx:AnimateProperty target="myImage" fromValue="0" toValue="-90" property="rotationY" duration="2000" easingFunction="Back.easeOut"/>
「isStyle=true」とすればスタイルもOKです。
ちょちょっとしたところに使うと便利ですよ。
すべてのソースはこちら。
Box2Dとかと組み合わせると面白いんじゃないかなぁ。アイディア元はcssniteのマツさんなんですけどね(^−^)
ソースのっけてますんでよかったら使ってください。
Flex部分のソースはこちら
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="creationCompleteHandler(event)" backgroundGradientColors="[0xffffff,0xcccccc]" clipContent="false" viewSourceURL="srcview/index.html"> <mx:Script> <![CDATA[ import com.theflashblog.fp10.SimpleZSorter; import mx.effects.easing.Back; //初期化。タイマー作成 private var timer:Timer; private function creationCompleteHandler(e:Event):void{ myLog.text = "init\n"; timer = new Timer( 3000 ); timer.addEventListener(TimerEvent.TIMER , myTimer ); timer.start(); } //タイマーイベント private var cnt:int = 0; private function myTimer(e:Event):void{ cnt+=1; myLog.text += "now loading " + cnt + "\n"; hts.send(); } //httpレザルトイベント private function onResult():void{ if( hts.lastResult.image != "" ){ myAnime01.play(); myAnime02.play(); myLog.text += "mail found"; timer.removeEventListener(TimerEvent.TIMER , myTimer ); } } //メール発見。画像を作成してステージに配置 [Bindable]private var myImage07:Image; private function onEffectEnd():void{ var loader:URLLoader = new URLLoader(new URLRequest( hts.lastResult.image ) ); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE , function():void{ SimpleZSorter.sortClips( myCanvas , true); myImage07 = new Image(); myImage07.width = 180; myImage07.height = 180; myImage07.source = loader.data; myImage07.rotationX = Math.random() * 360; myImage07.rotationY = Math.random() * 360; myImage07.rotationZ = Math.random() * 360; myLog.text = hts.lastResult.image; myCanvas.addChild(myImage07); myAnime03.play(); }); loader.load(new URLRequest( hts.lastResult.image ) ); } ]]> </mx:Script> <!--############## HTTP ##############--> <mx:HTTPService id="hts" url="http://moeten.info/flex/20081201_mail2present/" resultFormat="e4x" result="onResult()"/> <!--############## エフェクト ##############--> <mx:AnimateProperty id="myAnime01" fromValue="20" toValue="380" target="{myCanvas}" property="rotationY" duration="1000" easingFunction="Back.easeInOut"/> <mx:AnimateProperty id="myAnime02" fromValue="0" toValue="-100" target="{myImage01}" property="rotationX" duration="1000" easingFunction="Back.easeOut" startDelay="1200" effectEnd="onEffectEnd()"/> <mx:Sequence id="myAnime03" target="{myImage07}"> <mx:Parallel> <mx:AnimateProperty fromValue="0" toValue="1" property="alpha" duration="2000" easingFunction="Back.easeOut"/> <mx:AnimateProperty toValue="200" property="y" duration="2000" easingFunction="Back.easeOut"/> <mx:AnimateProperty toValue="-300" property="z" duration="2000" easingFunction="Back.easeOut"/> <mx:AnimateProperty fromValue="0" toValue="-40" property="x" duration="2000" easingFunction="Back.easeOut"/> </mx:Parallel> <mx:Parallel> <mx:AnimateProperty toValue="-90" property="rotationX" duration="2000" easingFunction="Back.easeOut"/> <mx:AnimateProperty toValue="-90" property="rotationY" duration="2000" easingFunction="Back.easeOut"/> <mx:AnimateProperty toValue="0" property="rotationZ" duration="2000" easingFunction="Back.easeOut"/> <mx:AnimateProperty toValue="2" property="scaleX" duration="2000" easingFunction="Back.easeOut"/> <mx:AnimateProperty toValue="2" property="scaleY" duration="2000" easingFunction="Back.easeOut"/> </mx:Parallel> </mx:Sequence> <!--############## コンポーネント ##############--> <mx:TextArea id="myLog" x="10" y="10" height="140"/> <mx:DataGrid x="178" y="8" dataProvider="{hts.lastResult}" width="442"> <mx:columns> <mx:DataGridColumn headerText="列 1" dataField="title"/> <mx:DataGridColumn headerText="列 2" dataField="comment"/> <mx:DataGridColumn headerText="列 3" dataField="image"/> </mx:columns> </mx:DataGrid> <mx:Image source="qr.jpg" x="10" y="158"/> <mx:Canvas id="myCanvas" x="300" y="300" rotationX="270" rotationY="-30" rotationZ="20" z="200"> <mx:Image id="myImage01" source="01.jpg" alpha="0.5" filters="{[gf]}"/> <mx:Image id="myImage02" source="01.jpg" rotationX="90" alpha="0.5" filters="{[gf]}"/> <mx:Image id="myImage03" source="01.jpg" rotationY="90" z="200" alpha="0.5" filters="{[gf]}"/> <mx:Image id="myImage04" source="01.jpg" rotationZ="90" x="200" z="200" alpha="0.5" filters="{[gf]}"/> <mx:Image id="myImage05" source="01.jpg" rotationX="90" rotationY="90" x="0" y="200" z="200" alpha="0.5" filters="{[gf]}"/> <mx:Image id="myImage06" source="01.jpg" rotationX="90" rotationY="90" rotationZ="90" x="200" y="0" z="200" alpha="0.5" filters="{[gf]}"/> </mx:Canvas> <mx:GlowFilter id="gf" blurX="3" blurY="3" color="0xffffff" strength="10" /> <mx:Label x="92" y="183" text="メールに画像を添付してね。たぶんJPGのみ"/> </mx:Application>
php部分のソースはこちら
ソースの原型はレッツPHP!さんの写メール BBSでっす。
<?php /*======================================== FUNCTION マイ関数 ========================================*/ /* コマンドー送信!! */ function _sendcmd($cmd) { global $sock; fputs($sock, $cmd."\r\n"); $buf = fgets($sock, 512); if(substr($buf, 0, 3) == '+OK') { return $buf; } else { die($buf); } return false; } /* ヘッダと本文を分割する */ function mime_split($data) { $part = split("\r\n\r\n", $data, 2); $part[1] = ereg_replace("\r\n[\t ]+", " ", $part[1]); return $part; } /* メールアドレスを抽出する */ function addr_search($addr) { if (eregi("[-!#$%&\'*+\\./0-9A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+", $addr, $fromreg)) { return $fromreg[0]; } else { return false; } } function h($str){ if(is_array($str)){ return array_map( "h",$str ); }else{ return htmlspecialchars($str,ENT_QUOTES); } } function e($str){ if(is_array($str)){ return array_map( "e" , $str ); }else{ return mysql_real_escape_string( $str ); } } /* 文字コードコンバートJIS→SJIS */ function convert($str) { if (function_exists('mb_convert_encoding')) { return mb_convert_encoding($str, "SJIS", "JIS,SJIS,UTF-8"); } elseif (function_exists('JcodeConvert')) { return JcodeConvert($str, 0, 2); } return true; } /*======================================== メール設定 ========================================*/ $host = ""; $user = ""; $pass = ""; $maxbyte = 402400;//100KB $maxtext = 1000; // 対応MIMEサブタイプ(正規表現)Content-Type: image/jpegの後ろの部分。octet-streamは危険かも //$subtype = "gif|jpe?g|png|bmp|pmd|mld|mid|smd|smaf|mpeg|kjx|3gpp|octet-stream"; $subtype = "gif|jpe?g|png"; // 添付メールのみ記録する?Yes=1 No=0(本文のみはログに載せない) $imgonly = 1; // 件名がないときの題名 $nosubject = "匿名さん"; // 次の秒数以内の同一送信者からの連続投稿禁止 $wtime = 100000; // 元ファイル名で保存する?Yes=1 No=0(0の場合 10桁時間-ファイル名) $original = 1; /*======================================== メール問い合わせ ========================================*/ $sock = fsockopen($host, 110, $err, $errno, 10) or die("サーバーに接続できません"); $buf = fgets($sock, 512); if(substr($buf, 0, 3) != '+OK') die($buf); $buf = _sendcmd("USER $user"); $buf = _sendcmd("PASS $pass"); $data = _sendcmd("STAT");//STAT -件数とサイズ取得 +OK 8 1234 sscanf($data, '+OK %d %d', $num, $size); if ($num == "0") { $buf = _sendcmd("QUIT"); //バイバイ fclose($sock); $xml = <<<EOD <result> <title/> <comment/> <image/> </result> EOD; header ("Content-Type: text/xml; charset=UTF-8"); echo mb_convert_encoding( $xml , "UTF-8" , "SJIS"); exit; } // 件数分 for($i=1;$i<=$num;$i++) { $line = _sendcmd("RETR $i");//RETR n -n番目のメッセージ取得(ヘッダ含) while (!ereg("^\.\r\n",$line)) {//EOFの.まで読む $line = fgets($sock,512); $dat[$i].= $line; } $data = _sendcmd("DELE $i");//DELE n n番目のメッセージ削除 } $buf = _sendcmd("QUIT"); fclose($sock); $lines = array(); $lines = @file($log); $write2 = false; /*======================================== 取得メールの処理 ========================================*/ for($j=1;$j<=$num;$j++) { $flag = 0; $write = true; $subject = $from = $text = $atta = $part = $attach = ""; list($head, $body) = mime_split($dat[$j]); // 日付の袖しつ eregi("Date:[ \t]*([^\r\n]+)", $head, $datereg); $now = strtotime($datereg[1]); if ($now == -1) $now = time(); $head = ereg_replace("\r\n? ", "", $head); // サブジェクトの抽出 if (eregi("\nSubject:[ \t]*([^\r\n]+)", $head, $subreg)) { $subject = $subreg[1]; while (eregi("(.*)=\?iso-2022-jp\?B\?([^\?]+)\?=(.*)",$subject,$regs)) {//MIME Bデコード $subject = $regs[1].base64_decode($regs[2]).$regs[3]; } while (eregi("(.*)=\?iso-2022-jp\?Q\?([^\?]+)\?=(.*)",$subject,$regs)) {//MIME Bデコード $subject = $regs[1].quoted_printable_decode($regs[2]).$regs[3]; } $subject = h(convert($subject)); } // 送信者アドレスの抽出 if (eregi("From:[ \t]*([^\r\n]+)", $head, $freg)) { $from = addr_search($freg[1]); } elseif (eregi("Reply-To:[ \t]*([^\r\n]+)", $head, $freg)) { $from = addr_search($freg[1]); } elseif (eregi("Return-Path:[ \t]*([^\r\n]+)", $head, $freg)) { $from = addr_search($freg[1]); } // マルチパートならばバウンダリに分割 if (eregi("\nContent-type:.*multipart/",$head)) { eregi('boundary="([^"]+)"', $head, $boureg); $part = explode("--".$boureg[1],$body); if (eregi('boundary="([^"]+)"', $part[1], $boureg2)) {//multipart/altanative $npart = explode("--".$boureg2[1],$part[1]); array_splice($part, 1, 1, $npart); } } else { $part[0] = $dat[$j];// 普通のテキストメール //画像が添付されてないよ $flag = 1; } foreach ($part as $multi) { list($m_head, $m_body) = mime_split($multi); $m_body = ereg_replace("\r\n\.\r\n$", "", $m_body); if (!eregi("Content-type: *([^;\n]+)", $m_head, $type)) continue; list($main, $sub) = explode("/", $type[1]); // 本文をデコード if (strtolower($main) == "text") { if (strtolower($sub) == "html" && $text != "") continue; if (eregi("Content-Transfer-Encoding:.*base64", $m_head)) $m_body = base64_decode($m_body); if (eregi("Content-Transfer-Encoding:.*quoted-printable", $m_head)) $m_body = quoted_printable_decode($m_body); $text = convert($m_body); } $title = $subject; $comment = $text; $filename = md5( $from ); $mtmp = array(); $mm = array(); $mquery_a = split( '&' , $mtext_2 ); foreach( $mquery_a as $mkey => $mval ){ $mtmp = split( '=' , $mval ); $mm[] = e( $mtmp[1] ); } $mm[3] = intval( $mm[3] ); if (eregi("Content-Transfer-Encoding:.*base64", $m_head) && eregi($subtype, $sub)) { header("Content-type:image/jpeg"); $myimage = base64_decode($m_body); file_put_contents( "image/{$filename}.jpg" , $myimage ); $myimage = e( $myimage ); $xml = <<<EOD <result> <title>{$title}</title> <comment>{$comment}</comment> <image>http://moeten.info/flex/20081201_mail2present/image/{$filename}.jpg</image> </result> EOD; header ("Content-Type: text/xml; charset=UTF-8"); echo mb_convert_encoding( $xml , "UTF-8" , "SJIS"); exit; } } } ?>