Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable Laravel email during db seed

Tags:

php

email

laravel

I use Mandrill mail driver for tests. I have a remote staging, that I seed after deploy. And during seeding I try to disable email sends, that are linked to certain events.

Placing this in seeder:

Config::set('mail.driver', 'log'); Config::set('mail.pretend', true);

Has no effect. I don't understand why. I place this in root DatabaseSeeder@run or/and in child seeders — the same. Calls to Mandrill are still performed.

Is there a solution for this problem?

like image 664
Terion Avatar asked Aug 29 '14 22:08

Terion


3 Answers

The reason your

Config::set('mail.driver', 'log');
Config::set('mail.pretend', true);

aren't working is because the mail object doesn't check these values before sending mail. Whaaaaaaaa?. If you take a look at the sendSwiftMessage method in the mailer class

#File: vendor/laravel/framework/src/Illuminate/Mail/Mailer.php
protected function sendSwiftMessage($message)
{
    if ($this->events)
    {
        $this->events->fire('mailer.sending', array($message));
    }

    if ( ! $this->pretending)
    {
        $this->swift->send($message, $this->failedRecipients);
    }
    elseif (isset($this->logger))
    {
        $this->logMessage($message);
    }
}

You can see the class checks $this->pretending, and not the configuration, before deciding if it should send the mail or not. So what sets pretending? That's in the MailServiceProvider class's register method.

public function register()
{
    //...
    $pretend = $app['config']->get('mail.pretend', false);
    $mailer->pretend($pretend);
    //...
}

When Laravel boots up and registers each service provider, it eventually registers the mail service provider and that's when it reads the configuration, and then tells the mailer if it should "pretend" or not. By the time you're calling this in your seeder, the mailer's already loaded it's configuration value.

Fortunately, there's a pretty easy solution. The mailer object is a singleton/shared service, and has public methods available to control if it should pretend or not. Just call the pretend method yourself instead of setting configuration values

Mail::pretend(true); //using the `Mail` facade to access the mailer object. 

you should be able to turn the mailer off programatically.

like image 64
Alan Storm Avatar answered Oct 19 '22 11:10

Alan Storm


This is an answer for Laravel 5.7, because pretend doesn't exists:

If you want to disable mail while seeding the database, you could simply 'abuse'

Mail::fake()
like image 30
Rolf Avatar answered Oct 19 '22 12:10

Rolf


I think in two possibilities, you can try:

  1. You can set the command to enable the mail pretend on-the-fly:

    Mail::pretend();

  2. The db seed are running with more than one request:

As is write here:

Configuration values that are set at run-time are only set for the current request, and will not be carried over to subsequent requests.

So you can try set this config over requests, like a session, than finish in the end of the seeding.

like image 2
insign Avatar answered Oct 19 '22 10:10

insign