Catch incoming emails in your Laravel application

Overview

Laravel Mailbox 📬

Latest Version on Packagist Build Status Quality Score Total Downloads

Handle incoming emails in your Laravel application.

Mailbox::from('{username}@gmail.com', function (InboundEmail $email, $username) {
    // Access email attributes and content
    $subject = $email->subject();
    
    $email->reply(new ReplyMailable);
});

https://phppackagedevelopment.com

If you want to learn how to create reusable PHP packages yourself, take a look at my upcoming PHP Package Development video course.

Installation

You can install the package via composer:

composer require beyondcode/laravel-mailbox

Usage

Take a look at the official documentation.

Testing

composer test

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

Comments
  • Possibility to use non-mime version for mailgun driver?

    Possibility to use non-mime version for mailgun driver?

    When you use an endpoint other than one ending in /mime mailgun sends across a bunch of really useful content in the request - e.g. "trimmed-text" which is the message text without any signatures or similar.

    Unfortunately mailgun don't send this information when using a /mime endpoint and instead sends across "mime-body" which we're using to construct the message.

    I'm not sure it would be possible but thought I'd float the idea of seeing if we can reconstruct the message from the extended mailgun information rather than the mime version which would give developers easy access to this additional information.

    opened by hailwood 8
  • Support for laravel 9

    Support for laravel 9

    I saw that the composer.json was updated in master to support Laravel 9 but there are a couple of other changes necessary to support L9 since the Swift Mailer was replaced with the Symfony Mailer.

    The Log driver and InboundEmail files needed updates. I implemented to be backward compatible by checking the app()->version() in each instance. I also added a run-tests action to test against L6-9 on php 7.3, 8 and 8.1 I confirmed that all tests failed prior to my changes and they all pass on all supported php/laravel combinations.

    opened by samtlewis 7
  • Add PHP 8.0 support

    Add PHP 8.0 support

    Move composer dependency zendframework/zend-mail to laminas/laminas-mail due to Zend Framework migration.

    Upgraded the tests to use the new Laminas namespace.

    This will help to speed things up when they add PHP 8 support (see https://github.com/laminas/laminas-mail/pull/117) to fix issue https://github.com/beyondcode/laravel-mailbox/issues/78 ;)

    Edit, March 9 2021: now that Laminas added support for PHP 8, I updated the composer.json php versions and renamed the PR from "Migrate composer dependency from Zend to Laminas" to "Add PHP 8.0 support"

    opened by clementmas 7
  • Major overhaul

    Major overhaul

    Hello @mpociot, as promised, here comes the big change PR. Take a look and feel free to comment. Independently of the outcome, I will continue to support my version since I need it anyways. I understand if this is too much of a change to accept, and that is fine as well. Thanks in advance.

    Change log

    Concept

    The main entity is a MailboxGroup. What it enables you to do is to have multiple Mailboxes, each with its own set of patterns and actions to execute.

    Refactor has been done so that Mailbox provides a fluent API to define same set of features as before with some nice additions.

    Example:

    $mailbox = new Mailbox();
    
    $mailbox
        ->from('{user}@gmail.com')
        ->to('{user2}@gmail.com')
        ->subject('Subject to match')
        ->where('user', '.*')
        ->where('user2', '.*')
        ->action(function (InboundEmail $email) {
            Log::info("Mail received");
        })
        ->matchEither()
        ->priority(10);
    
    

    The concept now is that each mailbox has a single or multiple rules it can match, however it can have only one action to execute. Reason being to enable matching all or either of the rules imposed.

    By default, all patterns need to be matched in order for action to be executed. So if you provide from and to, they both need to match. This can be changed by including a matchEither() function which will transform this logic to matching at least one.

    Due to the fact that multiple mailboxes can exist now, MailboxGroup is responsible for running them. Executing MailboxGroup::run($email) will run all the mailboxes, but will before order them by given priority(). Mailbox has a default priority of 0. The bigger the number, the sooner it is executed.

    Group example:

    $group = new MailboxGroup(); 
    
    $group
        ->add($mailbox)
        ->add($mailbox2)
        ->add($mailbox3) 
        ->fallback(function (InboundEmail $email) {
            Log::info("Fell back");
        })
        ->continuousMatching()
        ->run($email);
    

    You are responsible for adding mailboxes to the group (be it in the service provider or the controller itself). Fallback is pulled out to MailboxGroup for logical reasons. If none of the mailboxes match, fallback will be executed. A new feature here is that mailboxes will, by default, stop at first match. Meaning, if out of 5 mailboxes, second one matches the incoming mail, execution will stop. This can be overridden including the continuousMatching() function which will run through all mailboxes. So if match is found in 3/5 mailboxes, those 3 callbacks will be executed.

    Dependencies

    PHP version has been bumped to 7.4. Breaking changes are introduced, 7.3 is no longer supported, and in the next few days I will complete all type hints and return types, together with strict modes included.

    Support for 6.x Laravel has been dropped. composer install requires a ton of memory with it, breaking most of the times if you don't give more memory to it. This is also the reason Scrutinizer checks break.

    Drivers

    I have removed drivers all together. Reason being that they were (at least for me) ambiguous, and their only purpose was exposing routes behind the scenes. Current setup also doesn't limit you in using a single driver.

    I like my code to be explicit, so currently in order to set up the package you need to:

    1. Set up endpoint manually (I like single action controllers for these purposes, but not mandatory):
    Route::post('receive', ReceiveEmailController::class);
    
    1. Add a MailboxRequest form request validation, or extend it if needed.
    public function __invoke(MailboxRequest $request)
    {
        ...
    }
    
    1. Define mailboxes and run them:
    public function __invoke(MailboxRequest $request)
    {
        $mailbox = (new Mailbox())->from(...)->action(...);
    
        MailboxGroup::add($mailbox);
        MailboxGroup::run($request->email());
    }
    
    1. Alternatively, you can define mailboxes in your service provider boot method, leaving the controller clean:
    // App service provider
    public function boot()
    {
        $mailbox = (new Mailbox())->from(...)->action(...);
    
        MailboxGroup::add($mailbox);
    }
    
    // Controller
    public function __invoke(MailboxRequest $request)
    {
        MailboxGroup::run($request->email());
    }
    
    1. Alternatively, option I prefer is to pull out mailbox definition to a separate class and include it within the controller so that it doesn't overburden the rest of API calls.
    public function __invoke(MailboxRequest $request)
    {
        // Factory leading to defining mailboxes, and ultimately running them.
        MailboxService::receiveEmail($request->email());
    }
    

    6.. Controllers being used as driver callbacks are still there for your convenience, so you can point the routes to different variants of those:

    Route::post('receive/mailgun', MailgunController::class);
    Route::post('receive/mailcare', MailCareController::class);
    Route::post('receive/postmark', PostmarkController::class);
    Route::post('receive/sendgrid', SendGridController::class);
    

    Dev naming

    Some concepts, variables etc. have been renamed to be more intuitive.

    Tests

    Tests which made sense were modified to pass, other were deleted as things like Route and RouteCollection no longer exist. I am willing to support new features with tests.

    Readme

    I think readme is a tad outdated and unnecessarily long. I will probably rewrite it.

    opened by Norgul 7
  • Class 'BeyondCode\Mailbox\Facades\Mailbox' not found

    Class 'BeyondCode\Mailbox\Facades\Mailbox' not found

    I was trying to implement the laravel-mailbox on our project but got this error saying:

    Class 'BeyondCode\Mailbox\Facades\Mailbox' not found

    I've used something like this on the web.php file:

    <?php
    
    use Illuminate\Support\Facades\Route;
    use BeyondCode\Mailbox\Facades\Mailbox;
    
    
    Route::post('/laravel-mailbox/sendgrid', function () use ($router) {
        \Log::info('Webhook arrives');
    
        Mailbox::from(config('mail.from.address'), function (InboundEmail $email) {
            // Handle the incoming email
            \Log::info(['id' => $email->id]);
            \Log::info(['subject' => $email->subject]);
            \Log::info(['message' => $email->message]);
        });
    });
    
    "beyondcode/laravel-mailbox": "^2.2",
    "laravel/framework": "^8.75",
    
    opened by jhayg12 4
  • Drivers extensible through configuration

    Drivers extensible through configuration

    Hello,

    I've modified the code to provide truly extensible code with configuration which I deem is simpler than overriding complete classes and re-binding them.

    Some of the changes are also due to what I consider misleading nomenclature, but you will find those changes are not so drastic.

    I've also added readme for extending.

    Keep up the good work, and hit me back if something else is needed.

    Regards

    opened by Norgul 4
  • Laravel 5.8 support

    Laravel 5.8 support

    I need this package in a project I'm working on. Since there's no (yet) support for Laravel 5.8 I decided to make one :)

    In this PR I've just bumped package versions. This (+simple fix in a test case) was enough to make the tests pass.

    I have to admit that I didn't test this on a real Laravel installation.

    opened by radmen 4
  • [Question] How to test Mailbox in application?

    [Question] How to test Mailbox in application?

    I'd like to add some tests for handling incoming emails.

    How can I do it? Should I mock Mailbox facade, or just send some dummy requests to one of the incoming endpoints?

    opened by radmen 4
  • Extending the save method

    Extending the save method

    Hi

    I have defined my own model called Email, that is extending the default InboundEmail model.

    I can see in the Routing/Router.php file, the save() method is like this:

    protected function storeEmail(InboundEmail $email)
    {
         $email->save();
    }
    

    Now in my Email model, I:

    • Have extended it to use a new table.
    • Is setting a custom variable, in order to "combine" it to a relationship.

    In my AppServiceProvider, I am passing the custom variable (token) to my Model:

    //AppServiceProvider:
    Mailbox::to('{token}@myapp.com', Email::class);
    

    Email.php:

        protected $table = 'emails';
    
        public function __invoke(InboundEmail $email, $token)
        {
            $email->stream_token = $token;
        }
    
        /**
         * An email belongs to a Stream.
         */
        public function stream()
        {
            return $this->belongsTo(Stream::class, 'stream_token');
        }
    

    Now my question is: how can I extend the save method, so I can check if the relationship exists in the database before persiting it?

    Because my code will fail (500 internal server error), if I send an email to an internal email, but where the {token) does not exist in the database.

    Can I do something like this in my Email.php model:

    protected function storeEmail(InboundEmail $email, $token)
    {
         if($email->stream->exists()){
         $email->stream_token = $token;
         $email->save();
         }else{
          Log::debug('Invalid "to" token. It does not exist in our system');
         
        }
    }
    
    opened by oliverbj 4
  • Get wrong Parameter

    Get wrong Parameter

    Hello,

    I have a problem with the parameter in my inbox handler. The handler is defined as Mailbox::from('{application}@yourname.xyz', SupportMailbox::class);

    The SupportMailbox Class simple logs the application parameter:

    public function __invoke(InboundEmail $email, $application) 
        {
            Log::debug($application);
        }
    

    Everytime I get postmaster as parameter no matter from which mail address the message was sent. Is there a problem with this package?

    opened by markusheinemann 4
  • Installing Mailbox on Lumen 6

    Installing Mailbox on Lumen 6

    I can't install Mailbox on my Lumen 6 project.

    Lumen doesn't automaticaly register the provider, then, I did a $app->register(BeyondCode\Mailbox\MailboxServiceProvider::class); in bootstrap/app.php.

    But then I get the error

    Call to undefined function BeyondCode\Mailbox\config_path()

    So I've tried a solution found on the Internet https://gist.github.com/mabasic/21d13eab12462e596120 But then I get the error

    Call to undefined method Laravel\Lumen\Routing\Router::aliasMiddleware()

    I've also installed https://github.com/laravelista/lumen-vendor-publish to have access to vendor:publish

    Now I can't do anything but uninstall all of theses...

    opened by tony5Dim 3
  • 302 redirection for inbound email handling for real emails using Mailgun

    302 redirection for inbound email handling for real emails using Mailgun

    I am using laravel-mailbox on laravel 8 with mailgun driver. I only need to simply forward the email message. The setup works fine and successfully forwards the email as expected when using mailgun sample webhook but not with realworld emails. When an email is sent from gmail or other medium to the mailgun domain configured, application redirects with a 302 image image

    to the root domain. I have tried clearing cache also adding the route laravel-mailbox/mailgun/mime to exclude csrftoken in the middleware, but no luck. Has anyone encountered this? Any help is greatly appreciated.

    opened by Tiththa 1
  • Laravel 9 missing on packagist (failed deploy?)

    Laravel 9 missing on packagist (failed deploy?)

    Hi

    it looks like it failed to deploy the proper dependencies for Laravel 9: https://packagist.org/packages/beyondcode/laravel-mailbox

    image

    even though your code in repo suggests 9.0 is allowed: https://github.com/beyondcode/laravel-mailbox/blob/master/composer.json

    image

    could you try a re-deploy?

    opened by joelharkes 6
  • Add testing array driver

    Add testing array driver

    Add support for new MAILBOX_DRIVER in-memory "array" driver. It's now the default config.

    Deprecate unnecessary MAILBOX_DRIVER "log" driver. If I'm not mistaking, Mailbox doesn't log any emails. Only the Laravel MAIL_MAILER does.

    So I believe most people would use these testing environment variables (inside phpunit.xml):

    <server name="MAIL_MAILER" value="array"/>
    <server name="MAILBOX_DRIVER" value="array"/>
    

    Or if they want to log the test emails:

    <server name="MAIL_MAILER" value="log"/>
    <server name="MAILBOX_DRIVER" value="array"/>
    

    Fixes issue https://github.com/beyondcode/laravel-mailbox/issues/72

    opened by clementmas 0
  • Fix memory limit issues when running mailbox:cleanup

    Fix memory limit issues when running mailbox:cleanup

    I sometimes get a memory limit error when running mailbox:cleanup since the command fetches all columns of the table which includes entire emails + raw attachments, this PR optimizes the command to run the delete statement right on the database level.

    opened by emargareten 6
Releases(3.0.0)
Laravel telegram log is a package that can catch your logs all quite simply

Laravel Telegram log Laravel telegram log is a package that can catch your logs all quite simply. Requirments This package is tested with Laravel v8 i

Muath Alsowadi 4 Aug 3, 2022
A package to keep track of outgoing emails in your Laravel application.

Keep track of outgoing emails and associate sent emails with Eloquent models This package helps you to keep track of outgoing emails in your Laravel a

Stefan Zweifel 108 Nov 1, 2022
Simple project to send bulk comma-separated emails using laravel and messenger module from quick admin panel generator.

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Novath Thomas 1 Dec 1, 2021
This package provides a Filament resource to view all Laravel sent emails.

This package provides a Filament resource to view all Laravel outgoing emails. It also provides a Model for the database stored emails. Installation Y

Ramón E. Zayas 22 Jan 2, 2023
Automatically load your helpers in your laravel application.

Laravel AutoHelpers Automatically load your helpers in your laravel application. Installation You can install the package via composer: composer requi

Florian Wartner 6 Jul 26, 2021
Laravel Segment is an opinionated, approach to integrating Segment into your Laravel application.

Laravel Segment Laravel Segment is an opinionated, approach to integrating Segment into your Laravel application. Installation You can install the pac

Octohook 13 May 16, 2022
Jetstrap is a lightweight laravel 8 package that focuses on the VIEW side of Jetstream / Breeze package installed in your Laravel application

A Laravel 8 package to easily switch TailwindCSS resources generated by Laravel Jetstream and Breeze to Bootstrap 4.

null 686 Dec 28, 2022
Laravel Larex lets you translate your whole Laravel application from a single CSV file.

Laravel Larex Translate Laravel Apps from a CSV File Laravel Larex lets you translate your whole Laravel application from a single CSV file. You can i

Luca Patera 68 Dec 12, 2022
Laravel package to find performance bottlenecks in your laravel application.

Laravel Meter Laravel Meter monitors application performance for different things such as requests, commands, queries, events, etc and presents result

Sarfraz Ahmed 230 Dec 27, 2022
Laravel-tagmanager - An easier way to add Google Tag Manager to your Laravel application.

Laravel TagManager An easier way to add Google Tag Manager to your Laravel application. Including recommended GTM events support. Requirements Laravel

Label84 16 Nov 23, 2022
Laravel Logable is a simple way to log http request in your Laravel application.

Laravel Logable is a simple way to log http request in your Laravel application. Requirements php >= 7.4 Laravel version >= 6.0 Installation composer

Sagar 6 Aug 25, 2022
Laravel comments - This package enables to easily associate comments to any Eloquent model in your Laravel application

Laravel comments - This package enables to easily associate comments to any Eloquent model in your Laravel application

Rubik 4 May 12, 2022
Deploy and execute non-PHP AWS Lambda functions from your Laravel application.

Sidecar for Laravel Deploy and execute non-PHP AWS Lambda functions from your Laravel application. Read the full docs at hammerstone.dev/sidecar/docs.

Hammerstone 624 Dec 30, 2022
Livewire component that brings Spotlight/Alfred-like functionality to your Laravel application.

About LivewireUI Spotlight LivewireUI Spotlight is a Livewire component that provides Spotlight/Alfred-like functionality to your Laravel application.

Livewire UI 792 Jan 3, 2023
A Laravel package helps you add a complete real-time messaging system to your new / existing application with only one command.

A Laravel package helps you add a complete real-time messaging system to your new / existing application with only one command.

Munaf Aqeel Mahdi 1.7k Jan 5, 2023
Laravel package that converts your application into a static HTML website

phpReel Static Laravel Package phpReel Static is a simple Laravel Package created and used by phpReel that converts your Laravel application to a stat

phpReel 16 Jul 7, 2022
Dashboard to view your http client requests in laravel application

Laravel Blanket is a package with wraps laravel http client requests and provide logs for request and response, also give option to retry any request from dashboard and more...

Ahmed waleed 215 Dec 29, 2022
Interact with TMDB data in your Laravel application.

Laravel TMDB Installation composer require astrotomic/laravel-tmdb php artisan vendor:publish --tag=tmdb-migrations Configuration Add your TMDB API v4

Astrotomic 32 Dec 21, 2022
A simple package allowing for consistent API responses throughout your Laravel application

Laravel API Response Helpers A simple package allowing for consistent API responses throughout your Laravel application. Requirements PHP ^7.4 | ^8.0

F9 Web Ltd. 441 Jan 5, 2023