2021-07-15 14:54:23 +00:00
< ? php
namespace App\Jobs ;
2021-10-18 12:10:15 +00:00
use Carbon\Carbon ;
2021-07-15 14:54:23 +00:00
use Illuminate\Bus\Queueable ;
use Illuminate\Contracts\Queue\ShouldQueue ;
use Illuminate\Foundation\Bus\Dispatchable ;
use Illuminate\Queue\InteractsWithQueue ;
use Illuminate\Queue\SerializesModels ;
2023-09-20 10:29:23 +00:00
use Illuminate\Support\Facades\DB ;
2021-07-23 14:53:35 +00:00
use Illuminate\Support\Facades\Log ;
2023-07-23 07:27:52 +00:00
use Illuminate\Support\Facades\Notification ;
2021-07-15 14:54:23 +00:00
2023-07-23 07:27:52 +00:00
use App\Classes\FTN\Message ;
2023-08-02 12:42:59 +00:00
use App\Models\ { Address , Echoarea , Echomail , Netmail , Setup , User };
use App\Notifications\Netmails\ { EchoareaNotExist , EchoareaNotSubscribed , EchoareaNoWrite , NetmailForward , Reject };
2023-09-20 10:29:23 +00:00
use App\Traits\ParseAddresses ;
2021-07-15 14:54:23 +00:00
2021-09-06 13:39:32 +00:00
class MessageProcess implements ShouldQueue
2021-07-15 14:54:23 +00:00
{
2021-09-11 14:07:02 +00:00
private const LOGKEY = 'JMP' ;
2021-08-18 14:20:34 +00:00
2023-09-20 10:29:23 +00:00
use Dispatchable , InteractsWithQueue , Queueable , SerializesModels , ParseAddresses ;
2021-07-15 14:54:23 +00:00
2023-07-15 00:46:19 +00:00
private Address $sender ;
2021-07-15 14:54:23 +00:00
private Message $msg ;
2023-08-05 11:32:45 +00:00
private Address $pktsrc ;
private Carbon $recvtime ;
2021-09-10 14:38:11 +00:00
private bool $skipbot ;
2023-01-24 11:37:41 +00:00
private string $packet ;
2021-07-15 14:54:23 +00:00
2023-08-05 11:32:45 +00:00
public function __construct ( Message $msg , string $packet , Address $sender , Address $pktsrc , Carbon $recvtime , bool $skipbot = FALSE )
2021-07-15 14:54:23 +00:00
{
$this -> msg = $msg ;
2023-01-24 11:37:41 +00:00
$this -> packet = $packet ;
2023-07-15 00:46:19 +00:00
$this -> sender = $sender ;
2023-08-05 11:32:45 +00:00
$this -> pktsrc = $pktsrc ;
$this -> recvtime = $recvtime ;
2023-07-15 00:46:19 +00:00
$this -> skipbot = $skipbot ;
2021-07-15 14:54:23 +00:00
}
2023-09-05 07:42:41 +00:00
public function __get ( $key ) : mixed
{
switch ( $key ) {
case 'subject' :
return sprintf ( '%s-%s-%s' , $this -> packet , $this -> sender -> ftn , $this -> msg -> msgid );
default :
return NULL ;
}
}
2021-07-15 14:54:23 +00:00
/**
2023-07-20 10:04:41 +00:00
* When calling MessageProcess - we assume that the packet is from a valid source , and
* the destination ( netmail / echomail ) is also valid
2021-07-15 14:54:23 +00:00
*/
public function handle ()
{
// Load our details
2023-12-18 04:13:16 +00:00
$ftns = our_address ();
2021-07-15 14:54:23 +00:00
// If we are a netmail
if ( $this -> msg -> isNetmail ()) {
2023-07-15 00:46:19 +00:00
Log :: info ( sprintf ( '%s:- Processing Netmail [%s] to (%s) [%s] from (%s) [%s].' ,
2023-01-25 05:26:10 +00:00
self :: LOGKEY ,
$this -> msg -> msgid ,
$this -> msg -> user_to , $this -> msg -> tftn ,
$this -> msg -> user_from , $this -> msg -> fftn ,
));
2021-07-15 14:54:23 +00:00
// @todo Enable checks to reject old messages
2023-07-15 00:46:19 +00:00
// 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 ;
}
}
2021-07-23 14:53:35 +00:00
// @todo Enable checks to see if this is a file request or file send
2021-07-15 14:54:23 +00:00
2023-07-23 07:27:52 +00:00
$o = new Netmail ;
$o -> to = $this -> msg -> user_to ;
$o -> from = $this -> msg -> user_from ;
$o -> fftn_id = ( $x = $this -> msg -> fftn_o ) ? $x -> id : NULL ;
$o -> tftn_id = ( $x = $this -> msg -> tftn_o ) ? $x -> id : NULL ;
$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 -> subject = $this -> msg -> subject ;
$o -> msg = $this -> msg -> message ;
foreach ( $this -> msg -> via as $v )
$o -> msg .= sprintf ( " \01 Via %s \r " , $v );
$o -> msg_src = $this -> msg -> message_src ;
$o -> msg_crc = md5 ( $this -> msg -> message );
2023-07-15 00:46:19 +00:00
$o -> set_pkt = $this -> packet ;
$o -> set_sender = $this -> sender ;
2023-09-20 10:29:23 +00:00
$o -> set_path = $this -> msg -> via ;
2023-08-05 11:32:45 +00:00
$o -> set_recvtime = $this -> recvtime ;
2023-07-20 10:04:41 +00:00
// Strip any local/transit flags
$o -> flags &= ~ ( Message :: FLAG_LOCAL | Message :: FLAG_INTRANSIT );
2023-01-24 11:37:41 +00:00
2021-07-15 14:54:23 +00:00
// Determine if the message is to this system, or in transit
2023-06-27 07:39:11 +00:00
if ( $ftns -> search ( function ( $item ) { return $this -> msg -> tftn === $item -> ftn ; }) !== FALSE ) {
2021-07-15 14:54:23 +00:00
// @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
2021-09-10 14:38:11 +00:00
if ( ! $this -> skipbot )
foreach ( config ( 'process.robots' ) as $class ) {
2023-08-02 12:42:59 +00:00
if ( $processed = $class :: handle ( $this -> msg )) {
2023-07-15 00:46:19 +00:00
$o -> flags |= Message :: FLAG_RECD ;
2023-01-25 05:35:58 +00:00
$o -> save ();
2023-07-17 06:36:53 +00:00
Log :: info ( sprintf ( '%s:= Netmail [%s] from (%s:%s) - was processed by us internally [%d]' ,
2023-07-15 12:10:05 +00:00
self :: LOGKEY ,
$this -> msg -> msgid ,
$this -> msg -> user_from ,
$this -> msg -> fftn ,
$o -> id ,
));
2021-09-10 14:38:11 +00:00
break ;
}
2021-07-15 14:54:23 +00:00
}
2023-08-02 12:42:59 +00:00
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 -> msg -> user_to )))
-> orWhereRaw ( sprintf ( " LOWER(alias)='%s' " , strtolower ( $this -> msg -> user_to )));
})
-> whereNotNull ( 'system_id' )
-> single ();
if ( $uo && ( $ao = $uo -> system -> match ( $this -> msg -> tftn_o -> 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 -> msg -> tftn_o -> ftn );
$note .= " +---------------------------------------------------------+ \r \r " ;
$o -> msg = $note . $this -> msg -> message ;
$o -> tftn_id = $ao -> id ;
$o -> flags |= Message :: FLAG_INTRANSIT ;
$o -> save ();
$processed = TRUE ;
// Dont send an advisement to an areabot
2023-09-22 04:45:44 +00:00
if ( ! in_array ( strtolower ( $this -> msg -> user_from ), config ( 'fido.areabots' )))
2023-08-02 12:42:59 +00:00
Notification :: route ( 'netmail' , $this -> msg -> fftn_o ) -> notify ( new NetmailForward ( $this -> msg , $ao ));
// We'll ignore messages from *fix users
2023-09-22 04:45:44 +00:00
} elseif ( in_array ( strtolower ( $this -> msg -> user_from ), config ( 'fido.areabots' ))) {
2023-08-02 12:42:59 +00:00
$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 ;
}
2021-08-14 14:21:04 +00:00
}
2021-07-15 14:54:23 +00:00
// If not processed, no users here!
if ( ! $processed ) {
2023-07-15 00:46:19 +00:00
Log :: alert ( sprintf ( '%s:! Netmail to the Hub from (%s) [%s] but no users here.' , self :: LOGKEY , $this -> msg -> user_from , $this -> msg -> fftn ));
2021-07-23 14:53:35 +00:00
2023-07-23 07:27:52 +00:00
Notification :: route ( 'netmail' , $this -> msg -> fftn_o ) -> notify ( new Reject ( $this -> msg ));
2021-07-15 14:54:23 +00:00
}
// 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
2023-07-15 00:46:19 +00:00
$o -> flags |= Message :: FLAG_INTRANSIT ;
2021-07-23 14:53:35 +00:00
$o -> save ();
2023-01-24 11:37:41 +00:00
2023-07-15 00:46:19 +00:00
Log :: info ( sprintf ( '%s:= Netmail [%s] in transit to (%s:%s) from (%s:%s) [%d].' ,
2023-01-24 11:37:41 +00:00
self :: LOGKEY ,
$this -> msg -> msgid ,
$this -> msg -> user_to , $this -> msg -> tftn ,
$this -> msg -> user_from , $this -> msg -> fftn ,
2023-07-15 00:46:19 +00:00
$o -> id ,
2023-01-24 11:37:41 +00:00
));
2021-07-15 14:54:23 +00:00
}
// Else we are echomail
} else {
2023-07-15 00:46:19 +00:00
Log :: debug ( sprintf ( '%s:- Looking for echomail area [%s] for mail from [%s]' , self :: LOGKEY , $this -> msg -> echoarea , $this -> msg -> fboss ));
2023-01-01 02:50:12 +00:00
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 ;
}
2022-02-16 12:01:55 +00:00
$ea = Echoarea :: where ( 'name' , strtoupper ( $this -> msg -> echoarea ))
2021-08-22 06:25:43 +00:00
-> where ( 'domain_id' , $this -> msg -> fboss_o -> zone -> domain_id )
2021-08-11 13:45:30 +00:00
-> single ();
2022-02-11 23:21:46 +00:00
if ( ! $ea ) {
2023-09-17 05:46:09 +00:00
Log :: alert ( sprintf ( '%s:! Echoarea [%s] doesnt exist for zone [%d-%d]' , self :: LOGKEY , $this -> msg -> echoarea , $this -> msg -> fboss_o -> zone -> domain_id , $this -> msg -> fboss_o -> zone -> zone_id ));
2023-07-29 03:17:36 +00:00
2023-08-05 11:32:45 +00:00
Notification :: route ( 'netmail' , $this -> pktsrc ) -> notify ( new EchoareaNotExist ( $this -> msg ));
2022-02-11 23:21:46 +00:00
return ;
}
2023-07-15 00:46:19 +00:00
Log :: debug ( sprintf ( '%s:- Processing echomail [%s] in [%s].' , self :: LOGKEY , $this -> msg -> msgid , $this -> msg -> echoarea ));
2021-11-24 11:34:40 +00:00
2023-09-17 05:46:09 +00:00
if ( ! $this -> pktsrc -> zone -> domain -> zones -> pluck ( 'zone_id' ) -> contains ( $this -> msg -> fboss_o -> zone -> zone_id )) {
2023-09-20 10:29:23 +00:00
Log :: alert ( sprintf ( '%s:! The message [%s] is from a different zone [%d] than the packet sender [%d] - not importing' ,
2023-09-17 05:46:09 +00:00
self :: LOGKEY ,
$this -> msg -> msgid ,
$this -> msg -> fboss_o -> zone -> zone_id ,
$this -> pktsrc -> zone -> zone_id ));
2023-09-20 10:29:23 +00:00
return ;
2023-09-17 05:46:09 +00:00
}
2021-08-18 14:20:34 +00:00
// Check for duplicate messages
2021-10-18 12:10:15 +00:00
// FTS-0009.001
2021-08-18 14:20:34 +00:00
if ( $this -> msg -> msgid ) {
2021-10-18 12:10:15 +00:00
$o = Echomail :: where ( 'msgid' , $this -> msg -> msgid )
-> where ( 'fftn_id' ,( $x = $this -> msg -> fboss_o ) ? $x -> id : NULL )
2023-09-20 10:29:23 +00:00
-> where ( 'datetime' , '>=' , $this -> msg -> date -> subYears ( 3 ))
-> where ( 'datetime' , '<=' , $this -> msg -> date )
2021-10-18 12:10:15 +00:00
-> single ();
2021-08-18 14:20:34 +00:00
2023-07-15 00:46:19 +00:00
Log :: debug ( sprintf ( '%s:- Checking for duplicate from host id [%d].' , self :: LOGKEY ,( $x = $this -> msg -> fboss_o ) ? $x -> id : NULL ));
2021-11-24 11:34:40 +00:00
2021-08-18 14:20:34 +00:00
if ( $o ) {
2021-11-24 11:34:40 +00:00
Log :: alert ( sprintf ( '%s:! Duplicate echomail [%s] in [%s] from (%s) [%s] to (%s) - updating seenby.' ,
2021-08-18 14:20:34 +00:00
self :: LOGKEY ,
$this -> msg -> msgid ,
$this -> msg -> echoarea ,
2022-01-22 12:08:46 +00:00
$this -> msg -> user_from , $this -> msg -> fftn ,
$this -> msg -> user_to ,
2021-08-18 14:20:34 +00:00
));
2021-11-24 11:34:40 +00:00
if ( ! $o -> msg_crc )
$o -> msg_crc = md5 ( $this -> msg -> message );
2022-01-15 02:06:15 +00:00
$o -> save ();
2021-11-25 10:22:36 +00:00
// @todo This duplicate message may have gone via a different path, be nice to record it.
2023-09-20 10:29:23 +00:00
// 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 -> msg -> path , $this -> pktsrc -> zone , $dummy );
2023-11-17 09:49:25 +00:00
/*
2023-11-17 01:18:55 +00:00
// If our sender is not in the path, add it
if ( ! $path -> contains ( $this -> sender -> id )) {
Log :: alert ( sprintf ( '%s:? Echomail adding sender to PATH [%s] for [%d].' , self :: LOGKEY , $x -> ftn , $o -> id ));
$path -> push ( $this -> sender -> id );
}
2023-11-17 09:49:25 +00:00
*/
2023-11-17 01:18:55 +00:00
2023-09-20 10:29:23 +00:00
$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 ;
}
}
2022-01-15 02:06:15 +00:00
// @todo if we have an export for any of the seenby addresses, remove it
2023-09-20 10:29:23 +00:00
$seenby = $this -> parseAddresses ( 'seenby' , $this -> msg -> seenby , $this -> pktsrc -> zone , $o -> rogue_seenby );
$x = $o -> seenby () -> syncWithoutDetaching ( $seenby );
// In case our rogue_seenby changed
if ( $o -> getDirty ())
$o -> save ();
2021-11-24 11:34:40 +00:00
2021-08-18 14:20:34 +00:00
return ;
}
}
2021-11-24 11:34:40 +00:00
// 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 ( '|' )
));
}
2023-07-29 03:17:36 +00:00
// Can the system send messages to this area?
2023-08-05 11:32:45 +00:00
if ( ! $ea -> sec_write || ( $this -> pktsrc -> security < $ea -> sec_write )) {
2023-09-20 10:29:23 +00:00
Log :: alert ( sprintf ( '%s:! FTN [%s] is not allowed to post [%s] to [%s].' , self :: LOGKEY , $this -> pktsrc -> ftn , $this -> msg -> msgid , $ea -> name ));
2023-09-17 05:46:09 +00:00
if ( ! $this -> msg -> rescanned -> count ())
Notification :: route ( 'netmail' , $this -> pktsrc ) -> notify ( new EchoareaNoWrite ( $this -> msg ));
2023-07-29 03:17:36 +00:00
return ;
}
2023-08-05 11:32:45 +00:00
// If the node is not subscribed
2023-09-17 05:46:09 +00:00
if ( $this -> pktsrc -> echoareas -> search ( function ( $item ) use ( $ea ) { return $item -> id === $ea -> id ; }) === FALSE ) {
2023-09-20 10:29:23 +00:00
Log :: alert ( sprintf ( '%s:! FTN [%s] is not subscribed to [%s] for [%s].' , self :: LOGKEY , $this -> pktsrc -> ftn , $ea -> name , $this -> msg -> msgid ));
2023-09-17 05:46:09 +00:00
if ( ! $this -> msg -> rescanned -> count ())
Notification :: route ( 'netmail' , $this -> pktsrc ) -> notify ( new EchoareaNotSubscribed ( $this -> msg ));
}
2021-07-15 14:54:23 +00:00
// We know about this area, store it
2021-07-30 14:35:52 +00:00
$o = new Echomail ;
2022-11-04 12:14:47 +00:00
$o -> init ();
2021-07-30 14:35:52 +00:00
$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 ();
2023-11-17 01:18:55 +00:00
if ( $x = $this -> msg -> fboss_o ) {
$o -> fftn_id = $x -> id ;
} else {
$o -> fftn_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
}
2022-02-11 23:21:46 +00:00
$o -> echoarea_id = $ea -> id ;
2021-07-30 14:35:52 +00:00
$o -> msgid = $this -> msg -> msgid ;
2022-10-30 12:42:30 +00:00
$o -> replyid = $this -> msg -> replyid ;
2021-07-30 14:35:52 +00:00
2022-02-16 12:01:55 +00:00
$o -> msg = $this -> msg -> message_src . " \r " ;
2022-10-30 12:42:30 +00:00
$o -> msg_src = $this -> msg -> message_src ;
2021-11-21 05:53:56 +00:00
$o -> msg_crc = md5 ( $this -> msg -> message );
2023-11-17 01:18:55 +00:00
2023-09-20 10:29:23 +00:00
$o -> set_path = $this -> msg -> path ;
$o -> set_seenby = $this -> msg -> seenby ;
2023-08-05 11:32:45 +00:00
$o -> set_recvtime = $this -> recvtime ;
2023-11-22 02:14:21 +00:00
$o -> set_sender = $this -> pktsrc -> id ;
2023-07-15 00:46:19 +00:00
// Record receiving packet and sender
2023-07-15 12:10:05 +00:00
$o -> set_pkt = $this -> packet ;
2021-07-30 14:35:52 +00:00
$o -> save ();
2023-07-15 00:46:19 +00:00
Log :: info ( sprintf ( '%s:= Echomail [%s] in [%s] from (%s) [%s] to (%s) - [%s].' ,
2021-08-19 13:35:48 +00:00
self :: LOGKEY ,
$this -> msg -> msgid ,
$this -> msg -> echoarea ,
2021-09-11 14:07:02 +00:00
$this -> msg -> user_from , $this -> msg -> fftn ,
$this -> msg -> user_to ,
2021-08-19 13:35:48 +00:00
$o -> id ,
));
2021-09-13 13:02:39 +00:00
// 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 ()))
2021-09-10 14:38:11 +00:00
foreach ( config ( 'process.echomail' ) as $class ) {
if ( $class :: handle ( $this -> msg )) {
break ;
}
2021-07-30 14:35:52 +00:00
}
2021-07-15 14:54:23 +00:00
}
}
}