Back | Home
الـ Path الحالي: /home/picotech/domains/instantly.picotech.app/public_html/public/../resources/./../app/Http/Controllers
الملفات الموجودة في هذا الـ Path:
.
..
Admin
AssetController.php
Auth
Controller.php
Customer
FrontController.php
InboundController.php
RouteController.php
ScheduleController.php
UpgradeController.php

مشاهدة ملف: ScheduleController.php

<?php

namespace App\Http\Controllers;

use App\EmailProvider\SendMailProcess;
use App\Events\SendEMail;
use App\Models\Contact;
use App\Models\Domain;
use App\Models\EmailAccount;
use App\Models\EmailQueue;
use App\Models\Message;
use App\Models\SendingServer;
use App\Models\Unsubscribe;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;


class ScheduleController extends Controller
{
    public function process()
    {
        $sendFailed = [];
        $allNumbers = [];
        $messages = EmailQueue::where(['schedule_completed' => 'no'])
            ->whereNotNull('schedule_datetime')
            ->whereNull('delivered_at')
            ->where('schedule_datetime', '<', now())
            ->where('status', 'running')
            ->limit(100)
            ->get()
            ->mapToGroups(function ($item, $key) {
                return ["" . $item->from => $item];
            })->map(function ($q) {
                return $q->take(15);
            });

        $mergedMessages = [];
        $queueIds = [];
        foreach ($messages as $items) {
            foreach ($items as $item) {
                $queueIds[] = $item->id;
                $mergedMessages[] = $item;
            }
        }
       if (empty($queueIds)) {
           if (config('app.debug')) {
               Log::info("Queue is empty");
           }
           exit;
       }

        $messages = $mergedMessages;
        $messageBody = [];
        //getting limit crossed list
        $totalNewQueueCount = count($messages);
        //    dd($totalNewQueueCount);
        $sendingServers = SendingServer::where('status', 'active')->where('sending_type','production')->get()->all();

        #region Monthly Limit Check
        $monthlyEmailQueue = EmailQueue::selectRaw("count(*) as total,sending_server_id")
            ->where('schedule_completed', 'yes')
            ->whereBetween('schedule_datetime', [now()->subMonth(), now()])
            ->groupBy('sending_server_id')
            ->pluck('total', 'sending_server_id')
            ->all();
        $availableMonthlySendingServerIds = [];
        foreach ($sendingServers as $sendingServer) {
            if (isset($monthlyEmailQueue[$sendingServer->id])) {
                $totalUsed = $monthlyEmailQueue[$sendingServer->id] + $totalNewQueueCount; // count new queue ;
                if ($sendingServer->monthly_limit > $totalUsed) {
                    $availableMonthlySendingServerIds[] = $sendingServer->id;
                }
            } else {
                $availableMonthlySendingServerIds[] = $sendingServer->id;
            }
        }
        #endregion

        #region Daily Limit Check
        $dailyEmailQueue = EmailQueue::selectRaw("count(*) as total,sending_server_id")
            ->where('schedule_completed', 'yes')
            ->whereIn('sending_server_id', $availableMonthlySendingServerIds)
            ->whereBetween('schedule_datetime', [now()->subDay(), now()])
            ->groupBy('sending_server_id')
            ->pluck('total', 'sending_server_id')
            ->all();
        $availableDailySendingServerIds = [];
        foreach ($sendingServers as $sendingServer) {
            if (isset($dailyEmailQueue[$sendingServer->id])) {
                $totalUsed = $dailyEmailQueue[$sendingServer->id] + $totalNewQueueCount; // count new queue ;
                if ($sendingServer->daily_limit > $totalUsed) {
                    $availableDailySendingServerIds[] = $sendingServer->id;
                }
            } else {
                $availableDailySendingServerIds[] = $sendingServer->id;
            }
        }
        #endregion

        #region Hourly Limit Check
        $hourlyEmailQueue = EmailQueue::selectRaw("count(*) as total,sending_server_id")
            ->where('schedule_completed', 'yes')
            ->whereBetween('schedule_datetime', [now()->subHour(), now()])
            ->whereIn('sending_server_id', $availableDailySendingServerIds)
            ->groupBy('sending_server_id')
            ->pluck('total', 'sending_server_id')
            ->all();

        $availableHourlySendingServer = collect([]);
        foreach ($sendingServers as $sendingServer) {
            if (isset($hourlyEmailQueue[$sendingServer->id])) {
                $totalUsed = $hourlyEmailQueue[$sendingServer->id] + $totalNewQueueCount; // count new queue ;
                if ($sendingServer->hourly_limit > $totalUsed) {
                    $availableHourlySendingServer->push($sendingServer);
                }
            } else {
                $availableHourlySendingServer->push($sendingServer);
            }
        }
        #endregion

       if ($availableHourlySendingServer->isEmpty()) {
           if (config('app.debug')) {
               Log::info("server is empty");
           }
           exit;
       }


       EmailQueue::whereIn('id', $queueIds)->update(['schedule_completed' => 'yes']);
        foreach ($messages as $message) {
            try {
                $allNumbers[] = $message->to;
                $messageBody[$message->to][] = $message->body;
                $current_plan = $message->user->plan;

                if (!$current_plan){
                    Log::error("plan not found for message " . $message->id);
                    return response()->json(['message' => 'Plan not found']);
                }

                $pre_available_email = $current_plan->available_emails;

                $new_available_email = $pre_available_email - 1;

                //if not enough email then return
                if ($new_available_email < 0) {
                    Log::error("Don\'t have enough email. Email id:" . $message->id);
                    return response()->json(['message' => 'Don\'t have enough email']);
                }
                $domain = Domain::where(['id' => $message->domain_id])->first();

                $server_config_value = [];

                foreach ($availableHourlySendingServer as $server) {
                    $server->send_dkim_private_key = false;
                    if ($domain && isset($domain->dkim_private_key) && $domain->dkim_private_key && $server->value) {
                        $dns_key = explode('.', $domain->dnskey); // pmail._domainkey.example.com
                        $value = (object)json_decode($server->value);
                        $value->dkim_private_key = $domain->dkim_private_key;
                        $value->dkim_domain = $domain->name;
                        $value->dkim_selector = $dns_key[0] ?? 'pmail';
                        $value->from = $message->from;
                        $server->value = json_encode($value);
                        $server->send_dkim_private_key = true;
                    }
                    $server_config_value[$server->from] = $server; // TODO::convert model to collect
                }
                $availableServerFirst = $availableHourlySendingServer->sortBy('priority')->first();
                $provider = $availableServerFirst->from;

               //if domain verified then send using sendmail
               if ($domain && isset($domain->dkim_private_key) && $domain->dkim_private_key) {
                   $availableServerSendmail = $availableHourlySendingServer->where('from', 'sendmail')->first();
                   if ($availableServerSendmail) {
                       $provider = 'sendmail';
                   }
               }
                if (isset($availableServerSendmail) && $availableServerSendmail) {
                    $availableServerFirst = $availableServerSendmail;
                }
                $message->update(['sending_server_id' => $availableServerFirst->id]);
               // dd($server_config_value,$message);

                $sendEmail = new SendMailProcess();
                $sendEmail = $sendEmail->setProvider($provider?$provider:'google_gmail_smtp')
                    ->serverConfig($server_config_value)
                    ->setMessage($message)
                    ->process();
                if ($sendEmail->hasErrors()) {
                    $errors = $sendEmail->getErrors();
                   // dd($errors);
                }
            } catch (\Exception $ex) {
                Log::error($ex->getMessage());
                 $message->status = 'failed';
                  $message->save();
            }
        }
    }

    public function check(){
        Log::info("checking schedule");
        $this->process();
    }

    public function processEmail()
    {
        Artisan::call("queue:work", ['--stop-when-empty' => true]);
    }
}