├── .gitignore ├── config └── switchable-mail.php ├── src ├── MailDriver.php ├── SwiftMessageHelper.php ├── Mailer.php ├── MailServiceProvider.php └── SwiftMailerManager.php ├── composer.json ├── LICENSE ├── README.zh_CN.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .php_cs.cache 5 | .DS_Store 6 | Thumbs.db 7 | /phpunit.xml 8 | .idea/ -------------------------------------------------------------------------------- /config/switchable-mail.php: -------------------------------------------------------------------------------- 1 | [ 6 | // 'qq.com', '163.com', '126.com', 'sina.com', 'sina.com.cn', 'sohu.com', 7 | // ], 8 | 9 | // 'mailgun' => [ 10 | // 'example.com', 11 | // ], 12 | 13 | ]; 14 | -------------------------------------------------------------------------------- /src/MailDriver.php: -------------------------------------------------------------------------------- 1 | 0; 24 | }, 25 | ARRAY_FILTER_USE_BOTH 26 | )); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kevinzheng/laravel-switchable-mail", 3 | "description": "For Laravel to support multiple and switchable on runtime mail drivers.", 4 | "homepage": "https://github.com/kevinzheng/laravel-switchable-mail", 5 | "support": { 6 | "issues": "https://github.com/kevinzheng/laravel-switchable-mail/issues", 7 | "source": "https://github.com/kevinzheng/laravel-switchable-mail" 8 | }, 9 | "require": { 10 | "php": ">=5.6.4", 11 | "illuminate/mail": "5.3.*" 12 | }, 13 | "license": "MIT", 14 | "authors": [ 15 | { 16 | "name": "Kevin Zheng", 17 | "email": "realkvz@gmail.com" 18 | }, 19 | { 20 | "name": "Elf Sundae", 21 | "email": "elf.sundae@gmail.com" 22 | } 23 | ], 24 | "minimum-stability": "dev", 25 | "autoload": { 26 | "psr-4": { 27 | "KVZ\\Laravel\\SwitchableMail\\": "src/" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Kevin Zheng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.zh_CN.md: -------------------------------------------------------------------------------- 1 | # laravel-switchable-mail 2 | 3 | 该补丁可以使Laravel同时维护多个`Mail Driver`,且自动根据目标邮箱地址切换使用不同的`Mail Driver`。 4 | 5 | ## 说明 6 | 7 | [English](README.md) 8 | 9 | [中文简体](README.zh_CN.md) 10 | 11 | ## 安装 12 | 13 | 1. 使用`Composer`安装: 14 | 15 | ```sh 16 | composer require kevinzheng/laravel-switchable-mail 17 | ``` 18 | 19 | 2. 在`config/app.php`中**替换**`Illuminate\Mail\MailServiceProvider::class`为`KVZ\Laravel\SwitchableMail\MailServiceProvider::class`。 20 | 21 | 3. 生成配置文件 22 | 23 | ```sh 24 | php artisan vendor:publish --tag=switchable-mail 25 | ``` 26 | 27 | ## 配置 28 | 29 | 默认使用`.env`中配置的`MAIL_DRIVER`作为邮件发送服务商,如果有特定邮箱地址需要指定不同`Mail Driver`,可以在`switchable-mail.php`中进行配置。如果要使用`Laravel`未提供的邮件服务商驱动,需要同时安装对应驱动。比如阿里云`Direct Mail`和搜狐的`SendCloud`需要安装对应的支持才可以。 30 | 31 | ```php 32 | // 'directmail' => [ 33 | // 'qq.com', '163.com', '126.com', 'sina.com', 'sina.com.cn', 'sohu.com', 34 | // ], 35 | 36 | // 'mailgun' => [ 37 | // 'example.com', 38 | // ], 39 | ``` 40 | 41 | 提供两个邮件驱动供大家参考选用: 42 | 43 | [laravel-directmail](https://github.com/kevinzheng/laravel-directmail) 44 | 45 | [laravel-sendcloud](https://github.com/kevinzheng/laravel-sendcloud) 46 | 47 | ## 使用 48 | 49 | 什么都不需要做,像使用`Laravel Mail`那样正常使用即可。 50 | 51 | ## 鸣谢 52 | 53 | [ElfSundae](https://github.com/ElfSundae) 54 | -------------------------------------------------------------------------------- /src/SwiftMessageHelper.php: -------------------------------------------------------------------------------- 1 | getTo(), 25 | (array) $message->getReplyTo(), 26 | (array) $message->getCc(), 27 | (array) $message->getBcc() 28 | ); 29 | 30 | if (! $associated) { 31 | $recipients = array_keys($recipients); 32 | } 33 | 34 | return $recipients; 35 | } 36 | 37 | /** 38 | * Get domains of the email addresses for the message recipients. 39 | * 40 | * @param \Swift_Message $message 41 | * @return string[] 42 | */ 43 | public static function getRecipientsDomains(Swift_Message $message) 44 | { 45 | return array_values(array_unique(array_map( 46 | function ($address) { 47 | return strtolower(last(explode('@', $address))); 48 | }, 49 | static::getRecipients($message, false) 50 | ))); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # laravel-switchable-mail 2 | 3 | It makes `Laravel` be able to maintain multiple mail drivers at the same time, and be able to send to different mail addresses with specified mail drivers as configured at runtime automatically. 4 | 5 | ## Instructions 6 | 7 | [English](README.md) 8 | 9 | [中文简体](README.zh_CN.md) 10 | 11 | ## Installation 12 | 13 | 1. Install this package using the Composer manager: 14 | 15 | ```sh 16 | composer require kevinzheng/laravel-switchable-mail 17 | ``` 18 | 19 | 2. **Replace** `Illuminate\Mail\MailServiceProvider::class` with `KVZ\Laravel\SwitchableMail\MailServiceProvider::class` in the `config/app.php` file. 20 | 21 | 3. Publish configuration file: 22 | 23 | ```sh 24 | php artisan vendor:publish --tag=switchable-mail 25 | ``` 26 | 27 | ## Configuration 28 | 29 | It uses the `MAIL_DRIVER` configured in `.env` as the default mail driver, for those addresses you want to send to with specified mail drivers, configure it at `switchable-mail.php`. 30 | You should install the mail drivers not provided by `Laravel` at the meantime, such as Aliyun `Direct Mail` and `SendCloud`: 31 | 32 | ```php 33 | // 'directmail' => [ 34 | // 'qq.com', '163.com', '126.com', 'sina.com', 'sina.com.cn', 'sohu.com', 35 | // ], 36 | 37 | // 'mailgun' => [ 38 | // 'example.com', 39 | // ], 40 | ``` 41 | 42 | Two mail drivers are available: 43 | 44 | [laravel-directmail](https://github.com/kevinzheng/laravel-directmail) 45 | 46 | [laravel-sendcloud](https://github.com/kevinzheng/laravel-sendcloud) 47 | 48 | ## Usage 49 | 50 | Nothing needs to be done, just use `Laravel Mail` as usual. 51 | 52 | ## Thanks to 53 | [ElfSundae](https://github.com/ElfSundae) 54 | -------------------------------------------------------------------------------- /src/Mailer.php: -------------------------------------------------------------------------------- 1 | swiftManager; 25 | } 26 | 27 | /** 28 | * Set the Swift Mailer Manager instance. 29 | * 30 | * @param \KVZ\Laravel\SwitchableMail\SwiftMailerManager $manager 31 | * @return void 32 | */ 33 | public function setSwiftMailerManager($manager) 34 | { 35 | $this->swiftManager = $manager; 36 | } 37 | 38 | /** 39 | * Send a Swift Message instance. 40 | * 41 | * @param \Swift_Message $message 42 | * @return void 43 | */ 44 | protected function sendSwiftMessage($message) 45 | { 46 | if ($this->events) { 47 | $this->events->fire(new MessageSending($message)); 48 | } 49 | 50 | $swift = $this->swiftManager->mailer(MailDriver::forMessage($message)); 51 | 52 | try { 53 | return $swift->send($message, $this->failedRecipients); 54 | } finally { 55 | $this->forceReconnection($swift); 56 | } 57 | } 58 | 59 | /** 60 | * Force the transport to re-connect. 61 | * 62 | * This will prevent errors in daemon queue situations. 63 | * 64 | * @param \Swift_Mailer $swiftMailer 65 | * @return void 66 | */ 67 | protected function forceReconnection($swiftMailer = null) 68 | { 69 | if (is_null($swiftMailer)) { 70 | $swiftMailer = $this->getSwiftMailer(); 71 | } 72 | 73 | $swiftMailer->getTransport()->stop(); 74 | } 75 | 76 | /** 77 | * Get the Swift Mailer instance. 78 | * 79 | * @return \Swift_Mailer 80 | */ 81 | public function getSwiftMailer() 82 | { 83 | return $this->swiftManager->mailer(); 84 | } 85 | 86 | /** 87 | * Set the Swift Mailer instance. 88 | * 89 | * @param \Swift_Mailer $swift 90 | * @return void 91 | */ 92 | public function setSwiftMailer($swift) 93 | { 94 | $this->swiftManager->setDefaultMailer($swift); 95 | 96 | // Our $swift is managed by the SwiftMailerManager singleton, 97 | // so just let $this->swift go. 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/MailServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 17 | __DIR__.'/../config/switchable-mail.php' => config_path('switchable-mail.php'), 18 | ], 'switchable-mail'); 19 | } 20 | 21 | /** 22 | * Register the service provider. 23 | * 24 | * @return void 25 | */ 26 | public function register() 27 | { 28 | $this->mergeConfigFrom(__DIR__.'/../config/switchable-mail.php', 'switchable-mail'); 29 | 30 | $this->registerSwiftMailer(); 31 | 32 | $this->registerSwiftMailerManager(); 33 | 34 | $this->registerMailer(); 35 | } 36 | 37 | /** 38 | * Register the swift mailer manager. 39 | * 40 | * @return void 41 | */ 42 | protected function registerSwiftMailerManager() 43 | { 44 | $this->app->singleton('swift.mailer.manager', function ($app) { 45 | return (new SwiftMailerManager($app)) 46 | ->setTransportManager($app['swift.transport']); 47 | }); 48 | } 49 | 50 | /** 51 | * Register the Mailer instance. 52 | * 53 | * @return void 54 | */ 55 | protected function registerMailer() 56 | { 57 | $this->app->singleton('mailer', function ($app) { 58 | // Once we have create the mailer instance, we will set a container instance 59 | // on the mailer. This allows us to resolve mailer classes via containers 60 | // for maximum testability on said classes instead of passing Closures. 61 | $mailer = new Mailer( 62 | $app['view'], $app['swift.mailer'], $app['events'] 63 | ); 64 | 65 | $this->setMailerDependencies($mailer, $app); 66 | 67 | // If a "from" address is set, we will set it on the mailer so that all mail 68 | // messages sent by the applications will utilize the same "from" address 69 | // on each one, which makes the developer's life a lot more convenient. 70 | $from = $app['config']['mail.from']; 71 | 72 | if (is_array($from) && isset($from['address'])) { 73 | $mailer->alwaysFrom($from['address'], $from['name']); 74 | } 75 | 76 | $to = $app['config']['mail.to']; 77 | 78 | if (is_array($to) && isset($to['address'])) { 79 | $mailer->alwaysTo($to['address'], $to['name']); 80 | } 81 | 82 | return $mailer; 83 | }); 84 | 85 | $this->app->alias('mailer', Mailer::class); 86 | } 87 | 88 | /** 89 | * Set a few dependencies on the mailer instance. 90 | * 91 | * @param \KVZ\Laravel\SwitchableMail\Mailer $mailer 92 | * @param \Illuminate\Foundation\Application $app 93 | * @return void 94 | */ 95 | protected function setMailerDependencies($mailer, $app) 96 | { 97 | parent::setMailerDependencies($mailer, $app); 98 | 99 | $mailer->setSwiftMailerManager($app['swift.mailer.manager']); 100 | } 101 | 102 | /** 103 | * Get the services provided by the provider. 104 | * 105 | * @return array 106 | */ 107 | public function provides() 108 | { 109 | return array_merge(parent::provides(), ['swift.mailer.manager']); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/SwiftMailerManager.php: -------------------------------------------------------------------------------- 1 | transportManager; 33 | } 34 | 35 | /** 36 | * Set the mail transport manager. 37 | * 38 | * @param \Illuminate\Mail\TransportManager $manager 39 | * @return $this 40 | */ 41 | public function setTransportManager(TransportManager $manager) 42 | { 43 | $this->transportManager = $manager; 44 | 45 | return $this; 46 | } 47 | 48 | /** 49 | * Get a swift mailer instance. 50 | * 51 | * @param string|null $driver 52 | * @return \Swift_Mailer 53 | */ 54 | public function mailer($driver = null) 55 | { 56 | return $this->driver($driver); 57 | } 58 | 59 | /** 60 | * Get all of the created swift mailer instances. 61 | * 62 | * @return array 63 | */ 64 | public function getMailers() 65 | { 66 | return $this->drivers; 67 | } 68 | 69 | /** 70 | * Get the name of mail driver for the given swift mailer instance. 71 | * 72 | * @param \Swift_Mailer $mailer 73 | * @return string|null 74 | */ 75 | public function getDriverForMailer(Swift_Mailer $mailer) 76 | { 77 | return array_search($mailer, $this->drivers) ?: null; 78 | } 79 | 80 | /** 81 | * Reset a swift mailer instance. 82 | * 83 | * @param string|\Swift_Mailer $mailer 84 | * @return $this 85 | */ 86 | public function resetMailer($mailer) 87 | { 88 | if ($driver = $this->validDriverName($mailer)) { 89 | unset($this->drivers[$driver]); 90 | } 91 | 92 | return $this; 93 | } 94 | 95 | /** 96 | * Reset all of the created swift mailer instances. 97 | * 98 | * @return $this 99 | */ 100 | public function resetMailers() 101 | { 102 | $this->drivers = []; 103 | 104 | return $this; 105 | } 106 | 107 | /** 108 | * Validate the given driver or mailer, and return the driver name. 109 | * 110 | * @param mixed $driver 111 | * @return string|null 112 | */ 113 | protected function validDriverName($driver) 114 | { 115 | if ($driver instanceof Swift_Mailer) { 116 | $driver = $this->getDriverForMailer($driver); 117 | } 118 | 119 | if (is_string($driver)) { 120 | return $driver; 121 | } 122 | } 123 | 124 | /** 125 | * Create a new swift mailer instance. 126 | * 127 | * @param string $driver 128 | * @return \Swift_Mailer 129 | */ 130 | protected function createDriver($driver) 131 | { 132 | return new Swift_Mailer($this->transportManager->driver($driver)); 133 | } 134 | 135 | /** 136 | * Get the default mail driver name. 137 | * 138 | * @return string 139 | */ 140 | public function getDefaultDriver() 141 | { 142 | return $this->defaultDriver ?: $this->transportManager->getDefaultDriver(); 143 | } 144 | 145 | /** 146 | * Set the default mail driver name. 147 | * 148 | * @param string $driver 149 | * @return $this 150 | */ 151 | public function setDefaultDriver($driver) 152 | { 153 | $this->defaultDriver = $driver; 154 | 155 | return $this; 156 | } 157 | 158 | /** 159 | * Set the default swift mailer. 160 | * 161 | * @param string|\Swift_Mailer $mailer 162 | * @return $this 163 | */ 164 | public function setDefaultMailer($mailer) 165 | { 166 | if ($driver = $this->validDriverName($mailer)) { 167 | $this->setDefaultDriver($driver); 168 | } 169 | 170 | return $this; 171 | } 172 | } 173 | --------------------------------------------------------------------------------