mo = serialize($mo); $this->skipbot = $skipbot; } public function __get($key): mixed { switch ($key) { case 'jobname': $mo = unserialize($this->mo); return sprintf('%s-%s-%s',$mo->set->get('set_pkt'),$mo->set->get('set_sender')->ftn,$mo->msgid); default: return NULL; } } public function __serialize() { return $this->encode(); } public function __unserialize(array $values) { $this->decode($values); } /** * At this point, we know that the packet is from a system we know about, and the packet is to us: * + From a system that is configured with us, and the password has been validated * + From a system that is not configured with us, and it may have netmails for us */ public function handle() { $this->mo = unserialize($this->mo); // Load our details $ftns = our_address(); // If we are a netmail if ($this->mo instanceof Netmail) { // @todo generate exception when netmail to system that doesnt exist (node/point) and its this host's responsibility Log::info(sprintf('%s:- Processing Netmail [%s] to (%s) [%s] from (%s) [%s].', self::LOGKEY, $this->mo->msgid, $this->mo->to,$this->mo->tftn->ftn, $this->mo->from,$this->mo->fftn->ftn, )); // @todo Enable checks to reject old messages // Check for duplicate messages // FTS-0009.001 if ($this->mo->msgid) { Log::debug(sprintf('%s:- Checking for duplicate from host [%s].',self::LOGKEY,$this->mo->fftn->ftn)); $o = Netmail::where('msgid',$this->mo->msgid) ->where('fftn_id',$this->mo->fftn->id) ->where('datetime','>',Carbon::now()->subYears(3)) ->single(); if ($o) { Log::alert(sprintf('%s:! Duplicate netmail #%d [%s] from (%s) [%s] to (%s) - ignoring.', self::LOGKEY, $o->id, $this->mo->msgid, $this->mo->from,$this->mo->fftn->ftn, $this->mo->to, )); return; } } // @todo Enable checks to see if this is a file request or file send // Strip any local/transit flags $this->mo->flags &= ~(Message::FLAG_LOCAL|Message::FLAG_INTRANSIT); // Determine if the message is to this system, or in transit if ($ftns->contains($this->mo->tftn)) { $processed = FALSE; // If the message is to a bot, we'll process it if (! $this->skipbot) foreach (config('process.robots') as $class) { if ($processed=$class::handle($this->mo)) { $this->mo->flags |= Message::FLAG_RECD; $this->mo->save(); Log::info(sprintf('%s:= Netmail [%s] from (%s:%s) - was processed by us internally [%d]', self::LOGKEY, $this->mo->msgid, $this->mo->from, $this->mo->fftn->ftn, $this->mo->id, )); break; } } if (! $processed) { // Check if the netmail is to a user, with netmail forwarding enabled $uo = User::active() ->where(function($query) { return $query->whereRaw(sprintf("LOWER(name)='%s'",strtolower($this->mo->to))) ->orWhereRaw(sprintf("LOWER(alias)='%s'",strtolower($this->mo->to))); }) ->whereNotNull('system_id') ->single(); if ($uo && ($ao=$uo->system->match($this->mo->tftn->zone)?->pop())) { $note = "+--[ FORWARDED MESSAGE ]----------------------------------+\r"; $note .= "+ This message has been forwarded to you, it was originally sent to you\r"; $note .= sprintf("+ at [%s]\r",$this->mo->tftn->ftn); $note .= "+---------------------------------------------------------+\r\r"; $this->mo->msg = $note.$this->mo->content; $this->mo->tftn_id = $ao->id; $this->mo->flags |= Message::FLAG_INTRANSIT; $this->mo->save(); $processed = TRUE; // Dont send an advisement to an areabot if (! in_array(strtolower($this->mo->from),config('fido.areabots'))) Notification::route('netmail',$this->mo->fftn)->notify(new NetmailForward($this->mo,$ao)); // We'll ignore messages from *fix users } elseif (in_array(strtolower($this->mo->from),config('fido.areabots'))) { $this->mo->flags |= Message::FLAG_RECD; $this->mo->save(); Log::alert(sprintf('%s:! Ignoring Netmail [%s] to the Hub from (%s:%s) - its from a bot [%d]', self::LOGKEY, $this->mo->msgid, $this->mo->from, $this->mo->fftn->ftn, $this->mo->id, )); $processed = TRUE; } } // If not processed, no users here! if (! $processed) { Log::alert(sprintf('%s:! Netmail to the Hub from (%s) [%s] but no users here.',self::LOGKEY,$this->mo->from,$this->mo->fftn->ftn)); Notification::route('netmail',$this->mo->fftn)->notify(new NetmailHubNoUser($this->mo)); } // If in transit, store for collection } else { // @todo In transit loop checking // @todo In transit TRACE response $this->mo->flags |= Message::FLAG_INTRANSIT; $this->mo->save(); Log::info(sprintf('%s:= Netmail [%s] in transit to (%s:%s) from (%s:%s) [%d].', self::LOGKEY, $this->mo->msgid, $this->mo->to,$this->mo->tftn->ftn, $this->mo->from,$this->mo->fftn->ftn, $this->mo->id, )); } // Else we are echomail } else { // The packet sender $sender = $this->mo->set->get('set_sender'); // @todo Check that this does evaulate to true if a message has been rescanned $rescanned = $this->mo->kludges->get('RESCANNED',FALSE); // Echoarea doesnt exist, cant import the message if (! $this->mo->echoarea) { Log::alert(sprintf('%s:! Echoarea [%s] doesnt exist for zone [%d@%s]',self::LOGKEY,$this->mo->set->get('set_echoarea'),$sender->zone->zone_id,$sender->zone->domain->name)); Notification::route('netmail',$sender)->notify(new EchoareaNotExist($this->mo)); return; } Log::debug(sprintf('%s:- Processing echomail [%s] in [%s] from [%s].',self::LOGKEY,$this->mo->msgid,$this->mo->echoarea->name,$sender->ftn)); // Message from zone is incorrect for echoarea if (! $this->mo->echoarea->domain->zones->contains($this->mo->fftn->zone)) { Log::alert(sprintf('%s:! The message [%s] is from a different zone [%d] than the packet sender [%d] - not importing', self::LOGKEY, $this->mo->msgid, $this->mo->fftn->zone->zone_id, $this->mo->fftn->zone->zone_id)); return; } // Check for duplicate messages // FTS-0009.001 if ($this->mo->msgid) { $o = Echomail::where('msgid',$this->mo->msgid) ->where('fftn_id',$this->mo->fftn->id) ->where('datetime','>=',$this->mo->date->subYears(3)) ->where('datetime','<=',$this->mo->date) ->single(); Log::debug(sprintf('%s:- Checking for duplicate from host id [%d].',self::LOGKEY,$this->mo->fftn->id)); if ($o) { // @todo Actually update seenby Log::alert(sprintf('%s:! Duplicate echomail [%s] in [%s] from (%s) [%s] to (%s) - updating seenby.', self::LOGKEY, $this->mo->msgid, $this->mo->echoarea->name, $this->mo->from,$this->mo->fftn->ftn, $this->mo->to, )); //$o->save(); // @todo This duplicate message may have gone via a different path, be nice to record it. /* // If we didnt get the path on the original message, we'll override it if (! $o->path->count()) { $dummy = collect(); $path = $this->parseAddresses('path',$this->mo->path,$sender->zone,$dummy); $ppoid = NULL; foreach ($path as $aoid) { $po = DB::select('INSERT INTO echomail_path (echomail_id,address_id,parent_id) VALUES (?,?,?) RETURNING id',[ $o->id, $aoid, $ppoid, ]); $ppoid = $po[0]->id; } } */ // @todo if we have an export for any of the seenby addresses, remove it //$seenby = $this->parseAddresses('seenby',$this->mo->seenby,$sender->zone,$o->rogue_seenby); //$this->mo->seenby()->syncWithoutDetaching($seenby); // In case our rogue_seenby changed //$this->mo->save(); return; } } // Find another message with the same msg_crc if ($this->mo->msg_crc) { $o = Echomail::where('msg_crc',$xx=md5($this->mo->msg_crc)) ->where('fftn_id',$this->mo->fftn->id) ->where('datetime','>',Carbon::now()->subWeek()) ->get(); if ($o->count()) Log::alert(sprintf('%s:! Duplicate message CRC [%s] in [%s].', self::LOGKEY, $xx, $o->pluck('id')->join('|') )); } // Can the system send messages to this area? if (! $this->mo->echoarea->can_write($sender->security)) { Log::alert(sprintf('%s:! FTN [%s] is not allowed to post [%s] to [%s].',self::LOGKEY,$sender->ftn,$this->mo->msgid,$this->mo->echoarea->name)); if (! $rescanned) Notification::route('netmail',$sender)->notify(new EchoareaNoWrite($this->mo)); return; } // If the node is not subscribed, we'll accept it, but let them know if (! $sender->echoareas->contains($this->mo->echoarea)) { Log::alert(sprintf('%s:! FTN [%s] is not subscribed to [%s] for [%s].',self::LOGKEY,$sender->ftn,$this->mo->echoarea->name,$this->mo->msgid)); if (! $rescanned) Notification::route('netmail',$sender)->notify(new EchoareaNotSubscribed($this->mo)); } // We know about this area, store it $this->mo->save(); Log::info(sprintf('%s:= Echomail [%s] in [%s] from (%s) [%s] to (%s) - [%s].', self::LOGKEY, $this->mo->msgid, $this->mo->echoarea->name, $this->mo->from,$this->mo->fftn->ftn, $this->mo->to, $this->mo->id, )); // If the message is to a bot, but not rescanned, or purposely skipbot set, we'll process it if ((! $this->skipbot) && (! $rescanned)) foreach (config('process.echomail') as $class) { if ($class::handle($this->mo)) { break; } } } } }