'ÄNDRA_DETTA_LÖSENORD', // Cron-nyckel (hemlig URL-parameter för automatisk sändning) 'cron_key' => 'ÄNDRA_DENNA_NYCKEL_OCKSÅ', // SMTP-inställningar (Strato) 'smtp_host' => 'smtp.strato.com', 'smtp_port' => 465, 'smtp_secure' => 'ssl', 'smtp_user' => 'din@oftaicd.se', // Din Strato-mejladress 'smtp_pass' => 'DITT_STRATO_LÖSENORD', // Avsändare 'from_email' => 'din@oftaicd.se', 'from_name' => 'Ditt Namn - OFTAICD', // Sändningsinställningar 'emails_per_run' => 1, // Antal mejl per cron-körning 'min_interval_sec' => 1800, // Minsta tid mellan mejl (1800 = 30 min) // Filsökvägar 'data_dir' => __DIR__ . '/data', ]; // ==================== INITIERA ==================== session_start(); error_reporting(E_ALL); ini_set('display_errors', 0); // Skapa data-katalog if (!is_dir($CONFIG['data_dir'])) { mkdir($CONFIG['data_dir'], 0755, true); } $queue_file = $CONFIG['data_dir'] . '/queue.json'; $sent_file = $CONFIG['data_dir'] . '/sent.json'; $template_file = $CONFIG['data_dir'] . '/template.json'; $log_file = $CONFIG['data_dir'] . '/log.txt'; // Initiera filer om de inte finns if (!file_exists($queue_file)) file_put_contents($queue_file, json_encode([])); if (!file_exists($sent_file)) file_put_contents($sent_file, json_encode([])); if (!file_exists($template_file)) file_put_contents($template_file, json_encode([ 'subject' => '', 'body' => '', ])); // ==================== FUNKTIONER ==================== function loadJson($file) { $content = file_get_contents($file); return json_decode($content, true) ?: []; } function saveJson($file, $data) { file_put_contents($file, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); } function addLog($file, $message) { $timestamp = date('Y-m-d H:i:s'); file_put_contents($file, "[$timestamp] $message\n", FILE_APPEND); } function sendEmailViaSMTP($config, $to, $subject, $body) { // Använder PHP:s inbyggda mail() eller fsockopen för SMTP // För bästa resultat, använd PHPMailer - men detta fungerar med Strato $headers = []; $headers[] = 'MIME-Version: 1.0'; $headers[] = 'Content-Type: text/plain; charset=UTF-8'; $headers[] = 'From: ' . $config['from_name'] . ' <' . $config['from_email'] . '>'; $headers[] = 'Reply-To: ' . $config['from_email']; $headers[] = 'X-Mailer: PHP/' . phpversion(); $headerStr = implode("\r\n", $headers); // Försök med PHP mail() först (fungerar på Strato) $result = @mail($to, '=?UTF-8?B?' . base64_encode($subject) . '?=', $body, $headerStr); if (!$result) { // Fallback: Direkt SMTP via fsockopen return sendViaSMTPSocket($config, $to, $subject, $body); } return $result; } function sendViaSMTPSocket($config, $to, $subject, $body) { $host = $config['smtp_secure'] === 'ssl' ? 'ssl://' . $config['smtp_host'] : $config['smtp_host']; $port = $config['smtp_port']; $socket = @fsockopen($host, $port, $errno, $errstr, 30); if (!$socket) return false; $response = fgets($socket, 515); // EHLO fputs($socket, "EHLO " . $config['smtp_host'] . "\r\n"); $response = ''; while ($line = fgets($socket, 515)) { $response .= $line; if (substr($line, 3, 1) == ' ') break; } // AUTH LOGIN fputs($socket, "AUTH LOGIN\r\n"); fgets($socket, 515); fputs($socket, base64_encode($config['smtp_user']) . "\r\n"); fgets($socket, 515); fputs($socket, base64_encode($config['smtp_pass']) . "\r\n"); $auth_response = fgets($socket, 515); if (substr($auth_response, 0, 3) != '235') { fclose($socket); return false; } // MAIL FROM fputs($socket, "MAIL FROM:<" . $config['from_email'] . ">\r\n"); fgets($socket, 515); // RCPT TO fputs($socket, "RCPT TO:<$to>\r\n"); fgets($socket, 515); // DATA fputs($socket, "DATA\r\n"); fgets($socket, 515); // Mejlinnehåll $message = "From: " . $config['from_name'] . " <" . $config['from_email'] . ">\r\n"; $message .= "To: <$to>\r\n"; $message .= "Subject: =?UTF-8?B?" . base64_encode($subject) . "?=\r\n"; $message .= "MIME-Version: 1.0\r\n"; $message .= "Content-Type: text/plain; charset=UTF-8\r\n"; $message .= "\r\n"; $message .= $body . "\r\n"; $message .= ".\r\n"; fputs($socket, $message); $data_response = fgets($socket, 515); // QUIT fputs($socket, "QUIT\r\n"); fclose($socket); return (substr($data_response, 0, 3) == '250'); } function isLoggedIn() { return isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === true; } // ==================== ROUTING ==================== $action = $_GET['action'] ?? $_POST['action'] ?? 'login'; // CRON-endpoint (ingen inloggning krävs, bara rätt nyckel) if ($action === 'cron') { header('Content-Type: application/json'); if (($_GET['key'] ?? '') !== $CONFIG['cron_key']) { echo json_encode(['error' => 'Ogiltig nyckel']); exit; } $queue = loadJson($queue_file); $sent = loadJson($sent_file); $template = loadJson($template_file); if (empty($queue)) { echo json_encode(['status' => 'Kön är tom', 'sent_total' => count($sent)]); exit; } if (empty($template['subject']) || empty($template['body'])) { echo json_encode(['error' => 'Ingen mejlmall konfigurerad']); exit; } // Kolla senaste sändning $last_sent_time = 0; if (!empty($sent)) { $last = end($sent); $last_sent_time = $last['timestamp'] ?? 0; } if ((time() - $last_sent_time) < $CONFIG['min_interval_sec']) { $wait = $CONFIG['min_interval_sec'] - (time() - $last_sent_time); echo json_encode(['status' => "Väntar $wait sekunder till nästa mejl"]); exit; } // Skicka nästa mejl i kön $email = array_shift($queue); $success = sendEmailViaSMTP($CONFIG, $email, $template['subject'], $template['body']); if ($success) { $sent[] = [ 'email' => $email, 'timestamp' => time(), 'date' => date('Y-m-d H:i:s'), 'status' => 'skickat' ]; saveJson($queue_file, $queue); saveJson($sent_file, $sent); addLog($log_file, "SKICKAT: $email"); echo json_encode([ 'status' => 'Skickat', 'to' => $email, 'remaining' => count($queue), 'sent_total' => count($sent) ]); } else { // Lägg tillbaka i kön (sist) $queue[] = $email; saveJson($queue_file, $queue); addLog($log_file, "MISSLYCKAT: $email"); echo json_encode([ 'status' => 'Misslyckades', 'to' => $email, 'remaining' => count($queue) ]); } exit; } // Inloggning if ($action === 'login' && $_SERVER['REQUEST_METHOD'] === 'POST') { if (($_POST['password'] ?? '') === $CONFIG['admin_password']) { $_SESSION['logged_in'] = true; header('Location: ?action=dashboard'); exit; } } // Logga ut if ($action === 'logout') { session_destroy(); header('Location: ?'); exit; } // Skyddade sidor if (!isLoggedIn() && !in_array($action, ['login', 'cron'])) { $action = 'login'; } // Hantera POST-actions if ($_SERVER['REQUEST_METHOD'] === 'POST' && isLoggedIn()) { if ($action === 'add_emails') { $queue = loadJson($queue_file); $sent = loadJson($sent_file); $sent_emails = array_column($sent, 'email'); $new_emails = preg_split('/[\n,;]+/', $_POST['emails'] ?? ''); $added = 0; foreach ($new_emails as $email) { $email = strtolower(trim($email)); if (filter_var($email, FILTER_VALIDATE_EMAIL) && !in_array($email, $queue) && !in_array($email, $sent_emails)) { $queue[] = $email; $added++; } } saveJson($queue_file, $queue); $_SESSION['message'] = "$added nya mejladresser tillagda i kön."; header('Location: ?action=dashboard'); exit; } if ($action === 'save_template') { $template = [ 'subject' => $_POST['subject'] ?? '', 'body' => $_POST['body'] ?? '', ]; saveJson($template_file, $template); $_SESSION['message'] = "Mejlmall sparad."; header('Location: ?action=dashboard'); exit; } if ($action === 'clear_queue') { saveJson($queue_file, []); $_SESSION['message'] = "Kön rensad."; header('Location: ?action=dashboard'); exit; } if ($action === 'clear_sent') { saveJson($sent_file, []); $_SESSION['message'] = "Skickat-loggen rensad."; header('Location: ?action=dashboard'); exit; } if ($action === 'send_test') { $template = loadJson($template_file); $test_email = trim($_POST['test_email'] ?? ''); if (filter_var($test_email, FILTER_VALIDATE_EMAIL) && !empty($template['subject'])) { $result = sendEmailViaSMTP($CONFIG, $test_email, $template['subject'], $template['body']); $_SESSION['message'] = $result ? "Testmejl skickat till $test_email!" : "Misslyckades att skicka testmejl."; } header('Location: ?action=dashboard'); exit; } if ($action === 'send_one_now') { $queue = loadJson($queue_file); $sent = loadJson($sent_file); $template = loadJson($template_file); if (!empty($queue) && !empty($template['subject'])) { $email = array_shift($queue); $result = sendEmailViaSMTP($CONFIG, $email, $template['subject'], $template['body']); if ($result) { $sent[] = ['email' => $email, 'timestamp' => time(), 'date' => date('Y-m-d H:i:s'), 'status' => 'skickat']; saveJson($queue_file, $queue); saveJson($sent_file, $sent); addLog($log_file, "MANUELLT SKICKAT: $email"); $_SESSION['message'] = "Skickat till $email!"; } else { $queue[] = $email; saveJson($queue_file, $queue); $_SESSION['message'] = "Misslyckades att skicka till $email."; } } header('Location: ?action=dashboard'); exit; } } // Hämta data för dashboard $queue = loadJson($queue_file); $sent = loadJson($sent_file); $template = loadJson($template_file); $message = $_SESSION['message'] ?? ''; unset($_SESSION['message']); ?> OFTAICD E-postutskick

OFTAICD E-postutskick

Logga ut
I kön
Skickade
Totalt
0): ?>
Nästa mejl: — Uppskattad tid kvar: timmar ( dagar)

Mejlmall


Lägg till mejladresser

Redan skickade och dubbletter filtreras bort automatiskt.

0 && !empty($template['subject'])): ?>

Manuell sändning

Skicka nästa mejl manuellt (utan att vänta på cron):

Kö ( mejl)

0): ?>
$email): ?>
50): ?>
... och till

Kön är tom. Lägg till mejladresser ovan.

Skickade ()

0): ?>

Inga mejl skickade ännu.

Automatisk sändning (Cron)

Ställ in ett cron-jobb i Stratos kundpanel som anropar denna URL var 30:e minut:

Eller använd knappen "Skicka 1 mejl nu" ovan för manuell sändning.