Pleskin postfix ei toimittanut postia oikein. Nyt send.php lähettää suoraan MX-palvelimelle port 25 kautta. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
153 lines
5.1 KiB
PHP
153 lines
5.1 KiB
PHP
<?php
|
||
header('Content-Type: application/json; charset=utf-8');
|
||
|
||
// Vain POST-pyynnöt
|
||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||
http_response_code(405);
|
||
echo json_encode(['success' => false, 'error' => 'Virheellinen pyyntö']);
|
||
exit;
|
||
}
|
||
|
||
// Rate limiting (yksinkertainen, IP-pohjainen)
|
||
$rateLimitDir = __DIR__ . '/data';
|
||
if (!is_dir($rateLimitDir)) {
|
||
mkdir($rateLimitDir, 0755, true);
|
||
}
|
||
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
|
||
$rateLimitFile = $rateLimitDir . '/ratelimit_' . md5($ip) . '.txt';
|
||
$now = time();
|
||
if (file_exists($rateLimitFile)) {
|
||
$lastSent = (int) file_get_contents($rateLimitFile);
|
||
if ($now - $lastSent < 60) {
|
||
http_response_code(429);
|
||
echo json_encode(['success' => false, 'error' => 'Odota hetki ennen uutta lähetystä']);
|
||
exit;
|
||
}
|
||
}
|
||
|
||
// Honeypot-kenttä (botisuoja)
|
||
if (!empty($_POST['website'])) {
|
||
http_response_code(200);
|
||
echo json_encode(['success' => true]);
|
||
exit;
|
||
}
|
||
|
||
// Kentät
|
||
$company = trim($_POST['company'] ?? '');
|
||
$email = trim($_POST['email'] ?? '');
|
||
$address = trim($_POST['address'] ?? '');
|
||
$city = trim($_POST['city'] ?? '');
|
||
$message = trim($_POST['message'] ?? '');
|
||
|
||
// Validointi
|
||
if (empty($company) || empty($email) || empty($address) || empty($city)) {
|
||
http_response_code(400);
|
||
echo json_encode(['success' => false, 'error' => 'Täytä kaikki pakolliset kentät']);
|
||
exit;
|
||
}
|
||
|
||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||
http_response_code(400);
|
||
echo json_encode(['success' => false, 'error' => 'Tarkista sähköpostiosoite']);
|
||
exit;
|
||
}
|
||
|
||
// Sanitointi
|
||
$company = htmlspecialchars($company, ENT_QUOTES, 'UTF-8');
|
||
$email = htmlspecialchars($email, ENT_QUOTES, 'UTF-8');
|
||
$address = htmlspecialchars($address, ENT_QUOTES, 'UTF-8');
|
||
$city = htmlspecialchars($city, ENT_QUOTES, 'UTF-8');
|
||
$message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
|
||
|
||
// Sähköpostin sisältö
|
||
$to = 'asiakaspalvelu@cuitunet.fi';
|
||
$subject = "Saatavuuskysely: $company – $address, $city";
|
||
|
||
$body = "Uusi saatavuuskysely cuitunet.fi-sivustolta\n";
|
||
$body .= "=========================================\n\n";
|
||
$body .= "Yritys: $company\n";
|
||
$body .= "Sähköposti: $email\n";
|
||
$body .= "Osoite: $address\n";
|
||
$body .= "Kaupunki: $city\n";
|
||
if (!empty($message)) {
|
||
$body .= "Lisätiedot: $message\n";
|
||
}
|
||
$body .= "\n-----------------------------------------\n";
|
||
$body .= "Lähetetty: " . date('d.m.Y H:i') . "\n";
|
||
$body .= "IP: $ip\n";
|
||
|
||
$headers = "From: sivusto@cuitunet.fi\r\n";
|
||
$headers .= "Reply-To: $email\r\n";
|
||
$headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
|
||
$headers .= "X-Mailer: Cuitunet-Web\r\n";
|
||
|
||
// Lähetys suoraan SMTP:llä MX-palvelimelle (ohittaa Pleskin postfixin)
|
||
function sendViaSMTP(string $from, string $to, string $subject, string $body, string $replyTo): string {
|
||
$mx = 'mx.mail2.fi';
|
||
$port = 25;
|
||
$hostname = 'cuitunet.fi';
|
||
|
||
$sock = @fsockopen($mx, $port, $errno, $errstr, 10);
|
||
if (!$sock) return "Yhteys MX-palvelimeen epäonnistui: $errstr ($errno)";
|
||
|
||
$resp = fgets($sock, 512);
|
||
if (substr($resp, 0, 3) !== '220') { fclose($sock); return "MX hylkäsi yhteyden: $resp"; }
|
||
|
||
$cmds = [
|
||
"EHLO $hostname",
|
||
"MAIL FROM:<$from>",
|
||
"RCPT TO:<$to>",
|
||
"DATA",
|
||
];
|
||
foreach ($cmds as $cmd) {
|
||
fwrite($sock, "$cmd\r\n");
|
||
$resp = fgets($sock, 512);
|
||
$code = substr($resp, 0, 3);
|
||
// EHLO voi palauttaa monta riviä
|
||
if ($cmd === "EHLO $hostname") {
|
||
while (substr($resp, 3, 1) === '-') { $resp = fgets($sock, 512); }
|
||
}
|
||
if ($cmd === 'DATA' && $code !== '354') { fwrite($sock, "QUIT\r\n"); fclose($sock); return "DATA hylätty: $resp"; }
|
||
elseif ($cmd !== 'DATA' && $code[0] !== '2') { fwrite($sock, "QUIT\r\n"); fclose($sock); return "SMTP virhe ($cmd): $resp"; }
|
||
}
|
||
|
||
// Viesti
|
||
$msg = "From: $from\r\n";
|
||
$msg .= "To: $to\r\n";
|
||
$msg .= "Reply-To: $replyTo\r\n";
|
||
$msg .= "Subject: $subject\r\n";
|
||
$msg .= "Content-Type: text/plain; charset=UTF-8\r\n";
|
||
$msg .= "X-Mailer: Cuitunet-Web\r\n";
|
||
$msg .= "Date: " . date('r') . "\r\n";
|
||
$msg .= "Message-ID: <" . uniqid('cuitunet-') . "@$hostname>\r\n";
|
||
$msg .= "\r\n";
|
||
$msg .= str_replace("\n.", "\n..", $body); // Dot-stuffing
|
||
$msg .= "\r\n.\r\n";
|
||
|
||
fwrite($sock, $msg);
|
||
$resp = fgets($sock, 512);
|
||
fwrite($sock, "QUIT\r\n");
|
||
fclose($sock);
|
||
|
||
return (substr($resp, 0, 3) === '250') ? '' : "Lähetys epäonnistui: $resp";
|
||
}
|
||
|
||
$fromAddr = 'sivusto@cuitunet.fi';
|
||
$smtpError = sendViaSMTP($fromAddr, $to, $subject, $body, $email);
|
||
|
||
if (empty($smtpError)) {
|
||
// Tallenna rate limit
|
||
file_put_contents($rateLimitFile, $now);
|
||
|
||
// Tallenna kopio kyselyistä
|
||
$logFile = $rateLimitDir . '/kyselyt.log';
|
||
$logEntry = date('Y-m-d H:i:s') . " | $company | $email | $address, $city | $message\n";
|
||
file_put_contents($logFile, $logEntry, FILE_APPEND | LOCK_EX);
|
||
|
||
echo json_encode(['success' => true]);
|
||
} else {
|
||
error_log("cuitunet.fi send.php SMTP error: $smtpError");
|
||
http_response_code(500);
|
||
echo json_encode(['success' => false, 'error' => 'Viestin lähetys epäonnistui. Yritä myöhemmin uudelleen.']);
|
||
}
|