ao = $ao; $this->mo = $mo; $this->onQueue(self::QUEUE); } public function __get($key): mixed { switch ($key) { case 'address': return $this->ao; case 'subject': return $this->ao->ftn; default: return NULL; } } /** * Because pluck doesnt return __get() defined vars * * @param $key * @return bool */ public function __isset($key): bool { $keys = ['address']; return in_array($key,$keys); } /** * Time to wait between tries * * @return int[] in seconds */ public function backoff(): array { return [ 60*5, // 5 mins 60*60, // 1 hr 60*60*6, // 6 hrs 60*60*12 // 12 hrs ]; } /** * When calling MessageProcess - we assume that the packet is from a valid source */ public function handle() { if (! $this->ao->system->mailer_preferred->count() || ($this->mo && (! $this->ao->system->mailer_preferred->find($this->mo)))) { $this->fail('Missing mailer details'); return; } Log::info(sprintf('%s:- Polling [%s] - attempt [%d]',self::LOGKEY,$this->ao->ftn,$this->attempts())); foreach ($this->ao->system->mailer_preferred as $o) { // If we chose a protocol, skip to find the mailer details for it if ($this->mo && ($o->id !== $this->mo->id)) continue; switch ($o->name) { case 'BINKP': $s = new Binkp(Setup::findOrFail(config('app.id'))); $session = Binkp::SESSION_BINKP; break; case 'EMSI': $s = new EMSI(Setup::findOrFail(config('app.id'))); $session = EMSI::SESSION_AUTO; break; default: $this->fail('Mailer type unhandled'); return; } Log::info(sprintf('%s:- Trying a [%s] session to [%s:%d] (%s)', self::LOGKEY,$o->name,$this->ao->system->address,$o->pivot->port,$this->ao->ftn)); try { $client = SocketClient::create($this->ao->system->address,$o->pivot->port); if (($s->session($session,$client,$this->ao) & Protocol::S_MASK) === Protocol::S_OK) { Log::info(sprintf('%s:= Connection ended successfully with [%s] (%s)',self::LOGKEY,$client->address_remote,$this->ao->ftn)); return; } else { Log::alert(sprintf('%s:! Connection failed to [%s] (%s)',self::LOGKEY,$client->address_remote,$this->ao->ftn)); } } catch (SocketException $e) { Log::error(sprintf('%s:! Unable to connect to [%s]: %s',self::LOGKEY,$this->ao->ftn,$e->getMessage())); break; } } $delay = (int)($this->backoff()[$this->attempts()-1] ?? last($this->backoff())); Log::info(sprintf('%s:= Retrying poll in %d seconds',self::LOGKEY,$delay)); $this->release($delay); } public function failed(\Throwable $exception): void { switch (get_class($exception)) { case ManuallyFailedException::class: Log::error(sprintf('%s:! Address Poll failed for [%s] (%s)',self::LOGKEY,$this->ao->ftn,$exception->getMessage())); break; case MaxAttemptsExceededException::class: Log::error(sprintf('%s:! Address Poll was tried too many times for [%s]',self::LOGKEY,$this->ao->ftn)); Notification::route('netmail',$this->ao)->notify(new PollingFailed); $this->ao->system->autohold = TRUE; $this->ao->system->save(); exit(0); default: Log::error(sprintf('%s:! Address Poll to [%s] with an unknown exception (%s)[%s]',self::LOGKEY,$this->ao->ftn,get_class($exception),$exception->getMessage())); } } public function uniqueId(): string { return $this->ao->id; } }