Laravelでメール(IMAP)を受信して添付ファイルを抽出する
はじめに
メールを定期的に受信して、添付ファイルを自動的に保存するという仕組みを作りたくて調べてみました。
できそうな方法
AWSのSES
AWSのメールサービスSESを使ってできそう。受信したメールをS3へ保存する機能があり、それをトリガーとしてLambdaを起動。Lambda関数でメールデータを取得して添付ファイルを抽出し再びS3へ保存。
MicrosoftのPower Automate
Microsoftのいろいろ自動化ツール。メールを自動受信して添付ファイルを各種クラウドサービスへ保存する機能がある。
Gmail
柔軟な拡張性を持ったメールサービス。単体ではなく各種サービスと連携して色々な操作ができそう。
自作
ライブラリなどを使えば比較的簡単にメールサーバにアクセスできる。様々な操作や添付ファイル抽出もできたりする。
自作を選択
SESやPower Automateを使った方法は月々のコストがかかるので今回はスルー。Gmailでいろいろしようと思ったけど、laravel-imapというLaravelのライブラリを見つけたので、Laravel使いの自分としてはこちらを選択。
laravel-imapの使い方
laravel-imapはphp-imapのLaravel仕様。php-imapはPHPの拡張モジュールであるIMAPを独自にパッケージ化したライブラリー。(なのでPHPのIMAP拡張モジュールがサーバに入ってなくてもOK)
インストール
laravel-imapは、サーバーに以下の2つのモジュールが入っていることが必須。
- mbstring
- mcrypt
ただ、mcryptはPHP7.2から非推奨(削除)となっています。
これを踏まえた上で使用したい場合は、読み進めてください😅
レンタルサーバ(XSERVER、さくらレンタルサーバ)の場合はどちらも有効になっていますが、VPSやクラウド、開発環境では有効になっているか確認してください。
自分の環境では、mcrypt
がなくても使えました。なんで?
ちなみにDockerで開発環境を作っている場合は、Dockerfileに以下のように書くとmcrypt
が有効になります。
RUN apt-get -y install \ libmcrypt-dev \ && pecl install mcrypt-1.0.4
それとphp.iniファイルに
extension=mcrypt.so
を追記。
laravel-imapをインストール
環境が整ったらインストールします。すでにLaravelはインストールされている前提です。Composerでインストールします。
$ composer require webklex/laravel-imap
設定ファイルをconfig/内に設置します。
$ php artisan vendor:publish --provider="Webklex\IMAP\Providers\LaravelServiceProvider"
設定
.envファイルにメールサーバの情報を追記します。
IMAP_HOST=somehost.com IMAP_PORT=993 IMAP_ENCRYPTION=ssl IMAP_VALIDATE_CERT=true IMAP_USERNAME=root@example.com IMAP_PASSWORD=secret IMAP_DEFAULT_ACCOUNT=default IMAP_PROTOCOL=imap
先程設置したconfig/imap.phpでメールアカウントの設定などできます。(しなくても.envの情報で取得できます)
添付ファイル取得・保存
例えば、Controllerで使う場合。
<?php namespace App\Http\Controllers; use Illuminate\Support\Facades\Storage; use Webklex\IMAP\Facades\Client; class ImapMailController extends Controller { public function index() { $client = Client::account('default'); // config/imap.phpで設定しているdefaultアカウント(.envの設定)を使用 $client->connect(); $folder = $client->getFolderByName('INBOX'); // フォルダ名を指定して取得(受信BOXはだいたいINBOX) // メッセージ取得(フィルター) $messages = $folder->messages() ->from('hoge@example.com') // 特定のメールアドレスからのみ ->setFetchOrder('desc') // 新しい順、ascで古い順 ->limit($limit = 100, $page = 1) // 取得数を制限(1ページ辺り100件、1ページ目を取得) ->get(); foreach ($messages as $message) { if ($message->hasAttachments()) { // 添付ファイルがあるかどうか // 添付ファイル保存 foreach ($message->getAttachments() as $attachment) { Storage::put('path/' . $attachment->name, $attachment->content); } } } return; } }
こんな感じで取得、保存できる。
その他の機能
メール情報の取得
// ヘッダー取得 $message->getHeader(); // タイトル取得 $message->getSubject(); // 添付ファイル数取得 $message->getAttachments()->count(); // 本文(テキスト)の取得 $message->getTextBody(); // 本文(HTML)の取得 $message->getHTMLBody(); // 解析前の生メールを取得 $message->getRawBody();
他にも、メールのコピーや移動、削除とか、フォルダやフラグ操作など色々できます。詳しくは、PHP-IMAPのドキュメント参照
まとめ
ライブラリを使うと簡単にメール操作できるんですね。いろいろ自動化ツールの開発には便利なんじゃないでしょうか。
ちなみにGmailのメールを取得する場合の.envは、以下の通り。
IMAP_HOST=imap.gmail.com IMAP_PORT=993 IMAP_ENCRYPTION=ssl IMAP_VALIDATE_CERT=false IMAP_USERNAME=username@gmail.com IMAP_PASSWORD=password # ←アプリパスワード IMAP_DEFAULT_ACCOUNT=default IMAP_PROTOCOL=imap
Gmailのメールサーバへ接続するには、Gmail側(Googleアカウント)の設定で2段階認証の有効化とアプリパスワードの発行をする必要があります。アプリパスワードの設定は2段階認証を有効化するとメニューに現れます。
-
前の記事
Laravelのイベントとリスナを非同期で実行してみる 2022.01.27
-
次の記事
【Laravel】vendor/bin/phpunit実行時の警告文の解消 2022.03.10
コメントを書く