From d937547599c3aacd927eb122fadbf1dd9f95efc4 Mon Sep 17 00:00:00 2001 From: Deon George Date: Sat, 31 Jul 2021 00:35:52 +1000 Subject: [PATCH] Some message optimisation, added Echomail processing --- app/Classes/FTN/Message.php | 152 ++++++++++++++++++++-------- app/Classes/FTN/Packet.php | 8 +- app/Classes/FTN/Process/Ping.php | 16 ++- app/Classes/FTN/Process/Test.php | 77 ++++++++++++++ app/Classes/File/Receive.php | 13 ++- app/Interfaces/Packet.php | 11 ++ app/Jobs/ProcessPacket.php | 66 +++++++++--- app/Models/Address.php | 56 +++++++--- app/Models/Echomail.php | 76 +++++++++++--- app/Models/Netmail.php | 67 +++++------- app/Traits/MsgID.php | 25 +++++ app/Traits/UseMongo.php | 33 ++++++ composer.json | 2 + config/process.php | 6 ++ resources/views/pkt/debug.blade.php | 2 +- 15 files changed, 476 insertions(+), 134 deletions(-) create mode 100644 app/Classes/FTN/Process/Test.php create mode 100644 app/Interfaces/Packet.php create mode 100644 app/Traits/MsgID.php create mode 100644 app/Traits/UseMongo.php diff --git a/app/Classes/FTN/Message.php b/app/Classes/FTN/Message.php index 23d7759..256667d 100644 --- a/app/Classes/FTN/Message.php +++ b/app/Classes/FTN/Message.php @@ -23,6 +23,7 @@ class Message extends FTNBase { private const cast_utf8 = [ 'message', + 'message_src', ]; // Single value kludge items @@ -30,10 +31,10 @@ class Message extends FTNBase 'chrs' => 'CHRS: ', 'charset' => 'CHARSET: ', 'codepage' => 'CODEPAGE: ', + 'mid' => 'MID: ', 'pid' => 'PID: ', 'replyid' => 'REPLY: ', 'tid' => 'TID: ', - 'tzutc' => 'TZUTC: ', ]; // Flags for messages @@ -72,20 +73,29 @@ class Message extends FTNBase private const SUBJECT_LEN = 71; // FTS-0001.016 Subject: upto 72 chars null terminated private const AREATAG_LEN = 35; // - private ?ValidatorResult $errors = NULL; // Packet validation + private ?ValidatorResult $errors; // Packet validation private array $header; // Message Header private Collection $kludge; // Hold kludge items private string $user_from; // User message is From private string $user_to; // User message is To private string $subject; // Message subject + private string $msgid; // MSG ID + private string $reply; // Reply ID + private string $echoarea; // FTS-0004.001 private string $intl; // Netmail details - private string $message; // The actual message content + + private string $message; // The parsed message content + private string $message_src; // The actual message part + + private string $tagline; private string $tearline; private string $origin; // FTS-0004.001 + private int $tzutc; + private array $zone; // Zone the message belongs to. (src/dst - for netmail) private array $point; // Point the message belongs to (Netmail) @@ -145,17 +155,26 @@ class Message extends FTNBase $this->domain = $domain; $this->kludge = collect(); + + $this->msgid = ''; + $this->reply = ''; + + $this->echoarea = ''; + $this->intl = ''; + + $this->tearline = ''; + $this->tagline = ''; + $this->origin = ''; + + $this->tzutc = 0; + + $this->zone = []; + $this->point = []; + $this->path = collect(); $this->seenby = collect(); $this->via = collect(); $this->unknown = collect(); - $this->zone = []; - $this->point = []; - $this->tearline = ''; - $this->origin = ''; - $this->msgid = ''; - $this->echoarea = ''; - $this->intl = ''; } /** @@ -249,25 +268,35 @@ class Message extends FTNBase case 'date': return Carbon::createFromFormat('d M y H:i:s O', - sprintf('%s %s',chop(Arr::get($this->header,$key)),(! is_null($x=$this->kludge->get('tzutc')) && ($x < 0)) ? $x : '+'.($x ?: '0000'))); + sprintf('%s %s%04d',chop(Arr::get($this->header,$key)),($this->tzutc < 0) ? '-' : '+',abs($this->tzutc))); case 'flags': case 'cost': return Arr::get($this->header,$key); - case 'message': - case 'tearline': - case 'origin': - case 'subject': + case 'tzutc': + case 'user_to': case 'user_from': + case 'subject': + case 'echoarea': + + case 'msgid': + case 'reply': + + case 'message': + case 'message_src': + + case 'tearline': + case 'tagline': + case 'origin': + case 'kludge': case 'path': case 'seenby': case 'via': - case 'msgid': + case 'errors': - case 'echoarea': return $this->{$key}; default: @@ -278,16 +307,25 @@ class Message extends FTNBase public function __set($key,$value) { switch ($key) { - case 'echoarea': + case 'flags': case 'header': - case 'intl': - case 'message': - case 'tearline': - case 'origin': - case 'msgid': - case 'subject': + case 'tzutc': + case 'user_from': case 'user_to': + case 'subject': + + case 'msgid': + case 'reply': + + case 'echoarea': + case 'intl': + + case 'message': + + case 'tagline': + case 'tearline': + case 'origin': case 'via': $this->{$key} = $value; break; @@ -403,28 +441,46 @@ class Message extends FTNBase $return .= $this->user_from."\00"; $return .= $this->subject."\00"; - if ($this->isNetmail()) - $return .= sprintf("\01INTL %s\r",$this->intl); - else - $return .= "AREA:".$this->echoarea."\r"; + if (! $this->isNetmail()) + $return .= sprintf("AREA:%s\r",$this->echoarea); - // Add some kludges - $return .= sprintf("\01MSGID: %s\r",$this->msgid); + // If the message is local, then our kludges are not in the msg itself, we'll add them + if ($this->isFlagSet(self::FLAG_LOCAL)) { + if ($this->isNetmail()) + $return .= sprintf("\01INTL %s\r",$this->intl); - foreach ($this->_kludge as $k=>$v) { - if ($x=$this->kludge->get($k)) - $return .= sprintf("\01%s%s\r",$v,$x); + $return .= sprintf("\01TZUTC: %s\r",str_replace('+','',$this->date->getOffsetString(''))); + + // Add some kludges + $return .= sprintf("\01MSGID: %s\r",$this->msgid); + + if ($this->reply) + $return .= sprintf("\01REPLY: %s\r",$this->reply); + + foreach ($this->_kludge as $k=>$v) { + if ($x=$this->kludge->get($k)) + $return .= sprintf("\01%s%s\r",$v,$x); + } + + $return .= $this->message."\r"; + if ($this->tagline) + $return .= sprintf("... %s\r",$this->tagline); + if ($this->tearline) + $return .= sprintf("--- %s\r",$this->tearline); + if ($this->origin) + $return .= sprintf(" * Origin: %s\r",$this->origin); + + } else { + dump([__METHOD__=>'NOT LOCAL']); + $return .= $this->message."\r"; } - $return .= $this->message."\r"; - if ($this->tearline) - $return .= $this->tearline."\r"; - if ($this->origin) - $return .= $this->origin."\r"; - if ($this->isNetmail()) { foreach ($this->via as $v) $return .= sprintf("\01Via %s\r",$v); + + } else { + // @todo Add echomail SEEN-BY and PATH } $return .= "\00"; @@ -543,14 +599,17 @@ class Message extends FTNBase $message = preg_replace("/\n\r/","\r",$message); // Split out the lines - $result = collect(explode("\01",$message))->filter(); + $result = collect(explode("\x01",$message))->filter(); $this->message = ''; + $this->message_src = ''; + $srcpos = 0; foreach ($result as $v) { // Search for \r - if that is the end of the line, then its a kludge $x = strpos($v,"\r"); $t = ''; + $srcpos += 1+$x+1; // SOH+text+\r // If there are more characters, then put the kludge back into the result, so that we process it. if ($x != strlen($v)-1) { @@ -559,6 +618,10 @@ class Message extends FTNBase $this->message .= substr($v,$x+1,$y-$x-1); $this->parseOrigin(substr($v,$y)); + // Capture the raw message, in case we send it on + // length = src, remove current 1+$x+1, add soh, $y + origin_start + origin_length + 0d + $this->message_src .= substr($message,0,$srcpos-(1+$x+1)+1+$y+12+strlen($this->origin)+1); + // If this is netmail, the FQFA will have been set by the INTL line, we can skip the rest of this $matches = []; @@ -573,8 +636,9 @@ class Message extends FTNBase $ftn = Address::parseFTN($matches[1]); // We'll double check our FTN - if (($ftn['n'] !== $this->fn) || ($ftn['f'] !== $this->ff)) - Log::error(sprintf('FTN [%s] doesnt match message header',$matches[1]),['ftn'=>$ftn]); + if ($this->isNetmail() && ($ftn['n'] !== $this->fn) || ($ftn['f'] !== $this->ff)) { + Log::error(sprintf('FTN [%s] doesnt match message header',$matches[1]),['ftn'=>$ftn,'fn'=>$this->fn,'ff'=>$this->ff]); + } // http://ftsc.org/docs/fsc-0068.001 // MSGID should be the basis of the source @@ -584,6 +648,7 @@ class Message extends FTNBase // The message is the rest? } elseif (strlen($v) > $x+1) { $this->message .= substr($v,$x+1); + $this->message_src .= substr($v,$x+1); } $v = substr($v,0,$x+1); @@ -636,6 +701,9 @@ class Message extends FTNBase } } + elseif ($t = $this->kludge('TZUTC: ',$v)) + $this->tzutc = $t; + elseif ($t = $this->kludge('MSGID: ',$v)) $this->msgid = $t; diff --git a/app/Classes/FTN/Packet.php b/app/Classes/FTN/Packet.php index c711a9c..55d2cdd 100644 --- a/app/Classes/FTN/Packet.php +++ b/app/Classes/FTN/Packet.php @@ -157,6 +157,10 @@ class Packet extends FTNBase $message = ''; } + // If our message is still set, then we have an unprocessed message + if ($message) + $o->parseMessage($message,$domain); + return $o; } @@ -300,7 +304,7 @@ class Packet extends FTNBase * * @param Message $o */ - public function addNetmail(Message $o): void + public function addMail(Message $o): void { $this->messages->push($o); } @@ -354,7 +358,7 @@ class Packet extends FTNBase Log::error(sprintf('%s:%s Skipping...',self::LOGKEY,join('|',$msg->errors->messages()->get('from')))); } else { - $this->messages->push(Message::parseMessage($message,$domain)); + $this->messages->push($msg); } } } \ No newline at end of file diff --git a/app/Classes/FTN/Process/Ping.php b/app/Classes/FTN/Process/Ping.php index 99fecc1..370788d 100644 --- a/app/Classes/FTN/Process/Ping.php +++ b/app/Classes/FTN/Process/Ping.php @@ -28,6 +28,7 @@ final class Ping extends Process return FALSE; Log::info(sprintf('Processing PING message from (%s) [%s]',$msg->user_from,$msg->fftn)); + $ftns = Setup::findOrFail(config('app.id'))->system->match($msg->fftn_o->zone); $reply = sprintf("Your ping was received here on %s and it looks like you sent it on %s. If that is correct, then it took %s to get here.\r", $msg->date->toDateTimeString(), @@ -45,13 +46,18 @@ final class Ping extends Process $o->to = $msg->user_from; $o->from = Setup::PRODUCT_NAME; $o->subject = 'Ping Reply'; - $o->fftn_id = ($x=$msg->tftn_o) ? $x->id : NULL; - $o->tftn_id = ($x=$msg->fftn_o) ? $x->id : NULL; - $o->msg = static::format_msg($reply,self::$logo); - $o->reply = $msg->msgid; + $o->datetime = Carbon::now(); + $o->tzoffset = $o->datetime->utcOffset(); + $o->reply = $msg->msgid; + $o->fftn_id = $ftns->id; + $o->tftn_id = ($x=$msg->fftn_o) ? $x->id : NULL; + $o->flags = Message::FLAG_LOCAL; + $o->cost = 0; + + $o->msg = static::format_msg($reply,self::$logo); $o->tagline = 'My ping pong opponent was not happy with my serve. He kept returning it.'; - $o->tearline = sprintf('--- %s (%s)',Setup::PRODUCT_NAME,(new Setup)->version); + $o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID); $o->save(); return TRUE; diff --git a/app/Classes/FTN/Process/Test.php b/app/Classes/FTN/Process/Test.php new file mode 100644 index 0000000..3b51dae --- /dev/null +++ b/app/Classes/FTN/Process/Test.php @@ -0,0 +1,77 @@ +user_to) !== 'all') || ! in_array(strtolower($msg->subject),self::testing)) + return FALSE; + + Log::info(sprintf('Processing TEST message from (%s) [%s]',$msg->user_from,$msg->fftn)); + $ftns = Setup::findOrFail(config('app.id'))->system->match($msg->fftn_o->zone); + + $reply = sprintf("Your test was received here on %s and it looks like you sent it on %s. If that is correct, then it took %s to get here.\r", + $msg->date->toDateTimeString(), + Carbon::now()->toDateTimeString(), + $msg->date->diffForHumans(['parts'=>3,'syntax'=>CarbonInterface::DIFF_ABSOLUTE]) + ); + + $reply .= "\r"; + $reply .= "\r"; + $reply .= "------------------------------ BEING MESSAGE ------------------------------\r"; + $reply .= sprintf("TO: %s\r",$msg->user_to); + $reply .= sprintf("SUBJECT: %s\r",$msg->subject); + $reply .= $msg->message."\r"; + $reply .= "------------------------------ CONTROL LINES ------------------------------\r"; + $reply .= sprintf("DATE: %s\r",$msg->date->format('Y-m-d H:i:s')); + $reply .= sprintf("MSGID: %s\r",$msg->msgid); + + foreach ($msg->kludge as $k=>$v) + $reply .= sprintf("@%s: %s\n",strtoupper($k),$v); + foreach ($msg->via as $via) + $reply .= sprintf("VIA: %s\n",$via); + + $reply .= "------------------------------ END MESSAGE ------------------------------\r"; + + $o = new Echomail; + $o->to = $msg->user_from; + $o->from = Setup::PRODUCT_NAME; + $o->subject = 'Test Reply'; + $o->datetime = Carbon::now(); + $o->tzoffset = $o->datetime->utcOffset(); + $o->echoarea = $msg->echoarea; + $o->reply = $msg->msgid; + $o->fftn_id = $ftns->id; + + $o->flags = Message::FLAG_LOCAL; + $o->msg = static::format_msg($reply,self::$logo); + $o->tagline = 'I ate a clock yesterday, it was very time-consuming.'; + $o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID); + $o->origin = sprintf('%s (%s)',Setup::PRODUCT_NAME,$ftns->ftn4d); + $o->save(); + + return TRUE; + } +} \ No newline at end of file diff --git a/app/Classes/File/Receive.php b/app/Classes/File/Receive.php index b0afa19..e14b647 100644 --- a/app/Classes/File/Receive.php +++ b/app/Classes/File/Receive.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Log; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\Exception\FileException; +use App\Classes\FTN\InvalidPacketException; use App\Classes\FTN\Packet; use App\Jobs\ProcessPacket; use App\Models\Address; @@ -83,7 +84,7 @@ final class Receive extends Item if (! $this->f) throw new Exception('No file to close'); - if (! $this->file_pos != $this->receiving->file_size) + if ($this->file_pos != $this->receiving->file_size) Log::warning(sprintf('%s: - Closing [%s], but missing [%d] bytes',__METHOD__,$this->receiving->file_name,$this->receiving->file_size-$this->file_pos)); $this->receiving->received = TRUE; @@ -100,7 +101,15 @@ final class Receive extends Item case self::IS_PKT: Log::info(sprintf('%s: - Processing mail packet [%s]',__METHOD__,$this->file)); - $po = Packet::open(new File($this->file),$this->ao->zone->domain); + try { + $po = Packet::open(new File($this->file),$this->ao->zone->domain); + + } catch (InvalidPacketException $e) { + Log::error(sprintf('%s: - Not deleting packet [%s], as it generated an exception',__METHOD__,$this->file)); + + break; + } + foreach ($po->messages as $msg) { Log::info(sprintf('%s: - Mail from [%s] to [%s]',__METHOD__,$msg->fftn,$msg->tftn)); diff --git a/app/Interfaces/Packet.php b/app/Interfaces/Packet.php new file mode 100644 index 0000000..fc68083 --- /dev/null +++ b/app/Interfaces/Packet.php @@ -0,0 +1,11 @@ +to = $this->msg->user_from; $o->from = Setup::PRODUCT_NAME; $o->subject = 'Message Undeliverable - '.$this->msg->msgid; + $o->datetime = $this->msg->date; + $o->tzoffset = $this->msg->date->utcOffset(); + + $o->cost = 0; + $o->flags = Message::FLAG_LOCAL; + $o->fftn_id = ($x=$this->msg->tftn_o) ? $x->id : NULL; $o->tftn_id = ($x=$this->msg->fftn_o) ? $x->id : NULL; - $o->msg = Process::format_msg($reply,$reject); $o->reply = $this->msg->msgid; + $o->msg = Process::format_msg($reply,$reject); $o->tagline = 'Do you think it was fate which brought us together? Nah, bad luck :('; - $o->tearline = sprintf('--- %s (%s)',Setup::PRODUCT_NAME,(new Setup)->version); + $o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID); $o->save(); } @@ -108,32 +114,62 @@ class ProcessPacket implements ShouldQueue // @todo In transit loop checking // @todo In transit TRACE response - $o = new Netmail(); + $o = new Netmail; $o->to = $this->msg->user_to; $o->from = $this->msg->user_from; $o->subject = $this->msg->subject; - $o->fftn_id = ($x=$this->msg->fftn_o) ? $x->id : NULL; - $o->tftn_id = ($x=$this->msg->tftn_o) ? $x->id : NULL; - $o->msg = $this->msg->message; - $o->tearline = $this->msg->tearline; - $o->origin = $this->msg->origin; - $o->kluge = json_encode($this->msg->kludge); + $o->datetime = $this->msg->date; + $o->tzoffset = $this->msg->date->utcOffset(); + $o->flags = $this->msg->flags; $o->cost = $this->msg->cost; + $o->msgid = $this->msg->msgid; + + $o->fftn_id = ($x=$this->msg->fftn_o) ? $x->id : NULL; + $o->tftn_id = ($x=$this->msg->tftn_o) ? $x->id : NULL; + $o->msg = $this->msg->message_src; $o->save(); } // Else we are echomail } else { - dump('echomail'); - // Determine if we know about this echo area - // Can the sender create it if it doesnt exist? - // Create it, or + Log::info(sprintf('Echomail [%s] in [%s] from (%s) [%s] to (%s).', + $this->msg->msgid, + $this->msg->echoarea, + $this->msg->user_to,$this->msg->tftn, + $this->msg->user_from, + )); - // Else record in bad area + // @todo Determine if we know about this echo area + // @todo Can the sender create it if it doesnt exist? + // - Create it, or + // - Else record in bad area // We know about this area, store it + $o = new Echomail; + $o->to = $this->msg->user_to; + $o->from = $this->msg->user_from; + $o->subject = $this->msg->subject; + $o->datetime = $this->msg->date; + $o->tzoffset = $this->msg->date->utcOffset(); + + $o->fftn_id = ($x=$this->msg->fftn_o) ? $x->id : NULL; + $o->echoarea = $this->msg->echoarea; + $o->msgid = $this->msg->msgid; + + $o->msg = $this->msg->message_src; + // @todo Record Path + // @todo Record SeenBy + + $o->save(); + + // If the message is to a bot, we'll process it + foreach (config('process.echomail') as $class) { + if ($class::handle($this->msg)) { + break; + } + } } } } \ No newline at end of file diff --git a/app/Models/Address.php b/app/Models/Address.php index 2f215b2..598d65a 100644 --- a/app/Models/Address.php +++ b/app/Models/Address.php @@ -4,6 +4,7 @@ namespace App\Models; use Carbon\Carbon; use Exception; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; @@ -151,6 +152,26 @@ class Address extends Model return ($o && $o->system->active) ? $o : NULL; } + /** + * Get echomail for this node + * + * @return Packet|null + */ + public function getEchomail(): ?Packet + { + if (($x=Echomail::select('*') //where('tftn_id',$this->id) + ->where(function($q) { + return $q->whereNull('sent') + ->orWhere('sent',FALSE); + })) + ->count()) + { + return $this->getPacket($x->get()); + } + + return NULL; + } + /** * Get netmail for this node (including it's children) * @@ -165,23 +186,34 @@ class Address extends Model })) ->count()) { - $o = new Packet($this); - - foreach ($x->get() as $oo) { - $o->addNetmail($oo->packet()); - - $oo->packet = $o->name; - $oo->sent = TRUE; - $oo->sent_at = Carbon::now(); - $oo->save(); - } - - return $o; + return $this->getPacket($x->get()); } return NULL; } + /** + * Return a packet of mail + * + * @param Collection $c + * @return Packet + */ + private function getPacket(Collection $c): Packet + { + $o = new Packet($this); + + foreach ($c as $oo) { + $o->addMail($oo->packet($this)); + + $oo->packet = $o->name; + $oo->sent = TRUE; + $oo->sent_at = Carbon::now(); + $oo->save(); + } + + return $o; + } + /** * Parse a string and split it out as an FTN array * diff --git a/app/Models/Echomail.php b/app/Models/Echomail.php index 37f2da0..247d7b1 100644 --- a/app/Models/Echomail.php +++ b/app/Models/Echomail.php @@ -2,25 +2,77 @@ namespace App\Models; -use Illuminate\Database\Eloquent\Model; +use Carbon\Exceptions\Exception; +use Jenssegers\Mongodb\Eloquent\Model; +use Jenssegers\Mongodb\Eloquent\SoftDeletes; -class Echomail extends Model +use App\Classes\FTN\Message; +use App\Interfaces\Packet; +use App\Traits\{MsgID,UseMongo}; + +class Echomail extends Model implements Packet { - protected $dates = ['date']; - protected $fillable = ['date','msgid','from_ftn']; + use SoftDeletes,MsgID,UseMongo; - public function kludges() + protected $dates = ['datetime']; + + /* RELATIONS */ + + public function fftn() { - return $this->belongsToMany(Kludge::class); + return $this + ->setConnection('pgsql') + ->belongsTo(Address::class) + ->withTrashed(); } - public function seenbys() - { - return $this->belongsToMany(Seenby::class,NULL,NULL,'node_id'); - } + /* METHODS */ - public function paths() + /** + * Return this model as a packet + */ + public function packet(Address $ao): Message { - return $this->belongsToMany(Path::class,NULL,NULL,'node_id'); + // @todo Dont bundle mail to nodes that have been disabled, or addresses that have been deleted + $o = new Message; + + $o->header = [ + 'onode' => $this->fftn->node_id, + 'dnode' => $ao->node_id, + 'onet' => $this->fftn->host_id, + 'dnet' => $ao->host_id, + 'flags' => 0, // @todo? + 'cost' => 0, + 'date'=>$this->datetime->format('d M y H:i:s'), + ]; + + $o->tzutc = $this->datetime->utcOffset($this->tzoffset)->getOffsetString(''); + $o->user_to = $this->to; + $o->user_from = $this->from; + $o->subject = $this->subject; + $o->echoarea = $this->echoarea; + $o->flags = $this->flags; + + $o->kludge->put('mid',$this->id); + + $o->msgid = $this->msgid; + if ($this->reply) + $o->reply = $this->reply; + + $o->message = $this->msg; + + if ($this->tagline) + $o->tagline = $this->tagline; + + if ($this->tearline) + $o->tearline = $this->tearline; + + if ($this->origin) + $o->origin = $this->origin; + + // @todo SEENBY + // @todo PATH + + return $o; } } \ No newline at end of file diff --git a/app/Models/Netmail.php b/app/Models/Netmail.php index 1f9f6ba..f859670 100644 --- a/app/Models/Netmail.php +++ b/app/Models/Netmail.php @@ -7,26 +7,15 @@ use Jenssegers\Mongodb\Eloquent\Model; use Jenssegers\Mongodb\Eloquent\SoftDeletes; use App\Classes\FTN\Message; +use App\Interfaces\Packet; +use App\Traits\UseMongo; -class Netmail extends Model +class Netmail extends Model implements Packet { - use SoftDeletes; + use SoftDeletes,UseMongo; - //protected $connection = 'mongodb'; protected $dates = ['datetime','sent_at']; - /** - * Resolve a connection instance. - * We need to do this, because our relations are in pgsql and somehow loading a relation changes this models - * connection information. Using protected $connection is not enough. - * - * @param string|null $connection - */ - public static function resolveConnection($connection = null) - { - return static::$resolver->connection('mongodb'); - } - /* RELATIONS */ public function fftn() @@ -44,49 +33,47 @@ class Netmail extends Model ->belongsTo(Address::class); } - /* ATTRIBUTES */ - - public function getMsgAttribute($value): string - { - return utf8_decode($value); - } - - public function setMsgAttribute($value): void - { - $this->attributes['msg'] = utf8_encode($value); - } - /* METHODS */ /** * Return this model as a packet */ - public function packet(): Message + public function packet(Address $ao): Message { - $o = new Message; - // @todo Dont bundle mail to nodes that have been disabled, or addresses that have been deleted + $o = new Message; $o->header = [ 'onode' => $this->fftn->node_id, - 'dnode' => $this->tftn->node_id, + 'dnode' => $ao->node_id, 'onet' => $this->fftn->host_id, - 'dnet' => $this->tftn->host_id, + 'dnet' => $ao->host_id, 'flags' => 0, // @todo? 'cost' => 0, - 'date'=>$this->created_at->format('d M y H:i:s'), + 'date'=>$this->datetime->format('d M y H:i:s'), ]; + $o->tzutc = $this->datetime->utcOffset($this->tzoffset)->getOffsetString(''); $o->user_to = $this->to; $o->user_from = $this->from; $o->subject = $this->subject; - $o->message = $this->msg; - if ($this->tagline) - $o->message .= "\r... ".$this->tagline."\r"; - $o->tearline .= $this->tearline; + // INTL kludge + // @todo Point handling FMPT/TOPT + $o->intl = sprintf('%s %s',$this->tftn->ftn3d,$this->fftn->ftn3d); + $o->flags = $this->flags; $o->msgid = sprintf('%s %08x',$this->fftn->ftn3d,crc32($this->id)); + if ($this->reply) + $o->reply = $this->reply; + + $o->message = $this->msg; + + if ($this->tagline) + $o->message .= $this->tagline; + + if ($this->tearline) + $o->tearline .= $this->tearline; // VIA kludge $via = $this->via ?: collect(); @@ -103,12 +90,6 @@ class Netmail extends Model $o->via = $via; - // INTL kludge - // @todo Point handling FMPT/TOPT - $o->intl = sprintf('%s %s',$this->tftn->ftn3d,$this->fftn->ftn3d); - - // TZUTC - $o->kludge->put('tzutc',str_replace('+','',$this->created_at->getOffsetString(''))); return $o; } diff --git a/app/Traits/MsgID.php b/app/Traits/MsgID.php new file mode 100644 index 0000000..bb417ea --- /dev/null +++ b/app/Traits/MsgID.php @@ -0,0 +1,25 @@ +exists) { + $ftns = Setup::findOrFail(config('app.id'))->system->match($this->fftn->zone); + + if (is_null(Arr::get($this->attributes,'msgid'))) + $this->attributes['msgid'] = sprintf('%s %08x',$ftns->ftn4d,timew()); + } + + return parent::save($options); + } +} \ No newline at end of file diff --git a/app/Traits/UseMongo.php b/app/Traits/UseMongo.php new file mode 100644 index 0000000..5b786c1 --- /dev/null +++ b/app/Traits/UseMongo.php @@ -0,0 +1,33 @@ +connection('mongodb'); + } + + /* ATTRIBUTES */ + + public function getMsgAttribute($value): string + { + return utf8_decode($value); + } + + public function setMsgAttribute($value): void + { + $this->attributes['msg'] = utf8_encode($value); + } +} \ No newline at end of file diff --git a/composer.json b/composer.json index 15bb3e4..16b8f4c 100644 --- a/composer.json +++ b/composer.json @@ -8,6 +8,8 @@ "php": "^8.0", "ext-pcntl": "*", "ext-sockets": "*", + "ext-zlib": "*", + "ext-zip": "*", "eduardokum/laravel-mail-auto-embed": "^1.0", "fideloper/proxy": "^4.4", "fruitcake/laravel-cors": "^2.0", diff --git a/config/process.php b/config/process.php index bc26578..059804b 100644 --- a/config/process.php +++ b/config/process.php @@ -1,6 +1,12 @@ [ + \App\Classes\FTN\Process\Test::class, + ], + + // Netmail 'robots' => [ \App\Classes\FTN\Process\Ping::class, ], diff --git a/resources/views/pkt/debug.blade.php b/resources/views/pkt/debug.blade.php index 4bbb353..62a4804 100644 --- a/resources/views/pkt/debug.blade.php +++ b/resources/views/pkt/debug.blade.php @@ -104,7 +104,7 @@
-
{!! \App\Classes\FTN\Message::tr($msg->message) !!}
+
{!! \App\Classes\FTN\Message::tr($msg->message).sprintf("\r * Origin: %s",$msg->origin) !!}