[Laravel]laravel-imapを使って、メールを取得する

Laravel

laravel-imapを使ってメールを取ってくる処理を書いたので、使い方などを復習で下記に記載しています。
dockerへのphp-fpmのimap導入についても記載しています。

docker(php-fpm)のimapを有効にする

Dockerfileを修正する

# php module
RUN apt-get update && apt-get install -y \
   zlib1g-dev \
   git \
   libzip* \
   libonig-dev \
   libc-client-dev \
   libkrb5-dev

RUN rm -r /var/lib/apt/lists/*

RUN PHP_OPENSSL=yes docker-php-ext-configure imap --with-kerberos --with-imap-ssl \
    && docker-php-ext-install zip pdo_mysql mysqli mbstring imap

apt-getでlibc-client-dev、libkrb5-devを追加したのと、

docker-php-ext-configureにimap --with-kerberos --with-imap-sslを書き加えて、
docker-php-ext-installでimapを追加しました。

出現したエラー

上記の記述で導入できましたが、imapを有効にしようとしたら、下記エラーや

configure: error: utf8_mime2text() has new signature, but U8T_CANONICAL

下記のエラーが出てきました。

configure: error: OpenSSL libraries not found. imap

OpenSSLがなぜ・・・?😅

laravel-imapを導入する

composerで入れます。

composer require webklex/laravel-imap

下記のコマンドでconfigディレクトリの下にconfigファイル(imap.php)を作成してくれます。
ここにimapでの接続先設定を書きます。

php artisan vendor:publish --provider="Webklex\IMAP\Providers\LaravelServiceProvider"

config/imap.phpの設定を書き換える

googleでimapに繋ぎにいく場合に下記のように設定を書きました。

        'default' => [// account identifier
            'host'  => env('IMAP_HOST', 'imap.gmail.com'),
            'port'  => env('IMAP_PORT', 993),
            'protocol'  => env('IMAP_PROTOCOL', 'imap'), //might also use imap, [pop3 or nntp (untested)]
            'encryption'    => env('IMAP_ENCRYPTION', 'ssl'), // Supported: false, 'ssl', 'tls', 'notls', 'starttls'
            'validate_cert' => env('IMAP_VALIDATE_CERT', false),
            'username' => env('IMAP_USERNAME', 'xxxxxxxx@gmail.com'),
            'password' => env('IMAP_PASSWORD', 'password'),
        ],

使ってみました(imapでgmail接続)

サンプルコード

laravelでコマンドバッチを作成し、下記のような処理を書いてみました。

public function handle()
{
    echo "test laravel-imap start\n";

    $client = new Client();
    $client->connect();

    /** @var FolderCollection $folder */
    $folder = $client->getFolder('test');

    $messages = $folder->messages()->all()->get();

    /** @var Message $message */
    foreach ($messages as $message) {
        echo '添付ファイル件数:' . $message->getAttachments()->count() . "\n";
        echo "件名:" . $message->getSubject() . "\n";
        echo "本文:" . $message->getTextBody() . "\n";

        // 添付ファイル保存
        if ($message->hasAttachments()) {
            foreach ($message->getAttachments() as $attachment) {
                Storage::disk('local')->put('file.png', $attachment->content);
            }
        }
    }
    echo "test laravel-imap end\n";
}

getFolderで、メールサーバーのフォルダにアクセスしに行きますが、
今回はgmailのtestラベルにアクセスしています。

今回は1つのフォルダにアクセスしていますが、
フォルダを全件取得したいときは、getFoldersメソッドを使います。

$folder->messages()->all()->get() でメッセージの全件を取得して、ループで回して処理しています。
getSubjectで件名、getTextBodyで本文が取れて、

hasAttachmentsで添付ファイルがあるか確認して、
ある場合はローカルに保存するようにしました。
(ここではファイルタイプとか見ずにとりあえず、pngで保存しています。)

gmailの設定

gmailにアクセスする場合、安全性の低いアプリに許可しておかないと、動かないようでした。
こちらから設定は変更できます。大事なアカウントで動作させるときは、動作確認が終わったら戻しておきましょう!

下記の証明書に関連するのかな。。。

証明書エラー

imap.phpのvalidate_certがfalseになっていないと下記のエラーが出ます…
とりあえず、今回は繋いで動かしてみたかっただけなので、オプションのvalidate_certをfalseに設定しました。

Webklex\IMAP\Exceptions\ConnectionFailedException  : imap_open(): Couldn't open stream {imap.gmail.com:993/imap/ssl}. Certificate failure for imap.gmail.com: self signed certificate: /OU=No SNI provided; please fix your client./CN=invalid2.invalid

動作確認

php artisan でコマンドを実行すると、

テスト用に置いたメールが2つ取れて。。

ファイルが保存されました!

github

今回のサンプルをここに置いています。

コメント

タイトルとURLをコピーしました