349 lines
11 KiB
PHP
349 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Jobs;
|
|
|
|
use Carbon\Carbon;
|
|
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\Log;
|
|
|
|
use App\Classes\FTN\{Message,Process};
|
|
use App\Models\{Address,Echoarea,Echomail,Netmail,Setup};
|
|
|
|
class MessageProcess implements ShouldQueue
|
|
{
|
|
private const LOGKEY = 'JMP';
|
|
|
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
|
|
private Address $sender;
|
|
private Message $msg;
|
|
private bool $skipbot;
|
|
private string $packet;
|
|
|
|
public function __construct(Message $msg,string $packet,Address $sender,bool $skipbot=FALSE)
|
|
{
|
|
$this->msg = $msg;
|
|
$this->packet = $packet;
|
|
$this->sender = $sender;
|
|
$this->skipbot = $skipbot;
|
|
}
|
|
|
|
/**
|
|
* When calling MessageProcess - we assume that the packet is from a valid source
|
|
*/
|
|
public function handle()
|
|
{
|
|
// Load our details
|
|
$ftns = Setup::findOrFail(config('app.id'))->system->addresses;
|
|
|
|
// If we are a netmail
|
|
if ($this->msg->isNetmail()) {
|
|
Log::info(sprintf('%s:- Processing Netmail [%s] to (%s) [%s] from (%s) [%s].',
|
|
self::LOGKEY,
|
|
$this->msg->msgid,
|
|
$this->msg->user_to,$this->msg->tftn,
|
|
$this->msg->user_from,$this->msg->fftn,
|
|
));
|
|
|
|
// @todo Enable checks to reject old messages
|
|
|
|
// Check for duplicate messages
|
|
|
|
// FTS-0009.001
|
|
if ($this->msg->msgid) {
|
|
$o = Netmail::where('msgid',$this->msg->msgid)
|
|
->where('fftn_id',($x=$this->msg->fboss_o) ? $x->id : NULL)
|
|
->where('datetime','>',Carbon::now()->subYears(3))
|
|
->single();
|
|
|
|
Log::debug(sprintf('%s:- Checking for duplicate from host id [%d].',self::LOGKEY,($x=$this->msg->fboss_o) ? $x->id : NULL));
|
|
|
|
if ($o) {
|
|
Log::alert(sprintf('%s:! Duplicate netmail [%s] in [%s] from (%s) [%s] to (%s) - ignorning.',
|
|
self::LOGKEY,
|
|
$this->msg->msgid,
|
|
$this->msg->echoarea,
|
|
$this->msg->user_from,$this->msg->fftn,
|
|
$this->msg->user_to,
|
|
));
|
|
|
|
if (! $o->msg_crc)
|
|
$o->msg_crc = md5($this->msg->message);
|
|
|
|
$o->save();
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
// @todo Enable checks to see if this is a file request or file send
|
|
|
|
$o = $this->create_netmail($this->msg);
|
|
$o->set_pkt = $this->packet;
|
|
$o->set_sender = $this->sender;
|
|
$o->set_path = $this->msg->pathaddress;
|
|
// Strip any local flag
|
|
$o->flags &= ~Message::FLAG_LOCAL;
|
|
|
|
// Determine if the message is to this system, or in transit
|
|
if ($ftns->search(function($item) { return $this->msg->tftn === $item->ftn; }) !== FALSE) {
|
|
// @todo Check if it is a duplicate message
|
|
// @todo Check if the message is from a system we know about
|
|
|
|
$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->msg)) {
|
|
$o->flags |= Message::FLAG_RECD;
|
|
$o->save();
|
|
|
|
Log::info(sprintf('%s:= Netmail [%s] from (%s:%s) - was processed by us internally [%d]',
|
|
self::LOGKEY,
|
|
$this->msg->msgid,
|
|
$this->msg->user_from,
|
|
$this->msg->fftn,
|
|
$o->id,
|
|
));
|
|
break;
|
|
}
|
|
}
|
|
|
|
// We'll ignore messages from *fix users
|
|
if (in_array(strtolower($this->msg->user_from),['filefix','areafix'])) {
|
|
$o->flags |= Message::FLAG_RECD;
|
|
$o->save();
|
|
|
|
Log::alert(sprintf('%s:! Ignoring Netmail [%s] to the Hub from (%s:%s) - its from a bot [%d]',
|
|
self::LOGKEY,
|
|
$this->msg->msgid,
|
|
$this->msg->user_from,
|
|
$this->msg->fftn,
|
|
$o->id,
|
|
));
|
|
|
|
$processed = TRUE;
|
|
}
|
|
|
|
// If not processed, no users here!
|
|
if (! $processed) {
|
|
$reject = [
|
|
'ÚÄ¿ÚÄ¿ ÂÚÄ¿ÚÄ¿Ú¿',
|
|
'³ ³ÄÙ ³³ÄÙ³ ³ ',
|
|
'Á ÀÄÙÀÄÙÀÄÙÀÄÙ Á '
|
|
];
|
|
|
|
Log::alert(sprintf('%s:! Netmail to the Hub from (%s) [%s] but no users here.',self::LOGKEY,$this->msg->user_from,$this->msg->fftn));
|
|
|
|
$reply = "Your Netmail was not processed by the hub and cannot be delivered to anybody (as there are no users here).\r";
|
|
|
|
$reply .= "\r";
|
|
$reply .= "\r";
|
|
$reply .= "This is your original message:\r";
|
|
$reply .= "------------------------------ BEING MESSAGE ------------------------------\r";
|
|
$reply .= sprintf("TO: %s\r",$this->msg->user_to);
|
|
$reply .= sprintf("SUBJECT: %s\r",$this->msg->subject);
|
|
$reply .= $this->msg->message;
|
|
$reply .= "------------------------------ CONTROL LINES ------------------------------\r";
|
|
$reply .= sprintf("DATE: %s\r",$this->msg->date->format('Y-m-d H:i:s'));
|
|
$reply .= sprintf("MSGID: %s\r",$this->msg->msgid);
|
|
|
|
foreach ($this->msg->kludge as $k=>$v)
|
|
$reply .= sprintf("@%s: %s\r",strtoupper($k),$v);
|
|
foreach ($this->msg->via as $via)
|
|
$reply .= sprintf("VIA: %s\r",$via);
|
|
|
|
$reply .= "------------------------------ END MESSAGE ------------------------------\r";
|
|
|
|
$o = new Netmail;
|
|
$o->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->replyid = $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 (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
|
|
$o->save();
|
|
}
|
|
|
|
// If in transit, store for collection
|
|
} else {
|
|
// @todo Check if the message is to a system we know about
|
|
// @todo In transit loop checking
|
|
// @todo In transit TRACE response
|
|
|
|
$o->flags |= Message::FLAG_INTRANSIT;
|
|
$o->save();
|
|
|
|
Log::info(sprintf('%s:= Netmail [%s] in transit to (%s:%s) from (%s:%s) [%d].',
|
|
self::LOGKEY,
|
|
$this->msg->msgid,
|
|
$this->msg->user_to,$this->msg->tftn,
|
|
$this->msg->user_from,$this->msg->fftn,
|
|
$o->id,
|
|
));
|
|
}
|
|
|
|
// Else we are echomail
|
|
} else {
|
|
Log::debug(sprintf('%s:- Looking for echomail area [%s] for mail from [%s]',self::LOGKEY,$this->msg->echoarea,$this->msg->fboss));
|
|
|
|
if (! $this->msg->fboss_o) {
|
|
Log::error(sprintf('%s:! Cannot process message for echomail area [%s] for mail from [%s] with msgid [%s] - no boss object?',self::LOGKEY,$this->msg->echoarea,$this->msg->fboss,$this->msg->msgid));
|
|
return;
|
|
}
|
|
|
|
$ea = Echoarea::where('name',strtoupper($this->msg->echoarea))
|
|
->where('domain_id',$this->msg->fboss_o->zone->domain_id)
|
|
->single();
|
|
|
|
if (! $ea) {
|
|
Log::alert(sprintf('%s:! Echoarea [%s] doesnt exist for zone [%d]',self::LOGKEY,$this->msg->echoarea,$this->msg->fboss_o->zone->zone_id));
|
|
return;
|
|
}
|
|
|
|
Log::debug(sprintf('%s:- Processing echomail [%s] in [%s].',self::LOGKEY,$this->msg->msgid,$this->msg->echoarea));
|
|
|
|
// Check for duplicate messages
|
|
// FTS-0009.001
|
|
if ($this->msg->msgid) {
|
|
$o = Echomail::where('msgid',$this->msg->msgid)
|
|
->where('fftn_id',($x=$this->msg->fboss_o) ? $x->id : NULL)
|
|
->where('datetime','>',Carbon::now()->subYears(3))
|
|
->single();
|
|
|
|
Log::debug(sprintf('%s:- Checking for duplicate from host id [%d].',self::LOGKEY,($x=$this->msg->fboss_o) ? $x->id : NULL));
|
|
|
|
if ($o) {
|
|
Log::alert(sprintf('%s:! Duplicate echomail [%s] in [%s] from (%s) [%s] to (%s) - updating seenby.',
|
|
self::LOGKEY,
|
|
$this->msg->msgid,
|
|
$this->msg->echoarea,
|
|
$this->msg->user_from,$this->msg->fftn,
|
|
$this->msg->user_to,
|
|
));
|
|
|
|
if (! $o->msg_crc)
|
|
$o->msg_crc = md5($this->msg->message);
|
|
|
|
$o->save();
|
|
|
|
// If the path is empty, then its probably because of the previous bug, we'll replace it.
|
|
// @todo This duplicate message may have gone via a different path, be nice to record it.
|
|
//$o->path()->sync($o->path->pluck('id')->merge($this->msg->pathaddress)->toArray());
|
|
// @todo if we have an export for any of the seenby addresses, remove it
|
|
// @todo add received packet details
|
|
$o->seenby()->sync($o->seenby->pluck('id')->merge($this->msg->seenaddress)->filter()->toArray());
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Find another message with the same msg_crc
|
|
if ($this->msg->message) {
|
|
$o = Echomail::where('msg_crc',$xx=md5($this->msg->message))
|
|
->where('fftn_id',($x=$this->msg->fboss_o) ? $x->id : NULL)
|
|
->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('|')
|
|
));
|
|
}
|
|
|
|
// @todo Can the sender create it if it doesnt exist?
|
|
// @todo Can the sender send messages to this area?
|
|
// - Create it, or
|
|
// - Else record in bad area
|
|
|
|
// We know about this area, store it
|
|
$o = new Echomail;
|
|
$o->init();
|
|
|
|
$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->fboss_o) ? $x->id : NULL; // @todo This should be the node that originated the message - but since that node is not in the DB it would be null
|
|
$o->echoarea_id = $ea->id;
|
|
$o->msgid = $this->msg->msgid;
|
|
$o->replyid = $this->msg->replyid;
|
|
|
|
$o->msg = $this->msg->message_src."\r";
|
|
$o->msg_src = $this->msg->message_src;
|
|
$o->msg_crc = md5($this->msg->message);
|
|
$o->rogue_seenby = $this->msg->rogue_seenby;
|
|
$o->rogue_path = $this->msg->rogue_path;
|
|
$o->set_path = $this->msg->pathaddress;
|
|
$o->set_seenby = $this->msg->seenaddress;
|
|
// Record receiving packet and sender
|
|
$o->set_pkt = $this->packet;
|
|
|
|
$o->save();
|
|
|
|
Log::info(sprintf('%s:= Echomail [%s] in [%s] from (%s) [%s] to (%s) - [%s].',
|
|
self::LOGKEY,
|
|
$this->msg->msgid,
|
|
$this->msg->echoarea,
|
|
$this->msg->user_from,$this->msg->fftn,
|
|
$this->msg->user_to,
|
|
$o->id,
|
|
));
|
|
|
|
// If the message is to a bot, but not rescanned, or purposely skipbot set, we'll process it
|
|
if ((! $this->skipbot) && (! $this->msg->rescanned->count()))
|
|
foreach (config('process.echomail') as $class) {
|
|
if ($class::handle($this->msg)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private function create_netmail(Message $msg): Netmail
|
|
{
|
|
$o = new Netmail;
|
|
$o->to = $msg->user_to;
|
|
$o->from = $msg->user_from;
|
|
|
|
$o->fftn_id = ($x=$msg->fftn_o) ? $x->id : NULL;
|
|
$o->tftn_id = ($x=$msg->tftn_o) ? $x->id : NULL;
|
|
|
|
$o->datetime = $msg->date;
|
|
$o->tzoffset = $msg->date->utcOffset();
|
|
|
|
$o->flags = $msg->flags;
|
|
$o->cost = $msg->cost;
|
|
$o->msgid = $msg->msgid;
|
|
|
|
$o->subject = $msg->subject;
|
|
$o->msg = $msg->message;
|
|
|
|
foreach ($msg->via as $v)
|
|
$o->msg .= sprintf("\01Via %s\r",$v);
|
|
|
|
$o->msg_src = $msg->message_src;
|
|
$o->msg_crc = md5($msg->message); // @todo DB schema needs to handle this
|
|
|
|
return $o;
|
|
}
|
|
} |