【php】IMAPでメールをチェックしてコマンド実行するスクリプト
追記:VerUP他
RaspberryPi
以下、時報の時の記事。https://blog.ahh.jp/?p=6418
久々に、PHPスクリプトをこしらえてみました。超ど忘れしとる(;´Д`)
まんま、スクリプトを貼ります。
アカウントとパスワードを書き換えれば、どこでも動くんではないでしょうか(Gmailなら)INBOXに続くパスを加えれば、振り分けルール等を対象に出来ます。
cronとかで定期的に動かす感じでしょうか。
注意する点として、IMAPサーバに負荷を掛けたくなかったので、純粋な最新メールを取得する訳ではありません。厳密には日付ソートによるメールではなく、メールサーバが受信した最新のメールとなります。
どういう事かというと、IMAPサーバの構成を変更した時に、メールの受信が前後する場合があります。レアケースですけどね(;^ω^)テストしてたら分かったんだけども・・。
コマンドには好きなものを書けるはずです。CRON内なら、必要な環境変数をCRONに渡す必要があるので注意。Pathとか
棒読みちゃんで、件名とか喋らしたいんだけども、さすがにラズパイには厳しいでしょうね。
追記:
ちょっとだけバージョンアップしました。あと、サンプル用に、ゆっくりの音声を用意しました。よければどうぞ。
動作説明: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秒)
そういや、無意識に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で検索。