#1 2025-08-26 23:12:27

marpolda
Endora uživatel
Místo: Ústí nad Labem
Registrován: 2015-05-04
Příspěvky: 127
Web

Nefunkční funkce mail() v PHP

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ář?


Jen dvě věci na světě jsou nekonečné: Vesmír a lidská hloupost. U toho prvního si však nejsem jistý.
- Albert Einstein

Offline

#2 2025-09-01 14:05:55

JF
Endora rádce
Místo: ....nice u Plzně
Registrován: 2010-06-22
Příspěvky: 12,055

Re: Nefunkční funkce mail() v PHP

Dobrý den, prověřte si prosím jestli email nese všechny bezpečnostní prvky, tj SPF, DKIM a DMARC v DNS vaši domény a tyto jsou v emailu dodrženy. Test je možné provést na mail-tester.com děkuji


Ján Fačkovec - Endora.cz by Webglobe
Email, Web, Webadmin, Webmail, Nápověda, Ceník

Offline

#3 2025-09-02 15:05:21

marpolda
Endora uživatel
Místo: Ústí nad Labem
Registrován: 2015-05-04
Příspěvky: 127
Web

Re: Nefunkční funkce mail() v PHP

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ý).

Upravil marpolda (2025-09-02 15:10:07)


Jen dvě věci na světě jsou nekonečné: Vesmír a lidská hloupost. U toho prvního si však nejsem jistý.
- Albert Einstein

Offline

#4 2025-09-02 15:25:21

marpolda
Endora uživatel
Místo: Ústí nad Labem
Registrován: 2015-05-04
Příspěvky: 127
Web

Re: Nefunkční funkce mail() v PHP

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.


Jen dvě věci na světě jsou nekonečné: Vesmír a lidská hloupost. U toho prvního si však nejsem jistý.
- Albert Einstein

Offline

#5 2025-09-09 16:39:31

JF
Endora rádce
Místo: ....nice u Plzně
Registrován: 2010-06-22
Příspěvky: 12,055

Re: Nefunkční funkce mail() v PHP

Dobrý den, php funkce mail() se nepřipojuje k žádnému SMTP. Odesílá to přímo webový server. Pokud používáte odesilatele vaši gmail adresu, tak tyto emaily server příjemce rovnou zahazuje, nejsou totiž odeslané z povolené IP adresy domény gmail a taktéž neobsahují další prvek, DKIM podpis. V poslední roky se tyto podmínky začali přísně dodržovat a již podvrhnutý email z nepovolených serverů prostě neprojde do cílové schránky.


Ján Fačkovec - Endora.cz by Webglobe
Email, Web, Webadmin, Webmail, Nápověda, Ceník

Offline

#6 2025-09-10 13:55:30

marpolda
Endora uživatel
Místo: Ústí nad Labem
Registrován: 2015-05-04
Příspěvky: 127
Web

Re: Nefunkční funkce mail() v PHP

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).


Jen dvě věci na světě jsou nekonečné: Vesmír a lidská hloupost. U toho prvního si však nejsem jistý.
- Albert Einstein

Offline

#7 2025-10-22 18:33:57

marpolda
Endora uživatel
Místo: Ústí nad Labem
Registrován: 2015-05-04
Příspěvky: 127
Web

Re: Nefunkční funkce mail() v PHP

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


Jen dvě věci na světě jsou nekonečné: Vesmír a lidská hloupost. U toho prvního si však nejsem jistý.
- Albert Einstein

Offline

#8 2025-10-23 22:30:49

JF
Endora rádce
Místo: ....nice u Plzně
Registrován: 2010-06-22
Příspěvky: 12,055

Re: Nefunkční funkce mail() v PHP

Dobrý den, nastavení vaši aplikace můžete provést dle https://www.endora.cz/napoveda/wp-mail- … ani-emailu děkuji


Ján Fačkovec - Endora.cz by Webglobe
Email, Web, Webadmin, Webmail, Nápověda, Ceník

Offline

#9 Včera 01:37:25

marpolda
Endora uživatel
Místo: Ústí nad Labem
Registrován: 2015-05-04
Příspěvky: 127
Web

Re: Nefunkční funkce mail() v PHP

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;

?>

Upravil marpolda (Včera 01:46:27)


Jen dvě věci na světě jsou nekonečné: Vesmír a lidská hloupost. U toho prvního si však nejsem jistý.
- Albert Einstein

Offline

#10 Včera 19:34:13

JF
Endora rádce
Místo: ....nice u Plzně
Registrován: 2010-06-22
Příspěvky: 12,055

Re: Nefunkční funkce mail() v PHP

Dobrý den, doporučuji použít phpmailer https://github.com/PHPMailer/PHPMailer - ten umí jak posílání emailů přes php funkci mail() tak i pomocí SMTP existující email schránky. nějaké příklady pro něj naleznete například zde https://mailtrap.io/blog/phpmailer/


Ján Fačkovec - Endora.cz by Webglobe
Email, Web, Webadmin, Webmail, Nápověda, Ceník

Offline

#11 Dnes 00:13:37

marpolda
Endora uživatel
Místo: Ústí nad Labem
Registrován: 2015-05-04
Příspěvky: 127
Web

Re: Nefunkční funkce mail() v PHP

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.


Jen dvě věci na světě jsou nekonečné: Vesmír a lidská hloupost. U toho prvního si však nejsem jistý.
- Albert Einstein

Offline

#12 Dnes 21:23:52

JF
Endora rádce
Místo: ....nice u Plzně
Registrován: 2010-06-22
Příspěvky: 12,055

Re: Nefunkční funkce mail() v PHP

Dobrý den, ve From musí být email na vaši doméně. Toto je bezpečnostní opatření aby nebylo možné spamovat z emailů někoho jiného. Případně tam může být jakákoliv adresa ale je nutné email odeslat s SMTP serveru kde daná schránka běží.


Ján Fačkovec - Endora.cz by Webglobe
Email, Web, Webadmin, Webmail, Nápověda, Ceník

Offline

Zápatí

Založeno na FluxBB | CZ a SK