#4 Re: Ostatní problémy » Nefunkční funkce mail() v PHP » 2025-10-29 00:13:37

Ok, díky za rady. Zkusím se mrknout, co mohu udělat. Možná využiju druhou schránku, kterou jsem si teď vytvořil. Potřebuju, aby kontaktní formulář odeslal email s hlavičkou "From" odpovídající tomu, co zadá uživatel do formuláře (tedy Jméno <email>). Email musí být SPF compliant. Pokud to nepůjde, tak holt bude ve "From" hlavičce email schránky, a v hlavičce "Reply-To" vlastní email odesílatele.

#7 Problémy s administrací » Let's Encrypt odmítá vygenerovat SSL certifikát pro mou doménu » 2025-10-28 02:50:04

marpolda
Odpovědi: 7

Nelze vygenerovat SSL certifikát Let's Encrypt pro mou doménu czghost.cz, jelikož systém detekuje jinou IP adresu serveru. To bude patrně IP adresa Cloudflaru, jelikož web je schován za proxy. Lze to nějak nastavit, aby to bralo proxy od Cloudflare, nebo musím proxy vypnout?

7mmcA4Pf1.png

#9 Re: Ostatní problémy » Nefunkční funkce mail() v PHP » 2025-10-28 01:37:25

Tak já si dělám webové stránky pomocí vlastního kódu, na blogu ve WP kontaktní formulář nebude. Rád bych viděl, když tam někdo zadá údaje, předmět a text zprávy, abych v seznamu viděl:

  1. Jméno

  2. Předmět

  3. Úvod zprávy

(viz tento obrázek)
7mlWEc98n.png

A po rozkliknutí pak v okně emailu vedle jména a příjmení také adresu odesílatele (emailová adresa).
7mlXf03Ur.png

Takže pokud někdo zadá následující údaje:

  • Jméno: Prokop Buben

  • email: prokop.buben@seznam.cz

  • Předmět: Něco se mi nelíbí

tak bych rád viděl hned v seznamu emailů, že email přišel od někoho jménem Prokop Buben, s předmětem "Něco se mi nelíbí", a po rozkliknutí bych rád viděl jeho emailovou adresu "prokop.buben@seznam.cz". Jde to udělat tak, aby to odpovídalo mé představě a zároveň to splňovalo podmínky pro SPF compliance, a aby to fungovalo? Nově by měly emaily chodit na mou veřejnou schránku na Endoře, a svůj Gmail chci uchovat více v soukromí. To je jeden z hlavních důvodů, proč jsem si pořizoval doménu druhého řádu. Email má být odesílaný pomocí PHP skriptu Ajaxem, chráněný pomocí Cloudflare Turnstile.

Zde je PHP kód, který mám zatím napsaný:

<?php

// Supress error displaying (error reports are in HTML format, which messes up JSON formatting)
$void = ini_set('display_errors', 0);
$void = ini_set('display_startup_errors', 0);

// Check success and error displaying status
if ($void === false && (ini_get('display_errors') === '1' || ini_get('display_startup_errors') === '1')) {
    http_response_code(500);
    echo json_encode([
        'success' => false,
        'error' => 'Internal Server Error',
        'message' => 'Failed to supress error displaying.',
        'code' => 500
    ]);
    error_log('Failed to supress error displaying.');
    exit;
}

// Start session => Should make session variables accessible
session_start();

// Set content type to JSON
header('Content-Type: application/json');

// Determine language
$lang = isset($_POST['lang']) ? preg_replace('/[^a-zA-Z0-9\-]/', '', $_POST['lang']) : 'en-US';
if (!in_array($lang, ['en-US', 'cs-CZ'])) {
    $lang = 'en-US';
}

// Include ajax response templates
$ajax_templates = json_decode(file_get_contents(__DIR__ . "/../.incl/translations/$lang/ajax/responses.json"));

// Get session token and given token
$session_token = isset($_SESSION['token']) ? $_SESSION['token'] : null;
$given_token = isset($_POST['token']) ? $_POST['token'] : null;

// Check that referer is local server
if (!isset($_SERVER['HTTP_REFERER']) || (parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) != $_SERVER['SERVER_NAME'])) {
    http_response_code(403);
    echo json_encode([
        'success' => false,
        'error' => $ajax_templates->invalid_referer->heading ?? 'Invalid referer',
        'message' => $ajax_templates->invalid_referer->message ?? 'Direct access not permitted.',
        'code' => 403
    ]);
    error_log('Invalid referer: ' . ($_SERVER['HTTP_REFERER'] ?? '(none)'));
    exit;
}

// Check that this is a valid POST request
if ($_SERVER['REQUEST_METHOD'] != 'POST' || empty($_POST)) {
    http_response_code(400);
    echo json_encode([
        'success' => false,
        'error' => $ajax_templates->invalid_request->heading ?? 'Invalid request',
        'message' => $ajax_templates->invalid_request->message ?? 'This endpoint expects a POST request with valid parameters.',
        'code' => 400
    ]);
    error_log('Invalid request method: ' . ($_SERVER['REQUEST_METHOD'] ?? '(none)'));
    exit;
}

// Check session token
if (is_null($session_token) || is_null($given_token) || $session_token !== $given_token) {
    http_response_code(401);
    echo json_encode([
        'success' => false,
        'error' => $ajax_templates->invalid_session_token->heading ?? 'Invalid session token',
        'message' => $ajax_templates->invalid_session_token->message
            ?? 'Session token is invalid. Please reload the page and try again.',
        'code' => 401
    ]);
    error_log('Invalid session token.\n  Given: ' . ($given_token ?? '(none)')
        . '\n  Expected: ' . ($session_token ?? '(session token not initiated)'));
    exit;
}

// Include Cloudflare Turnstile validation
require_once(__DIR__ . '/../.incl/functions/cf_validate.php');

// Prepare email data
//----------------------------------------------------------------

// Host information
$host = $_SERVER['HTTP_HOST'];

// Contact info
$to = 'kontakt@czghost.cz';                 // Recipient email address
$sender = 'REDACTED_FOR_PRIVACY';             // Sender/return path address to avoid SPF errors

// Email details
$email = isset($_POST['from']) ? filter_var($_POST['from'], FILTER_SANITIZE_EMAIL) : null;
$name = isset($_POST['name']) ? (trim($_POST['name']) ?? 'Anonymous') : 'Anonymous';
$subject = isset($_POST['subject']) ? trim($_POST['subject']) : null;
$message = isset($_POST['message']) ? (trim($_POST['message']) ?? 'Message not provided') : 'Message not provided';

// Email headers
$headers = [
    "From"          => "\"$name\" <$email>",            // Sender's name and email address
    "Reply-To"      =>  $email,                         // Reply-To email address
    'Sender'        =>  $sender,                        // Technical sender address to avoid SPF errors
    'Return-Path'   =>  $sender,                        // Return-Path address to avoid SPF errors
    'MIME-Version'  => '1.0',                           // MIME protocol version
    'Content-Type'  => 'text/plain; charset=UTF-8',     // MIME Content-Type header
    'X-Mailer'      => "Contact form at $host"          // Mailer application
];

// Prepare MIME headers and set up valid format
$mime_headers = [];
foreach ($headers as $key => $value) {
    $mime_headers[] = "$key: $value";
}
$mail_headers = join("\n", $mime_headers);

// Validate form fields
//----------------------------------------------------------------

// Check for empty email field
if (is_null($email) || empty($email)) {
    http_response_code(400);
    echo json_encode([
        'success' => false,
        'error' => $ajax_templates->email_is_required->heading ?? 'Email is required',
        'message' => $ajax_templates->email_is_required->message ?? 'Please provide your email address.',
        'code' => 400
    ]);
    error_log('Missing sender email address');
    exit;
}

// Check for valid email format
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    http_response_code(400);
    echo json_encode([
        'success' => false,
        'error' => $ajax_templates->invalid_email_address->heading ?? 'Invalid email address',
        'message' => $ajax_templates->invalid_email_address->message ?? 'Please provide a valid email address.',
        'code' => 400
    ]);
    error_log('Invalid sender email address: ' . $email);
    exit;
}

// Validate other fields as needed
if (is_null($subject) || empty($subject)) {
    http_response_code(400);
    echo json_encode([
        'success' => false,
        'error' => $ajax_templates->subject_is_required->heading ?? 'Subject is required',
        'message' => $ajax_templates->subject_is_required->message ?? 'Please provide a subject for your message.',
        'code' => 400
    ]);
    error_log('Missing subject in contact form');
    exit;
}

// Send email
if (mail($to, $subject, "New message from $name sent via contact form at $host:\n\n$message", $mail_headers, '-f' . $sender)) {
    // Email successfully sent
    http_response_code(200);
    echo json_encode([
        'success' => true,
        'title' => $ajax_templates->email_sent_successfully->heading ?? 'Email sent successfully',
        'message' => $ajax_templates->email_sent_successfully->message ?? 'Your message has been sent successfully.',
        'code' => 200
    ]);
} else {
    // Email failed to send
    http_response_code(500);
    echo json_encode([
        'success' => false,
        'error' => $ajax_templates->failed_to_send_email->heading ?? "Failed to send email",
        'message' => str_replace('${host}', $host, $ajax_templates->failed_to_send_email->message) ?? "Failed to send email, please try again later. If the problem persists, contact me at <a href=\"mailto:contact@$host\">contact@$host</a>.",
        'code' => 500
    ]);
    error_log('Failed to send email: ' . print_r(error_get_last(), true));
}

// Clear session data and destroy session
session_unset();
session_destroy();
exit;

?>

#10 Re: Ostatní problémy » Nefunkční funkce mail() v PHP » 2025-10-22 18:33:57

Ochota zřejmě nulová. Zeptám se tedy jinde. Děkuji.

#11 Náměty na inovace » Reklamní patička » 2025-10-15 19:26:46

marpolda
Odpovědi: 0

Reklamní patička překrývá v mém starém webu skutečnou patičku stránky, protože je nastavená jako fixní v okně prohlížeče, a je tedy vyjmuta z kontextu stránky. Patička stránky tak není vidět. Abych si obsah patičky mohl přečíst, reklamu jsem si musel pomocí developer tools v prohlížeči lokálně skrýt.

7ldRjg2aX.png
7ldRpnQNN.png

Ne, že by mi na tom nějak záleželo, mám doménu druhého řádu, kam chci umístit svůj nový web (je v aktivním vývoji), a tam mám hosting zaplacený čiže bez reklam. Ale někomu jinému to může vadit, a celkem to omezuje možnosti stylování stránek, protože musí stránky stylovat okolo toho.

#12 Re: Ostatní problémy » Doména stále ukazuje na starý webhosting » 2025-09-10 14:13:34

Máte aktualizované DNS záznamy, aby směřovaly na Endoru? Buď nameservery nasměrované na Endoru s DNS na Endoře, nebo DNS záznamy (třeba na Cloudflare) směřované na server, kde máte nový web? Tyto změny obvykle trvají maximálně 24 hodin.

#13 Re: Ostatní problémy » Nefunkční funkce mail() v PHP » 2025-09-10 13:55:30

Dobrá, poradíte mi tedy, jak mám nastavit kontaktní formulář, aby email v pořádku dorazil, prošel SPF a DKIM kontrolou a abych jako odesílatele viděl toho, kdo to poslal?

Jde mi o to, abych viděl hned v seznamu emailů odesílatele (jméno), předmět zprávy, a případně začátek této zprávy.
7hZFzkpzN.png

A v zobrazeném emailu, aby byla vidět emailová adresa odesílatele:
7hZFWdZrD.png

Email samozřejmě musí projít SPF i DKIM kontrolou, a musí být odeslán přes kontaktní formulář.

Co vyplňuje odesílatel na kontaktním formuláři je jméno, email, předmět a zpráva. Samozřejmostí je ochrana proti spamu captchou (Cloudflare Turnstile), a mám implementovanou i svou vlastní ochranu proti zneužití API endpointu (neboť nový kontaktní formulář bude využívat AJAX).

#14 Re: Problém s přesměrováním domény » Doména a hosting chybí v administraci » 2025-09-05 02:06:01

Doporučuju si přečíst tuto stránku (a všechny stránky pod ní přidružené, včetně FAQ):
https://migrace.endora.cz/

#15 Re: Ostatní problémy » Nefunkční funkce mail() v PHP » 2025-09-02 15:25:21

Ale jednu věc jsem objevil při testování emailu ze svého kontaktního emailu na mé doméně, a sice, že DKIM zřejmě není správně nastaven. SPF projde, ale DKIM nikoliv. Nevím, jestli je to Outlookem (MS Office), protože mail tester mi neukázal žádný klíč, ani neříkal, že by byl klíč neplatný, prostě jako by neexistoval. Klíč tam přitom je.

#16 Re: Ostatní problémy » Nefunkční funkce mail() v PHP » 2025-09-02 15:05:21

To nevím, jak bych dokázal udělat. Jedná se o email odesílaný jménem toho, kdo vyplňuje kontaktní formulář, z technických důvodů se používá Sender hlavička, která se nastavuje na moji Gmail adresu, a kontaktní formulář stále odesílá email na moji Gmail adresu (nebo se o to alespoň snaží). Sender hlavička se používá právě kvůli SPF. Ale nevím co se stalo, jestli došlo někdy ke změně buď v Googlu nebo u vás, protože aniž bych dělal jakékoliv změny v kontaktním formuláři, přestalo to fungovat. Formulář sice oznámí, že se email odeslal, ale email nedorazí. Takže SMTP server, ke kterému se funkce mail() připojuje, musel email odeslat a oznámit úspěšný pokus. Někde po cestě musela nastat chyba. Zřejmě je na vině Gmail, který nejspíš zavrhuje emaily, které jsou označené Sender hlavičkou s jinou emailovou adresou než tou, která je v hlavičce From. Google používá celou řadu obranných mechanismů na detekci spamu, a ty spamy, které se objeví ve spamové složce, jsou možná ani ne 1 % z celkového množství spamu, který se pokouší o spojení. Zdá se, že Google emaily odesílané mým kontaktním formulářem automaticky zavrhuje jako zjevný pokus o spam, díky té Sender hlavičce.

No nic, pokud na straně Endory není žádná chyba, pak to řešit nebudu. Stejně dělám nové webové stránky, které budou používat nový kontaktní formulář již s kontaktem na můj veřejný email, a celé webovky budou na nové adrese. Starou doménu třetího řádu ještě nechám běžet a udělám z toho přesměrování na subdoménu na mé nové doméně druhého řádu, kde bude kopie starého webu (kde ovšem znefunkčním starý kontaktní formulář a hodím do něj odkaz na ten nový).

#17 Ostatní problémy » Nefunkční funkce mail() v PHP » 2025-08-26 23:12:27

marpolda
Odpovědi: 12

Z ničeho nic mi přestal fungovat na mých free stránkách kontaktní formulář. Po odeslání emailu se sice zobrazí, že došlo k odeslání emailu, ale do schránky mi nic nedorazí. Logy si nedokážu momentálně zobrazit (respektive teď nevím jak na to).

Kontaktní formulář mám k dispozici zde: http://czghost.4fan.cz/cz/contact

Je funkce mail() zakázána? Jak si mám udělat na stránkách kontaktní formulář?

#19 Re: Vaše připomínky k fóru » get_apache_version() vrací Error 500 » 2024-11-24 21:25:58

V phpinfo() jsem se verzi Apache nedozvěděl. V kolonce $_SERVER['SERVER_SOFTWARE'] bylo pouze "Apache", bez verze. Nikde jinde verze Apache zmíněna nebyla, pouze verze PHP. A migrace na Webglobe je již hotová nebo se ještě bude uskutečňovat?

#20 Vaše připomínky k fóru » get_apache_version() vrací Error 500 » 2024-11-24 21:17:23

marpolda
Odpovědi: 2

Chtěl jsem se podívat na jaké verzi Apache běží Endora, neboť od verze 2.3 je změněná syntaxe allow/deny v .htaccess, a já mám u sebe na localhostu Apache 2.4, což znamená, že pokud je na Endoře starší verze, nepůjdou mi nové direktivy. Nicméně zatímco u mě na localhostu PHP funkce get_apache_version() funguje, na Endoře to vrací error 500. Funkce je tedy zřejmě vypnutá. Existuje nějaký způsob, jak zjistit verzi Apache na serveru? Ve webové administraci bohužel nic vidět není.

Dále bych se rád zeptal, jak je na tom migrace na servery Webglobe. Dozvěděl jsem se, že se IP adresa sasanky změnila, pravděpodobně asi i ostatních. Souvisí to s tou migrací pod Webglobe? Děkuji.

#21 Re: Jen tak » HTTPS na Free doménách » 2024-11-23 23:07:55

Aha. Tak mě osobně to nevadí, já stejně své webové stránky migruju společně s kompletním redesignem a restrukturizací na novou adresu = pořídil jsem si doménu druhého řádu a k tomu Endora Plus webhosting. Těžko říct, kdy dojde k migraci Endory na Webglobe servery (pokud již k tomu nedošlo).

#22 Problémy s administrací » Administrace: Error 504 po označení zpráv za přečtené » 2024-11-23 21:52:53

marpolda
Odpovědi: 2

Zdravím. Označování zpráv (oznámení) v administraci za přečtené na několik minut zablokuje celou administraci. Chtěl jsem označit upozornění na překročené limity běžících PHP procesů za přečtené, poté byla administrace nedostupná. Ztratil jsem heslo k FTP, z nějakého důvodu se mi ztratil uložený trezor v Total Commanderu, nicméně vím, že v administraci si jej lze obnovit.
6SeWU2Kum.png

Chtělo by to tuto chybu opravit.

#23 Náměty na inovace » Zranitelnost v glibc = zranitelnost v PHP » 2024-05-21 10:38:00

marpolda
Odpovědi: 1

Zdravím.

Bylo by na místě okamžitě updatovat verzi glibc na nedávný hotfix, pokud jste tak ještě neučinili, která opravuje zranitelnost umožňující nepovolený přístup do paměti (čímž lze spustit nevyžádaný kód na cílovém stroji, v tomto případě na serverovém stroji hostující webové stránky).

Ponecháním zranitelné verze vystavujete nejen sebe, ale i všechny zákazníky potenciálnímu riziku zneužití této zranitelnosti.

https://youtu.be/u8jLUjpCWrs

#24 Re: Ostatní problémy » Platný certifikát, spojení není plně zabezpečené » 2024-03-08 13:34:26

Chyba, která se opraví sama od sebe, je ta nejhorší, co může existovat. big_smile

#25 Re: Návody a postupy » ChatGPT a rady k .htaccess » 2024-03-03 12:14:28

Stránka do chyby 500 nespadla, ale nefunguje to podle představ.
6tPFyj7Du.png,

V path selectoru se má objevit "test". Vypadá to, že ChatGPT si trošku vymýšlí.

Zde je .htaccess soubor:

# No directory listing, no multi views
Options -Indexes

# Redirects and rewrites allowed
RewriteEngine on

# Redirect HTTP to HTTPS
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R,L]

# Redirect direct requests for "index.php?lang=xyz" to "/xyz/"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} lang=([a-z]{2,3})
RewriteRule ^(index\.php)?$ https://%{HTTP_HOST}/%1/? [R=301,L]

# Redirect direct requests for "root.php?lang=xyz" to "/xyz/root/"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} lang=([a-z]{2,3})
RewriteRule ^(root\.php)$ https://%{HTTP_HOST}/%1/root/? [R=301,L]

# Redirect direct requests for "root.php?lang=xyz&path=<anything>" to "/xyz/root/<anything>"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} lang=([a-z]{2,3})
RewriteCond %{QUERY_STRING} path=(.+)
RewriteRule ^(root\.php)$ https://%{HTTP_HOST}/%1/root/%{QUERY_STRING_UNESCAPED:path}? [R=301,L,NE]

# Redirect direct requests for "root.php?path=<anything>" to "/root/<anything>"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} path=(.+)
RewriteRule ^(root\.php)$ https://%{HTTP_HOST}/root/%{QUERY_STRING_UNESCAPED:path}? [R=301,L,NE]

# Redirect direct requests for "index.php" to "/"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php$ https://%{HTTP_HOST}/? [R=301,L]

# Redirect direct requests for "root.php" to "/root/"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^root\.php$ https://%{HTTP_HOST}/root/? [R=301,L]

# Redirect "/xyz/root" to "/xyz/root/" (with the slash at the end)
RewriteRule ^([a-z]{2,3})/root$ ./root/? [R=301,L]

# Internally rewrite "/xyz/root/" to "/root.php?lang=xyz"
RewriteRule ^([a-z]{2,3})/root/$ ./root.php?lang=$1 [L]

# Encode forward slashes in query string
#RewriteCond %{QUERY_STRING} ^(.*&|\?)path=([^&]*)(.*)$
#RewriteRule ^ - [E=PATH_ENCODED:${urlencoder:$2}]

# Internally rewrite "/xyz/root/<anything>" to "/root.php?lang=xyz&path=<anything>"
#RewriteRule ^([a-z]{2,3})/root/(.+)$ ./root.php?lang=$1&path=%{ENV:PATH_ENCODED}
RewriteRule ^([a-z]{2,3})/root/(.+)$ ./root.php?lang=$1&path=${urlencoder:$2} [B,L]

# Internally rewrite "/xyz/" or "/xyz/index/" to "/index.php?lang=xyz"
RewriteRule ^([a-z]{2,3})(/(index/?)?)?$ ./index.php?lang=$1 [L]

# Internally rewrite "/index/" to "/index.php"
RewriteRule ^index/?$ ./index.php [L]

# Internally rewrite "/root/" to "/root.php"
RewriteRule ^root/$ ./root.php [L]

# Encode forward slashes in query string
#RewriteCond %{QUERY_STRING} ^(.*&|\?)path=([^&]*)(.*)$
#RewriteRule ^ - [E=PATH_ENCODED:${urlencoder:$2}]

# Internally rewrite "/root/<anything>" to "/root.php?path=<anything>"
#RewriteRule ^root/(.+)$ ./root.php?path=%{ENV:PATH_ENCODED} [B,L]
RewriteRule ^root/(.+)$ ./root.php?path=${urlencoder:$2} [B,L]

Zde je soubor root.php:

<!DOCUMENT HTML>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Hello World</title>
    </head>
    <body>
        <h1>Test: Hello World</h1>
        <ol>
            <li>Language selector: <?php echo $_GET['lang']; ?></li>
            <li>Path selector: <?php echo $_GET['path']; ?></li>
        </ol>
    </body>
</html>

Jen dodám, že czghost.test je moje lokální testovací doména, která není přístupná z jiného počítače.

Zápatí

Založeno na FluxBB | CZ a SK