携帯メールで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;
        }
    }
 }
?>