https://t.me/RX1948
Server : Apache
System : Linux server.lienzindia.com 4.18.0-348.7.1.el8_5.x86_64 #1 SMP Wed Dec 22 13:25:12 UTC 2021 x86_64
User : plutus ( 1007)
PHP Version : 7.4.33
Disable Function : NONE
Directory :  /etc/exim/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //etc/exim/exim.pl
#!/usr/bin/perl

#VERSION=31
my %user_cache = ( 'root' => 0 );
my $local_connection_uid;
my $local_connection_user;
my $check_mail_validity_data       = '';
my %sender_host_address_cache;
use constant {
    _SENDER_SYSTEM => '-system-',
};
my $sender_lookup;

sub convert_address_directory_to_dovecot_lda_destination_username {
    my $local_part = Exim::expand_string('$local_part');
    my $domain     = Exim::expand_string('$domain');
    $primary_hostname ||= Exim::expand_string('$primary_hostname');
    my $address_file = Exim::expand_string('$address_file');

    if ( $address_file !~ m{mail/\Q$domain\E} ) {
        return ( getpwuid($>) )[0];
    }
    else {
        return $local_part . '@' . $domain;
    }

}

sub convert_address_directory_to_dovecot_lda_mailbox {
    my $address_file = Exim::expand_string('$address_file');

    my ($mailbox) = $address_file =~ m{/\.([^\/]+)};
    if ($mailbox) {
        return "INBOX.$mailbox";
    }

    return 'INBOX';

}

sub unquoted_encode_string_literal {
    my $string = shift;
    return if !defined $string;

    $string =~ s/\\N/\\N\\\\N\\N/g;    # Only use / here for perl compat
    return "\\N$string\\N";
}

sub getuid {
    my $user = shift;
    my $uid = Exim::expand_string( '${extract{2}{:}{${lookup passwd{' .unquoted_encode_string_literal($user). '}{$value}}}}' );
    return defined $uid ? $uid : '';
}

sub user2uid {
    my $user = shift;
    return exists $user_cache{$user} ? $user_cache{$user} : ( $user_cache{$user} = getuid($user) );
}

sub spamd_is_available {
	$spamdir = '/usr/bin/spamassassin';
	
	if (-e $spamdir) {
		return 1;
	}
	
	return 0;
}

sub store_spam {
    my $sender_host_address = shift;
    my $spam_score          = shift;
    my $now                 = time();
    open( my $spam_fh, '>>', '/var/webuzo-data/mail/spamstore' );

    #uncomment to deploy
    #    syswrite($spam_fh, $now . ':' . $sender_host_address . ':' . $spam_score . ":.\n");
    close($spam_fh);
}


sub get_suspended_shell {
    my ($user) = @_;
    my $passwd_file_shell = Exim::expand_string( '${extract{6}{:}{${lookup passwd{' .unquoted_encode_string_literal($user) . '}}}}' );
    if ( !length($passwd_file_shell) ) {
        return '';
    }
	
    if ( $passwd_file_shell ne '/bin/false' ) {
        return $passwd_file_shell;
    }
	
    return '/sbin/nologin';
}

# TODO:
sub increment_max_emails_per_hour_if_needed {
	
	return 'no';
}

# Untaint a string for exim. This is not a perl untaint
sub untaint {
    return $_[0];
}

sub mailtrapheaders {
    $primary_hostname ||= Exim::expand_string('$primary_hostname');
    my $original_domain       = Exim::expand_string('$original_domain');
    my $sender_address_domain = Exim::expand_string('$sender_address_domain');
    my $originator_uid        = Exim::expand_string('$originator_uid');
    my $originator_gid        = Exim::expand_string('$originator_gid');
    my $caller_uid            = Exim::expand_string('$caller_uid');
    my $caller_gid            = Exim::expand_string('$caller_gid');
    my $headers =
        "X-AntiAbuse: This header was added to track abuse, please include it with any abuse report\n"
      . "X-AntiAbuse: Primary Hostname - $primary_hostname\n"
      . "X-AntiAbuse: Original Domain - $original_domain\n"
      . "X-AntiAbuse: Originator/Caller UID/GID - [$originator_uid $originator_gid] / [$caller_uid $caller_gid]\n"
      . "X-AntiAbuse: Sender Address Domain - $sender_address_domain\n";

    if ( -e '/etc/eximmailtrap' ) {
        my $xsource     = $ENV{'X-SOURCE'};
        my $xsourceargs = $ENV{'X-SOURCE-ARGS'};
        my $xsourcedir  = maskdir( $ENV{'X-SOURCE-DIR'} );

        $headers .= "X-Source: ${xsource}\n" . "X-Source-Args: ${xsourceargs}\n" . "X-Source-Dir: ${xsourcedir}";
    }
    return ($headers);

}

#TODO
sub sender_domain_can_dkim_sign {
	return 0;
}

sub get_sender_lookup {
    return $sender_lookup || '';
}

sub check_mail_permissions_headers {
    return "X-Get-Message-Sender-Via: " . ( $primary_hostname ||= Exim::expand_string('$primary_hostname') ) . ": " . get_sender_lookup_method() . "\n" . "X-Authenticated-Sender: " . ( $primary_hostname ||= Exim::expand_string('$primary_hostname') ) . ": " . get_sender_lookup();
}

sub check_mail_validity {
	
	my $uid = int( Exim::expand_string('$originator_uid') );
	my $gid = int( Exim::expand_string('$originator_gid') );
	$check_mail_validity_data       = ':unknown:';
	
    my $message_exim_id = Exim::expand_string('$message_exim_id');
	my $domain = Exim::expand_string('$domain');
	my $sender_address_domain = Exim::expand_string('$sender_address_domain');
	
	$domain_sender_owner = getdomainowner($sender_address_domain);
	if(!$domain_sender_owner || $domain_sender_owner eq ""){
		return 'no';
	}
	
	# $domain_hl = get_hourly_limit($sender_address_domain);
	$user_hl = get_hourly_limit($domain_sender_owner);
	#Exim::log_write("!DEBUG! running check_mail_validity ".$uid." ".$gid." user:".$domain_sender_owner." domain:".$domain." sender_domain:".$sender_address_domain." dom_cl:".$dom_cl." user_hl:".$user_hl);
	
	#if(!$user_hl || $user_hl == 0 ){
		#return 'no';
	#}
	
	# _check_tracker_dir($domain_sender_owner);
	_check_tracker_dir($sender_address_domain);
	$dom_cl = get_emails_per_hour_count($sender_address_domain, time());
	
	# +1 about to send this email (not send yet)
	if( ($user_hl > 0) && ( ($dom_cl + 1) > $user_hl ) ){
		$check_mail_validity_data  = ":fail: Domain $sender_address_domain is reached hourly send limit.";
		return 'yes';
	}
	
	# Set admin max send limit on each domain
	my $admin_email_hourly_limit = get_hourly_limit_domain_admin();
	if ( ( $admin_email_hourly_limit > 0 ) && ( ($dom_cl + 1) > $admin_email_hourly_limit ) && !( ( $user_hl >= 0 ) ||  ( $user_hl >= $admin_email_hourly_limit ) ) ) {
		$check_mail_validity_data  = ":fail: Domain $sender_address_domain is reached hourly send limit.";
		return 'yes';
	}
	
	return 'no';
}

sub check_mail_validity_results {
    return $check_mail_validity_data;
}

# It only increment the email count
sub increment_email_per_hour_count_if{
	
	my $message_exim_id = Exim::expand_string('$message_exim_id');
	my $domain = Exim::expand_string('$domain');
	my $sender_address_domain = Exim::expand_string('$sender_address_domain');
	$domain_sender_owner = getdomainowner($sender_address_domain);
	
	if(!$domain_sender_owner || $domain_sender_owner eq ""){
		return 'no';
	}
	
	if ( $sender_address_domain && $sender_address_domain ne _SENDER_SYSTEM ) {
        # Check if domain exceed warning level then warn admin
        my $mail_count       = get_emails_per_day_count($sender_address_domain) + 1;    # +1 for we are about to send.
		my $emails_to_notify = get_daily_limit_notify();
        if ( ( $emails_to_notify > 0 ) && ( $mail_count > $emails_to_notify ) ) {
            if ( ! -e '/var/webuzo-data/mail/notify/' . $sender_address_domain  ) {
                create_daily_notify_file($sender_address_domain);
                Exim::log_write("increment_email_per_hour_count_if Hit daily email notify limit for domain $sender_address_domain");
            }
        } else {
			if( -e '/var/webuzo-data/mail/notify/' . $sender_address_domain){
				unlink('/var/webuzo-data/mail/notify/' . $sender_address_domain);
			}
		}
	}
	
	# _check_tracker_dir($sender_address_domain);
	increment_mail_count($sender_address_domain, time());

	return 'no';
}

sub _check_tracker_dir {
    my $domain = shift;
    $domain =~ s/\///g;    #jic

    if ( !-e '/var/webuzo-data/mail/track/' . $domain ) {
        mkdir( '/var/webuzo-data/mail',             	 0751 );
		mkdir( '/var/webuzo-data/mail/track',            0750 );
        mkdir( '/var/webuzo-data/mail/track/' . $domain, 0750 );
    }
}

sub _check_limit_dir {
    my $domain = shift;
    $domain =~ s/\///g;    #jic

    if ( !-e '/var/webuzo-data/mail/limit/' . $domain ) {
		mkdir( '/var/webuzo-data/mail',                  0751 );
        mkdir( '/var/webuzo-data/mail/limit',            0750 );
        mkdir( '/var/webuzo-data/mail/limit/' . $domain, 0750 );
    }
}

sub _check_sendbandwidth_log {
    my ($u, $t) = @_;
    $u =~ s/\///g;    #jic

    if ( !-e '/var/webuzo-data/mail/log/' . $u .'.'.$t ) {
        mkdir( '/var/webuzo-data/mail',                  0751 );
        mkdir( '/var/webuzo-data/mail/log',            0750 );
        mkdir( '/var/webuzo-data/mail/log/' . $u.'.'.$t, 0750 );
    }
}

sub log_bandwidth {
	
	my ($u,$d, $t) = @_;
	my $bytes = Exim::expand_string('$message_size');
	
	if ($bytes == -1) { return; }
	
	if ( open( my $mail_log, '>>', "/var/webuzo-data/mail/log/".$u.".".$t ) ) {

       print $mail_log "$d&bytes=$bytes\n";
       close($mail_log);
    }
}

sub get_emails_per_hour_count {
    ( ( stat( "/var/webuzo-data/mail/track/$_[0]/" . join( '.', ( gmtime( $_[1] || time() ) )[ 2, 3, 4, 5 ] ) ) )[7] || 0 );
}

sub get_emails_per_day_count {
    my $domain = shift;
    $domain =~ s/\///g;    #jic

    return 0 if ( !-e '/var/webuzo-data/mail/track/' . $domain );
    my $total_size = 0;
    if ( opendir( my $domain_track_fh, '/var/webuzo-data/mail/track/' . $domain ) ) {
        while ( my $domaintime = readdir($domain_track_fh) ) {
            next if ( $domaintime =~ /^\.\.?$/ );
            my $tracker_file_size = ( stat("/var/webuzo-data/mail/track/$domain/$domaintime") )[7];
            $total_size += $tracker_file_size;
        }
    }
    return $total_size;
}

sub get_hourly_limit {
	
	 my $domain = shift;
    $domain =~ s/\///g;    #jic
	
	return 0 if ( !-e '/var/webuzo-data/mail/limit/' . $domain );
	
	if ( open( $max_hl, '<', '/var/webuzo-data/mail/limit/' . $domain ) ){
		$maxemails = readline $max_hl;
		close $max_hl;
		
		return 0 if !$maxemails || $maxemails eq 'unlimited';
		return ( $maxemails ? int($maxemails) : 0 );
	}
   
   return 0;
}

sub reached_max_emails_per_hour_count {
    my $domain = shift;
    $domain =~ s/\///g;    #jic
    my $max_allowed = int( shift || 0 );
    my $time = shift || time();

    if ($max_allowed) {

        # AKA number_of_emails_sent >= $max_allowed
        if ( get_emails_per_hour_count( $domain, $time ) >= $max_allowed ) {
            return 1;
        }
        else {
            return 0;
        }
    }
    return 0;
}

sub increment_mail_count{
	
	my ( $d, $t ) = @_;
	
	_check_tracker_dir($d);
	
	$t ||= time();
	
	if ( open( my $email_hic, '>>', "/var/webuzo-data/mail/track/$d/" . join( '.', ( gmtime($t) )[ 2, 3, 4, 5 ] ) ) ) {

        print {$email_hic} '1';
        close($email_hic);
    }
}

sub gethomedir {
    my $user = shift;
    return Exim::expand_string( '${extract{5}{:}{${lookup passwd{' . unquoted_encode_string_literal($user) . '}{$value}}}}' ) || '';
}

sub getdomainowner {
    my $domain = shift;
	
    substr($domain,0,4,'') if index($domain,'www.') == 0;
    return Exim::expand_string( '${lookup{' . unquoted_encode_string_literal($domain) . '}lsearch{/etc/userdomains}{$value}}' ) || '';
}

sub lookup_key_in_file {
    my ( $file, $key ) = @_;
    return Exim::expand_string( '${lookup{' . unquoted_encode_string_literal($key) . '}lsearch{' . $file . '}{$value}}' ) || '';
}

sub isdemo {
    my $user = shift;
    return if ( !$user );
    return 0 if $user eq '0' || $user eq 'exim' || $user eq 'webuzo' || $user eq 'root';
    if ( $user =~ /^\d+$/ ) {
        return user_exists_in_db( $user, '/etc/demouids' );
    }
	return user_exists_in_db( $user, '/etc/demousers' );
}

sub user_exists_in_db {
    my ( $user, $db ) = @_;

    return 0 if !$user || $user !~ tr{ \t}{}c;
	
    return Exim::expand_string( '${lookup{' . unquoted_encode_string_literal($user) . '}lsearch{' . $db . '}{1}{0}}' ) || '0';
}

sub get_daily_limit_notify {

    # The value is the size of the file so we can avoid the open/close overhead (just a stat)
	return 0 if ( !-e '/var/webuzo-data/mail/daily_notify' );
    my $limit = ( stat('/var/webuzo-data/mail/daily_notify') )[7];
    if ( !defined $limit ) { $limit = 0; }
    return $limit;
}

sub get_hourly_limit_domain_admin {

    # The value is the size of the file so we can avoid the open/close overhead (just a stat)
	return 0 if ( !-e '/var/webuzo-data/mail/hourly_limit' );
    my $limit = ( stat('/var/webuzo-data/mail/hourly_limit') )[7];
    if ( !defined $limit ) { $limit = 0; }
    return $limit;
}
 
sub create_daily_notify_file {

    my $domain = shift;
    $domain =~ s/\///g;    #jic
    mkdir( '/var/webuzo-data/mail/notify', 0750 ) if !-e '/var/webuzo-data/mail/notify';
    if ( open( my $daily_limit_fh, '>', '/var/webuzo-data/mail/notify/' . $domain ) ) {
        close $daily_limit_fh;
    }
    return undef;
} 


sub resolve_vhost_owner {

    if ( file_exists('/var/webuzo-data/mail/trust_x_php_script') ) {

        if ( my $x_php_script = Exim::expand_string('$h_x-php-script:') ) {
			
            my ( $servername, $uri ) = split( m{/}, $x_php_script, 2 );
            if ( $uri =~ m/^\/?\~([^\/\s]+)/ ) {
                my $http_user = $1;
                my $uid       = user2uid($http_user);

                Exim::log_write("nobody send identification H=localhost A=127.0.0.1 U=$http_user ID=$uid B=acl_c_vhost_owner M=trust_x_php_script");
                return $uid . ':' . '//' . $servername . '/' . $uri . ' ';
            }
            elsif ( my $http_user = getdomainowner($servername) ) {
                my $uid = user2uid($http_user);

                Exim::log_write("nobody send identification H=localhost A=127.0.0.1 U=$http_user ID=$uid B=acl_c_vhost_owner M=trust_x_php_script");
                return $uid . ':' . '//' . $servername . '/' . $uri . ' ';
            }
        }
    }

    return;
}

sub getdomainfromaddress {
    my $address = shift;
    $address =~ s/\/.*$//g if $address =~ tr/\///;
    if ( $address =~ tr/@+%:// ) {
        unless ( $address =~ tr/@// ) {
            $address =~ s/[+:%]/@/;
        }
        $primary_hostname ||= Exim::expand_string('$primary_hostname');
        if ( $address =~ m/[@]\Q$primary_hostname\E$/ ) {
            return getusersdomain( ( split( m/[@]/, $address, 2 ) )[0] ) || _SENDER_SYSTEM; 
        }
        else {
            return ( split( m/[@]/, $address, 2 ) )[1];
        }
    }
    else {
        return getusersdomain($address) || _SENDER_SYSTEM;
    }
}

my %domain_to_user_cache;

sub getusersdomain {
    return '' if !$_[0] || $_[0] eq 'root' || $_[0] =~ tr{/}{} || !-e "/var/webuzo/users/$_[0]";
    return ( $domain_to_user_cache{ $_[0] } || ( $domain_to_user_cache{ $_[0] } = lookup_key_in_file( '/etc/domainusers', $_[0] ) ) );
}

sub get_recent_authed_mail_ips_text_entry {
    my ( $sender, $domain ) = get_recent_authed_mail_ips_entry(@_);
    return join( '|', ( $sender || '' ), $domain );
}

sub popbeforesmtpwarn {
    if ( my @possible_users = _get_possible_users_from_recent_authed_mail_ips_users() ) {
        return ( "X-PopBeforeSMTPSenders: " . join( ",", @possible_users ) );
    }
    return '';
}

sub get_recent_authed_mail_ips_entry {
    my $log = shift;

    # SENDING OVER POP B4 SMTP or NOAUTH
    # case 43151, case 43150
    $get_recent_authed_mail_ips_lookup_method = '';

    my $sender_host_address = Exim::expand_string('$sender_host_address');

    # Exim::log_write("!DEBUG! get_recent_authed_mail_ips_entry sender_host_address=[$sender_host_address] log=[$log]");
    my ( $sender, $domain );

    if ( exists $sender_recent_authed_mail_ips_address_cache{$sender_host_address} ) {

        # Exim::log_write("!DEBUG! get_recent_authed_mail_ips_entry sender_host_address=[$sender_host_address] USING CACHE");
        ( $sender, $domain, $get_recent_authed_mail_ips_lookup_method ) = @{ $sender_recent_authed_mail_ips_address_cache{$sender_host_address} };
        $get_recent_authed_mail_ips_lookup_method = "cached: " . $get_recent_authed_mail_ips_lookup_method;
        $log                                      = 0;
    }
    else {
        my $recent_authed_mail_ips_users_is_up_to_date = ( stat('/etc/recent_authed_mail_ips_users') )[9] + 7200 > time() ? 1 : 0;
        my $sender_address_domain;

        # Exim::log_write("!DEBUG! get_recent_authed_mail_ips_entry sender_host_address=[$sender_host_address] recent_authed_mail_ips_users_is_up_to_date= $recent_authed_mail_ips_users_is_up_to_date");

        # If we have a recent_authed_mail_ips_users file that is up to date, we can verify the ip matches
        if ($recent_authed_mail_ips_users_is_up_to_date) {

            # This is what the user has claimed as the sender
            my $sender_address   = Exim::expand_string('$sender_address');
            my $from_h_domain    = Exim::expand_string('${domain:$h_from:}');
            my $from_h_localpart = Exim::expand_string('${local_part:$h_from:}');
            my $from_h           = "$from_h_localpart\@$from_h_domain";

            # First we try to find the address in the recent_authed_mail_ips_users file (with a cached exim lookup)
            if ( my @possible_users = _get_possible_users_from_recent_authed_mail_ips_users() ) {

                if ( grep { tr/@// ? $from_h eq $_ : $from_h eq $_ . '@' . $primary_hostname } @possible_users ) {
                    $sender                                   = $from_h;
                    $domain                                   = getdomainfromaddress($from_h);
                    $get_recent_authed_mail_ips_lookup_method = "full match of from_h in recent_authed_mail_ips_users";
                }
                elsif ( grep { tr/@// ? $sender_address eq $_ : $sender_address eq $_ . '@' . $primary_hostname } @possible_users ) {
                    $sender                                   = $sender_address;
                    $domain                                   = getdomainfromaddress($sender_address);
                    $get_recent_authed_mail_ips_lookup_method = "full match of sender_address in recent_authed_mail_ips_users";
                }
                elsif ( ( $sender_address_domain = ( split( m/\@/, $sender_address ) )[1] ) && grep( m/\@\Q$sender_address_domain\E$/, @possible_users ) ) {
                    $domain                                   = $sender_address_domain;
                    $sender                                   = '-unknown-@' . $domain;
                    $get_recent_authed_mail_ips_lookup_method = "match of sender_address_domain in recent_authed_mail_ips_users";
                }
                elsif ( grep { tr/@// ? ( $from_h eq $_ ) : ( $from_h_localpart eq $_ && ( !length $from_h_domain || $from_h_domain eq $primary_hostname ) ) } @possible_users ) {
                    $sender                                   = $from_h;
                    $domain                                   = $from_h_domain;
                    $get_recent_authed_mail_ips_lookup_method = "full match of from_h in recent_authed_mail_ips_users";
                }
                elsif ( grep( m/\@\Q$from_h_domain\E$/, @possible_users ) ) {
                    $domain                                   = $from_h_domain;
                    $sender                                   = '-unknown-@' . $from_h_domain;
                    $get_recent_authed_mail_ips_lookup_method = "match of from_h_domain in recent_authed_mail_ips_users";
                }
                elsif ( $possible_users[0] && $possible_users[0] eq '-alwaysrelay-' ) {
                    if ($from_h_domain) {
                        Exim::log_write("$sender_host_address in /etc/alwaysrelay trusting from_h_domain of: $from_h_domain and from_h_localpart: $from_h_localpart");
                        $domain                                   = $from_h_domain;
                        $sender                                   = $from_h;
                        $get_recent_authed_mail_ips_lookup_method = "in alwaysrelay trusted from_h";
                    }
                    else {
                        Exim::log_write("$sender_host_address in /etc/alwaysrelay trusting sender_address_domain of: $sender_address_domain");
                        $domain                                   = $sender_address_domain;
                        $sender                                   = $sender_address;
                        $get_recent_authed_mail_ips_lookup_method = "in alwaysrelay trusted sender_address";
                    }
                }
                else {

                    # If none of them matched, we have to assume they authenticated in some we so we go with the first one
                    $domain                                   = getdomainfromaddress( $possible_users[0] );
                    $sender                                   = $possible_users[0];
                    $get_recent_authed_mail_ips_lookup_method = "in recent_authed_mail_ips_users using first address";
                }
                if ( $sender =~ m/^\*/ ) {
                    $sender =~ s/^\*/-unknown-/;
                }
                $sender_recent_authed_mail_ips_address_cache{$sender_host_address} = [ $sender, $domain, $get_recent_authed_mail_ips_lookup_method ];
            }
        }

        # we need to check alwaysrelay since we don't require recentauthedmailiptracker to be enabled
        if ( !$domain && -e '/etc/alwaysrelay' ) {
            my $alwaysrelay_result = Exim::expand_string('${lookup{$sender_host_address}iplsearch{/etc/alwaysrelay}{$sender_host_address $value}}');
            if ($alwaysrelay_result) {
                my ( $alwaysrelay_ip, $alwaysrelay_user ) = split( /\s+/, $alwaysrelay_result );
                if ($alwaysrelay_user) {
                    $domain                                   = getdomainfromaddress($alwaysrelay_user);
                    $sender                                   = $alwaysrelay_user;
                    $get_recent_authed_mail_ips_lookup_method = "full match in alwaysrelay with recentauthedmailiptracker disabled";
                    Exim::log_write("$sender_host_address in /etc/alwaysrelay using domain $domain from lookup of $alwaysrelay_user");
                }
                if ( !$domain ) {
                    $domain = $sender_address_domain = ( split( /\@/, Exim::expand_string('$sender_address') ) )[1];
                    $sender = "-unknown-\@$domain";
                    $get_recent_authed_mail_ips_lookup_method = "in alwaysrelay with recentauthedmailiptracker disabled";
                    Exim::log_write("$sender_host_address in /etc/alwaysrelay trusting sender_address_domain of: $sender_address_domain");
                }
            }

            # no need to check /etc/alwaysrelay as they are automaticlly built into recent_authed_mail_ips_users
        }
    }
    if ($domain) {
        if ($log) {
            my $message_exim_id                   = Exim::expand_string('$message_exim_id');
            my $sender_host_name                  = Exim::expand_string('${if match_ip{$sender_host_address}{+loopback}{localhost}{$sender_host_name}}');
            my $sender_host_port                  = Exim::expand_string('$sender_host_port');
            my $recent_authed_mail_ips_local_user = getdomainowner($domain);
            my $recent_authed_mail_ips_local_uid  = user2uid($recent_authed_mail_ips_local_user);
            Exim::log_write("SMTP connection identification H=$sender_host_name A=$sender_host_address P=$sender_host_port U=$recent_authed_mail_ips_local_user ID=$recent_authed_mail_ips_local_uid S=$sender B=get_recent_authed_mail_ips_entry");
        }
        return ( $sender, $domain, $get_recent_authed_mail_ips_lookup_method );
    }

    return ( '', '', '' );
}

sub _get_possible_users_from_recent_authed_mail_ips_users {
    my $recent_authed_mail_ips_users_result = Exim::expand_string('${lookup{$sender_host_address}lsearch{/etc/recent_authed_mail_ips_users}{$value}}');
    return map {
        s/\/.*$//g if tr/\///;
        tr/+%:/@/;
        $_;
    } split( m/\s*\,\s*/, $recent_authed_mail_ips_users_result );
}

sub maskdir {
    my ($dir) = @_;

    # Try the user first
    my $maskeddir = $dir;
    my ($likely_user) = ( split( m{/}, $dir ) )[2];
    if ( my $likely_homedir = gethomedir($likely_user) ) {
        chop $likely_homedir if substr( $likely_homedir, -1 ) eq '/';
        if ( rindex( $dir, "$likely_homedir/", 0 ) == 0 ) {
            substr( $maskeddir, 0, length($likely_homedir), getusersdomain($likely_user) . ":" );
            return $maskeddir;
        }
    }

    # Next try all users in /etc/passwd
    if ( open my $passwd_fh, '<', "/etc/passwd" ) {
        while ( readline($passwd_fh) ) {
            my ( $homedir, $uid, $user ) = ( split( /:/, $_ ) )[ 0, 2, 5 ];
            next if $uid < 100 || length $homedir < 3;
            chop $homedir if substr( $homedir, -1 ) eq '/';
            if ( rindex( $dir, "$homedir/", 0 ) == 0 ) {
                substr( $maskeddir, 0, length($homedir), getusersdomain($user) . ":" );
                return $maskeddir;
            }
        }
    }
    else {
        warn "open(/etc/passwd): $!";
    }

    return $dir;

}

sub get_message_sender_domain {
    my ( $uid, $gid, $log ) = @_;
    $uid = int( Exim::expand_string('$originator_uid') ) if !defined $uid;
    $gid = int( Exim::expand_string('$originator_gid') ) if !defined $gid;
    return ( ( get_message_sender( $uid, $gid, $log ) )[1] ) || '';
}

# This must match the logic extactly for Cpanel::TailWatch::EximStats ($direction eq '<=')
sub get_message_sender {

    #passes but not for production
    #use strict;

    my ( $uid, $gid, $log ) = @_;
    my ( $authenticated_local_user, $authenticated_id, $recent_authed_mail_ips_text_entry, $domain, $counted_domain, $sender, $is_mailman, $username );

    $sender_lookup_method = '';

    my ( $acl_c_vhost_owner, $acl_c_vhost_owner_url ) = split( m{:}, Exim::expand_string('$acl_c_vhost_owner') || '', 2 );
    my $message_exim_id = Exim::expand_string('$message_exim_id');

    # SMTP AUTH
    if ( $authenticated_id = Exim::expand_string('$authenticated_id') ) {
        $authenticated_id =~ s/[\r\n\f]//g;
        if ( $authenticated_id eq 'nobody' ) {
            if ($acl_c_vhost_owner) {
                $authenticated_id = uid2user($acl_c_vhost_owner);
            }
            $sender_lookup_method = 'uid via acl_c_vhost_owner from authenticated_id: ' . $authenticated_id . ' from ' . $acl_c_vhost_owner_url;
        }
        else {
            $sender_lookup_method = 'authenticated_id: ' . $authenticated_id;
        }
        $sender = $authenticated_id;
        $domain = getdomainfromaddress($authenticated_id);

        # If the sender owns the domain they are sending
        # from we can trust it
        if ( length $sender && $sender !~ tr/\@// ) {
            ( $sender, $domain, $sender_lookup_method ) = resolve_authenticated_sender( $sender, $domain, $sender_lookup_method );
        }

        #Exim::log_write("!DEBUG! get_message_sender() got domain $domain from authenticated_id ($authenticated_id)");
    }

    # FROM A CONNECTION TO LOCALHOST (linux only)
    elsif ( $authenticated_local_user = Exim::expand_string('${if match_ip{$sender_host_address}{+loopback}{$acl_c_authenticated_local_user}{}}') ) {
        my $authenticated_local_uid = user2uid($authenticated_local_user);
        my $sender_host_address     = Exim::expand_string('$sender_host_address');
        my $sender_host_name        = Exim::expand_string('${if match_ip{$sender_host_address}{+loopback}{localhost}{$sender_host_name}}');
        my $sender_host_port        = Exim::expand_string('$sender_host_port');

        $domain               = getusersdomain($authenticated_local_user) || _SENDER_SYSTEM;
        $sender               = $authenticated_local_user;
        $sender_lookup_method = 'acl_c_authenticated_local_user: ' . $authenticated_local_user;
        if ($log) { Exim::log_write("SMTP connection identification H=$sender_host_name A=$sender_host_address P=$sender_host_port M=$message_exim_id U=$authenticated_local_user ID=$authenticated_local_uid S=$sender B=authenticated_local_user"); }    #replay for tailwatchd

        #Exim::log_write("!DEBUG! get_message_sender() got domain $domain from acl_c_authenticated_local_user");
    }

    # RELAY HOSTS
    elsif ( $recent_authed_mail_ips_text_entry = Exim::expand_string('$acl_c_recent_authed_mail_ips_text_entry') ) {

        #FIXME: need to get sender
        ( $sender, $domain ) = split( /\|/, $recent_authed_mail_ips_text_entry );
        my $sender_host_address = Exim::expand_string('$sender_host_address');
        my $sender_host_name    = Exim::expand_string('${if match_ip{$sender_host_address}{+loopback}{localhost}{$sender_host_name}}');
        my $sender_host_port    = Exim::expand_string('$sender_host_port');

        my $recent_authed_mail_ips_local_user = getdomainowner($domain);
        my $recent_authed_mail_ips_local_uid  = user2uid($recent_authed_mail_ips_local_user);

        $sender_lookup_method = 'acl_c_recent_authed_mail_ips_text_entry: ' . $recent_authed_mail_ips_text_entry;
        if ($log) { Exim::log_write("SMTP connection identification H=$sender_host_name A=$sender_host_address P=$sender_host_port M=$message_exim_id U=$recent_authed_mail_ips_local_user ID=$recent_authed_mail_ips_local_uid S=$sender B=recent_authed_mail_ips_domain") }

        #Exim::log_write("!DEBUG! get_message_sender() got domain $domain from acl_c_recent_authed_mail_ips_text_entry");
    }
    elsif ( Exim::expand_string('$received_protocol') eq 'local' ) {
        my $sender_ident = Exim::expand_string('$sender_ident');
        $sender_ident =~ s/[\r\n\f]//g;

        my $used_vhost_owner_lookup = 0;
        if ( $sender_ident eq 'nobody' ) {
            if ($acl_c_vhost_owner) {
                $used_vhost_owner_lookup = 1;
                $sender_ident            = uid2user($acl_c_vhost_owner);
            }
        }

        $sender               = $sender_ident;
        $domain               = getusersdomain($sender_ident) || _SENDER_SYSTEM;
        $sender_lookup_method = 'sender_ident via received_protocol == local: ' . $sender_ident . ( $used_vhost_owner_lookup ? ' : used vhost owner lookup from: ' . $acl_c_vhost_owner_url : '' );

        # If the sender owns the domain they are sending
        # from we can trust it
        if ( length $sender && $sender !~ tr/\@// ) {
            ( $sender, $domain, $sender_lookup_method ) = resolve_authenticated_sender( $sender, $domain, $sender_lookup_method );
        }

        #Exim::log_write("!DEBUG! get_message_sender() got domain $domain from local user ($sender_ident)");
    }
    else {
        $mail_gid ||= int( ( getgrnam('mail') )[2] );

        #Exim::log_write("!DEBUG! mailgid=$mail_gid == gid=$gid (uid=$uid)");
        if ( $gid == $mail_gid ) {
            my ( $recent_authed_mail_ips_sender, $recent_authed_mail_ips_domain, $recent_authed_mail_ips_lookup_method ) = get_recent_authed_mail_ips_entry();
            if ($recent_authed_mail_ips_domain) {
                $sender = $recent_authed_mail_ips_sender;
                $sender =~ s/[\r\n\f]//g;
                $domain               = $recent_authed_mail_ips_domain;
                $sender_lookup_method = 'mailgid via get_recent_authed_mail_ips_entry: ' . $sender . "/$recent_authed_mail_ips_lookup_method";

                #Exim::log_write("!DEBUG! get_message_sender() got domain $domain from get_recent_authed_mail_ips_entry() or sender_address_domain");
            }
            $primary_hostname ||= Exim::expand_string('$primary_hostname');
            if ( $domain && $domain eq $primary_hostname ) {
                $username             = Exim::expand_string('$sender_address_local_part');
                $sender               = $username;
                $domain               = getusersdomain($username) || _SENDER_SYSTEM;
                $sender_lookup_method = 'mailgid via primary_hostname' . "/$recent_authed_mail_ips_lookup_method";
            }
            if ( !$domain ) {

                # If we cannot find the sender and it is not _SENDER_SYSTEM it is a redirected/forwarded message
                my $parent_domain     = Exim::expand_string('$parent_domain');
                my $parent_local_part = Exim::expand_string('$parent_local_part');
                my $local_part        = Exim::expand_string('$local_part');
                my $delivery_domain   = Exim::expand_string('$domain');

                $parent_domain     =~ s/[^\w\.\-\/]//g;
                $parent_local_part =~ s/[^\w\.\-\/]//g;
                $local_part        =~ s/[^\w\.\-\/]//g;
                $delivery_domain   =~ s/[^\w\.\-\/]//g;

                # If we have a parent_domain its probably a redirect
                if ( $parent_domain && ( $parent_domain ne $delivery_domain || $parent_local_part ne $local_part ) ) {

                    # If the parent_domain is the primary_hostname its a localuser redirect
                    if ( my $local_user = $parent_domain eq $primary_hostname ? $parent_local_part : getdomainowner($parent_domain) ) {
                        my $local_uid         = user2uid($local_user);
                        my $redirected_domain = $parent_domain eq $primary_hostname ? getusersdomain($parent_local_part) : $parent_domain;
                        if ($log) { Exim::log_write("SMTP connection identification D=$redirected_domain O=$parent_local_part\@$parent_domain E=$local_part\@$delivery_domain M=$message_exim_id U=$local_user ID=$local_uid B=redirect_resolver") }
                        ;    #replay for tailwatchd

                        $domain               = $redirected_domain;
                        $sender               = $parent_domain eq $primary_hostname ? $local_user : "$parent_local_part\@$parent_domain";
                        $sender_lookup_method = "redirect/forwarder owner $parent_local_part\@$parent_domain -> $local_part\@$delivery_domain";
                    }
                }
            }
            if ( !$domain ) {
                $sender_lookup_method = 'mailgid no entry from get_recent_authed_mail_ips_entry';

                #Exim::log_write("!DEBUG! get_message_sender() failed to get the domain.  However the sender domain claims to be $sender_address_domain");
            }
        }
        else {

            # FROM A SHELL OR CGI
            $username = uid2user($uid);

            if ($username) {
                if ( $username eq 'nobody' ) {
                    if ($acl_c_vhost_owner) {
                        $username = uid2user($acl_c_vhost_owner);
                    }
                    $sender_lookup_method = 'uid via acl_c_vhost_owner from shell cgi: ' . $username . ' from: ' . $acl_c_vhost_owner_url;
                }
                else {
                    $sender_lookup_method = 'uid via shell cgi: ' . $username;
                }
                $domain = getusersdomain($username) || _SENDER_SYSTEM;
                $sender = $username;
            }

            # If the sender owns the domain they are sending
            # from we can trust it
            if ( length $sender && $sender !~ tr/\@// ) {
                ( $sender, $domain, $sender_lookup_method ) = resolve_authenticated_sender( $sender, $domain, $sender_lookup_method );
            }

            #Exim::log_write("!DEBUG! get_message_sender() got domain $domain from UID");
        }
    }

    if ($domain) {
        $domain =~ s/[^\w\.\-\/]//g;
        $domain         = lc $domain;
        $counted_domain = $domain;
        if ($sender) {
            $sender =~ tr/+%:/@/;
            $sender =~ s/[^\w\.\-\/\@]//g;
        }
    }
    $sender_lookup = $sender;

    if ( $log && $message_exim_id ) {
        $username ||= ( ( $sender =~ tr{@}{} ) ? getdomainowner( ( split( m{@}, $sender ) )[1] ) : $sender );

        if ($username) {

            # Will log as 2017-05-26 13:42:22 1dEKBq-0007HB-6R Sender identification S=nick
            Exim::log_write("Sender identification U=$username D=$domain S=$sender");    #replay for tailwatchd
        }
    }

    return ( $sender, $domain, $counted_domain, $is_mailman );
}

sub uid2user {
    my $uid = shift;
    return exists $uid_cache{$uid} ? $uid_cache{$uid} : ( $uid_cache{$uid} = ( getpwuid($uid) )[0] );
}

sub user2uid {
    my $user = shift;
    return exists $user_cache{$user} ? $user_cache{$user} : ( $user_cache{$user} = getuid($user) );
}

sub get_sender_from_uid {
    my $uid  = int( Exim::expand_string('$originator_uid') );
    my $user = uid2user($uid);
    return getdomainfromaddress($user);
}

sub resolve_authenticated_sender {
    my ( $sender, $domain, $sender_lookup_method ) = @_;

    my $sender_address        = Exim::expand_string('$sender_address');
    my $sender_address_domain = Exim::expand_string('$sender_address_domain');

    # We only want to use the sender in the from header if they have already
    # authenticated with at least the permissions of the account
    my ( $from_h_sender, $from_h_localpart, $from_h_domain ) = _get_from_h_sender();
    $primary_hostname ||= Exim::expand_string('$primary_hostname');

    # The user expects to be able to just set the From: headers
    # we try to accomodate that first if they have permissions on the account
    if ( $from_h_domain eq $primary_hostname ) {
        $sender_lookup_method .= "/primary_hostname/system user";
    }
    elsif ( $sender eq getdomainowner($from_h_domain) ) {
        $sender = $from_h_localpart . '@' . $from_h_domain;
        $domain = $from_h_domain;
        $sender_lookup_method .= "/from_h";
    }

    # otherwise we fallback to the sender_address_domain
    elsif ( $sender eq getdomainowner($sender_address_domain) ) {
        $sender = $sender_address;
        $domain = $sender_address_domain;
        $sender_lookup_method .= "/sender_address_domain";
    }
    else {

        # finally we accept that we don't know who sent it besdies the
        # authenticated user
        $sender_lookup_method .= "/only user confirmed/virtual account not confirmed";
    }

    return ( $sender, $domain, $sender_lookup_method );
}

# Obtain the from header from the message
# We fallback to the envelope sender if there
# is no from header set (ie sendmail -bt or missing From header)
sub _get_from_h_sender {
    my $from_h_domain     = Exim::expand_string('${domain:$h_from:}');
    my $from_h_local_part = Exim::expand_string('${local_part:$h_from:}');

    if ( length $from_h_local_part ) {
        if ( length $from_h_domain ) {
            return ( $from_h_local_part . '@' . $from_h_domain, $from_h_local_part, $from_h_domain );
        }
        else {
            $primary_hostname ||= Exim::expand_string('$primary_hostname');
            return ( $from_h_local_part . '@' . $primary_hostname, $from_h_local_part, $primary_hostname );
        }
    }
    else {
        # Handle fallback to sender_address when message is missing a from header
        my $sender_address_domain     = Exim::expand_string('$sender_address_domain');
        my $sender_address_local_part = Exim::expand_string('$sender_address_local_part');
        return ( $sender_address_local_part . '@' . $sender_address_domain, $sender_address_local_part, $sender_address_domain );
    }
}

https://t.me/RX1948 - 2025