PHPでメール着弾時、メール本文をパースしDBへ格納する(2)〜メールパース編〜
2年前に、私はこんなことを言っていた。
次回は、PHPをキックしてメールをパースしてDBに格納するよっ♥
お楽しみにね★
その次回が、令和という元号が発表された節目の日になろうとは、私も読者も思っていなかっただろう。
びっくり!
この作業について、これからも聞かれると思うのでまとめておきます。
おさらい
とあるメールアドレス(chakudan@example.com)にメールを送信すると
Laravelでつくったstore_emailというコマンドが叩かれて、
メールの内容をDBに格納してくれるという、メール内容データDB取り込みの機構を構築する。
まずは、メールサーバを構築し、着弾用ユーザをつくり、
そのユーザにメールが届いた際に別のアドレスに転送できるようにサーバを設定するというところまでが
前回の作業だった。
今回は、その次のPHPをキックしてDBに格納するところまでをまとめる。
やること
- Laravelでstore_emailコマンドを作成
- /etc/aliasesでメール受信時にstore_emailが叩かれるよう設定
- phpにmailparseモジュールを追加
- php-mime-mail-parserをinstall
- メールをパースしてDBに格納する
Laravelでstore_emailコマンドを作成
まずはメール送信時に、そのコマンドが本当に叩かれるかどうかというのを確かめたいので、 ログを吐き出すだけのコマンドを作成する。
.env
MAIL_DRIVER=sendmail
コマンドを作成
php artisan make:command StoreEmail
*古いバージョンのLaravelをお使いの方はmake:commandではなくmake:consoleになる。
app/Console/Commands/StoreEmail.php
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use \Log; class StoreEmail extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'command:store_email'; /** * The console command description. * * @var string */ protected $description = 'メールをDBに保存するコマンド'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { Log::info('メールを受信しました。'); } }
/etc/aliasesでメール受信時にstore_emailが叩かれるよう設定
chakudan@example.comにメールを送ったら、chakudanユーザのメールボックスにメールが届き、
さらにstore_emailコマンドがキックされるように、/etc/aliasesのchakudanユーザの箇所を以下のようにしておく
sudo vi /etc/aliases
/etc/aliases
chakudan: chakudan, "| /usr/bin/php /var/www/hogehoge/artisan command:store_email"
chakudai@example.comにメールを送信したら、ログに「メールを受信しました。」が記載されていたら メール送信&PHPキックが成功している。
phpにmailparseモジュールを追加
php-mime-mail-parserというライブラリを使ってメールのパースを行おうと思うが、 インストールするにはmailparseモジュールをphpに追加する必要がある。
cd /tmp pecl download mailparse tar xvzf mailparse-3.0.2.tgz cd mailparse-3.0.2 phpize ./configure sed -i 's/^\(#error .* the mbstring extension!\)/\/\/\1/' mailparse.c make make install echo "extension=mailparse.so" > /etc/php.d/30-mailparse.ini httpd -k graceful
mailparseのモジュールがちゃんと入ってるか確認する
php -i| grep mailparse mailparse mailparse support => enabled mailparse.def_charset => us-ascii => us-ascii
php-mime-mail-parserをinstall
php-mime-mail-parserというライブラリをinstallする。
composer require php-mime-mail-parser/php-mime-mail-parser
メールをパースしてDBに格納する
app/Console/Commands/StoreEmail.php
<?php use PhpMimeMailParser\Parser; use App\Inquiry; public function handle() { Log::info('メールを受信しました。'); $parser = new Parser(); $parser->setStream(fopen('php://stdin', 'r')); $to = $parser->getHeader('to'); $addressesTo = $parser->getAddresses('to'); $from = $parser->getHeader('from'); $addressesFrom = $parser->getAddresses('from'); $subject = $parser->getHeader('subject'); $body = $parser->getMessageBody('text'); $text_arr = explode("\n", $body); // ↓こんな感じでデータが取得できる // $from = 'example@example.co.jp'; // $subject = '◯◯システムお問い合わせ'; // $text_arr = [ // "◯◯システムWebサイトからお問い合わせがありました。\n", // "\n", // "--\n", // "お問い合わせ番号: 0000000203\n", // "氏名(漢字): 山田 太郎\n", // "氏名(カタカナ): ヤマダ タロウ\n", // "性別: 男\n", // "年齢: 32歳\n", // "お電話番号: 03-1234-5678\n", // "メールアドレス: hogehoge@example.com\n", // "お問い合わせ内容:\n", // "商品について質問があります。\n", // "よろしくお願いします。\n", // "--\n", // "\n", // "※このメールは◯◯システムのお問い合わせフォームから送信され\n", // "ました\n", // "\n", // "\n", // ]; Inquiry::create([ 'subject' => $subject, 'body' => $body, 'from' => $from, ]); }
詳しくはphp-mime-mail-parserのgithubページに使い方が書いてあるので、
そちらを参照してみてください。
あとがき
どうでしたでしょうか、二年越しの私のメールパース編。
メール送信してデバッグして、修正して送信してとかやるのが結構たいへんなので、 Laravel5.7.7以上ならメールパースのデバッグはLaravel Telescopeを使ったほうがいいのでは、と思います。
次のブログは令和元年になるかなーw
次の時代で会おうねー!!!!!!