|
Server : LiteSpeed System : Linux terra.hostitbro.com 5.14.0-611.54.3.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Thu May 7 16:31:24 EDT 2026 x86_64 User : outerorb ( 1091) PHP Version : 8.1.34 Disable Function : mail Directory : /home2/outerorb/www/ | |
|
Path: /home2/outerorb/www/mailer.php
Size: 10.49 KB
Permissions: 0666
<?php
/**
* Outer Orbit Technologies – Form Mail Handler
* Uses PHPMailer + hostitbro cPanel SMTP for reliable delivery.
*/
// Only accept POST requests
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('Method Not Allowed');
}
require_once __DIR__ . '/vendor/autoload.php';
include __DIR__ . '/inc/config.php';
include __DIR__ . '/inc/smtp-config.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
// ── Session must be active (config.php starts it; guard for edge-cases) ──────
if (session_status() === PHP_SESSION_NONE) {
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
'httponly' => true,
'samesite' => 'Strict',
]);
session_start();
}
// ── CSRF validation ───────────────────────────────────────────────────────────
$submitted_token = $_POST['csrf_token'] ?? '';
if (empty($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $submitted_token)) {
http_response_code(403);
exit('Invalid or missing security token. Please refresh the page and try again.');
}
// ── Honeypot: bots fill the hidden "fax" field; humans never see it ───────────
if (!empty($_POST['fax'])) {
// Silently return success to confuse scrapers/bots
http_response_code(200);
echo 'Thank you! Your enquiry has been received. We will get back to you within 24 hours.';
exit;
}
// ── Rate limiting (session-based: max 5 submissions per 10 minutes) ───────────
$rl_key = 'mailer_rl';
$rl_limit = 5;
$rl_window = 600; // seconds
$now = time();
if (empty($_SESSION[$rl_key])) {
$_SESSION[$rl_key] = ['count' => 0, 'window_start' => $now];
}
// Reset window if expired
if (($now - $_SESSION[$rl_key]['window_start']) >= $rl_window) {
$_SESSION[$rl_key] = ['count' => 0, 'window_start' => $now];
}
if ($_SESSION[$rl_key]['count'] >= $rl_limit) {
http_response_code(429);
exit('Too many submissions. Please wait a few minutes before trying again.');
}
$_SESSION[$rl_key]['count']++;
// Helper: sanitize a plain-text field
function sanitize_text(string $value): string {
return htmlspecialchars(strip_tags(trim($value)), ENT_QUOTES, 'UTF-8');
}
// Helper: validate email
function is_valid_email(string $email): bool {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
// Helper: remove newlines to prevent header injection
function sanitize_header(string $value): string {
return str_replace(["\r", "\n", "%0a", "%0d"], '', sanitize_text($value));
}
// Collect, sanitize, and length-cap inputs
$name = mb_substr(sanitize_text($_POST['name'] ?? ''), 0, 100);
$email = mb_substr(sanitize_header($_POST['email'] ?? ''), 0, 254);
$phone = mb_substr(sanitize_text($_POST['phone'] ?? ''), 0, 30);
$service = mb_substr(sanitize_text($_POST['service'] ?? ''), 0, 100);
$message = mb_substr(sanitize_text($_POST['message'] ?? ''), 0, 2000);
// Validation
$errors = [];
if (empty($name)) $errors[] = 'Name is required.';
if (empty($email) || !is_valid_email($email)) $errors[] = 'A valid email address is required.';
if (empty($message) && empty($phone)) $errors[] = 'Please provide a message or phone number.';
if (!empty($errors)) {
http_response_code(400);
echo implode(' ', $errors);
exit;
}
// Build plain-text body
$body = "New enquiry received via the website.\n\n";
$body .= "Name: {$name}\n";
$body .= "Email: {$email}\n";
if ($phone) $body .= "Phone: {$phone}\n";
if ($service) $body .= "Service: {$service}\n";
if ($message) $body .= "\nMessage:\n{$message}\n";
// Build HTML body
$htmlBody = "<h3>New Enquiry – Outer Orbit Technologies</h3>";
$htmlBody .= "<table cellpadding='6' cellspacing='0' style='font-family:sans-serif;font-size:14px;'>";
$htmlBody .= "<tr><td><strong>Name</strong></td><td>{$name}</td></tr>";
$htmlBody .= "<tr><td><strong>Email</strong></td><td><a href='mailto:{$email}'>{$email}</a></td></tr>";
if ($phone) $htmlBody .= "<tr><td><strong>Phone</strong></td><td><a href='tel:{$phone}'>{$phone}</a></td></tr>";
if ($service) $htmlBody .= "<tr><td><strong>Service</strong></td><td>{$service}</td></tr>";
if ($message) $htmlBody .= "<tr><td valign='top'><strong>Message</strong></td><td>" . nl2br($message) . "</td></tr>";
$htmlBody .= "</table>";
// Send via PHPMailer + MS365 SMTP
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = SMTP_HOST;
$mail->SMTPAuth = true;
$mail->Username = SMTP_USERNAME;
$mail->Password = SMTP_PASSWORD;
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; // port 465 SSL
$mail->Port = SMTP_PORT;
$mail->SMTPOptions = [
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
'allow_self_signed' => false,
],
];
$mail->setFrom(SMTP_FROM_EMAIL, SMTP_FROM_NAME);
$mail->addAddress(SMTP_TO_EMAIL);
$mail->addReplyTo($email, $name);
$mail->Subject = 'New Enquiry from ' . $name . ($service ? ' – ' . $service : '');
$mail->Body = $htmlBody;
$mail->AltBody = $body;
$mail->isHTML(true);
$mail->CharSet = 'UTF-8';
$mail->send();
// --- Acknowledgement email to the visitor ---
$ack = new PHPMailer(true);
$ack->isSMTP();
$ack->Host = SMTP_HOST;
$ack->SMTPAuth = true;
$ack->Username = SMTP_USERNAME;
$ack->Password = SMTP_PASSWORD;
$ack->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$ack->Port = SMTP_PORT;
$ack->SMTPOptions = [
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
'allow_self_signed' => false,
],
];
$ack->setFrom(SMTP_FROM_EMAIL, SMTP_FROM_NAME);
$ack->addAddress($email, $name);
$ack->Subject = 'We received your enquiry – Outer Orbit Technologies';
$ack->isHTML(true);
$ack->CharSet = 'UTF-8';
$ackHtml = "<!DOCTYPE html><html><head><meta charset='UTF-8'></head><body style='margin:0;padding:0;background:#f4f6fb;font-family:\"DM Sans\",Arial,sans-serif;'>";
$ackHtml .= "<table width='100%' cellpadding='0' cellspacing='0' style='background:#f4f6fb;padding:40px 0;'><tr><td align='center'>";
$ackHtml .= "<table width='600' cellpadding='0' cellspacing='0' style='background:#ffffff;border-radius:10px;overflow:hidden;box-shadow:0 2px 12px rgba(0,0,0,0.08);'>";
// Header
$ackHtml .= "<tr><td style='background:#073367;padding:32px 40px;text-align:center;'>";
$ackHtml .= "<h1 style='margin:0;color:#ffffff;font-size:22px;font-weight:700;letter-spacing:0.5px;'>Outer Orbit Technologies</h1>";
$ackHtml .= "<p style='margin:6px 0 0;color:rgba(255,255,255,0.75);font-size:13px;'>Transforming Business Through Innovation</p>";
$ackHtml .= "</td></tr>";
// Body
$ackHtml .= "<tr><td style='padding:40px;'>";
$ackHtml .= "<p style='margin:0 0 16px;font-size:16px;color:#0c1f3d;'>Dear <strong>{$name}</strong>,</p>";
$ackHtml .= "<p style='margin:0 0 16px;font-size:15px;color:#44546a;line-height:1.7;'>Thank you for reaching out to us. We have received your enquiry and our team will get back to you within <strong>24 business hours</strong>.</p>";
// Summary box
$ackHtml .= "<table width='100%' cellpadding='0' cellspacing='0' style='background:#f0f5ff;border-radius:8px;padding:20px;margin:24px 0;'>";
$ackHtml .= "<tr><td style='padding:8px 20px;font-size:14px;color:#44546a;'><strong style='color:#073367;'>Your enquiry summary</strong></td></tr>";
if ($service) $ackHtml .= "<tr><td style='padding:4px 20px;font-size:14px;color:#44546a;'><strong>Service:</strong> {$service}</td></tr>";
if ($phone) $ackHtml .= "<tr><td style='padding:4px 20px;font-size:14px;color:#44546a;'><strong>Phone:</strong> {$phone}</td></tr>";
if ($message) $ackHtml .= "<tr><td style='padding:4px 20px;font-size:14px;color:#44546a;'><strong>Message:</strong> " . nl2br($message) . "</td></tr>";
$ackHtml .= "</table>";
$ackHtml .= "<p style='margin:0 0 16px;font-size:15px;color:#44546a;line-height:1.7;'>In the meantime, feel free to explore our services or reach us directly:</p>";
$ackHtml .= "<p style='margin:0;font-size:14px;color:#44546a;'>📞 <a href='tel:{$company_phone}' style='color:#073367;text-decoration:none;'>{$company_phone}</a> | ✉ <a href='mailto:{$company_email}' style='color:#073367;text-decoration:none;'>{$company_email}</a></p>";
$ackHtml .= "</td></tr>";
// Footer
$ackHtml .= "<tr><td style='background:#f0f5ff;padding:20px 40px;text-align:center;border-top:1px solid #dde6f5;'>";
$ackHtml .= "<p style='margin:0;font-size:12px;color:#8a9bb0;'>This is an automated acknowledgement. Please do not reply to this email.</p>";
$ackHtml .= "<p style='margin:6px 0 0;font-size:12px;color:#8a9bb0;'>© " . date('Y') . " Outer Orbit Technologies. All rights reserved.</p>";
$ackHtml .= "</td></tr></table></td></tr></table></body></html>";
$ackPlain = "Dear {$name},\n\n";
$ackPlain .= "Thank you for reaching out to Outer Orbit Technologies.\n";
$ackPlain .= "We have received your enquiry and will get back to you within 24 business hours.\n\n";
if ($service) $ackPlain .= "Service: {$service}\n";
if ($phone) $ackPlain .= "Phone: {$phone}\n";
if ($message) $ackPlain .= "Message: {$message}\n";
$ackPlain .= "\nFor urgent queries:\nPhone: {$company_phone}\nEmail: {$company_email}\n\n";
$ackPlain .= "-- Outer Orbit Technologies";
$ack->Body = $ackHtml;
$ack->AltBody = $ackPlain;
// Best-effort: don't fail the whole request if ack fails
try { $ack->send(); } catch (Exception $e) { error_log('Ack mailer error: ' . $ack->ErrorInfo); }
http_response_code(200);
echo 'Thank you! Your enquiry has been received. We will get back to you within 24 hours.';
} catch (Exception $e) {
http_response_code(500);
// Log the actual error server-side, show friendly message to user
error_log('Mailer error: ' . $mail->ErrorInfo);
echo 'Sorry, there was a problem sending your message. Please call us directly on ' . $company_phone . '.';
}