Laravel5でphp-imapからgmailにアクセス【cloudpack 大阪 BLOG】

PHPからgmailを取得したいと思い、方法を調査していたところphp-imapを使って取得できることがわかりました。が、結構ハマってしまいました。
今回はLaravel5を使ってgmailから固定条件で検索したメールの件名を一覧で表示させるサンプルアプリを作成してみました。

環境

 以下の構成でサンプルアプリを作成しました。
 ApachePHPのインストール等、Laravel5が動作する環境を構築をしておいてください。

サーバー : Amazon Linux
Webサーバー : Apache 2.4
PHP : php 5.6
php framework : Laravel5

php-imapのインストール

 まずはphp-imapモジュールのインストールを行います。

yum install php56-imap

phpのバージョンに合わせてインストールしてください。

Controllerの作成

[project_root]/app/Http/Controller/GmailController.phpを作成する

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;

class GmailController extends Controller
{
     public function getIndex()
     {
        $server = "imap.gmail.com";
        $port = 993;                 // ポート番号
        $account = "test@gmail.com"; // Gmailアカウント
        $password = "password";      // パスワード
        $mailbox = "{".$server.":".$port."/novalidate-cert/imap/ssl}INBOX";

         // メールサーバ接続
        $mbox=null;
        $mbox = imap_open($mailbox, $account, $password) or die('Cannot connect to Gmail: ' . imap_last_error());
        
        // メール検索(検索条件:件名にTEST MAILが含んでおり、受信日時が2015/08/08以降)
        $result = imap_search($mbox,'SUBJECT "TEST MAIL" SINCE "8 August 2015" ', SE_UID);
        
        $mail=null;
        for($i = 0;$i<count($result);$i++){
            // ヘッダ情報の概要を取得
            $overview = imap_fetch_overview($mbox, $result[$i], FT_UID);
            // 件名、送信元アドレス、送信日を取得
            $subject = mb_convert_encoding(mb_decode_mimeheader($overview[0]->subject), 'utf-8');
            $from = mb_convert_encoding(mb_decode_mimeheader($overview[0]->from), 'utf-8');
            $date = date("Y-m-d H:i:s", strtotime($overview[0]->date));

            $mail['subject'] =$subject;
            $mail['date'] = $date;
            $mail['from'] =$from;

            array_push($mail_data,$mail);
        }
 
        // メールボックスのクローズ
        imap_close($mbox);

        return view('gmail.index')->with('mail_data',$mail_data);

     }
}

Viewの作成

resources/views/app.blade.phpを以下のように修正
共通レイアウトファイルでjqueryとbootstrapを読み込んでおきます。(好みで修正してください)

<!DOCTYPE html>
  <html lang="ja">
  <head>
      <meta charset="UTF-8">
      <title>Gmail Test</title>
      <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

  </head>
  <body>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>

      <div class="container">
          <div class="row">
              <div class="col-md-12">
                  @yield('content')
              </div>
          </div>
      </div>
  </body>
  </html>


[project_root]/resources/views/gmail/index.blade.php

@extends('app')
@section('content')

<h1>Gmail</h1>

<div  class="container">
    <table class="table table-striped table-bordered">
        <tr>
            <th>#</th>
            <th>date</th>
            <th>subject</th>
            <th>from</th>
        </tr>

@foreach ($mail_data as $index => $recorde)
        <tr>
            <td>{{$index+1 }}</td>
            <td> {{ $recorde['date'] }}</td>
            <td> {{ $recorde['subject'] }}</td>
            <td> {{ $recorde['from'] }}</td>
        </tr>
@endforeach

    </table>
</div>    

@endsection

Routingの設定

Route::controller('gmail', 'GmailController');

実行確認

「url/gmail」にアクセスしてみましょう。Gmailにアクセスしているため表示まで少し時間がかかります。
f:id:cloudfish:20151014212304p:plain
 正しく表示されない場合は、Gmailでブロックされている可能性が高いので、以下のハマったところを参考にしてみてください。

ハマったところ     

imap_openでCouldn't Open Stream エラー

以下のエラー画面が表示されました。
f:id:cloudfish:20151014203321p:plain

 まずは接続先、ポート番号、アカウント、パスワードに誤りがないか確認しましたが問題なさそうです。ググッてみましたが、設定を見直すというところで良く分かりませんでした。
そこで、以前にメールボックスtelnetでアクセスしたことを思い出し、コマンドで直接アクセスできるか試してみました。
 

openssl s_client -connect imap.gmail.com:993 -crlf 
? login test@gmail.com password

参考:telnet(openssl)でIMAPプロトコルを喋ってGmailに命令を出す。 - それマグで!

このコマンドで直接アクセスしても接続出来ませんでした。ということでもしかするとGmail側でブロックされているのかも?という可能性を疑ったところ、「ログイン試行をブロックしました」というメールが届いていました。(早くきづいておけば・・・)
ひとまず接続確認をしたかったので、セキュリティ的にオススメではありませんが「安全性の低いアプリがアカウントにアクセスするのを許可する」(下記参照)設定を行ったところ、コマンドでのアクセス確認ができアプリからも正常にアクセスできました。

参考:安全性の低いアプリがアカウントにアクセスするのを許可する - Google アカウント ヘルプ

このままではセキュリティ的によろしくないので他に方法がないか調べたところ、アプリ用のパスワードを設定する方法がありました。(下記参照)2段階認証を有効にしてアプリ用パスワードを発行し、プログラム内のパスワードをアプリ用パスワードに変更して再度実行して表示されることが確認できました。

参考:アプリ パスワードでログイン - Google アカウント ヘルプ

検索したメールが正しく表示されない

 次に固定文言で検索したメールを表示させたところ、タイトルにその文言が含まれていないメールが表示される問題がありました。
これは、imapの仕組みを良く分かっていなかったことと、imap_searchのリファレンスをしっかり読んでいなかったことが原因でした。コードをコピペして修正するだけではダメですね。
imapではメールにメッセージ番号とUIDの2種類の番号が割り当てられているようで、↑のコードではimap_searchの引数にSE_UIDを指定したためUIDが返されていました。当初、件名を取得するのにimap_headerinfo関数を使用していましたが、これはメッセージ番号をキーに取得する関数なので検索条件に該当しないメールが取得されていました。なので、ヘッダー情報をUIDでも取得できるimap_fetch_overview関数を使うことで解決しました。これでメールを取得できるようになったので、色々と効率化できそうです。

.ssh/configの便利な設定【cloudpack 大阪 BLOG】

 管理するサーバ台数が増えてくるとSSHでの接続が手間になりconfigに設定を書くことも多くなると思います。
 また、扱うサーバ台数が増えてくるとそもそもconfigに記載したかどうかすらも分からなくなってきます。そこで今回は、「.ssh/config」を利用するときにちょっと便利になる設定を紹介します。

Host名の補完機能

 これはHost名を補完してくれる機能です。地味に便利な機能です。

インストール方法

 以下のコマンドを実行し補完機能をインストールしてください。
この機能はsshだけでなくserviceコマンドなど他のコマンド実行時においても補完してくれます。

# Mac
brew install bash-completion
# CentOs
yum --enablerepo=epel install -y bash-completion
使い方

ssh a」とタイプしたあとTabをタイプすると一致するHost名を表示します。
候補が複数ある場合は可能性のある一覧が表示されます。

$ ssh a<Tab>
$ ssh abc_web_01

Host名の一覧表示

 Host名の一覧を表示するコマンドを自作しました。補完機能でほぼまかなえますが、Host名の先頭のを覚えていない時に。
 以下のコマンドを「.bash_profile」なりに設定してください。

設定方法
alias sshlist="cat ~/.ssh/config |grep ^Host\  |sed -e 's/^Host\ //g'"
使い方

使い方は「sshlist」とするだけでHostの一覧が表示されます。

下記のようなconfig設定があったとして

Host abc_web_01
HostName 111.111.111.001
IdentityFile ~/.ssh/abc_id_rsa1
User ec2-user

Host def_web_01
HostName 111.111.111.002
IdentityFile ~/.ssh/def_id_rsa1
User ec2-user


これに対して実行すると

$ sshlist
abc_web_01
def_web_01

Host名に「def」を含む一覧を表示

$ sshlist |grep def
def_web_01

タイムアウト防止

一定時間操作しなかった場合にタイムアウトすることがありますが、以下の設定をすると
指定時間時間ごとに通信をしてタイムアウトを防いでくれます。

ServerAliveInterval 15

サーバのタイムアウト設定は基本的にはセキュリティを考慮したもののため、
この設定をして回避するのは微妙な気がします。

おまけ

scpコマンドからでも.ssh/configが利用できます。

ファイル受信
scp  abc_web_01:/home/user/remotefile.txt /tmp/ 
ファイル送信
scp  localfile.txt abc_web_01:/home/user/

貝塚 2015.09.20

天候  :曇

釣行時間:04:00 - 07:00
釣果  :サゴシ 1匹、エソ 1匹

 

 朝の4時過ぎに釣座を確保し釣り開始。タチウオシーズンなのでこの時間でもかなり人が多いですね。かなり肌寒い状況です。まずはワインドでタチウオ狙い。今年はどうでしょうか?若干、風と波があり少しあたりが取り辛い状況でした。ワインドの色を変え、ジグに変えと色々試行して5時半過ぎまで粘りましたが、時合も特になく周りでは隣のえさ釣り師が1匹釣っていたくらいでした。 もちろん自分もヒットなし。本命の青物に期待することにします。

 

f:id:cloudfish:20150921234028j:image

 

 タチウオに見切りを付けて青物タックルに持ち替えて、ジグでキャスト開始。風もおさまってきました。1時間位キャストを続けていましたが、ベイトも見当たらずナブラもないので、今日もボウズかと諦めかけていました。が!6時半前に底付近でフォールでヒット!ヒットの仕方と引きからエソっぽいと思いつつ期待して寄せてみましたが、やっぱりエソでした。残念!せっかくですが、海にお帰りいただきました。引きだけは楽しませてもらいました。ともあれ、活性が上がってきたかと期待してキャストし続けると、中層付近でひったくるような感じでヒット!これは青物確実と思い寄せてみると今季初サゴシ!ヒットパターンは少しテンポの早いワンピッチジャークでした。サゴシを〆てすぐにキャストを開始しましたが、群れはもう去っていったのかこれ単発でした。

 
f:id:cloudfish:20150921233911j:image

 

今回はリーダーにワイヤーを使ってなかったのですが、針が1つサゴシに切られていました。サゴシの歯は鋭いですね。針を外すときはくれぐれも気をつけてください。もう一つも噛まれてボロボロになっていたので、抜き上げずにネットでランディングして良かったです。

 

 f:id:cloudfish:20150925095900j:plain

 

Cloud9でLaravel5の環境構築【cloudpack 大阪 BLOG】

  前回はCloud9の初期設定までしたもののPHPについては、Ruby on Railsのようにワンボタンでの環境構築が準備されていなかったので、CakePHPかLaravelのどちらにするか迷った末に軽量FWと言われているLaravel5を導入することにしました。

プロジェクト作成 

f:id:cloudfish:20150913020155p:plainWorkspace名とテンプレートにPHPを選択します。Hosted workspaceはPrivateでもPublicでもどちらも構いませんがPublicの場合はすべての人に公開されてしまいます。またフリー版ではPrivateのWorkspaceは1つだけとなっています。

 

Laravel5のプロジェクト作成

新しいタブでターミナルを開いてください。
以下のコマンドを実行してプロジェクトを作成してください。

rm README.md php.ini hello-world.php
sudo composer self-update
composer create-project laravel/laravel ./laravel --prefer-dist
shopt -s dotglob
mv laravel/* ./
rm -rf laravel

完了まで数分かかかります。

 

Apacheのconf設定

以下のファイルをviで開いて、DocumentRootを以下に変更してください。

sudo vim /etc/apache2/sites-enabled/001-cloud9.conf

編集箇所 

DocumentRoot /home/ubuntu/workspace/public


アップデート 

composer update

 

DB設定

プロジェクトを作成した際にMySQLのDBが同時に作成されています。
まずは下記コマンドを実行して接続先のホスト名を確認しましょう。

mysql-ctl cli
use c9;
select @@hostname;  ←ホスト名が表示される
exit

 

LaravelのDB接続設定 

 ワークスペースの直下に「.env」ファイルがありますが、エディタのエクスプローラーからは見えないです。(設定で表示可能かもしれませんが分かりませんでした。)ターミナルからファイルをvimで開いて編集してください。

 

DB_HOST=HOSTNAME  ←上で確認したホスト名をセット
DB_DATABASE=c9     ←初期値
DB_USERNAME=USERNAME ←cloud9のユーザー名
DB_PASSWORD=      ←初期値は空でOK

 

起動確認

ひと通り設定は完了したので、Apacheを起動して確認してみましょう。
Runボタンをクリックして画面下部に表示されたurlをクリックすると初期画面が表示されます。下記のように表示されていれば完了です。(Laravel5の場合)

f:id:cloudfish:20150913020234p:plain

 

手軽に環境を作成したいと思いましたが、テンプレートが用意されていないとまだまだ手間がかかります。ここはもう少し改善を期待したいです。


また、Laravelのプロジェクトとしてアプリを利用するためには、権限の変更などまだいくつか設定が 必要になりますが、そこは下記リンクや他で色々と紹介されていますので参照してみてください。

  

 

参考

Laravel · Cloud9

ReaDouble

Laravel5初期設定&環境設定まとめ - 魔法使いの卵

 

大磯サーフ 2015.09.16

天候  :小雨
釣行時間:16:00 - 18:00
釣果  :なし

 今年は雨が多いですね。天気予報の曇を信じて出発したものの大磯駅に到着してすぐに雨が降り出しました。家を出る時に降ってくれてれば諦めめもつきましたが。せっかくなので釣具店で簡易カッパを購入し、最近の釣果とポイントを聞きつつ海岸へ。今朝はワカシとサバがあがっていたそうです。
 波は結構穏やかでしたが、満ち潮なので少しずつ波がせり上がってきているため荷物を適当な場所に置いて釣り開始。30-40gのジグをローテーションし、途中弓角も試しました。無反応。ベイトも見当たらず穏やかな海でした。ちょくちょくポイント移動しましたが反応なし。ジグの着底が早いので全体的に水深は浅そうです。数回あたりらしきものもあったものの本日も撃沈。やっぱり早朝に行くべきか。車が必要だ

f:id:cloudfish:20150916214713j:image

 今回、中古品で状態の良さそうなコルトスナイパーS1000Mを手に入れたので、早速使用してみることにしました。普段はクロスライド1002LSJを使用しているのでそれと同程度の性能を見込んでいましたが、思った以上に先端が柔らかくジグを投げるのもアクションさせるのも結構疲れました。今の自分には合わないようです。3年前くらいなら丁度よかったかもしれません。やっぱりロッドは使ってみるまで分からないですね。



大磯海岸釣り日記

大磯サーフ 青物 - 大磯の釣りブログ|釣りペディアブログ

ジギング超入門テキスト●Gear-Labプロスタッフレポート

Cloud9でお手軽開発【cloudpack 大阪 BLOG】

 最近何かをちょっと試したり作ったりするのに開発環境を構築するのがすごく面倒に感じてきました。環境構築自体はすごくいい勉強になるのですが、脱線することも多くなるので手軽に環境構築したいと思いCloud9を試してみることにしました
 Cloud9とはWebブラウザ上で開発できる統合開発環境です。少し前まではブラウザで開発するのはパフォーマンスの問題などもありまだ先かと思っていましたが、使ってみてかなり完成度が高いと感じました。
 また、テンプレートとして「node.js」や「Ruby on Rails」などの環境がワンボタンで構築できるようになっており、かなり手軽にプログラミングが始めれます。
 今回は、導入方法について紹介したいと思います。

初期導入

https://c9.io/

f:id:cloudfish:20150904092731p:plain

「TRY IT NOW」をクリック

 

ユーザー情報登録ページ 

f:id:cloudfish:20150908002426p:plain

ユーザーID、メールアドレス、パスワードを入力して「Create your free account」をクリックする。

 

完了ページ

 f:id:cloudfish:20150904092759p:plain

 メールが来るのでメール認証を済ませておく。

  

 初期画面

f:id:cloudfish:20150904092800p:plain

この画面がプロジェクトを 管理するワークスペースになります。
まずは、エディタの雰囲気を知るためDemo Projectを開いてみましょう。

 

開発環境(初期画面)

f:id:cloudfish:20150904092804p:plain

デザインはクールですね。かなりサクサクと動作します。
もはやWebブラウザとは思えないです。

テキストエディタ

f:id:cloudfish:20150904092809p:plain

デモのPHPファイルを開いてみました。コードのハイライトもされています。
「Run」ボタンで実行してみましょう。

 

実行画面

f:id:cloudfish:20150904092813p:plain

Apacheが起動し、新しくタブでブラウザが開きます。ブラウザの中でブラウザが開きます。「Hello World」が表示されましたね。もちろん通常のブラウザからでも確認できます。

 

f:id:cloudfish:20150904092817p:plain

せっかくなので、少し修正してみます。phpinfoを表示させてみます。
コード補完が効いていい感じです。デバッグもできるのが凄いです。

 

f:id:cloudfish:20150904092820p:plain

リロードすると、phpinfoが表示されました。
ただ、よく分からなかったのは「Run」でApacheが起動するのですが、「Stop」では停止してくれないようなので、コマンドで停止するしかありませんでした。

 

 その他の機能

キーバインド設定
f:id:cloudfish:20150908003810p:plain

cloud9を気に入った理由の一つにエディタにvimが使えたことがあります。
他にもemacssublimeの入力モードが使えます。


ターミナル
f:id:cloudfish:20150908003817p:plain

cloud9はプロジェクトごとにコンテナで割り当てられてるようです。(多分)
なので、コマンドが実行できます。操作性も通常の仮想端末と遜色ありませんでした。
ただ、これは無料環境だからなのか分かりませんが、動作に時間がかかることがありました。

クリップボード
Cloud9 - Chrome Web Store

chrome.google.com

 デフォルトではクリップボードからのペーストが出来ませんが、上記のChromeのアドオンをインストールすると使えるようになります。

思った以上の完成度で驚きました。オープンソースなので自分の環境にインストールすることも可能です。ちょっと試したり新しい言語に触れたりするときにスムーズに環境を整えやすいと思います。次はもう少し突っ込んで触ってみたいと思います。

Ops JAWS#1の感想【cloudpack 大阪 BLOG】

 9/1(火)に目黒のアマゾン データ サービス ジャパンにて開催されたOpsJaws第1回に参加してきました。結構人気が高かったようで、告知から数時間で満席となりキャンセル待ちが30名程度あったそうです。たまたま告知に気付いて即申し込みをしたので運よく参加できました。
 今回は3本建てで、運用の目指すべきところ、実際の運用現場、AWSサポートの使い方といった運用に携わる人が実際に聞きたい話が聞けたのではないかと思います。

クラウド時代の運用エンジニアは何が変わるのか

 正直なところ運用に携わりはじめたばかりの自分にとって、波田野さんのお話は少し難しい話も多くありました。理解できたところとしては、運用業務のなかで本当にその作業が必要なのか?それをすることでサービス価値の向上に繋がっているのか?というところを運用エンジニアも突き詰めていく必要があるということでした。これは運用現場だけでなく開発現場でも通じる話ですし、日本の現場ではこれをもっと考えていく必要があると個人的には思ってます。
 もう一つ衝撃だったことが「 S S H ログインをしたら負け」ということを仰っていました。これに肯定的な人はクラウドネイティブな人だそうです。大きくはノンEC2を目指して可能な限りマネージドサービスを利用しろということかと思いますが、数年後にはそれが当たり前の時代が来るだろうということでした。皆さんはどう思われますか?

www.slideshare.net

cloudpack MSP運用の表と裏

 我らがボスの新谷さん。cloudpackを初期から支えてきた本当の運用現場を知る数少ない1人です。普段、職場では聞けない話が聞けると思い楽しみにしていました。表の話は淡々と裏の話は楽しそうに語っているのが印象的でした。やはり皆さん表より裏の話に興味があるようで、最後の「結局は人に頼らざるを得ない」という一言が身に沁みました。どれだけツールや仕組みを導入して属人性を排除しようとしてもそう簡単には物事は進まないということでしょうか。これは今後自分も身を持って知ることになるんだろうと思います。

www.slideshare.net

運用視点でのAWSサポートの利用Tipsの話

 ラストはAWSサポートの関山さん。サポートのうまい使い方として、問い合わせの際にどういった情報を提供すれば迅速に対応してもらえるのかということをお話しいただきました。重要な事は困っている度合いをしっかりと伝えることだそうです。
 また、AWSの機能として「AWS Trusted Advisor」というものを初めて知りました。これはコストや環境構成などについてAWSからアドバイスがもらえるようです。実際に使っていた人からもかなり使える機能だということでした。無料で始めれるのでまず自分のアカウントで使ってみようと思います。

www.slideshare.net

 こういった勉強会にはたまに参加するのですが、行くと色々な刺激があって来て良かったと思います。行くまでの心理的ハードルが結構高いかとは思うのですが、皆さんまずは参加してみてはどうでしょう?
 次回は10月末頃に開催されるそうです。