【php】IMAPでメールをチェックしてコマンド実行するスクリプト

2015年2月14日プライベートgmail,imap,mail,php,ゆっくり,新着

sc20150214235107

追記:VerUP他

RaspberryPiに繋いでるスピーカーを常時通電させているので、時報だけ言わせてるのはもったいないと思い、メールの重要な着信をお知らせしようかと。

以下、時報の時の記事。https://blog.ahh.jp/?p=6418

久々に、PHPスクリプトをこしらえてみました。超ど忘れしとる(;´Д`)

まんま、スクリプトを貼ります。

アカウントとパスワードを書き換えれば、どこでも動くんではないでしょうか(Gmailなら)INBOXに続くパスを加えれば、振り分けルール等を対象に出来ます。

cronとかで定期的に動かす感じでしょうか。

注意する点として、IMAPサーバに負荷を掛けたくなかったので、純粋な最新メールを取得する訳ではありません。厳密には日付ソートによるメールではなく、メールサーバが受信した最新のメールとなります。

どういう事かというと、IMAPサーバの構成を変更した時に、メールの受信が前後する場合があります。レアケースですけどね(;^ω^)テストしてたら分かったんだけども・・。

コマンドには好きなものを書けるはずです。CRON内なら、必要な環境変数をCRONに渡す必要があるので注意。Pathとか

棒読みちゃんで、件名とか喋らしたいんだけども、さすがにラズパイには厳しいでしょうね。

追記:

ちょっとだけバージョンアップしました。あと、サンプル用に、ゆっくりの音声を用意しました。よければどうぞ。

  • 音声サンプル(ゆっくり音声)
  • PHPスクリプト(PHP本体と音声再生用のシェルスクリプト)
    ※スクリプト内のパスなどは、適宜変更してください

動作説明:IMAP新メールから取得していき、指定時間内に受信したもの&未読メールで、指定ドメイン毎に、独自コマンドを実行できます。低負荷で動作します。送り元メールアドレスを、正規表現にて限定してます。

RaspberryPi(Rasbian/Debian)上で動作確認してますが、環境依存はしないはずです。PHP5/PHP5-IMAPパッケージが必要です。IMAPからの戻りに数秒掛かります。メモリの消費もType-Bなら大丈夫なようです。

<?php
date_default_timezone_set('Asia/Tokyo’);
/*
* IMAPから新しいメールを取得し、条件に合致した場合、コマンド実行
* (条件:未読・指定送元・時間)
*/

//IMAPサーバ設定
define('GMAIL_HOST’, 'imap.googlemail.com’);
define('GMAIL_PORT’, 993);
define('GMAIL_ACCOUNT’, 'foo@gmail.com’);
define('GMAIL_PASSWORD’, 'password’);
define('SERVER’,'{'.GMAIL_HOST.’:’.GMAIL_PORT.’/novalidate-cert/imap/ssl/readonly}’);
//設定
define('TARGET_MAILS’, 20);        //取得するメール数(最新から)
define('TARGET_HOURS’, 1);        //最新メールとする時間(時)
//
define('FIND_CMD’, ");            //実行するコマンド(その都度)
define('FIND_CMD_ONES’, '~nabe/check_imap/talk_maildesu.sh’);    //実行するコマンド(最後に一度だけ)

//対象のメール送元(正規表現記法 , コマンド)
//※コマンドが空の場合、FIND_CMDが実行される

$TARGET_SENDER = array(
    '/twitter\./’ => '~nabe/check_imap/talk_twitter.sh’,
    '/rakuten\.co/’ => '~nabe/check_imap/talk_rakuten.sh’,
    '/amazon\.co/’ => '~nabe/check_imap/talk_amazon.sh’,
    '/yahoo\.co/’ => '~nabe/check_imap/talk_yahoo.sh’,
    '/nicovideo\.jp$/’ => '~nabe/check_imap/talk_nikoniko.sh’

);
$find_mail = 0;
//IMAP
if (($mbox = @imap_open(SERVER."INBOX", GMAIL_ACCOUNT, GMAIL_PASSWORD)) == false) {
    echo “canot connect server.";
    exit(1);
}
//件数取得
$status = imap_status($mbox, “{“.GMAIL_HOST."}INBOX", SA_ALL);
if($status->messages != 0) {
    $mail = null;
    //取得
    for( $mailno = $status->messages – TARGET_MAILS;$mailno <= $status->messages; $mailno++ ) {
        $head = imap_header($mbox, $mailno);
        //未読?
        if(@$head->Unseen == 'U’){
            //整形
            $mail[$mailno]['date’] = $head->date;
            $mail[$mailno]['address’] = $head->from[0]->mailbox.’@’.$head->from[0]->host;
            if( !empty($head->subject) ) {
                $mhead = imap_mime_header_decode($head->subject);
                $mail[$mailno]['subject’] = ";
                foreach( $mhead as $key=>$value) {
                    if( $value->charset != 'default’ ) {
                        $mail[$mailno]['subject’] .= mb_convert_encoding($value->text,’UTF-8′,$value->charset);
                    }else{
                        $mail[$mailno]['subject’] = $value->text;
                    }
                }
            }
            $mtime = strtotime($mail[$mailno]['date’]);
            $tdiff = abs(time() – $mtime);
            //対象の最新メール?
            if($tdiff < TARGET_HOURS * 3600){
                $cmd = “";
                foreach($TARGET_SENDER as $key=>$value){
                    if(preg_match($key,$mail[$mailno]['address’])){
                        //対象メール発見
                        //var_dump($mail[$mailno]);
                        $cmd = FIND_CMD;
                        if($value != ") $cmd = $value;
                        $find_mail++;
                    }
                }
                //コマンド実行
                @exec($cmd);
            }

        }
    }
}
@imap_close($mbox);
if($find_mail > 0) {
    //コマンド実行
    @exec(FIND_CMD_ONES);
}
exit(0);
?>

テストはまだ数日程度ですので、自己責任にてお願いします。

コード内で、件名もエンコード取得してますが、特に利用してません。件名に引っ掛けて、動作するようにもできます。適当に改造してください。

私の場合は、時報と重なってしまうので、コードの上部に「sleep(30);」とか入れて、ちょっと遅らせてます(30秒)

sc20150215231754

そういや、無意識にPHPスクリプトを書いて、Windowsからラズパイにコピーして動作させようとしたら、動かない・・。

ラズパイに、PHPを入れてませんでしたw(;^ω^)そういや、ウェブサービス使ってないか。

以下、もしPHP環境が入ってなかった場合の手順です。

aptitude updateと、aptitude upgradeは事前に行っておく(パッケージを最新にしておく)

aptitude install apache2 php5 php5-imap

として、3パッケージ分入れます。ついでなので、apache2(Webサーバ)も入れておく。

ラズパイでの、php5-imapパッケージは、デフォでSSL利用可能らしいので、とても簡単です。

※他に必要なパッケージの案内が出たら、全部入れておこう

ここまで。

上のPHPコードのサンプルでは、aplayコマンドでWAV音声を鳴らしてます。これは標準で入っていたと思う。

CRONに登録する場合は、以下の感じになるかなぁ・・と思います。

*/5 * * * * /usr/bin/php (スクリプトを置いた場所)/chk_imap.php

これで、5分毎にスクリプトを実行してくれます。

夜間に鳴らしたくない場合は、*/5 6-23 * * * とかにすれば、AM6ーPM11までの稼働になります。詳しくはCRONTABで検索。

2015年2月14日プライベートgmail,imap,mail,php,ゆっくり,新着

Posted by nabe