Autor Zpráva
Edhel
Profil
Ahoj, potřeboval bych poradit s formulářem na odesílání mailu ze stránek.
S PHP zatím vůbec neumím, mám jen nějaké mlhavé tušení, co by kde být mělo a nemělo, a očividně to nestačí. Mám s ním tři problémy:
1. Mail se nepošle (není to nastavením hostingu, podařilo se mi zprovoznit jednodušší variantu, a samozřejmě to není tím, že je tu ve scriptu adresa fiktivní:) )
2. Vždycky vyskočí chybová hláška, že je potřeba vyplnit všechna pole, i když jsou vyplněná. (Původně byly ve skriptu různé hlášky pro různá nevyplněná pole, ale když na každou chybu odpovídal jen variantou pro chybu 1, ty ostatní nepotřebné jsem zahodil. Očividně byl problém jinde.)
3. Po kliknutí na odesílací tlačítko zmizí ze stránky všechno, co je pod mailovým formulářem (a tedy scriptem).

Tady je zdrojový kód (je to upravený skript ze stránek http://www.koding.cz/priklady.php?id=101 asi jsem ho upravil moc):
<?php
function show_form()
{
?>
<table class="prihlaska">

<form action="" method="post">

<tr><td class="vlevo">Jméno:</td><td class="vpravo"><input name="jmeno" type="text" class="pole1"/></td></tr>
<tr><td class="vlevo">E-mail:</td><td class="vpravo"><input name="email" type="email" value="@" class="pole1"/></td></tr>
<tr><td class="vlevo">Telefon:</td><td class="vpravo"><input name="telefon" type="text" class="pole1"/></td></tr>
<tr><td class="vlevo">Adresa:</td><td class="vpravo"><input name="adresa" type="text" class="pole1"/></td></tr>
<tr><td class="vlevo">Datum semináře, kterého se chcete zúčastnit, případně poznámka:</td><td class="vpravo"><textarea name="termin" rows="5" cols="25" class="pole2"></textarea></td></tr>
<tr><td class="vlevo"><input type="submit" name="submit" value="Přihlásit se" class="odeslat"/></td><td></td></tr>

</form>

</table>

<?php
}
function complete_mail() {
    $title = "Přihláška na seminář";
        $message =  substr(htmlspecialchars(trim($_POST['termin'])), 0, 1000000);
        $adresa =  substr(htmlspecialchars(trim($_POST['adresa'])), 0, 1000);
        $name =  substr(htmlspecialchars(trim($_POST['jmeno'])), 0, 30);
        $tel =  substr(htmlspecialchars(trim($_POST['telefon'])), 0, 30);
        $email =  substr(htmlspecialchars(trim($_POST['email'])), 0, 50);
        if(empty($jmeno))
             output_err(0);
        if(empty($email))
             output_err(0);
        if(empty($termin))
             output_err(0);
        if(empty($adresa))
             output_err(0);
        if(empty($telefon))
             output_err(0);
        $mess = '
Jméno odesílatele: '.$name.' <br>
Telefonní číslo: '.$tel.' <br>
Email: '.$email.' <br>
Adresa: '.$adresa.' <br>
'.$message;
        // $to - příjemce emailu 
        $to = "moje@adresa.cz";
        // $from - odesílatel
        $headers  = 'MIME-Version: 1.0' . "\r\n";
        $headers .= 'Content-type: text/html; charset=windows-1250' . "\r\n";
        $headers .= 'From: $email'. "\r\n";
        
        if(mail($to, $title, $mess, $headers)){
        echo '<p>Vaše přihláška byla úspěšně odeslána. V brzké době čekejte potvrzení Vaší účasti na semináři.</p>';
    }else{
        echo '<p>Něco se pokazilo a Vaše přihláška nebyla odeslána. Zkuste to znovu.</p>';
    }
}

function output_err($num)
{
    $err[0] = 'Je potřeba vyplnit všechna pole.';
    echo '<p><b>'.$err[$num].'</b></p>';
    show_form();
    exit();
}

if (!empty($_POST['submit'])) complete_mail();
else show_form();

 ?>
Davex
Profil
Domnívám se, že problém bude v podmínkách, kde se používají nedefinované proměnné a v první části by se asi neměly používat proměnné s jinými názvy než se kontrolují v části druhé.

        $message =  substr(htmlspecialchars(trim($_POST['termin'])), 0, 1000000);
        $adresa =  substr(htmlspecialchars(trim($_POST['adresa'])), 0, 1000);
        $name =  substr(htmlspecialchars(trim($_POST['jmeno'])), 0, 30);
        $tel =  substr(htmlspecialchars(trim($_POST['telefon'])), 0, 30);
        $email =  substr(htmlspecialchars(trim($_POST['email'])), 0, 50);

        if(empty($jmeno))
             output_err(0);
        if(empty($email))
             output_err(0);
        if(empty($termin))
             output_err(0);
        if(empty($adresa))
             output_err(0);
        if(empty($telefon))
             output_err(0);
Edhel
Profil
Davex:
Díky moc, podmínky jsem opravil a formulář už je schopný mail odeslat a dokonce i správně funguje při hlášení různých chybějících oken. Jenom pořád mizí zbytek stránky, když člověk nevyplní všechna pole. Nevíš, čím by mohlo být tohle? (Při správném vyplnění a odeslání se zbytek stránky objeví.)
Zjistil jsem, že se mi také špatně zobrazuje adresa, od koho ten e-mail přišel; ukáže se mi, že to přišlo z mého webu, ale měla se tam ukazovat adresa, kterou člověk vyplní, asi to mám špatně nastavené i tam.
Davex
Profil
Useknutí stránky způsobuje ukončení skriptu příkazem exit na 64. řádku.

Skutečná adresa odesílatele se nastavuje v pátém parametru funkce mail(). S jakoukoliv adresou (kterou lidé vyplní) to nemusí fungovat a e-mail může nedorazit nebo spadnout do složky se spamem.
Edhel
Profil
Davex
Tak to si s adresou odesílatele raději hrát nebudu, stejně ji v tom e-mailu budu mít vypsanou.
Zkusil jsem příkaz exit odstranit, což sice vedlo k tomu, že se ukázal zbytek stránky, ale taky to dovolilo odeslat e-mail, přestože nebylo všechno vyplněné (správnou chybovou hlášku to ale vyhodilo).
Davex
Profil
Správně by měl být skript poskládán trochu jinak. Vhodným řazením podmínek by se mělo zařídit, aby se e-mail odeslal pouze v případě správného vyplnění formuláře. Třeba jde jednoduše sloučit test vyplnění do jedné podmínky a e-mail odeslat ve větvi else.

Schematicky:
if (empty($jmeno) || empty($email) || empty($termin) || empty($adresa) || empty($telefon)) {
  output_err(0);
} else {
  // mail();
}
Edhel
Profil
Davex:
Zkusil jsem nacpat všechny podmínky do jedné, jak jsi radil, a zase to nefungovalo... a pak jsem zjistil, že tam zase zadávám špatné proměnné:) Už to funguje přesně, jak má, děkuju moc za tvou pomoc.
Edhel
Profil
Ahoj, po nějaké době... (komukoliv) Přestože přihláškový formulář fungoval, když jsem ho testoval na internetu, teď už nefunguje. Opravoval jsem v t stránce pár věcí, ale jsem si skoro stoprocentně jistý, že ve formuláři nic (ale asi jsem něco zmrvit musel). Podmínky fungují správně (mail se nepošle, když člověk nevyplní všechno), vypadá to, že se mail odešle, ale nic nepřijde. Nevíte někdo, čím to je tentokrát? (Nemůže to být třeba "špatným" doctype nebo něčím podobným?) Pro jistotu přikládám opravenou aktuální verzi kódu:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="cs">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1250 ">
</head>
<body class="terminy">
...
<?php
function show_form()
{
?>
<table class="prihlaska">
<form action="" method="post">
<tr><td class="vlevo">Jméno:</td><td class="vpravo"><input name="jmeno" type="text" class="pole1"/></td></tr>
<tr><td class="vlevo">E-mail:</td><td class="vpravo"><input name="email" type="email" value="@" class="pole1"/></td></tr>
<tr><td class="vlevo">Telefon:</td><td class="vpravo"><input name="telefon" type="text" class="pole1"/></td></tr>
<tr><td class="vlevo">Adresa:</td><td class="vpravo"><input name="adresa" type="text" class="pole1"/></td></tr>
<tr><td class="vlevo">Datum semináře, kterého se chcete zúčastnit, případně poznámka:</td><td class="vpravo"><textarea name="termin" rows="5" cols="25" class="pole2"></textarea></td></tr>
<tr><td class="vlevo"><input type="submit" name="submit" value="Přihlásit se" class="odeslat"/></td><td></td></tr>
</form>
</table>
<?php
}
function complete_mail() {
    $title = "Prihlaska na seminar";
        $message =  substr(htmlspecialchars(trim($_POST['termin'])), 0, 1000000);
        $adresa =  substr(htmlspecialchars(trim($_POST['adresa'])), 0, 1000);
        $name =  substr(htmlspecialchars(trim($_POST['jmeno'])), 0, 30);
        $tel =  substr(htmlspecialchars(trim($_POST['telefon'])), 0, 30);
        $email =  substr(htmlspecialchars(trim($_POST['email'])), 0, 50);
        $mess = '
Jméno odesílatele: '.$name.' <br>
Telefonní číslo: '.$tel.' <br>
Email: '.$email.' <br>
Adresa: '.$adresa.' <br>
Termín: '.$message;
        // $to - příjemce emailu 
        $to = "info@konstelace-hradiste.cz";
        // $from - odesílatel
        $headers  = 'MIME-Version: 1.0' . "\r\n";
        $headers .= 'Content-type: text/html; charset=windows-1250' . "\r\n";
        $headers .= 'From: $email'. "\r\n";
        
        if (empty($name) || empty($email) || empty($message) || empty($adresa) || empty($tel)) {
  output_err(0);}
        else {
        (mail($to, $title, $mess, $headers));
        echo '<p>Vaše přihláška byla úspěšně odeslána. V brzké době čekejte potvrzení Vaší účasti na semináři.<br><br><br><br><br><br><br></p>';}
}

function output_err($num)
{
    $err[0] = 'Musíte vyplnit všechna pole.';
    echo '<p><b>'.$err[$num].'</b></p>';
    show_form();

}

if (!empty($_POST['submit'])) complete_mail();
else show_form();

 ?>
...
</body>
</html>
Davex
Profil
1) Dost často nemusí odeslání e-mailu fungovat, když je naplatný odesílatel. Kromě toho, že text 'From: $email' není ve dvojitých uvozovkách, takže se proměnná $email nevypíše, je lepší mít jako odesílatele platnou adresu z domény, odkud se odesílá a ne toho, kdo formulář vyplnil. Je pak menší pravděpodobnost, že e-mail spadne do spamu.
2) Předmět obsahující diakritiku by měl být vždy zakódován do Quoted-Printable nebo Base64.
3) Pokud není tělo e-mailu nijak zakódováno a text obsahuje znaky s diakritikou, tak by se měla přidat hlavička
  Content-Transfer-Encoding: 8bit
4) Někdy je spolehlivější, když se místo odřádkování v hlavičce "\r\n" použije konstanta PHP_EOL.

Můžeš se inspirovat v Nejčastější potíže s PHP (FAQ) » Kódování e-mailu, aneb abychom neposílali otazníky..
Edhel
Profil
Davex: Opět jsi mě zachránil, děkuju moc. Zdá se, že to bylo tím odesílatelem. Vím, že toho jsem předtím neupravoval, ale přehlédl jsem, že už to tam nějak nastavené je... Každopádně teď tam je napevno daná adresa a funguje to. Pro jistotu jsem zakódoval i tělo mailu, nahradil to odřádkování a vyházel diakritiku z předmětu (přišlo mi to jednodušší, než další kódování). Doufám, že teď už to bude fungovat pořád a že už to nebude potřeba opravovat. Kdyby ano, adresu na FAQ mám uloženou:) Ještě jednou díky, je skvělé, že jsou lidi ochotní takhle pomoct.

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0