diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index a97b90b173..10cb1bb3f9 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -69,7 +69,7 @@ class Kernel extends ConsoleKernel /* Run hosted specific jobs */ if (Ninja::isHosted()) { - $schedule->job(new AdjustEmailQuota)->daily()->withoutOverlapping(); + $schedule->job(new AdjustEmailQuota)->dailyAt('23:00')->withoutOverlapping(); $schedule->job(new SendFailedEmails)->daily()->withoutOverlapping(); $schedule->command('ninja:check-data --database=db-ninja-02')->daily()->withoutOverlapping(); diff --git a/app/Jobs/Mail/NinjaMailerJob.php b/app/Jobs/Mail/NinjaMailerJob.php index 21cb877b25..987e79f657 100644 --- a/app/Jobs/Mail/NinjaMailerJob.php +++ b/app/Jobs/Mail/NinjaMailerJob.php @@ -72,9 +72,6 @@ class NinjaMailerJob implements ShouldQueue public function handle() { - - if($this->preFlightChecksFail()) - return; /*Set the correct database*/ MultiDB::setDb($this->nmo->company->db); @@ -82,6 +79,9 @@ class NinjaMailerJob implements ShouldQueue /* Serializing models from other jobs wipes the primary key */ $this->company = Company::where('company_key', $this->nmo->company->company_key)->first(); + if($this->preFlightChecksFail()) + return; + /* Set the email driver */ $this->setMailDriver(); diff --git a/app/Jobs/Ninja/AdjustEmailQuota.php b/app/Jobs/Ninja/AdjustEmailQuota.php index c122f0b227..dec4945673 100644 --- a/app/Jobs/Ninja/AdjustEmailQuota.php +++ b/app/Jobs/Ninja/AdjustEmailQuota.php @@ -13,26 +13,18 @@ namespace App\Jobs\Ninja; use App\Libraries\MultiDB; use App\Models\Account; +use App\Utils\Ninja; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Cache; class AdjustEmailQuota implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - const FREE_PLAN_DAILY_QUOTA = 10; - const PRO_PLAN_DAILY_QUOTA = 50; - const ENTERPRISE_PLAN_DAILY_QUOTA = 200; - - const FREE_PLAN_DAILY_CAP = 20; - const PRO_PLAN_DAILY_CAP = 100; - const ENTERPRISE_PLAN_DAILY_CAP = 300; - - const DAILY_MULTIPLIER = 1.1; - /** * Create a new job instance. * @@ -50,22 +42,27 @@ class AdjustEmailQuota implements ShouldQueue */ public function handle() { - if (! config('ninja.db.multi_db_enabled')) { - $this->adjust(); - } else { - //multiDB environment, need to - foreach (MultiDB::$dbs as $db) { - MultiDB::setDB($db); + if(!Ninja::isHosted()) + return; + + //multiDB environment, need to + foreach (MultiDB::$dbs as $db) { + + MultiDB::setDB($db); + + $this->adjust(); - $this->adjust(); - } } + } public function adjust() { - foreach (Account::cursor() as $account) { - //@TODO once we add in the two columns daily_emails_quota daily_emails_sent_ - } + + Account::query()->cursor()->each(function ($account){ + Cache::forget($account->key); + Cache::forget("throttle_notified:{$account->key}"); + }); + } } diff --git a/app/Mail/Ninja/EmailQuotaExceeded.php b/app/Mail/Ninja/EmailQuotaExceeded.php new file mode 100644 index 0000000000..12808cf8a4 --- /dev/null +++ b/app/Mail/Ninja/EmailQuotaExceeded.php @@ -0,0 +1,60 @@ +company = $company; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + $this->settings = $this->company->settings; + $this->logo = $this->company->present()->logo(); + $this->title = ctrans('texts.email_quota_exceeded_subject'); + $this->body = ctrans('texts.email_quota_exceeded_body', ['quota' => $this->company->account->getDailyEmailLimit()]); + $this->whitelabel = $this->company->account->isPaid(); + + return $this->from(config('mail.from.address'), config('mail.from.name')) + ->subject(ctrans('texts.email_quota_exceeded_subject')) + ->view('email.admin.email_quota_exceeded'); + } +} diff --git a/app/Models/Account.php b/app/Models/Account.php index 05b0cb7264..76f3e79b0f 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -11,14 +11,16 @@ namespace App\Models; +use App\Jobs\Mail\NinjaMailerJob; +use App\Jobs\Mail\NinjaMailerObject; use App\Models\Presenters\AccountPresenter; use App\Utils\Ninja; use App\Utils\Traits\MakesHash; use Carbon\Carbon; use DateTime; use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Laracasts\Presenter\PresentableTrait; use Illuminate\Support\Facades\Cache; +use Laracasts\Presenter\PresentableTrait; class Account extends BaseModel { @@ -357,7 +359,24 @@ class Account extends BaseModel if(is_null(Cache::get($this->key))) return false; - return Cache::get($this->key) > $this->getDailyEmailLimit(); + if(Cache::get($this->key) > $this->getDailyEmailLimit()) { + + if(is_null(Cache::get("throttle_notified:{$this->key}"))) { + + $nmo = new NinjaMailerObject; + $nmo->mailable = new MaxCompanies($account->companies()->first()); + $nmo->company = $account->companies()->first(); + $nmo->settings = $account->companies()->first()->settings; + $nmo->to_user = $account->companies()->first()->owner(); + NinjaMailerJob::dispatch($nmo); + + Cache::put("throttle_notified:{$this->key}", true, 60 * 24); + } + + return true; + } + + return false; } } diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index eed12cf3f4..c9cd5d7ffc 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -4289,6 +4289,8 @@ $LANG = array( 'back_to' => 'Back to :url', 'stripe_connect_migration_title' => 'Connect your Stripe Account', 'stripe_connect_migration_desc' => 'Invoice Ninja v5 uses Stripe Connect to link your Stripe account to Invoice Ninja. This provides an additional layer of security for your account. Now that you data has migrated, you will need to Authorize Stripe to accept payments in v5.

To do this, navigate to Settings > Online Payments > Configure Gateways. Click on Stripe Connect and then under Settings click Setup Gateway. This will take you to Stripe to authorize Invoice Ninja and on your return your account will be successfully linked!', + 'email_quota_exceeded_subject' => 'Account email quota exceeded.', + 'email_quota_exceeded_body' => 'In a 24 hour period you have sent :quota emails.
We have paused your outbound emails.

Your email quota will reset at 23:00 UTC.', ); return $LANG; diff --git a/resources/views/email/admin/email_quota_exceeded.blade.php b/resources/views/email/admin/email_quota_exceeded.blade.php new file mode 100644 index 0000000000..d63aaaf268 --- /dev/null +++ b/resources/views/email/admin/email_quota_exceeded.blade.php @@ -0,0 +1,7 @@ +@component('email.template.admin', ['logo' => $logo, 'settings' => $settings]) +
+

{!! $title !!}

+ +

{!! $body !!}

+
+@endcomponent