Skip to content

Commit

Permalink
Add feature to read mail configs from database
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Nielsen committed Apr 10, 2021
1 parent 0677ef0 commit af1c690
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 22 deletions.
39 changes: 20 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Install the package into your Laraval application with composer:

Publish the config file:

php artisan vendor:publish --provider="IWasHereFirst2\LaravelMultiMail\MultiMailServiceProvider"
php artisan vendor:publish --provider="IWasHereFirst2\LaravelMultiMail\MultiMailServiceProvider" --tag=config

Configure your email clients in `config/multimail.php`:

Expand Down Expand Up @@ -234,30 +234,31 @@ in your config file `config/multimail.php`. Note that `assertQueued` will never
### Get Mail From Database

If you want to load your mail account configuration from database
or anything else, just create a class that implements `\IWasHereFirst2\LaravelMultiMail\MailSettings`
and specify the class in `config/multimail.php` under the key `mail_settings_class`.
publish the package migrations:

For example:
php artisan vendor:publish --provider="IWasHereFirst2\LaravelMultiMail\MultiMailServiceProvider" --tag=migrations

In your migration folder are now two tabels, email_accounts and email_providers

Instead of adding emails to the config they should be added to the table email_accounts.

Make sure to update your config `config/multimail.php`:

<?php

return [
/*
|--------------------------------------------------------------------------
| List your email providers
|--------------------------------------------------------------------------
|
| Enjoy a life with multimail
|
*/
'use_default_mail_facade_in_tests' => true,

'mail_settings_class' => \App\MyCustomMailSettings::class,

'mail_settings_class' => \IWasHereFirst2\LaravelMultiMail\DatabaseConfigMailSettings::class,

//...
];

Notice that you do not need to specify `email` or `provider` in the config anymore.
They should be loaded by your custom class `\App\MyCustomMailSettings::class`.

The emails will now be read from the database instead from the configuration file.
If no provider is provided in email_accounts (column provider is nullable),
then the default profider from `config/multimail.php` will be considerd.

If you want to make customizations, copy the class `\IWasHereFirst2\LaravelMultiMail\DatabaseConfigMailSettings`
somewhere in your application, adjust the namespace, and update the reference `mail_settings_class` in your config file.

## Troubleshoot

Expand Down
202 changes: 202 additions & 0 deletions src/DatabaseConfigMailSettings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
<?php


namespace IWasHereFirst2\LaravelMultiMail;


use \IWasHereFirst2\LaravelMultiMail\MailSettings;
use IWasHereFirst2\LaravelMultiMail\Models\EmailAccount;

class DatabaseConfigMailSettings implements MailSettings
{
private $account;

private $provider;

/**
* Name from mail sender.
*
* @var string
*/
private $name;

/**
* Email from mail sender.
* Has to be set in `config/multimail.php`
*
* @var string
*/
private $email;


/**
* Email settings.
* This may include credentials, name, provider.
*
* @var array
*/
private $settings;

public function initialize($key): DatabaseConfigMailSettings
{
$this->parseEmail($key);

try {
$this->account = EmailAccount::where('email', '=', $this->email)->firstOrFail();
} catch (\Exception $e) {
throw new Exceptions\EmailNotInConfigException($this->email);
}

if (empty($this->name)) {
$this->name = $this->account->from_mail;
}

$this->loadProvider();

// If credentials are empty, load default values.
// This makes local testing for many emails
// very convenient.
if ($this->isEmpty()) {
$this->loadDefault();
}

return $this;
}
/**
* Check if log driver is used.
*
* @return boolean
*/
public function isLogDriver()
{
return (isset($this->provider['driver']) && $this->provider['driver'] == 'log');
}

/**
* Get provider.
*
* @return array
*/
public function getProvider()
{
return $this->provider;
}

/**
* Get setting.
*
* @return array
*/
public function getSetting()
{
return $this->account->toArray();
}

/**
* Return email of sender.
*
* @return string
*/
public function getFromEmail()
{
return $this->account->from_mail ?? $this->email;
}

/**
* Return name of sender.
*
* @return string
*/
public function getFromName()
{
return $this->name;
}

/**
* Return email of sender.
*
* @return string
*/
public function getReplyEmail()
{
return $this->account->reply_to_mail;
}

/**
* Return name of sender.
*
* @return string
*/
public function getReplyName()
{
return $this->account->reply_to_name;
}

public function getEmail()
{
return $this->email;
}

/**
* Check if email, pass and username are not empty
*
* @return boolean
*/
private function isEmpty()
{
return (empty($this->email) || empty($this->account) || empty($this->account->pass) || empty($this->account->username));
}

/**
* Load default setting. If default setting is
* invalid throw exception
*
* @return void
*/
private function loadDefault()
{
$this->account = (object) config('multimail.emails.default');

$this->loadProvider();

if ((!isset($this->provider['driver']) || $this->provider['driver'] != 'log') && (empty($this->acount->pass) || empty($this->account->username))) {
throw new Exceptions\NoDefaultException($this->email);
}
}

/**
* Parse $key into email and possible from name
*
* @param mixed string/array
* @return void
*/
private function parseEmail($key)
{
if (!is_array($key)) {
$this->email = $key;
return;
}

$this->name = $key['name'] ?? null;

if (empty($key['email'])) {
throw new Exceptions\InvalidConfigKeyException;
}

$this->email = $key['email'];
}


private function loadProvider()
{

if (!empty($this->account->provider)) {
$this->provider = $this->account->provider->toArray();
}

if (empty($this->provider)) {
$this->provider = config('multimail.provider.default');
}
}

}
2 changes: 1 addition & 1 deletion src/FileConfigMailSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,4 @@ private function loadProvider()
$this->provider = config('multimail.provider.default');
}
}
}
}
34 changes: 34 additions & 0 deletions src/Migrations/2021_04_10_141537_create_email_providers_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateEmailProvidersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('email_providers', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('host');
$table->string('port');
$table->string('encryption');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('email_providers');
}
}
40 changes: 40 additions & 0 deletions src/Migrations/2021_04_10_141626_create_email_accounts_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateEmailAccountsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('email_accounts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('email');
$table->string('pass');
$table->string('username')->nullable();
$table->string('from_name')->nullable();
$table->string('reply_to_mail')->nullable();
$table->string('reply_to_name')->nullable();
$table->bigInteger('provider_id')->unsigned()->nullable();
$table->timestamps();

$table->foreign('provider_id')->references('id')->on('email_providers');
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('email_accounts');
}
}
13 changes: 13 additions & 0 deletions src/Models/EmailAccount.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace IWasHereFirst2\LaravelMultiMail\Models;

use Illuminate\Database\Eloquent\Model;

class EmailAccount extends Model
{
public function provider()
{
return $this->belongsTo(EmailProvider::class);
}
}
10 changes: 10 additions & 0 deletions src/Models/EmailProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace IWasHereFirst2\LaravelMultiMail\Models;

use Illuminate\Database\Eloquent\Model;

class EmailProvider extends Model
{
//
}
9 changes: 7 additions & 2 deletions src/MultiMailServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function register()
public function boot()
{
$this->app->bind('iwasherefirst2-laravelmultimail', function () {
if(config()->has('multimail.config_class')){
if(config()->has('multimail.mail_settings_class')){
$configClass = config('multimail.mail_settings_class');
$config = new $configClass();
}
Expand All @@ -36,6 +36,11 @@ public function boot()

$this->publishes([
dirname(__DIR__) . '/publishable/config/multimail.php' => config_path('multimail.php'),
]);
], 'config');


$this->publishes([
__DIR__.'/Migrations/' => database_path('migrations')
], 'migrations');
}
}

0 comments on commit af1c690

Please sign in to comment.