3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

laravel-imapでメールを受信してみる。(編集中)

Last updated at Posted at 2021-09-21

laravel-imap と
IMAP Library for PHP
を混同しています。

ウ~ン(゜レ゜)
別にいいか。
編集中

リファレンスサイト

☆☆☆☆☆クラスにおけるメソッドが一覧で見れる。

↓のURLは
使えないコードもあるけど、メソッドの使い方がサンプルで記述してくれている。1番わかりやすい。ただ、量がすくない。


start project ---
laravel new laravel-admin-imap
composer require webklex/laravel-imap
config\app.php
------------------------------------------------------------------
    'providers' => [

//+
        Webklex\IMAP\Providers\LaravelServiceProvider::class,
    ],
------------------------------------------------------------------
    'aliases' => [

//+
        'Client'=>Webklex\IMAP\Facades\Client::class,
    ],
php artisan vendor:publish --provider="Webklex\IMAP\Providers\LaravelServiceProvider"
composer require laravel/ui
php artisan ui bootstrap --auth
npm install && npm run dev
npm run dev
env
DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel_admin_imap4
# DB_USERNAME=root
# DB_PASSWORD=
type NUL >  database/database.sqlite
php artisan migrate

メールを保存できるモデル・テーブルを作成

php artisan make:model MailBox
php artisan make:migration add_column_gmailpassword_to_users

mail_boxesとusersテーブルを編集する。

database\migrations_create_mail_boxes_table.php
        Schema::create('mail_boxes', function (Blueprint $table) {
            $table->id();
            $table->integer('uid');
            $table->text('subject');
            $table->text('from_email');
            $table->text('body');
            $table->text('attachments_path');
            $table->timestamps();
        });
database\migrations_add_column_gmailpassword_to_users.php
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
        $table->string('gmail_password')->nullable();
        });
    }
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('gmail_password');
        });
    }
php artisan migrate

ユーザー登録画面にgmail_passwordフォームを追加
edit:register.blade.php

resources\views\auth\register.blade.php
//+
    <div class="form-group row">
        <label for="gmail_password" class="col-md-4 col-form-label text-md-right">gmail_password</label>

        <div class="col-md-6">
            <input id="gmail_password" type="text" class="form-control @error('gmail_password') is-invalid @enderror" name="gmail_password" value="{{ old('gmail_password') }}" required autocomplete="gmail_password">

            @error('gmail_password')
                <span class="invalid-feedback" role="alert">
                    <strong>{{ $message }}</strong>
                </span>
            @enderror
        </div>
    </div>

edit:RegisterController

app\Http\Controllers\Auth\RegisterController.php
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
//+
            'gmail_password' => encrypt($data['gmail_password']),
        ]);
    }

edit:Userモデル

app\Models\User.php
    protected $fillable = [
        'name',
        'email',
        'password',
//+
        'gmail_password',
    ];

###メールを取得するための設定
gmailの設定
大阪コード学園「メール送信」動画でgmailの設定を説明してくれています。

レジスター登録をする。
emailは上記のgmail
gmailpasswordは上記で取得したパスワードで登録して下さい。

メールを取得・保存するルートを作成する

Route::get('/mailbox', [App\Http\Controllers\MailBoxController::class, 'store'])->name('mailbox.store');
app\Http\Controllers\MailBoxController.php
//+laravel-imapを使って接続しています。
use Webklex\IMAP\Facades\Client;

    public function store(Request $request)
    {      
        $client_user =[
        'host'          => 'smtp.gmail.com',
        'port'          => 993,
        'encryption'    => 'ssl',
        'validate_cert' => true,
        'username'      => $user->email,
        'password'      => decrypt($user->gmail_password),
        'protocol'      => 'imap',];

        $client = Client::make($client_user);

        $client->connect();

        $status = $client->isConnected();

        dd($status);
    }

mailboxにアクセスして、
image.png

true なら 接続成功です。

取り敢えず、取得するフォルダーネームを確認する。

    public function store(Request $request)
    {
        $user = User::find(Auth::id());

        $client_user =[
        'host'          => 'smtp.gmail.com',
        'port'          => 993,
        'encryption'    => 'ssl',
        'validate_cert' => true,
        'username'      => $user->email,
        'password'      => decrypt($user->gmail_password),
        'protocol'      => 'imap',];

        $client = Client::make($client_user);

        $client->connect();
//+
        $folders = $client->getFolders();
        dd($folders);
    }

image.png
それぞれのボックスのメール数を確認してみる。

    public function store(Request $request)
    {
        $user = User::find(Auth::id());
        $client_user =[
        'host'          => 'smtp.gmail.com',
        'port'          => 993,
        'encryption'    => 'ssl',
        'validate_cert' => true,
        'username'      => $user->email,
        'password'      => decrypt($user->gmail_password),
        'protocol'      => 'imap',];

        $client = Client::make($client_user);

        $client->connect();
//+
        $folders = $client->getFolders();

        foreach ($folders as $folder) {
            echo 'フォルダーの名前は' .$folder->name.'<br>';
            echo 'メールの数は'.$folder->query()->all()->count();
            echo "通です<br><hr>";
        }
    }

image.png
どうやら、INBOXにメールがあるみたい。
とりあえず、1日分取得して保存してみる。

    public function store(Request $request)
    {
        $user = User::find(Auth::id());
        $client_user = [
            'host'          => 'smtp.gmail.com',
            'port'          => 993,
            'encryption'    => 'ssl',
            'validate_cert' => true,
            'username'      => $user->email,
            'password'      => decrypt($user->gmail_password),
            'protocol'      => 'imap',
        ];
        $client = Client::make($client_user);
        $client->connect();
        // $folders = $client->getFolders();
        // foreach ($folders as $folder) {
        //     echo 'フォルダーの名前は' .$folder->name.'<br>';
        //     echo 'メールの数は'.$folder->query()->all()->count();
        //     echo "通です<br><hr>";
        // }
//+
        // $folder = $client->getFolder($folder = "INBOX", $delimiter = '/');
        $folder = $client->getFolder("INBOX");
        $query = $folder->query();
        $messages = $query->since(now()->subDays(1))->get();

        foreach ($messages as $message) {
            $mail = MailBox::firstOrNew([
                'uid' => $message->getUid(),
            ], [
                'subject' => $message->getSubject(),
                'from_email' => $message->getFrom()[0]->mail,
                'body' => $message->getHTMLBody(true) ?? $message->getTextBody() ?? 'なし',
                'reception_date' => $message->getdate(),
                'attachments_path' => $this->getattAchmentsPath($message)
            ]);
            $mail->save();
        }
        return '完了';
    }
//+
//どんどん、関数使って、文章を書いたらええと思う。多分・・・。
    protected function getattAchmentsPath($message)
    {
        if ($message->hasAttachments()) {
            $attach_pth = uniqid("attach_pth_") . "/";
            foreach ($message->getAttachments() as $attachment) {
                Storage::disk('local')->put('public/mail/' . $attach_pth . '/' . $attachment->name, $attachment->content);
            }
            return  $attach_pth;
        } else {
            return  $attach_pth = '';
        }
    }

image.png
 \(^o^)/ 無事データが取得、保存できました。
取得したデータをviewで吐き出してみる。
まずは、ルートを修正と追加

routes\web.php
//+
Route::get('/mailbox', [App\Http\Controllers\MailBoxController::class, 'index'])->name('mailbox.index');
Route::get('/mailbox/store', [App\Http\Controllers\MailBoxController::class, 'store'])->name('mailbox.store');
Route::get('/mailbox/{mail}', [App\Http\Controllers\MailBoxController::class, 'show'])->name('mailbox.show');

edit:MailBoxController.php

app\Http\Controllers\MailBoxController.php
//+
    public function index()
    {
        $mails = MailBox::simplePaginate(5);

        return view('mailboxes.index', compact('mails'));
    }
//+
    public function show(MailBox $mail)
    {
        return view('mailboxes.show',compact('mail'));
    }

viewの作成:レイアウトはコピペした、レスポンシブ対応のを選ぶべきだった。
layout/mailboxの作成。
create:resources\views\layouts\mailbox.blade.php

layouts.mailbox.blade.phpのコード
resources\views\layouts\mailbox.blade.php
@extends('layouts.app')
@push('css')
<style>
 body{
background:#eee;
}
.mail-box {
    border-collapse: collapse;
    border-spacing: 0;
    display: table;
    table-layout: fixed;
    width: 100%;
}

.mail-box aside {
    display: table-cell;
    float: none;
    height: 100%;
    padding: 0;
    vertical-align: top;
}

.mail-box .sm-side {
    width: 25%;
    background: #ecf0f1;
    border-radius: 4px 0 0 4px;
    -webkit-border-radius: 4px 0 0 4px;
}
.mail-box .lg-side {
    width: 75%;
    background: #fff;
    border-radius: 0px 4px 4px 0;
    -webkit-border-radius: 0px 4px 4px 0;
}

.mail-box .sm-side .user-head {
    background: #2980b9;
    border-radius: 4px 0px 0px 0;
    -webkit-border-radius: 4px 0px 0px 0;
    padding: 10px;
    color: #fff;
    min-height: 80px;
}

.user-head .inbox-avatar {
    width: 65px;
    float: left;
}

.user-head .inbox-avatar img {
    border-radius: 4px;
    -webkit-border-radius: 4px;
}
.user-head .user-name {
    display: inline-block;
    margin:0 0 0 10px;
}

.user-head .user-name h5 {
    font-size: 14px;
    margin-top: 15px;
    margin-bottom: 0;
    font-weight: 300;
}
.user-head .user-name h5 a {
    color: #fff;
}

.user-head .user-name span a {
    font-size: 12px;
    color: #87e2e7;
}

a.mail-dropdown {
    background: #1abc9c;
    padding:3px 5px;
    font-size: 10px;
    color: #ddd;
    border-radius: 2px;
    margin-top: 20px;
}

.inbox-body {
    padding: 20px;
}

.btn-compose {
    background: #9b59b6;
    padding: 12px 0;
    text-align: center;
    width: 100%;
    color: #fff;
}
.btn-compose:hover {
    background: #8e44ad;
    color: #fff;
}

ul.inbox-nav  {
    display: inline-block;
    width: 100%;
    margin: 0;
    padding: 0;
}

.inbox-divider {
    border-bottom: 1px solid #d5d8df;
}

ul.inbox-nav li {
    display: inline-block;
    line-height: 45px;
    width: 100%;
}

ul.inbox-nav li a  {
    color: #6a6a6a;
    line-height: 45px;
    width: 100%;
    display: inline-block;
    padding: 0 20px;
}

ul.inbox-nav li a:hover, ul.inbox-nav li.active a, ul.inbox-nav li a:focus  {
    color: #6a6a6a;
    background: #d5d7de;
}

ul.inbox-nav li a i {
    padding-right: 10px;
    font-size: 16px;
    color: #6a6a6a;
}

ul.inbox-nav li a span.label {
    margin-top: 13px;
}

ul.labels-info li h4 {
    padding-left:15px;
    padding-right:15px;
    padding-top: 5px;
    color: #5c5c5e;
    font-size: 13px;
    text-transform: uppercase;
}

ul.labels-info li  {
    margin: 0;
}

ul.labels-info li a {
    color: #6a6a6a;
    border-radius: 0;
}

ul.labels-info li a:hover, ul.labels-info li a:focus {
    color: #6a6a6a;
    background: #d5d7de;
}

ul.labels-info li a i {
    padding-right: 10px;
}

.nav.nav-pills.nav-stacked.labels-info p {
    margin-bottom: 0;
    padding: 0 22px;
    color: #9d9f9e;
    font-size: 11px;
}

.inbox-head {
    padding:20px;
    background: #3498db;
    color: #fff;
    border-radius: 0 4px 0 0;
    -webkit-border-radius: 0 4px 0 0;
    min-height: 80px;
}

.inbox-head  h3 {
    margin: 0;
    display: inline-block;
    padding-top: 6px;
    font-weight: 300;
}

.inbox-head  .sr-input {
    height: 40px;
    border: none;
    box-shadow: none;
    padding: 0 10px;
    float: left;
    border-radius: 4px 0 0 4px;
    color: #8a8a8a;
}
.inbox-head  .sr-btn {
    height: 40px;
    border: none;
    background: #2980b9;
    color: #fff;
    padding: 0 20px;
    border-radius: 0 4px 4px 0;
    -webkit-border-radius: 0 4px 4px 0;
}

.table-inbox {
    border: 1px solid #d3d3d3;
    margin-bottom: 0;
}

.table-inbox tr td{
    padding: 12px !important;
}

.table-inbox tr td:hover{
    cursor: pointer;
}

.table-inbox tr td .fa-star.inbox-started ,.table-inbox tr td .fa-star:hover{
    color: #f78a09;
}

.table-inbox tr td .fa-star{
    color: #d5d5d5;
}

.table-inbox tr.unread td {
    font-weight: 600;
    background: #f7f7f7;
}

ul.inbox-pagination  {
    float: right;
    list-style: none;
}

ul.inbox-pagination li {
    float: left;
}

.mail-option {
    display: inline-block;
    margin-bottom: 10px;
    width: 100%;
}

.mail-option .chk-all, .mail-option .btn-group {
    margin-right: 5px;
}

.mail-option .chk-all, .mail-option .btn-group a.btn {
    border: 1px solid #e7e7e7;
    padding: 5px 10px;
    display: inline-block;
    background: #fcfcfc;
    color: #afafaf;
    border-radius: 3px !important;
    -webkit-border-radius: 3px !important;
}
.inbox-pagination a.np-btn  {
    border: 1px solid #e7e7e7;
    padding: 5px 15px;
    display: inline-block;
    background: #fcfcfc;
    color: #afafaf;
    border-radius: 3px !important;
    -webkit-border-radius: 3px !important;
}

.mail-option .chk-all input[type=checkbox] {
    margin-top: 0;
}

.mail-option .btn-group a.all {
    padding: 0;
    border: none;
}

.inbox-pagination a.np-btn {
    margin-left: 5px;
}

.inbox-pagination li span {
    display: inline-block;
    margin-top: 7px;
    margin-right: 5px;
}

.fileinput-button {
    border: 1px solid #e6e6e6;
    background: #eeeeee;
}

.inbox-body .modal .modal-body input, .inbox-body .modal .modal-body textarea{
    border: 1px solid #e6e6e6;
    box-shadow: none;
}

.btn-send, .btn-send:hover {
    background: #00A8B3;
    color: #fff;
}

.btn-send:hover {
    background: #009da7;
}

.modal-header h4.modal-title {
    font-weight: 300;
    font-family: 'Open Sans', sans-serif;
}

.modal-body label {
    font-weight: 400;
    font-family: 'Open Sans', sans-serif;
}

.heading-inbox h4{
    font-size: 18px;
    color: #444;
    border-bottom: 1px solid #ddd;
    padding-bottom: 10px;
    margin-top: 20px;
}

.sender-info {
    margin-bottom: 20px;
}

.sender-info img {
    width: 30px;
    height: 30px;
}

.sender-dropdown {
    background: #eaeaea;
    padding:0 3px;
    color: #777;
    font-size: 10px;
}

.view-mail a {
    color: #FF6C60;
}

.attachment-mail {
    margin-top: 30px;
}
.attachment-mail ul {
    width: 100%;
    display: inline-block;
    margin-bottom: 30px;
}

.attachment-mail ul li {
    float: left;
    width: 150px;
    margin-right: 10px;
    margin-bottom: 10px;
}

.attachment-mail ul li img {
    width: 100%;
}

.attachment-mail ul li span {
    float: right;
}
.attachment-mail .file-name {
    float: left;
}

.attachment-mail .links {
    width: 100%;
    display: inline-block;
}
a,a:hover{
    text-decoration: none;
    color: grey;
}
</style>
@endpush
@section('content')
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<div class="container bootstrap snippets bootdeys">
<div class="row">
    <div class="col-lg-12">
        <div class="box">
            <!--mail inbox start-->
            <div class="mail-box">
                <aside class="sm-side">
                    <div class="user-head">
                        <a href="javascript:;" class="inbox-avatar">
                            <img src="https://bootdey.com/img/Content/avatar/avatar1.png" alt="" class="img-responsive img-fluid">
                        </a>
                        <div class="user-name">
                            <h5><a href="#">Jonathan Smith</a></h5>
                            <span><a href="#">jsmith@gmail.com</a></span>
                        </div>
                        <a href="javascript:;" class="mail-dropdown pull-right">
                            <i class="fa fa-chevron-down"></i>
                        </a>
                    </div>
                    <div class="inbox-body">
                        <a class="btn btn-compose" data-toggle="modal" href="#myModal" data-original-title="" title="">
                            Compose
                        </a>
                        <!-- Modal -->
                        <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
                            <div class="modal-dialog">
                                <div class="modal-content">
                                    <div class="modal-header">
                                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
                                        <h4 class="modal-title">Compose</h4>
                                    </div>
                                    <div class="modal-body">
                                        <form class="form-horizontal" role="form">
                                            <div class="form-group">
                                                <label class="col-lg-2 control-label">To</label>
                                                <div class="col-lg-10">
                                                    <input type="text" class="form-control" id="inputEmail1" placeholder="">
                                                </div>
                                            </div>
                                            <div class="form-group">
                                                <label class="col-lg-2 control-label">Cc / Bcc</label>
                                                <div class="col-lg-10">
                                                    <input type="text" class="form-control" id="cc" placeholder="">
                                                </div>
                                            </div>
                                            <div class="form-group">
                                                <label class="col-lg-2 control-label">Subject</label>
                                                <div class="col-lg-10">
                                                    <input type="text" class="form-control" id="inputPassword1" placeholder="">
                                                </div>
                                            </div>
                                            <div class="form-group">
                                                <label class="col-lg-2 control-label">Message</label>
                                                <div class="col-lg-10">
                                                    <textarea name="" id="" class="form-control" cols="30" rows="10"></textarea>
                                                </div>
                                            </div>

                                            <div class="form-group">
                                                <div class="col-lg-offset-2 col-lg-10">
                                                    <span class="btn green fileinput-button" data-original-title="" title="">
                                                      <i class="fa fa-plus fa fa-white"></i>
                                                      <span>Attachment</span>
                                                      <input type="file" multiple="" name="files[]">
                                                    </span>
                                                    <button type="submit" class="btn btn-send" data-original-title="" title="">Send</button>
                                                </div>
                                            </div>
                                        </form>
                                    </div>
                                </div><!-- /.modal-content -->
                            </div><!-- /.modal-dialog -->
                        </div><!-- /.modal -->
                    </div>

                    <ul class="inbox-nav inbox-divider">
                        <li class="active">
                            <a href="#"><i class="fa fa-inbox"></i> Inbox <span class="label label-danger pull-right">2</span></a>
                        </li>
                        <li>
                            <a href="#"><i class="fa fa-envelope-o"></i> Sent Mail</a>
                        </li>
                        <li>
                            <a href="#"><i class="fa fa-bookmark-o"></i> Important</a>
                        </li>
                        <li>
                            <a href="#"><i class=" fa fa-external-link"></i> Drafts <span class="label label-info pull-right">30</span></a>
                        </li>
                        <li>
                            <a href="#"><i class=" fa fa-trash-o"></i> Trash</a>
                        </li>
                    </ul>
                    <ul class="nav nav-pills nav-stacked labels-info inbox-divider">
                        <li> <h4>Labels</h4> </li>
                        <li> <a href="#"> <i class=" fa fa-sign-blank text-danger"></i> Work </a> </li>
                        <li> <a href="#"> <i class=" fa fa-sign-blank text-success"></i> Design </a> </li>
                        <li> <a href="#"> <i class=" fa fa-sign-blank text-info "></i> Family </a>
                        </li><li> <a href="#"> <i class=" fa fa-sign-blank text-warning "></i> Friends </a>
                        </li><li> <a href="#"> <i class=" fa fa-sign-blank text-primary "></i> Office </a>
                        </li>
                    </ul>
                    <ul class="nav nav-pills nav-stacked labels-info ">
                        <li> <h4>Buddy online</h4> </li>
                        <li> <a href="#"> <i class=" fa fa-circle text-success"></i> Jhone Doe <p>I do not think</p></a>  </li>
                        <li> <a href="#"> <i class=" fa fa-circle text-danger"></i> Sumon <p>Busy with coding</p></a> </li>
                        <li> <a href="#"> <i class=" fa fa-circle text-muted "></i> Anjelina Joli <p>I out of control</p></a>
                        </li><li> <a href="#"> <i class=" fa fa-circle text-muted "></i> Jonathan Smith <p>I am not here</p></a>
                        </li><li> <a href="#"> <i class=" fa fa-circle text-muted "></i> Tawseef <p>I do not think</p></a>
                        </li>
                    </ul>
                    <div class="inbox-body text-center">
                        <div class="btn-group">
                            <a href="javascript:;" class="btn mini btn-primary" data-original-title="" title="">
                                <i class="fa fa-plus"></i>
                            </a>
                        </div>
                        <div class="btn-group">
                            <a href="javascript:;" class="btn mini btn-success" data-original-title="" title="">
                                <i class="fa fa-phone"></i>
                            </a>
                        </div>
                        <div class="btn-group">
                            <a href="javascript:;" class="btn mini btn-info" data-original-title="" title="">
                                <i class="fa fa-cog"></i>
                            </a>
                        </div>
                    </div>
                </aside>
                <aside class="lg-side">
                <div class="inbox-head">
                    <h3>Inbox</h3>
                    <form class="pull-right position" action="#">
                        <div class="input-append">
                            <input type="text" placeholder="Search Mail" class="sr-input">
                            <button type="button" class="btn sr-btn" data-original-title="" title=""><i class="fa fa-search"></i></button>
                        </div>
                    </form>
                </div>
                <div class="inbox-body">
                    @yield('content2')
                </div>
                </aside>
</div>
        <!--mail inbox end-->
        </div>
    </div>
</div>
</div>
@endsection

INDEX画面の作成
create:resources\views\mailboxes\index.blade.php

resources\views\mailboxes\index.blade.php
@extends('layouts.mailbox')
@section('content2')

<div class="mail-option">
    <div class="chk-all">
        <input type="checkbox" class="mail-checkbox mail-group-checkbox">
        <div class="btn-group">
            <a class="btn mini all" href="#" data-toggle="dropdown" data-original-title="" title="">
                All
                <i class="fa fa-angle-down "></i>
            </a>
            <ul class="dropdown-menu">
                <li><a href="#"> None</a></li>
                <li><a href="#"> Read</a></li>
                <li><a href="#"> Unread</a></li>
            </ul>
        </div>
    </div>
    <div class="btn-group">
        <a class="btn mini tooltips" href="#" data-toggle="dropdown" data-placement="top" data-original-title="Refresh">
            <i class=" fa fa-refresh"></i>
        </a>
    </div>
    <div class="btn-group hidden-phone">
        <a class="btn mini blue" href="#" data-toggle="dropdown" data-original-title="" title="">
            More
            <i class="fa fa-angle-down "></i>
        </a>
        <ul class="dropdown-menu">
            <li><a href="#"><i class="fa fa-pencil"></i> Mark as Read</a></li>
            <li><a href="#"><i class="fa fa-ban"></i> Spam</a></li>
            <li class="divider"></li>
            <li><a href="#"><i class="fa fa-trash-o"></i> Delete</a></li>
        </ul>
    </div>
    <div class="btn-group">
        <a class="btn mini blue" href="#" data-toggle="dropdown" data-original-title="" title="">
            Move to
            <i class="fa fa-angle-down "></i>
        </a>
        <ul class="dropdown-menu">
            <li><a href="#"><i class="fa fa-pencil"></i> Mark as Read</a></li>
            <li><a href="#"><i class="fa fa-ban"></i> Spam</a></li>
            <li class="divider"></li>
            <li><a href="#"><i class="fa fa-trash-o"></i> Delete</a></li>
        </ul>
    </div>
    <ul class="unstyled inbox-pagination mt-3">
        {{ $mails->links() }}
    </ul>
</div>
<div class="d-flex text-small justify-content-end">
    {{ $mails->currentPage() }}/ページ目
</div>
<table class="table table-inbox table-hover">
<tbody>
    @foreach ($mails as $mail)

<tr class="unread">
    <td class="inbox-small-cells">
        <input type="checkbox" class="mail-checkbox">
    </td>
    <td class="inbox-small-cells"><i class="fa fa-star"></i></td>
    <td class="view-message  dont-show"></td>
    <td class="view-message "><a href="{{ route('mailbox.show',$mail) }}">{{ $mail->subject }}</a></td>
    <td class="view-message  inbox-small-cells">
        @if ($mail->attachments_path)
        <i class="fa fa-paperclip"></i>
        @endif
    </td>
    <td class="view-message  text-right">{{ $mail->reception_date }}</td>
</tr>
@endforeach
</tbody>
</table>
@endsection

show画面の作成
create:resources\views\mailboxes\show.blade.php

resources\views\mailboxes\show.blade.php
@extends('layouts.mailbox')
@section('content2')
<div class="vh-100">
<div class="card shadow-none mt-3 border border-light h-75">
    <div class="card-body overflow-auto">
        {!! $mail->body !!}
   </div>
 </div> <!-- card -->
</div>
@endsection

image.png
image.png
とりあえず、以上
IMAPという技術は、
通常のメールサーバーからメールを受信する際、元々リアルタイム受信は一般的ではなく、ユーザーがメールサーバーに定期的に確認しに行くしかありませんでした。 ところがIMAPというメール受信のプロトコルができてから、こういった従来のメールシステムでも定期的にサーバーに確認することなくメールをリアルタイムで受信することが可能になりました。
らしい。
そして、
imap-idleという関数が用意されている。
ここまでは記述するつもり。


リファレンスまとめ

###Single Account

env
IMAP_HOST=smtp.gmail.com
IMAP_PORT=993
IMAP_ENCRYPTION=ssl
IMAP_VALIDATE_CERT=true
IMAP_USERNAME=xxxx@gmail.com
IMAP_PASSWORD=xxxxxxxxxxxxx
IMAP_DEFAULT_ACCOUNT=default
IMAP_PROTOCOL=imap
コントローラー
//+
use Webklex\IMAP\Facades\Client;

//+
    $client = new Client();
//'default'を変更してコネクションを変更できる。
    $oClient = Client::account('default');
    $oClient->connect();
config\imap.php defaultの時、編集等、必要なしoptionsの編集の時使用
    'default' => env('IMAP_DEFAULT_ACCOUNT', 'default'/*gmail*/),
    'accounts' => [
        'default' => [// account identifier
            'host'  => env('IMAP_HOST', 'localhost'),
            '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', true),
            'username' => env('IMAP_USERNAME', 'root@example.com'),
            'password' => env('IMAP_PASSWORD', ''),
            'authentication' => env('IMAP_AUTHENTICATION', null),
            'proxy' => [
                'socket' => null,
                'request_fulluri' => false,
                'username' => null,
                'password' => null,
            ]
        ],
//好きにコネクションを追加していける。
        /*
        'gmail' => [ // account identifier
            'host' => 'imap.gmail.com',
            'port' => 993,
            'encryption' => 'ssl',
            'validate_cert' => true,
            'username' => 'example@gmail.com',
            'password' => 'PASSWORD',
            'authentication' => 'oauth',
        ],

        'another' => [ // account identifier
            'host' => '',
            'port' => 993,
            'encryption' => false,
            'validate_cert' => true,
            'username' => '',
            'password' => '',
            'authentication' => null,
        ]
        */
    ],

###Multi Accounts
データーベースのユーザーからメールの設定を取得する場合や、
マルチアカウントを利用する場合の設定

php-imapで接続
//+
use Webklex\PHPIMAP\ClientManager;
use Webklex\PHPIMAP\Client;

//+
    $cm = new ClientManager();
//+option
    $cm = new ClientManager([
        'options' => [
            'fetch' => \Webklex\PHPIMAP\IMAP::FT_PEEK,
            'fetch_order' => 'desc',
            'sequence' => \Webklex\PHPIMAP\IMAP::FT_UID,
        ],
    ]);
//
    $oClient = $cm->make([
        'host' => 'imap.mail.yahoo.co.jp',
        'port' => 993,
        'encryption' => 'ssl',
        'validate_cert' => true,
        'username'      => 'XXXXX@yahoo.co.jp',
        'password'      => 'XXXXXXXXX',
        'protocol' => 'imap',
    ]);
//未確認$cm = new ClientManager('path');これがイマイチ不明:不都合はないが・
//$oClient = $cm->account('※');※config\imap.phpのコネクションを指定
    $oClient->connect();
laravel-impaで接続
//こうやるみたい・・・なぜ、larablocksはこっちを載せない。
$client = \Webklex\IMAP\Facades\Client::make([
    'host'          => 'somehost.com',
    'port'          => 993,
    'encryption'    => 'ssl',
    'validate_cert' => true,
    'username'      => 'username',
    'password'      => 'password',
    'protocol'      => 'imap'
]);

//Connect to the IMAP Server
$oClient->connect();

//これは使えなかった。
//https://www.larablocks.com/package/medeirosrafael/laravel-imap
//Webklex\IMAP\Client not foundがでる。
//未確認 動作させるには、デフォルトの設定を手動で設定する必要があります
//ClientManager::$config=config('imap');

use Webklex\IMAP\Client; //not foundになる。
$oClient = new Client([
    'host'          => 'somehost.com',
    'port'          => 993,
    'encryption'    => 'ssl',
    'validate_cert' => true,
    'username'      => 'username',
    'password'      => 'password',
    'protocol'      => 'imap'
]);

###Client
接続関係

コントローラー等
//現在の接続がまだ確立されているかどうかを確認する場合
$status = $oClient->isConnected();
//現在の接続がまだ有効かどうかを確認し、必要に応じて再接続します
$oClient->checkConnection();
//再接続を強制する
$oClient->reconnect();
//接続を閉じる
$oClient->disconnect();

フォルダー関係

コントローラー等
//利用可能なすべてのフォルダを一覧表示します
//階層順序がtrueに設定されている場合、フォルダーのツリーが作成されます。それ以外
//の場合は、フラット配列が返されます。
$folders = $oClient->getFolders($hierarchical = true);

//パスでフォルダを探す
//フォルダパス全体を指定します。区切り文字は異なる場合があります。
$folder = $oClient->getFolderByPath('INBOX.name');

//名前でフォルダを探す
//フォルダ名のみを指定してください。区切り文字は必要ありません
$folder = $oClient->getFolderByName('name');

//名前またはパスでフォルダを検索する
//フォルダ名またはパスのいずれかを指定します。区切り文字は必須ではありません。
$folder = $oClient->getFolder($folder = "INBOX.name", $delimiter = null);
$folder = $oClient->getFolder($folder = "name", $delimiter = null);

//新しいフォルダを作成します
//消去を切り替えると、現在のimapセッションが新しいフォルダを認識しない可能性があります。
$folder = $oClient->createFolder($folder = 'INBOX.name', $expunge = true);

//フォルダの詳細を取得する
$info = $oClient->checkFolder($folder = 'INBOX.name');
//結果の例
array:5 [
  "flags" => array:1 [
    0 => array:6 [
      0 => "\Answered"
      1 => "\Flagged"
      2 => "\Deleted"
      3 => "\Seen"
      4 => "\Draft"
    ]
  ]
  "exists" => "65"
  "recent" => "0"
  "uidvalidity" => 1488899637
  "uidnext" => 202
]

###Folder

コントローラー等
//新しい検索クエリ 全部同じ。
$query = $folder->query();
$query = $folder->search();
$query = $folder->messages();

//現在のフォルダにサブフォルダまたは「子」があるかどうかを確認
$status = $folder->hasChildren();

/*アイドル接続
*接続をアイドル状態にして、新しい着信メッセージを「リッスン」できます。
*接続が切断された場合に自動的に再接続する場合は、
*$auto_reconnectしtrueに設定
*/
$folder->idle(function($message){
    echo "New message with the subject '".$message->subject."' received\n";
}, $timeout = 1200, $auto_reconnect = false);

//フォルダの詳細を取得する
$info = $folder->examine();

以下のアクションは元に戻せない可能性があります

//フォルダを移動する
$status = $folder->move($new_folder = "INBOX/othername");
$status = $folder->rename($new_folder = "INBOX/othername");

//フォルダを削除する
$status = $folder->delete();

###Query

//特定のメッセージを取得する
//フェッチ・オプションがST_MSGNに設定されている場合,
//またはuidを指定して、特定のメッセージを受信できます。
$message = $query->getMessage($id = 1);

//そのuidによって特定のメッセージを取得します
//フェッチオプションをST_MSGNに設定している場合でも、
//そのuidによって特定のメッセージをフェッチできます。
$message = $query->getMessageByUid($uid = 1);

//メッセージ番号で特定のメッセージを取得する
//フェッチオプションをST_UIDに設定している場合でも、
//メッセージ番号で特定のメッセージをフェッチできます。
$message = $query->getMessageByMsgn($msgn = 1);

//すべてのメッセージを取得する
//利用可能なすべてのメッセージのコレクションを取得します。
$messages = $query->all()->get();

//すべてのメッセージをまとめて取得する
//利用可能なすべてのメッセージをチャンクでフェッチして、
//「トランザクション」ごとの要求/応答サイズを減らします。
//この方法では、全体的にリクエストが増える可能性があるため、
//raitlimitsに注意する必要がある場合があります。

$query->all()->chunked(function($messages, $chunk){
    dump("chunk #$chunk");
    $messages->each(function($message){
        dump($message->uid);
    });
}, $chunk_size = 10, $start_chunk = 1);

//フェッチされたすべてのメッセージに既読のフラグを付ける
$query->markAsRead();

//フェッチされたすべてのメッセージに既読のフラグを付けない
$query->leaveUnread();

//メッセージ本文をフェッチしない
$query->setFetchBody(false);

//結果を制限する
//この場合、結果を10に制限しますが、が$page2に設定されているため、
//最初の10個の結果はスキップされ、次の10個が返されます。
$messages = $query->all()->limit($limit = 10, $page = 2)->get();

//結果を数える
$count = $query->all()->count();

//ページ付けされた結果を取得する
$paginator = $query->all()->paginate($per_page = 5, $page = null, $page_name = 'imap_page');

//並べ替え順序を設定する
$query->setFetchOrder("asc");
$query->setFetchOrderAsc();
$query->fetchOrderAsc();

$query->setFetchOrder("desc");
$query->setFetchOrderDesc();
$query->fetchOrderDesc();

//ソフトフェイルを有効にする
//バルクメッセージのフェッチ中に特定の例外を無視する場合は、
//「ソフトフェイル」モードを有効にします。
$messages = $query->all()->softFail()->get();
$errors = $query->errors();

//特定の送信者からすべてのメッセージを取得する
//特定の送信者から利用可能なすべてのメッセージのコレクションを取得します。
$messages = $query->from('example@domain.com')->get();

//特定の日付以降のすべてのメッセージを取得する
$messages = $query->since('15.03.2018')->get();
$messages = $query->since(now()->subDays(5))->get();

//特定のテキストを含むすべてのメッセージを取得する
//特定のテキストを含む利用可能なすべてのメッセージのコレクションを取得します。
$messages = $query->text('hello world')->get();
$messages = $query->whereText('hello world')->get();
$messages = $query->where([['TEXT', 'Hello world']])->get();

//除外して検索
条件に一致しないメッセージを検索することもできます
$messages = $query->notText('hello world')->get();
$messages = $query->not_text('hello world')->get();
$messages = $query->not()->text('hello world')->get();

//連鎖検索条件
$messages = $query->from('example@domain.com')->unseen()->text('hello world')->get();

カスタム検索条件
$messages = $query->where([["CUSTOM_FOOBAR" => "fooBar"]])->get();
$messages = $folder->query()
->where([['TEXT', 'Hello world'], ['SINCE', \Carbon\Carbon::parse('15.03.2018')]])
->get();

その他 利用可能なすべてのカスタム検索条件
ALL //一致するすべてのメッセージを返します
ANSWERED //ANSWERED(回答済み)フラグが設定されたメッセージと照合
BCC "string" //メッセージをBcc:フィールドの「文字列」と一致させます
BEFORE "date" //メッセージをDate:before "date"と照合します
BODY "string"  //メッセージの本文の「文字列」とメッセージを照合します
CC "string"  // メッセージをCc:フィールドの「文字列」と一致させます
DELETED   //削除されたメッセージに一致
FLAGGED   //FLAGGED(重要または緊急)フラグが設定されたメッセージを照合
FROM "string" //From:フィールドの "string"とメッセージを照合します
KEYWORD "string" //「文字列」をキーワードとしてメッセージを照合します
NEW  //新しいメッセージに一致する
NOT  //一致しません
OLD  //古いメッセージと一致する
ON "date"  //メッセージをDateと一致させます: "date"と一致します
RECENT //RECENTフラグが設定されたメッセージを照合します
SEEN //読み取られたメッセージに一致します(\ SEENフラグが設定されます)
SINCE //「日付」—メッセージを日付と一致させます:「日付」の後
SUBJECT //「文字列」—メッセージを件名の「文字列」と一致させます。
TEXT "string" //メッセージをテキスト "string"と一致させます
TO "string" //」メッセージを宛先の「文字列」と一致させます。
UNANSWERED  //応答されていないメッセージに一致する
UNDELETED  //削除されていないメッセージに一致する
UNFLAGGED  //フラグが立てられていないメッセージに一致する
UNKEYWORD "string" //キーワード "string"を持たないメッセージに一致します
UNSEEN //まだ読んでいないメッセージに一致する

Message

コントローラー等
本文が存在するか確認してください
/** @var \Webklex\PHPIMAP\Message $message */
/** @var boolean $status */

$status = $message->hasTextBody();
HTML本体が存在するかどうかを確認します
/** @var \Webklex\PHPIMAP\Message $message */
/** @var boolean $status */

$status = $message->hasHTMLBody();
//テキスト本文を取得する
//何も存在しない場合はnullを返します。
$body = $message->getTextBody();

//HTML本文を取得する
//何も存在しない場合はnullを返します。
$body = $message->getHTMLBody();

//体を手に入れる
//メッセージテキストとHTML本文の両方を取得します。
$bodies = $message->getBodies();

//ボディをフェッチ
//メッセージ本文をフェッチします。
$message->parseBody();

//含まれているフォルダを取得します
$folder = $message->getFolder();

//メッセージスレッド
//現在のメッセージと送信済みメッセージフォルダ内の
//すべてのメッセージの両方のmessage_idとin_reply_to
//ヘッダーを比較して、メッセージスレッドを取得します。
//このアクションは再帰的であり、
//接続されているすべてのメッセージを見つけるのに数秒かかる場合があります。
$messages = $message->thread($sent_folder = null);

//メッセージをコピーする
現在のメッセージを別のフォルダにコピーします
//メールプロバイダーによっては、nullが返されます。
$copy = $message->copy($folder_path = "INBOX/name");

//メッセージを移動
//現在のメッセージを別のフォルダに移動します。
//メールプロバイダーによっては、nullが返されます。
$message = $message->move($folder_path = "INBOX/name");

//メッセージを削除する
//$expungeがfalseに設定されている場合、
//接続が消去されるまで、このアクションは完了しません。
$message = $message->delete($expunge = true);

//メッセージを復元
現在のメッセージを復元します
//$expungeがfalseに設定されている場合、
//接続が消去されるまで、このアクションは完了しません。
$message = $message->restore($expunge = true);

//フラグを取得する
解析されたすべてのメッセージフラグを取得します
$flags = $message->getFlags();

//新しいフラグを追加します
一度に複数の新しいフラグを追加することも1つだけ追加することもできます
$message->setFlag(['Seen', 'Flagged']);
$message->setFlag('Seen');

//フラグを削除します
現在のメッセージから既存のメッセージフラグを削除します
$message->unsetFlag('Flagged');

//メッセージに添付ファイルがあるかどうかを確認します
$status = $message->hasAttachments();

//すべての添付ファイルを取得する
$attachments = $message->getAttachments();

//未加工の未解析のメッセージ本文を受信します。
$raw = $message->getRawBody();

//ヘッダーを取得
$header = $message->getHeader();

//すべての属性を取得する
$attributes = $message->getAttributes();

//アクセス属性
//マジックメソッドの詳細については、「属性」セクションを確認してください。
$subject = $message->subject;
$subject = $message->getSubject();
$subject = $message->get("subject");
$subject = $message->getAttributes()["subject"];

###Attachment

//添付ファイルを保存
//添付ファイル名がファイル名として使用されます。
$status = $attachment->save($path = "./some/location/", $filename = null);

//mimeタイプを取得する
$mime = $attachment->getMimeType();

//添付ファイルの拡張子を特定
$ext = $attachment->getExtension();

//すべての属性を取得する
$attributes = $attachment->getAttributes();
結果の例
array:9 [
  "content" => "some sample text\n"
  "type" => "text"
  "part_number" => 2
  "content_type" => "text/plain"
  "id" => null
  "name" => "test.txt"
  "disposition" => "attachment"
  "img_src" => null
  "size" => 24
]
アクセス属性
$name = $attachment->name;
$name = $attachment->getName();
$name = $attachment->get("name");
$name = $attachment->getAttributes()["name"];
どっかでまとめておきたいコード
$cm = new ClientManager('config/imap.php');
$client = $cm->account('account_identifier');

// or if you are using the laravel wrapper:
$client = \Webklex\IMAP\Facades\Client::account('account_identifier');

$folder = $client->getFolder('INBOX');
$overview = $folder->overview($sequence = "168:*");
$message = $aFolder->query()->getMessage($uid = 165);
$cm = new ClientManager('config/imap.php');
$client = $cm->account('account_identifier');

// or if you are using the laravel wrapper:
$client = \Webklex\IMAP\Facades\Client::account('account_identifier');

$folder = $client->getFolder('INBOX');
$overview = $folder->overview($sequence = "168:*");
$message = $aFolder->query()->getMessage($uid = 165);
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?