简体   繁体   中英

Disable Laravel email during db seed

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?

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.

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()

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM