#123: The framework of sending e-mails using Mailables but queued in the database is now there. Password reset e-mails are now the first ones being sent using the queue.
This commit is contained in:
parent
bfbf740810
commit
7418438d63
141
app/Console/Commands/SendEmailsCommand.php
Normal file
141
app/Console/Commands/SendEmailsCommand.php
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\EmailLog;
|
||||||
|
use App\Facade\UserConfig;
|
||||||
|
use App\Http\Middleware\GlobalConfiguration;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Mail\Mailer;
|
||||||
|
use Illuminate\Mail\Message;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
|
||||||
|
class SendEmailsCommand extends Command
|
||||||
|
{
|
||||||
|
const MAX_EMAILS_PER_BATCH = 100;
|
||||||
|
|
||||||
|
const MAX_NUMBER_ATTEMPTS = 5;
|
||||||
|
|
||||||
|
const SECONDS_TO_SLEEP = 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'bt-queue:send-emails {--poll}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Sends e-mails queued in the database.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
GlobalConfiguration::updateMailConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
if (!UserConfig::get('queue_emails'))
|
||||||
|
{
|
||||||
|
$this->output->error('E-mail queueing is not enabled. E-mails are being sent immediately.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->output->writeln('E-mail queue runner started');
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
$emailsToSend = EmailLog::where([
|
||||||
|
['sent_at', null],
|
||||||
|
['number_attempts', '<', self::MAX_NUMBER_ATTEMPTS]
|
||||||
|
])->limit(self::MAX_EMAILS_PER_BATCH)->get();
|
||||||
|
|
||||||
|
$this->output->writeln(sprintf(
|
||||||
|
'%d e-mail%s to send',
|
||||||
|
$emailsToSend->count(),
|
||||||
|
$emailsToSend->count() == 1 ? '' : 's'
|
||||||
|
));
|
||||||
|
|
||||||
|
/** @var EmailLog $emailToSend */
|
||||||
|
foreach ($emailsToSend as $emailToSend)
|
||||||
|
{
|
||||||
|
$this->sendEmail($emailToSend);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->option('poll'))
|
||||||
|
{
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(self::SECONDS_TO_SLEEP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendEmail(EmailLog $emailLog)
|
||||||
|
{
|
||||||
|
$this->output->writeln(sprintf('Sending message with subject \'%s\'', $emailLog->subject));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
app('mailer')->send(
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
function (Message $message) use ($emailLog)
|
||||||
|
{
|
||||||
|
$message->setFrom($emailLog->sender_address, $emailLog->sender_name);
|
||||||
|
$message->setSubject($emailLog->subject);
|
||||||
|
|
||||||
|
$this->addAddresses($emailLog->to_addresses, $message, 'To');
|
||||||
|
$this->addAddresses($emailLog->cc_addresses, $message, 'Cc');
|
||||||
|
$this->addAddresses($emailLog->bcc_addresses, $message, 'Bcc');
|
||||||
|
|
||||||
|
$message->addPart($emailLog->body_plain, 'text/plain');
|
||||||
|
$message->setBody($emailLog->body_html, 'text/html');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$emailLog->sent_at = new \DateTime();
|
||||||
|
|
||||||
|
$this->output->writeln('Send completed');
|
||||||
|
}
|
||||||
|
catch (\Exception $ex)
|
||||||
|
{
|
||||||
|
$this->output->error(sprintf('Send failed: %s', $ex->getMessage()));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
$emailLog->number_attempts++;
|
||||||
|
$emailLog->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addAddresses($dbFieldData, Message $message, $property)
|
||||||
|
{
|
||||||
|
$decoded = json_decode($dbFieldData);
|
||||||
|
|
||||||
|
if (is_array($decoded))
|
||||||
|
{
|
||||||
|
foreach ($decoded as $addressInfo)
|
||||||
|
{
|
||||||
|
$this->output->writeln(sprintf('Adding %s address: \'"%s" <%s>\'', $property, $addressInfo->name, $addressInfo->address));
|
||||||
|
|
||||||
|
$message->{"set{$property}"}($addressInfo->address, $addressInfo->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
app/EmailLog.php
Normal file
26
app/EmailLog.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class EmailLog extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'sender_user_id',
|
||||||
|
'queued_at',
|
||||||
|
'sent_at',
|
||||||
|
'sender_name',
|
||||||
|
'sender_address',
|
||||||
|
'to_addresses',
|
||||||
|
'cc_addresses',
|
||||||
|
'subject',
|
||||||
|
'body_plain',
|
||||||
|
'body_html'
|
||||||
|
];
|
||||||
|
}
|
@ -23,6 +23,44 @@ class GlobalConfiguration
|
|||||||
*/
|
*/
|
||||||
protected $app;
|
protected $app;
|
||||||
|
|
||||||
|
public static function updateMailConfig()
|
||||||
|
{
|
||||||
|
/** @var Mailer $mailer */
|
||||||
|
$mailer = app('mailer');
|
||||||
|
$swiftMailer = $mailer->getSwiftMailer();
|
||||||
|
|
||||||
|
/** @var \Swift_SmtpTransport $transport */
|
||||||
|
$transport = $swiftMailer->getTransport();
|
||||||
|
$transport->setHost(UserConfig::get('smtp_server'));
|
||||||
|
$transport->setPort(intval(UserConfig::get('smtp_port')));
|
||||||
|
|
||||||
|
$username = UserConfig::get('smtp_username');
|
||||||
|
if (!is_null($username))
|
||||||
|
{
|
||||||
|
$transport->setUsername($username);
|
||||||
|
}
|
||||||
|
|
||||||
|
$password = UserConfig::get('smtp_password');
|
||||||
|
if (!is_null($password))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$transport->setPassword(decrypt($password));
|
||||||
|
}
|
||||||
|
catch (DecryptException $ex)
|
||||||
|
{
|
||||||
|
// Unable to decrypt the password - presumably the app's key has changed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UserConfig::get('smtp_encryption'))
|
||||||
|
{
|
||||||
|
$transport->setEncryption('tls');
|
||||||
|
}
|
||||||
|
|
||||||
|
$mailer->alwaysFrom(UserConfig::get('sender_address'), UserConfig::get('sender_name'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new middleware instance.
|
* Create a new middleware instance.
|
||||||
*
|
*
|
||||||
@ -170,42 +208,4 @@ class GlobalConfiguration
|
|||||||
View::share('app_version', $version);
|
View::share('app_version', $version);
|
||||||
View::share('app_version_url', $version);
|
View::share('app_version_url', $version);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateMailConfig()
|
|
||||||
{
|
|
||||||
/** @var Mailer $mailer */
|
|
||||||
$mailer = $this->app->mailer;
|
|
||||||
$swiftMailer = $mailer->getSwiftMailer();
|
|
||||||
|
|
||||||
/** @var \Swift_SmtpTransport $transport */
|
|
||||||
$transport = $swiftMailer->getTransport();
|
|
||||||
$transport->setHost(UserConfig::get('smtp_server'));
|
|
||||||
$transport->setPort(intval(UserConfig::get('smtp_port')));
|
|
||||||
|
|
||||||
$username = UserConfig::get('smtp_username');
|
|
||||||
if (!is_null($username))
|
|
||||||
{
|
|
||||||
$transport->setUsername($username);
|
|
||||||
}
|
|
||||||
|
|
||||||
$password = UserConfig::get('smtp_password');
|
|
||||||
if (!is_null($password))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$transport->setPassword(decrypt($password));
|
|
||||||
}
|
|
||||||
catch (DecryptException $ex)
|
|
||||||
{
|
|
||||||
// Unable to decrypt the password - presumably the app's key has changed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UserConfig::get('smtp_encryption'))
|
|
||||||
{
|
|
||||||
$transport->setEncryption('tls');
|
|
||||||
}
|
|
||||||
|
|
||||||
$mailer->alwaysFrom(UserConfig::get('sender_address'), UserConfig::get('sender_name'));
|
|
||||||
}
|
|
||||||
}
|
}
|
41
app/Mail/MailableBase.php
Normal file
41
app/Mail/MailableBase.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use App\EmailLog;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\HtmlString;
|
||||||
|
|
||||||
|
abstract class MailableBase extends Mailable
|
||||||
|
{
|
||||||
|
public function buildEmailLog()
|
||||||
|
{
|
||||||
|
// Build the e-mail
|
||||||
|
$this->build();
|
||||||
|
|
||||||
|
// Get the current user for the ID
|
||||||
|
$currentUser = Auth::user();
|
||||||
|
|
||||||
|
// Build the body so we can use it as a string
|
||||||
|
$bodies = $this->buildView();
|
||||||
|
|
||||||
|
/** @var HtmlString $html */
|
||||||
|
$html = $bodies['html'];
|
||||||
|
|
||||||
|
/** @var HtmlString $text */
|
||||||
|
$text = $bodies['text'];
|
||||||
|
|
||||||
|
return new EmailLog([
|
||||||
|
'sender_user_id' => !is_null($currentUser) ? $currentUser->id : null,
|
||||||
|
'sender_name' => $this->from[0]['name'],
|
||||||
|
'sender_address' => $this->from[0]['address'],
|
||||||
|
'to_addresses' => json_encode($this->to),
|
||||||
|
'cc_addresses' => json_encode($this->cc),
|
||||||
|
'bcc_addresses' => json_encode($this->bcc),
|
||||||
|
'subject' => $this->subject,
|
||||||
|
'body_plain' => $text->toHtml(),
|
||||||
|
'body_html' => $html->toHtml()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
48
app/Mail/ResetMyPassword.php
Normal file
48
app/Mail/ResetMyPassword.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use App\Facade\Theme;
|
||||||
|
use App\Facade\UserConfig;
|
||||||
|
use App\User;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ResetMyPassword extends MailableBase
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
private $token;
|
||||||
|
private $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(User $user, $token)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
$this->token = $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
$subject = trans('email.reset_my_password_subject', ['app_name' => UserConfig::get('app_name')]);
|
||||||
|
|
||||||
|
return $this
|
||||||
|
->subject($subject)
|
||||||
|
->markdown(Theme::viewName('email.reset_my_password'))
|
||||||
|
->with([
|
||||||
|
'subject' => $subject,
|
||||||
|
'token' => $this->token,
|
||||||
|
'user' => $this->user
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
22
app/Notifications/EmailDatabaseWriterChannelBase.php
Normal file
22
app/Notifications/EmailDatabaseWriterChannelBase.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\EmailLog;
|
||||||
|
|
||||||
|
class EmailDatabaseWriterChannelBase
|
||||||
|
{
|
||||||
|
protected function writeToTable(EmailLog $logEntry, $shouldQueue = false)
|
||||||
|
{
|
||||||
|
if ($shouldQueue)
|
||||||
|
{
|
||||||
|
$logEntry->queued_at = new \DateTime();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$logEntry->sent_at = new \DateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
$logEntry->save();
|
||||||
|
}
|
||||||
|
}
|
24
app/Notifications/QueueEmailDatabaseChannel.php
Normal file
24
app/Notifications/QueueEmailDatabaseChannel.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\EmailLog;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
|
||||||
|
class QueueEmailDatabaseChannel extends EmailDatabaseWriterChannelBase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Send the given notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @param \Illuminate\Notifications\Notification $notification
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function send($notifiable, Notification $notification)
|
||||||
|
{
|
||||||
|
/** @var EmailLog $logEntry */
|
||||||
|
$logEntry = $notification->toQueueEmailDatabase($notifiable);
|
||||||
|
|
||||||
|
$this->writeToTable($logEntry, true);
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Notifications;
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\Facade\UserConfig;
|
||||||
|
use App\Mail\MailableBase;
|
||||||
|
use App\Mail\ResetMyPassword;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
use Illuminate\Notifications\Notification;
|
use Illuminate\Notifications\Notification;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Notifications\Messages\MailMessage;
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
@ -37,33 +41,40 @@ class ResetPassword extends Notification
|
|||||||
*/
|
*/
|
||||||
public function via($notifiable)
|
public function via($notifiable)
|
||||||
{
|
{
|
||||||
return ['mail'];
|
$drivers = [];
|
||||||
|
|
||||||
|
if (UserConfig::get('queue_emails'))
|
||||||
|
{
|
||||||
|
$drivers[] = QueueEmailDatabaseChannel::class;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$drivers[] = 'mail';
|
||||||
|
$drivers[] = SentEmailDatabaseChannel::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $drivers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toQueueEmailDatabase($notifiable)
|
||||||
|
{
|
||||||
|
return $this->toMail($notifiable)->buildEmailLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the mail representation of the notification.
|
* Get the mail representation of the notification.
|
||||||
*
|
*
|
||||||
* @param mixed $notifiable
|
* @param mixed $notifiable
|
||||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
* @return \Illuminate\Notifications\Messages\MailMessage|MailableBase
|
||||||
*/
|
*/
|
||||||
public function toMail($notifiable)
|
public function toMail($notifiable)
|
||||||
{
|
{
|
||||||
return (new MailMessage)
|
$notification = new ResetMyPassword($notifiable, $this->token);
|
||||||
->line('You are receiving this email because we received a password reset request for your account.')
|
|
||||||
->action('Reset Password', route('password.reset', $this->token, true))
|
|
||||||
->line('If you did not request a password reset, no further action is required.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Set to and from properties accordingly
|
||||||
* Get the array representation of the notification.
|
$notification->from(UserConfig::get('sender_address'), UserConfig::get('sender_name'));
|
||||||
*
|
$notification->to($notifiable->email, $notifiable->name);
|
||||||
* @param mixed $notifiable
|
|
||||||
* @return array
|
return $notification;
|
||||||
*/
|
|
||||||
public function toArray($notifiable)
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
//
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
app/Notifications/SentEmailDatabaseChannel.php
Normal file
24
app/Notifications/SentEmailDatabaseChannel.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\EmailLog;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
|
||||||
|
class SentEmailDatabaseChannel extends EmailDatabaseWriterChannelBase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Send the given notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @param \Illuminate\Notifications\Notification $notification
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function send($notifiable, Notification $notification)
|
||||||
|
{
|
||||||
|
/** @var EmailLog $logEntry */
|
||||||
|
$logEntry = $notification->toDatabaseWriter($notifiable);
|
||||||
|
|
||||||
|
$this->writeToTable($logEntry, false);
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@
|
|||||||
"type": "project",
|
"type": "project",
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.0.0",
|
"php": ">=7.0.0",
|
||||||
|
"ext-json": "*",
|
||||||
"laravel/framework": "5.5.*",
|
"laravel/framework": "5.5.*",
|
||||||
"rackspace/php-opencloud": "^1.16",
|
"rackspace/php-opencloud": "^1.16",
|
||||||
"doctrine/dbal": "^2.5",
|
"doctrine/dbal": "^2.5",
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
|
|
||||||
class CreateJobsTable extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::create('background_jobs', function (Blueprint $table) {
|
|
||||||
$table->bigIncrements('id');
|
|
||||||
$table->string('queue')->index();
|
|
||||||
$table->longText('payload');
|
|
||||||
$table->unsignedTinyInteger('attempts');
|
|
||||||
$table->unsignedInteger('reserved_at')->nullable();
|
|
||||||
$table->unsignedInteger('available_at');
|
|
||||||
$table->unsignedInteger('created_at');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('background_jobs');
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class CreateEmailLogsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('email_logs', function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id');
|
||||||
|
$table->unsignedInteger('sender_user_id')->nullable(true);
|
||||||
|
$table->dateTime('queued_at')->nullable(true);
|
||||||
|
$table->dateTime('sent_at')->nullable(true);
|
||||||
|
$table->string('sender_name');
|
||||||
|
$table->string('sender_address');
|
||||||
|
$table->text('to_addresses');
|
||||||
|
$table->text('cc_addresses')->nullable(true);
|
||||||
|
$table->text('bcc_addresses')->nullable(true);
|
||||||
|
$table->string('subject');
|
||||||
|
$table->longText('body_plain');
|
||||||
|
$table->longText('body_html');
|
||||||
|
$table->integer('number_attempts')->default(0);
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->foreign('sender_user_id')
|
||||||
|
->references('id')->on('users')
|
||||||
|
->onDelete('cascade');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('email_logs');
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,10 @@ return [
|
|||||||
'photo_comment_replied_to_p1' => 'A reply to your comment has been posted in the :album_name album.',
|
'photo_comment_replied_to_p1' => 'A reply to your comment has been posted in the :album_name album.',
|
||||||
'photo_comment_replied_to_p2' => 'Click the button below to view the photo\'s page to see the reply to your comment.',
|
'photo_comment_replied_to_p2' => 'Click the button below to view the photo\'s page to see the reply to your comment.',
|
||||||
'photo_comment_replied_to_subject' => 'A reply to your comment was posted in :album_name',
|
'photo_comment_replied_to_subject' => 'A reply to your comment was posted in :album_name',
|
||||||
|
'reset_my_password_action' => 'Reset Password',
|
||||||
|
'reset_my_password_p1' => 'You are receiving this email because we received a password reset request for your account.',
|
||||||
|
'reset_my_password_p2' => 'If you did not request a password reset, no further action is required.',
|
||||||
|
'reset_my_password_subject' => 'Your password reset link for :app_name',
|
||||||
'user_self_activated_p1' => 'A new user has been created and activated at :app_name. The user\'s details are shown below.',
|
'user_self_activated_p1' => 'A new user has been created and activated at :app_name. The user\'s details are shown below.',
|
||||||
'user_self_activated_p2' => 'Name: :user_name',
|
'user_self_activated_p2' => 'Name: :user_name',
|
||||||
'user_self_activated_p3' => 'E-mail address: :email_address',
|
'user_self_activated_p3' => 'E-mail address: :email_address',
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
@component('mail::message')
|
||||||
|
@lang('email.generic_intro', ['user_name' => $user->name])
|
||||||
|
|
||||||
|
|
||||||
|
@lang('email.reset_my_password_p1')
|
||||||
|
|
||||||
|
|
||||||
|
@component('mail::button', ['url' => route('password.reset', $token, true), 'color' => 'blue'])
|
||||||
|
@lang('email.reset_my_password_action')
|
||||||
|
@endcomponent
|
||||||
|
|
||||||
|
|
||||||
|
@lang('email.reset_my_password_p2')
|
||||||
|
|
||||||
|
|
||||||
|
@lang('email.generic_regards')<br/>
|
||||||
|
{{ UserConfig::get('app_name') }}<br/>
|
||||||
|
<a href="{{ route('home') }}">{{ route('home') }}</a>
|
||||||
|
@endcomponent
|
Loading…
Reference in New Issue
Block a user