信頼はずっと、挑戦はもっと。

お問い合わせ
TEL:03-3496-3888

BLOG コアテックの社員ブログ (毎週月曜~金曜更新中)

LIST OF ARTICLES

記事一覧

  • テクログ

    受信メールの解析について2

    こんにちわ。パグ(▼・(エ)・▼)です。最近お外が寒くて、早くこたつを 設置しないと風邪をひいちゃうなーと思ってます。 前回はこんな書き方はダメだという、メールの解析について書きました。 受信メールの解析について1が、前回の終わりだと、 「具体的にどうやって取り出せばいいのよ?ヽ(`Д´#)ノ ムキー!!」 となると思います。なので、今回は取り出すって所について書いていきます。 前回書いたブログを振り返りますと・・・ 1.メールをシングルパート、マルチパートで考えちゃダメ。 switch(strtolower($this->structure->ctype_primary)) { case "text": // シングルパート(テキストのみ) 処理 break; case "multipart":  // マルチパート(画像付き) 処理 break; 2.ファイル名の拡張子をCtype_secondaryからとっちゃダメ。 //添付ファイルの拡張子を取得する $type = strtolower($part->ctype_secondary); //ファイルネームを作成する。 $file_name = date("YmdHis") . "." . $type; ファイルの拡張子の取り方と、シングルパートとマルチパートの判定について記述しています。 では、早速、メールを分解してみます。 入れ物を宣言しましょう。$body に内容を入れます。$attachementsに添付の情報を入れますので、 配列で宣言して下さい。 var $body = array('text'=> null , 'html'=> null ); var $attachments = array(); このあたりはお約束のやつです。 // メールソースを標準入力から読み込み if(!$params['input']) { //ログの出力を行ったりして下さいね。 exit(); // 読み込み失敗 } //PAERmimedecodeでメールの解析を行う。 $decoder = new Mail_mimeDecode($params['input']); $this->structure = $decoder->decode($params); //解析の関数を呼び出す $this->_decodeMail($this->structure); ここから解析の関数です。 ここのサイトが秀逸でしたので、引き続き非常に参考にして作りましたぁ。 http://d.hatena.ne.jp/ya--mada/20080415/1208318475     function _decodeMail(&$decoder) { // 上記ブログに載っていたこの再帰処理部分で、 // 分かれているテキストなんかも同じ所にしまうことができるし、 // 階層が深くなる場合もとれる用になります。 if (!empty($decoder->parts)){ foreach ($decoder->parts as $part){ $this->_decodeMail($part); } }else{ if (!empty($decoder->body)){ // 本文 (text or html ) if ( 'text' === strToLower($decoder->ctype_primary) ) { // ガラケーの特定機種用です。textの方に画像ファイルが入ってしまいます。 if (isset($decoder->ctype_parameters['name']) || _                                         isset($decoder->d_parameters['filename'])) { $tmp = isset($decoder->ctype_parameters['name']) ? _                             explode('.', $decoder->ctype_parameters['name']) : _                             explode('.', $decoder->d_parameters['filename']); $type = strtolower(array_pop($tmp)); $this->_set_attachments($decoder, $type); //ここでplainテキストを取り出しています。 //下記のようにtext,htmlを分ける事で、メールの種類がHTML形式でもテキスト形式でも取り出せます♪ //メールがiphoneなどから送られた場合「テキスト、画像、テキスト」みたいにわかれても再帰処理で //全部取り出してしまうので、$body['text']につながって入っています。 //(ここが他の参考サイト様よりも秀逸だと思った点です。) } else {     if ( 'plain' === strToLower($decoder->ctype_secondary) ) { $get_contents =& $decoder->body; $this->body['text'] .= $get_contents;      }elseif ( 'html' === strToLower($decoder->ctype_secondary) ) { $get_contents =& $decoder->body; $this->body['html'] .= $get_contents;      } } // その他(添付ファイルです、動画も静止画もデコレーション絵文字も) }else { $type = strtolower($decoder->ctype_secondary); $this->_set_attachments($decoder, $type); } } } return; } private function _set_attachments($decoder, $type){ // デコメ判定はヘッダーのcontent-idが入っていたらデコメです。 //一部例外がございますが、ここでは触れていません。 $content_id = ""; foreach($decoder->headers as $key => $headers){ if ($key == "content-id") { $content_id = $headers; break; } } //ファイル名はCtypeパラメータの['name']に入っていますが・・・ //そこにないときはd_parameters['filename']に入っています。 //前回のブログのとおり3キャリア、WEBメール、メーラー、スマフォはiphone,アンドロイドで //試しましたが全部取得可能でした。 //紹介したブログと異なる点ではcontnt_idを取得しているところとtypeをとっている点です。 if (isset($decoder->ctype_parameters['name'])) {     $this->attachments[] = array('mime_type'=>$decoder->ctype_primary.'/'.$decoder->ctype_secondary,  'file_name'=>$decoder->ctype_parameters['name'],  'type'=>$type,  'content_id'=>$content_id,   'binary'=>&$decoder->body); }else{      $this->attachments[] = array('mime_type'=>$decoder->ctype_primary.'/'.$decoder->ctype_secondary,  'file_name'=>$decoder->d_parameters['filename'],   'type'=>$type,  'content_id'=>$content_id,   'binary'=>&$decoder->body); } return; } これで、本文も添付ファイルも取れます!! 添付ありなしで分岐させたいときは$this->attachmentsの数を数えればOK。 ただし、メールの難しいところは、解析してなお落とし穴がたくさんある点です・・・。 メールの内容を使う時はこんな感じで取り出せます♪。 //本文使う時 $this->body['text'] //添付ファイルを保存するとき //配列の場所はメールの保存状態に併せてヽ(・∀・)ノ $length = strlen($this->attachments[0]['binary']); //本文の長さを取得 file_put_contents($tmp_name,$this->attachments[0]['binary'],$length); @chmod($tmp_name, 0777); もちろん上記でほとんどのメールがカバーできるようになりましたが、「ほとんど」であって、 全機種、全キャリアではないって事です。 上記で注意すべき点はデコレーション絵文字などが、attachmentsに入ってしまう点。つまり、 添付ファイルと同様に処理される点です。もちろん取得しないようなシステムのときは、contents-idが 入っていたら、取得処理を飛ばす、など色々改造してみてくださいね☆。 はい、では今回はこれ位で~次回はデコレーション絵文字の落とし穴について 書きます。次回ブログアップはいつになることやら~。 ではでは、パグでしたぁ~ヽ(・∀・)ノばいばいぷぅ☆ミ
  • テクログ

    受信メールの解析について1

    こんにちわ。パグ(▼・(エ)・▼)です。 技術ブログ自分回以外での更新ですが、 鬼ぶちょうのOKが出たので、きまぐれに更新します。 最近業務でメールの解析業務があったので、忘れそうなとこを備忘録として残そう!と思いました。 技術で分からない点があるときは、私としても、ネットをウロウロして 近い事象を探したりするものですが、今回はこの例はバグる!!って話をします。 所々間違いがある場合は「間違ってやがる・・・うぷぷ」とか心の中で思うなり、 弊社お問い合わせ(https://core-tech.jp/)にご連絡いただけると嬉しいです。 解析はPEARのMimeDecodeで行いました。 使用したモジュールは ・Mail/mimeDecode.phpです。 今回検証した媒体は ・WEBメールだと  google  msn  yahoo ・PCのメーラー ・ガラケー(au,docomo,softbank) ・スマホ(iphone,アンドロイド)です。 簡単に検証した内容についてですが、 上記の媒体のうちどれかからメールが送られてきて、受信したメールを 解析し、保存するってとこまでです。 まずはメールを解析するところなんですが、メールというのは大きく分けて (大多数の)添付なしメールのシングルパート (大多数の)添付ありメールのマルチパートに分かれています。 サーバーに送られてきたメールデータをメモ帳やvmで開いてみると、興味深いことが分かります。 (上部省略) From: XXXXXX@XXXX.ne.jp         (送り元) To:   XXXXXX@XXXX.ne.jp         (送り先) Subject: =?iso-2022-jp?B?GyRCJCIbKEI=?= =?iso-2022-jp?B?GyRCJCsbKEI=?=   =?iso-2022-jp?B?GyRCJDUbKEI=?= =?iso-2022-jp?B?GyRCJD8bKEI=?=   =?iso-2022-jp?B?GyRCJEolIhsoQg==?=     =?iso-2022-jp?B?GyRCJSsbKEI=?=   =?iso-2022-jp?B?GyRCJTUbKEI=?= Message-ID:  MIME-Version: 1.0 Content-Type: text/plain; charset="iso-2022-jp" Content-Transfer-Encoding: 7bit メール本文 これはシングルパートのメールになります。 見ればすぐに分かると思いますが、構造がすごく単純になってます。 次はマルチパートのメールについてです。 (上部省略) From: XXXXXX@XXXX.ne.jp         (送り元) To:   XXXXXX@XXXX.ne.jp         (送り先) Subject: =?iso-2022-jp?B?GyRCJCsbKEI=?= Message-ID:  Date: Thu, 4 Oct 2012 15:39:15 +0900 Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="-----=_NextPart_39325_15894_57999" -------=_NextPart_39325_15894_57999 Content-Type: text/plain; charset="iso-2022-jp" Content-Transfer-Encoding: 7bit メール本文 -------=_NextPart_39325_15894_57999 Content-Type: video/3gpp; name="121003_2001~01.3gp" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="121003_2001~01.3gp" AAAAIGZ0eXBrZGRpAAAAAGtkZGkzZzJhM2dwNTNncDQAAAAkdXVpZG12bWyojBHUgZcAkCcIdwMA AAAA///oBcyRy4QAAAA8dXVpZGVuY2mojBHUgZcAkCcIdwMAAAAAS0RESS1TTgBXNjRTAAAAAFNO (以下省略) マルチパートメールは添付ファイルもこの文字列に凝縮されています。 添付したファイルはバイナリ型で保存されています。 「Content-Type: video/3gpp; name="121003_2001~01.3gp"」 が添付ファイルです。 添付ファイルが複数添付されている場合はその分 -------=_NextPart_39325_15894_57999 Content-Type: video/3gpp; name="121003_2001~01.3gp" AAAAIGZ0eXBrZGRpAAAAAGtkZGkzZzJhM2dwNTNncDQAAAAkdXVpZG12bWyojBHUgZcAkCcIdwMA(以下略) -------=_NextPart_39325_15894_57999 Content-Type: video/3gpp; name="121003_2001~02.3gp" AAAAIGZ0eXBrZGRpAAAAAGtkZGkzZzJhM2dwNTNncDQAAAAkdXVpZG12bWyojBHUgZcAkCcIdwMA(以下略) こんな感じで区切られています。 このうちこの部分が Content-Type: video/3gpp content-type の「ctype_primary/ctype_secondary」って言います。 添付ファイルの解析方法について検証をかさねた結果、あちこちのサイトでありがちな こんな書き方だとプログラムがバグるということがわかりました。 switch(strtolower($this->structure->ctype_primary)) { case "text": // シングルパート(テキストのみ) 処理 break; case "multipart":  // マルチパート(画像付き) 処理 break; これです!!調べた3サイトのうち2サイトがこんな検証方法を使用していました。 ctype_primary に入ってる値が必ずしもtext 、multipartとは限らないのです。 画像つきでもmultipartじゃなくてtextのほうに入ってるときがあるんですよ。ガラケーの特定機種なんですが、 textしかないからって「これはシングルパートメールなんだね☆」って判定しちゃうのは危ないことです。 次にこんな書き方を良く見ます。 //添付ファイルの拡張子を取得する $type = strtolower($part->ctype_secondary); //ファイルネームを作成する。 $file_name = date("YmdHis") . "." . $type; ctype_secondaryで拡張子付けちゃう人が多いですけどね・・・\(^o^)/これは大きな間違いです。 必ずしもctype_secondaryが拡張子になるとは限らないからです。WEBメールから送信した場合なんかは octet-streamやx-msvideo、alternativeになったり、iphone から送信した場合3gppなんかが ctype_secondaryに入ってきたりしますので、そのまま出来たものとして嬉々として公開するとバグります。 改修を行ったプログラムがまさにこの状態で( ՞ਊ ՞)コノヤローってなりました。 なら、どうしたら判断できるのか? まず、シングルパートなのかマルチパートなのかって判定方法はあきらめることです。 シングルパートなのか、マルチパートなのかってことよりも、添付ファイルがあるのかないのか? ってことを考えましょう。もちろん、添付ファイルが更にデコレーション系絵文字なのかどうか、 なんてことも判定可能です。 そんでもって、拡張子なんて元のファイル名の「.」以降からとっちゃえばいいですね。 ワザワザ別枠からとる必要がないってことです。 ちなみにこのサイトのコードは非常に秀逸でしたので、参考にして作りましたあ。 http://d.hatena.ne.jp/ya--mada/20080415/1208318475 マルチパートだとここにalternativeなどの意味が書いてあってよかったです。 http://www.atmarkit.co.jp/fnetwork/rensai/netpro04/netpro01.html 今回ネット情報は結構あてにならない!と思いました。内容はあくまで、とっかかりや参考程度に考えて、ちゃーんと検証して、修正してからリリースしましょう。次回もメールの解析を行います☆ 次回ブログアップはいつになることやら~。 ではでは、パグでしたぁ~ヽ(・∀・)ノばいばいぷぅ☆ミ
  • テクログ

    apache(XAMPP)のvhostsの設定について

    こんにちわ。パグ(▼・(エ)・▼)です。 まだ先だと思って油断してたら、投稿日になってしまいました・・・。 本日は、apacheから、バーチャルホストの設定方法を書いてみたいと思います。 ちなみに、実際のサーバーではもう少し細かく色々設定が 入ってきたりするので、あくまで、ローカルXAMPP上でのapacheの設定という前提をお忘れなく。 まず始めにパグの環境と、XAMPPバージョンは以下の通りです。 XAMPPインストール先ディレクトリ:Cドライブ直下 XAMPP 1.7.7 [PHP: 5.3.8] さて、バーチャルホストって何かというと、一つのサーバーに複数のホスト名(ドメイン名)を 割り当てて、複数サイトを管理・運営するための技術です。 XAMPPを入れた時に初期の設定では「localhost」と打ち込むか、XAMPPControlパネルから Apacheのadminボタンを押下すると、  こんな画面が表示されます・・・。 このXAMPP apacheに新しくWEBサイトを追加したいと思います。 じかにC:xampphtdocs配下に新しいプロジェクトを作成出来る人はよいのですが、 ecripsなどでSVNからファイルをとってきた場合、最初のディレクトリ構成が C:xampphtdocsプロジェクト名branshes C:xampphtdocsプロジェクト名tags C:xampphtdocsプロジェクト名trank 上記のように分かれていて、初期画面が更にtrankの下の下の下の・・・・ なんて深い階層になっている時があります。 新しくSVNから取得したこのサイトなんですが、トップページを表示させるためのURLが非常に複雑です。 実際の階層をみてみると・・・  C:xampphtdocsプロジェクト名trunksrcpublic このように、トップページがhtdocsのかなり下にあるのが分かります。 このままでも表示はされますが、都度、このURLを入力するのは面倒です。 「http://localhost」のように「http://test(任意の名前)」で表示できた方が便利だと思いませんか? そんな時に役立つのが、このバーチャルホストって技術です。 ではapacheの設定ファイルから変更していきます。XAMPPのC:xamppapacheconfextraというディレクトリ 配下にある「httpd-vhosts.conf」というファイルを開いてみてください。メモ帳やテキストエディタで開く事ができます。 インストール直後はこんな感じになってます。(以下) (上部省略) ##NameVirtualHost *:80 # # VirtualHost example: # Almost any Apache directive may go into a VirtualHost container. # The first VirtualHost section is used for all requests that do not # match a ServerName or ServerAlias in any  block. # ##     ##ServerAdmin postmaster@dummy-host.localhost     ##DocumentRoot "C:/xampp/htdocs/dummy-host.localhost"     ##ServerName dummy-host.localhost     ##ServerAlias www.dummy-host.localhost     ##ErrorLog "logs/dummy-host.localhost-error.log"     ##CustomLog "logs/dummy-host.localhost-access.log" combined ## ##     ##ServerAdmin postmaster@dummy-host2.localhost     ##DocumentRoot "C:/xampp/htdocs/dummy-host2.localhost"     ##ServerName dummy-host2.localhost     ##ServerAlias www.dummy-host2.localhost     ##ErrorLog "logs/dummy-host2.localhost-error.log"     ##CustomLog "logs/dummy-host2.localhost-access.log" combined ## お気付きかもしれませんが、##の部分はコメントアウトされており、有効になっていない状態です。 ここに、下記の通り設定を追加していきます。 NameVirtualHost *:80     DocumentRoot "C:/xampp/htdocs"     ServerName localhost     DocumentRoot "C:/xampp/htdocs/プロジェクト名/trunk/src/public"     ServerName test ではこれをブロック毎にみてゆきましょう。 NameVirtualHost *:80 ここで設定するためにみる、IPとポート番号を指定することができます。 上記の場合ですと、*(全部のIP)、80番ポートという意味になります。 勿論通常のサーバーでしたら、IPアドレス:ポート番号で指定することが可能です。 例えば「0.0.0.0:80」みたいな感じです。 よくわかんなーい!という人は上記の通り*全IPの80番を指定しましょう。 次に     DocumentRoot "C:/xampp/htdocs"     ServerName localhost これは元々表示されていた、xamppの管理画面をそのまま使うために必要な記述になります。 これを指定しないとxamppの管理画面が見れなくなってしまいます。 ここで指定している「」の「*:80」もIPアドレスとポート番号を意味しています。 DocumentRootは実際のファイルが設置してある場所を指定しましょう。 「C:」直下にXAMPPを入れた場合は上記と同様で良いでしょう。 次に     DocumentRoot "C:/xampp/htdocs/new_organic/trunk/src/public"     ServerName test(任意の名前) これが、先ほどの長いルートを短くまとめる箇所になります。 実際のファイルのトップページが配置されているルート。そして、servername に好きな名前を付けましょう。 さて、これでapacheのバーチャルホスト設定が完了致しました。 早速接続してみます。 これだけでは対象の画面を開く事ができません(´・ω・`)やだった・・・。 そうです、まだ設定が足りていないのです。 次はhostsの設定です。 C:WINDOWSsystem32driversetc の配下にある「hosts」というファイルをメモ帳やテキストエディタで開いてみましょう。 # Copyright (c) 1993-1999 Microsoft Corp. # # This is a sample HOSTS file used by Microsoft TCP/IP for Windows. # # This file contains the mappings of IP addresses to host names. Each # entry should be kept on an individual line. The IP address should # be placed in the first column followed by the corresponding host name. # The IP address and the host name should be separated by at least one # space. # # Additionally, comments (such as these) may be inserted on individual # lines or following the machine name denoted by a '#' symbol. # # For example: # #      102.54.94.97     rhino.acme.com          # source server #       38.25.63.10     x.acme.com              # x client host #127.0.0.1       localhost こんな具合になっているかと思います。ここに、 127.0.0.1 localhost 127.0.0.1 test 上記二行を追加します。hostsや、この127.0.0.1の意味を知らない人いるの!? やだあ・・・(´・ω・`)教えません!! 下記を読んでください。 http://ja.wikipedia.org/wiki/Hosts http://ja.wikipedia.org/wiki/Localhost あとは、ローカルループバックアドレスでググってみてください。良いサイトが見つかるかと思います。 これで設定完了です。XAMPPのapacheを再起動しましょう。 WebサーバはLINUXサーバーに乗っているときはコマンドでrestartさせるかと思いますが、 XAMPPはGUIから再起動がかけられるので非常に簡単ですね。 では接続してみます。  表示できましたので、これでOK!!ファイルを物理的に移動しなくても好きなドメイン名で サイトの表示が可能になりましたね。 一応XAMPP管理画面の表示も試してみましょう。問題なく表示されるかと思います。 バーチャルホストは便利で簡単だね!!これを活用して、色々なサイトをローカル環境で動かして見て下さい♪ ではでは、パグでしたぁ~ヽ(・∀・)ノばいばいぷぅ☆ミ