OhLifeというWebサービスがある。メールの送受信をフックとしたログ記録サービスで、以下のような特徴がある。
- 1日1回、決まった時間にメールを送ってくる
- このメールに返信すると、返信内容が記録される
- OhLifeが送ってくるメールの本文には、過去のログが含まれる
OhLifeの主な機能には満足しているのだけど、一点だけ不満がある。それは、過去のログの選ばれる規則を設定できないこと。個人的な用途としては、前日からの進捗確認に使いたいので、必ず昨日のログを表示してほしい。しかし、OhLifeの過去ログ抽出規則は、「前日・1週間前・1ヶ月前」等があり、古いものが優先されているように思える。
類似サービスも探したのだが、どうも無いみたい。
無いなら作ろう。
ということで、作ってみた(現在、一般公開はしていない)。
サーバはさくらVPSで、OSはDebian Wheezy。メールサーバとしてはPostfixを使用。今回一番ハマったのはPostfixの設定だったり。
Postfixで受け取ったメールをPHPスクリプトに渡す方法としては、 この記事が参考になる。
また、メールをパースする方法としては、ライブラリを使用することにした。最初は illuminate/mailなども検討したのだけど、サンプルコードが探しやすかったので PEAR::Mail_MimeDecodeにした(サンプルコードは この記事を参考にした)。
インストールはComposerで。
{ "repositories": [ { "type": "pear", "url": "http://pear.php.net/" } ], "require": { "pear-pear.php.net/Mail_mimeDecode" : "*" } }
メールを受信するプログラムはこんな感じ(受け取ったメールの本文をDBに保存する)。
<?php require_once __DIR__ . '/vendor/autoload.php'; $raw_mail = file_get_contents('php://stdin'); // メール本文を標準入力から受け取る $params = []; $params['include_bodies'] = true; $params['decode_bodies'] = true; $params['decode_headers'] = true; $params['input'] = $raw_mail; $params['crlf'] = '\r\n'; $mail_data = Mail_mimeDecode::decode($params); $mail_address = $mail_data->headers['from']; $mail_address = trim(substr($mail_address, strpos($mail_address, '<')), '<>'); $charset = $mail_data->ctype_parameters['charset']; $mail_body = mb_convert_encoding($mail_data->body, 'UTF-8', $charset); try { $dbh = require_once __DIR__ . '/db_connection.php'; // PDOオブジェクトを取得 // メールアドレスからユーザーを取得 $sql = 'SELECT * FROM users WHERE mail = :mail'; $stmt = $dbh->prepare($sql); $result = $stmt->execute([':mail' => $mail_address]); // DBにメール本文を保存 if (true === $result) { $row = $stmt->fetchAll(PDO::FETCH_ASSOC)[0]; $sql = 'INSERT INTO logs (users_id, body, created_at) VALUES (:users_id, :body, :created_at)'; $stmt = $dbh->prepare($sql); $stmt->bindParam('users_id', $row['id']); $stmt->bindParam('body', $mail_body); $stmt->bindParam('created_at', date('Y-m-d H:i:s')); $stmt->execute(); } } catch (Exception $e) { error_log($e->getMessage() . PHP_EOL, 3, __DIR__ . '/log/receiver.log'); exit(1); }
メール送信機能はmb_send_mail()使えば簡単。あとは、cronにメール送信スクリプトを登録して、定期実行すればOK。