【问题标题】:Laravel - changing email settings on the fly is not workingLaravel - 即时更改电子邮件设置不起作用
【发布时间】:2019-08-21 01:25:47
【问题描述】:

我的应用程序的所有电子邮件设置都存储在数据库中。用户可以选择更改这些设置,这一切都很好。但我正在尝试设置“发送测试电子邮件”功能,以允许用户在保存之前测试他们的设置。当他们提交用于发送测试电子邮件的表单时,电子邮件将通过原始设置而不是新设置发送。

表单提交到SettingsController.php

//  Send a test email
public function sendTestEmail(Request $request)
{
   Log::info(config('mail.host'));  
   //  Just to check the current email host - shows the proper host 
   //  from the database - i.e. smtp.mailtrap.io

   //  Make sure that all of the information properly validates
   $request->validate([
       'host'       => 'required',
       'port'       => 'required|numeric',
       'encryption' => 'required',
       'username'   => 'required'
   ]);

   //  Temporarily set the email settings
   config([
       'mail.host'       => $request->host,
       'mail.port'       => $request->port,
       'mail.encryption' => $request->encryption,
       'mail.username'   => $request->username,
   ]);
   //  Only update the password if it has been changed
   if(!empty($request->password))
   {
       config(['mail.password' => $request->password]);
   }

   //  Try and send the test email
   try
   {
       Log::info(config('mail.host'));
       //  Just to check the new setting - this also shows the correct
       //  email host - which is the newly assigned one via the form 
       //  i.e. smtp.google.com

       Mail::to(Auth::user()->email)->send(new TestEmail());
       return response()->json([
           'success' => true,
           'sentTo'  => Auth::user()->email
       ]);
   }
   catch(Exception $e)
   {
       Log::notice('Test Email Failed.  Message: '.$e);
       $msg = '['.$e->getCode().'] "'.$e->getMessage().'" on line '.
            $e->getTrace()[0]['line'].' of file '.$e->getTrace()[0]['file'];
       return response()->json(['message' => $msg]);
   }
}

在我的 TestEmail 课程中,我将其归结为基础

namespace App\Mail;

//use Illuminate\Bus\Queueable;  //  Commented out to be sure it is not queuing
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
//use Illuminate\Contracts\Queue\ShouldQueue;  //  Commented out to be sure it is not queuing

class TestEmail extends Mailable
{
//    use Queueable, SerializesModels;  //  Commented out to be sure it is not queuing

 /**
 * Create a new message instance.
 *
 * @return void
 */
public function __construct()
{
    //
}

/**
 * Build the message.
 *
 * @return $this
 */
public function build()
{
    return $this->subject('Test Email From '.config('app.name'))->markdown('email.testEmail');
}
}

即使日志显示配置设置的更新 smtp 主机,消息仍然通过原始设置发送出去 - 即 smtp.mailtrap.io。

【问题讨论】:

  • 您是否检查过您的配置是否已缓存php artisan config:clear 在 cli 中运行并检查它是否正常工作?
  • 是的,我确实尝试过清除缓存。不幸的是,这不起作用。

标签: php email laravel-5.8


【解决方案1】:

TL;DR

立即回答您的问题,请参考以下在 Laravel 5.8 上测试的代码:

$transport = app('swift.transport');
$smtp = $transport->driver('smpt');
$smpt->setHost('PUT_YOUR_HOST_HERE');
$smpt->setPort('THE_PORT_HERE');
$smpt->setUsername('YOUR_USERNAME_HERE');
$smpt->setPassword('YOUR_PASSWORD_HERE');
$smpt->setEncryption('YOUR_ENCRYPTION_HERE');

为什么即时设置配置不起作用?

在 laravel 架构中,首先要注册所有服务提供者,包括 MailServiceProvider。查看您的 config/app.php

    // inside config/app.php
    ...
    Illuminate\Mail\MailServiceProvider::class,
    ...

并且配置将在到达您的路线之前加载,请参阅 Illuminate\Mail\TransportManager

    /**
     * Create an instance of the SMTP Swift Transport driver.
     *
     * @return \Swift_SmtpTransport
     */
    protected function createSmtpDriver()
    {
        $config = $this->app->make('config')->get('mail');

        // The Swift SMTP transport instance will allow us to use any SMTP backend
        // for delivering mail such as Sendgrid, Amazon SES, or a custom server
        // a developer has available. We will just pass this configured host.
        $transport = new SmtpTransport($config['host'], $config['port']);

        if (isset($config['encryption'])) {
            $transport->setEncryption($config['encryption']);
        }
        //... rest of the code
   }

所以我使用 TransportManager 的驱动程序方法来处理这个问题,以获取所需的驱动程序并设置我想要的配置,因为上面的代码我们可以看到它的 api 的大量使用。

希望对你有帮助

【讨论】:

    【解决方案2】:

    我遇到了与我刚使用的相同的问题

    config(['mail.driver' => 'smtp']);
    

    当我调试时

    dd(config('mail.driver'));
    

    配置没问题

    我刚刚查看了 kfirba 的评论 here

    我很确定这个问题是因为当 laravel 在 IoC 容器中注册邮件密钥时,它使用了原始配置。更改不会导致 laravel 重新定义邮件程序密钥。 如果您查看 MailerServiceProvider,您会看到它是延迟的,这意味着一旦您调用它,它将实例化对象并使用单例。我相信您在应用程序的其他地方使用了 Mail::send() 方法,这导致在应用程序中注册邮件程序密钥。因为它是一个单例,所以当你重复使用它时,它不会再次读取你的配置文件。

    解决办法:

    config(['mail.driver' => 'smtp']);
    (new Illuminate\Mail\MailServiceProvider(app()))->register();
    

    适用于 Laravel 8

    【讨论】:

      【解决方案3】:

      您可以使用 Config::set: 即时设置/更改任何配置:

      Config::set('key', 'value'); 因此,要设置/更改 mail.php 中的端口,您可以尝试以下操作:

      Config::set('mail.port', 587); // default
      

      注意:运行时设置的配置值只针对当前请求设置,不会延续到后续请求中

      【讨论】:

      • 我尝试改变将配置变量分配给 Config::set 的方式,但这并没有改变任何东西。真正奇怪的是,当我在更改后记录设置时,它确实显示了新设置。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-28
      • 1970-01-01
      • 2018-08-29
      • 1970-01-01
      • 2018-11-30
      相关资源
      最近更新 更多