'Ä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
0): ?>
0 && !empty($template['subject'])): ?>
OFTAICD E-postutskick
OFTAICD E-postutskick
Logga ut= htmlspecialchars($message) ?>
= count($queue) ?>
I kön
= count($sent) ?>
Skickade
= count($queue) + count($sent) ?>
Totalt
Nästa mejl: = htmlspecialchars($queue[0]) ?>
— Uppskattad tid kvar: = round(count($queue) * 30 / 60) ?> timmar (= round(count($queue) * 30 / 60 / 24, 1) ?> dagar)
Mejlmall
Lägg till mejladresser
Redan skickade och dubbletter filtreras bort automatiskt.
Manuell sändning
Skicka nästa mejl manuellt (utan att vänta på cron):
Kö (= count($queue) ?> mejl)
0): ?>
$email): ?>
= $i + 1 ?>
= htmlspecialchars($email) ?>
50): ?>
... och = count($queue) - 50 ?> till
Kön är tom. Lägg till mejladresser ovan.
Skickade (= count($sent) ?>)
0): ?>
✓
= htmlspecialchars($entry['email']) ?>
— = $entry['date'] ?? '' ?>
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.