Administrare server open source

Platforma de hosting cu software liber, gratuit, open source.

In general siteurile detin pe langa sectiunile cu un continut specific si o pagina de contact care contine datele de contact ale firmei si de obicei un formular de contact pentru a livra rapid mesaje. Un astfel de formular se poate crea relativ usor folosind functia mail() din PHP dar pentru a ne asigura ca livrarea mesajului se face in conditii bune trebuie sa avem in vedere cateva lucruri.

Ca sa structuram putin ideea inainte de a ne pune pe treaba, sa facem o lista cu ce ar trebui sa faca un formular de contact:

  • sa preiau datele completate de utilizator;
  • se valideaza datele pentru a evita un potential atac;
  • se verifica daca expeditorul mesajului este om sau robot folosind CAPTCHA;
  • se incearca livrarea mesajului;
  • afisam o confirmare a livrarii mesajului sau o lista de erori.

Inainte de a crea formularul de contact trebuie mentionat ca avem nevoie de doua scripturi PHP care le gasim pe internet gratuit:

  • Securimage este un script open source, gratuit, folosit pentru functionalitatea CAPTCHA din cadrul formularului de contact;
  • Swift Mailer e probabil cel mai bun script folosit pentru livrarea mesajelor folosind autentificare SMTP.

Pentru inceput vom crea un fisier „contact.php” care va contine atat formularul de contact cat si scriptul de procesare a datelor si de livrare a mesajului.

Pe primele randuri ale fisierului vom deschide sesiunea, vom seta corect headerele scriptului (eliminam problema cacheului si setam charsetul pe UTF-8), cream o variabila care va contine formularul de contact si declaram variabilele care le vom folosi in livrarea mesajului:

< ?php
// Deschidem sesiunea pentru CAPTCHA
session_start();
 
// Continutul paginii va fi de tip text/html, UTF-8 pentru diacritice
header('Content-Type: text/html; charset=utf-8');
 
// Ne asiguram ca pagina nu e preluata din cache
header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');   // Data in trecut
 
// Formularul care trebuie completat
$formular = <<<END
    <form method="POST" action="contact.php">
        Nume:<br /><input type="text" name="nume" /><br />
        E-Mail:<br /><input type="text" name="email" /><br />
        Telefon:<br /><input type="text" name="telefon" /><br />
        Cod de securitate:<br />
        <img id="captcha" src="/lib/securimage/securimage_show.php" alt="CAPTCHA Image" />
        <a href="#" onclick="document.getElementById('captcha').src='/lib/securimage/securimage_show.php?' + Math.random(); return false">Rescrie imaginea</a><br />
        Verificare:<br />
        <input type="text" name="captcha_code" maxlength="6" /><br />
        Mesaj:<br />
        <textarea name="mesaj"></textarea><br />
        <input type="submit" value=" Trimite " />
 
END;
 
// Datele pentru livrarea mesajelor
$destinatar = '[email protected]';
$expeditor  = '[email protected]';
$utilizator = '[email protected]';
$parola     = 'parola';
$subiect    = 'Mesaj din formularul de contact';
$serverSMTP = 'mail.exemplu.ro';
?>

Formularul creat si pastrat in variabila „$formular” contine cinci campuri care trebuie completate: nume, email, telefon, captcha_code, si mesaj. captcha_code este codul care apare in imaginea din formular, cod folosit pentru a verifica daca cel care trimite mesajul e un om (capabil sa citeasca codul) sau un robot folosit pentru spam. Pus in aplicare formularul arata asa:
contact-form

Sub declararea formularului avem o sectiune in care declaram variabilele folosite in livrarea mesajului. La $destinatar trebuie sa punem adresa de mail la care va fi livrat mesajul dupa procesare. Avand in vedere ca folosim un script cu autentificare valoarea pentru $expeditor si cea pentru $utilizator de obicei coincid, avand in vedere ca sistemele de gestiune creaza utilizatorul pentru contul de mail folosind adresa de mail completa. $parola va contine parola pentru utilizatorul $utilizator, $subiect va fi subiectul mesajului care va fi livrat iar $serverSMTP este de obicei „localhost” sau adresa completa a serverului SMTP daca se foloseste un server extern.

Urmatoarea parte din contact este sectiunea de inceput a codului HTML si informatiile META.

<html>
<head>
    <title>Formular de contact</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <style type="text/css">
        body {
            font-family: Arial, Helvetica, Verdana;
            font-size: 11pt;
        }
 
        input, textarea { width: 200px; }
 
        form { width: 300px; margin:auto; }
    </style>
</head>
<body>
</body></html>

Partea care ne intereseaza in mod deosebit este instructiunea META care ii spune browserului ca encodingul paginii este UTF-8. Astfel vom putea folosi si diacritice.

Restul paginii e partea care proceseaza informatia si o expediaza. Inainte de a diseca codul, sa il vedem intreg:

< ?php
 
if( isset($_POST['email']) ) { // Procesam datele trimise
    // Lista cu eventualele erori
    $error = array();
 
    // Includem librariile pentru CAPTCHA si Swiftmailer
    include_once('lib/securimage/securimage.php');
    include_once('lib/mailer/swift_required.php');
 
    // 1. Preluam si validam datele
    $nume    = trim( htmlentities( $_POST['nume'], ENT_QUOTES, 'UTF-8' ) );
    $email   = trim( htmlentities( $_POST['email'], ENT_QUOTES, 'UTF-8' ) );
    $telefon = trim( htmlentities( $_POST['telefon'], ENT_QUOTES, 'UTF-8' ) );
    $mesaj   = trim( htmlentities( $_POST['mesaj'], ENT_QUOTES, 'UTF-8' ) );
 
    // 2. Verificam datele
    if( strlen($nume)    == 0 ) array_push( $error, 'Nu ati introdus numele.');
    if( strlen($email)   == 0 ) array_push( $error, 'Nu ati introdus adresa de e-mail.');
    if( strlen($telefon) == 0 ) array_push( $error, 'Nu ati introdus numarul de telefon.');
    if( strlen($mesaj)   == 0 ) array_push( $error, 'Nu ati introdus mesajul.');
 
    // 3. Verificam CAPTCHA
    $securimage = new Securimage();
    if( $securimage->check( $_POST['captcha_code'] ) == false ) array_push( $error, 'Codul de securitate nu este valid.');
 
    // 4. Verificam erorile
    if( count( $error ) != 0 ) {
        // Daca exista erori in arrayul $error nu trimitem mesajul
        echo 'Mesajul nu a putut fi transmis datorita urmatoarelor erori:<br /><ul>';
        foreach($error as $eroare) {
            echo "<li>$eroare</li>";
        }
        echo '</ul><br /><br />Incercati din nou completand corect campurile din formular.<br />' . $formular;
    } else {
        // Daca nu exista erori continuam trimiterea mesajului
        // 5. Pregatim si trimitem mesajul
        // 5.1 Pregatim metoda de transport
        $transport = Swift_SmtpTransport::newInstance($serverSMTP, 25)
            ->setUsername( $utilizator )
            ->setPassword( $parola );
 
        // 5.2 Pregatim mailerul
        $mailer = Swift_Mailer::newInstance( $transport );
 
        $azi = date("j, M, Y");
 
        // Pregatim mesajul final
        $body = "Azi $azi, ai primit un mesaj din formularul de contact. Datele completate sunt urmatoarele:\n\n";
        $body.= "Nume: $nume\n";
        $body.= "Telefon: $telefon\n";
        $body.= "E-Mail: $email\n";
        $body.= "Mesaj:\n$mesaj\n";
 
        // 5.3 Cream obiectul mesaj
        $mesajObj = Swift_Message::newInstance($subiect)
            ->setFrom( $expeditor )
            ->setTo( $destinatar )
            ->setBody( $body );
 
        // 5.4 Trimitem mesajul
        $result = $mailer->send( $mesajObj );
 
        // 5.5 Afisam un mesaj corespunzator
        if( $result ) {
            // Mesajul a fost trimis
            echo 'Va multumim ca ne-ati contactat. Veti primi un raspuns in cel mai scurt timp.';
        } else {
            echo 'Mesajul nu a putut fi livrat din motive tehnice.';
        }
    }
} else {
    // Afisam formularul
    echo $formular;
}
 
?>

Inainte de a procesa ceva trebuie sa verificam daca formularul a fost trimis. Pentru asta verificam daca este setata variabila „$_POST[‘email’]„, variabila care exista doar daca formularul a fost trimis. Daca exista, includem librariile necesare (Securimage si Swift Mailer) si procesam datele. Daca nu exista afisam formularul:

< ?php
if( isset($_POST['email']) ) { // Procesam datele trimise
    // Lista cu eventualele erori
    $error = array();
 
    // Includem librariile pentru CAPTCHA si Swiftmailer
    include_once('lib/securimage/securimage.php');
    include_once('lib/mailer/swift_required.php');
 
    // Procesarea datelor
} else {
    // Afisam formularul
    echo $formular;
}
?>

Partea care urmeaza sa fie studiata e cea legata de procesarea datelor. Pentru a intelege mai usor codul am adaugat comentarii la fiecare pas si am impartit procesarea in patru sectiuni:

  1. preluarea datelor;
  2. verificarea datelor;
  3. afisarea erorilor;
  4. livrarea mesajului.

Prima parte este preluarea datelor:

    $nume    = trim( htmlentities( $_POST['nume'], ENT_QUOTES, 'UTF-8' ) );
    $email   = trim( htmlentities( $_POST['email'], ENT_QUOTES, 'UTF-8' ) );
    $telefon = trim( htmlentities( $_POST['telefon'], ENT_QUOTES, 'UTF-8' ) );
    $mesaj   = trim( htmlentities( $_POST['mesaj'], ENT_QUOTES, 'UTF-8' ) );

Am folosit doua functii inainte de a pune valoarea unei variabile trimise prin formular intr-o variabila care sa fie folosita pentru expediere: htmlentities() pentru a converti caracterele speciale in entitati HTML si trim() pentru a sterge spatiile dinainte si de dupa variabile din motive estetice.

La al doilea pas verificam datele introduse:

    if( strlen($nume)    == 0 ) array_push( $error, 'Nu ati introdus numele.');
    if( strlen($email)   == 0 ) array_push( $error, 'Nu ati introdus adresa de e-mail.');
    if( strlen($telefon) == 0 ) array_push( $error, 'Nu ati introdus numarul de telefon.');
    if( strlen($mesaj)   == 0 ) array_push( $error, 'Nu ati introdus mesajul.');

Daca variabila nu corespunde cu ceea ce dorim, in cazul nostru daca variabila nu contine nimic, vom adauga un mesaj de eroare in array-ul $error care urmeaza sa fie afisat. Aici putem adauga functii suplimentare pentru validarea variabilelor. Putem pune o limita pentru marimea maxima, putem verifica cu ajutorul expresiilor regulate daca vreuna din variabile corespunde unui anumit sablon care ne intereseaza etc.

La urmatorul pas verificam codul CAPTCHA:

    $securimage = new Securimage();
    if( $securimage->check( $_POST['captcha_code'] ) == false ) array_push( $error, 'Codul de securitate nu este valid.');

Ceva mai sus am inclus libraria Securimage iar acum o vom folosi pentru a verifica daca codul transmis prin formular coincide cu cel din imaginea afisata inainte ca formularul sa fie trimis. Daca nu coincide vom adauga in arrayul $error un mesaj de eroare corespunzator.

Urmatorul pas este cel care decide daca mesajul va fi expediat sau nu:

    if( count( $error ) != 0 ) {
        // Daca exista erori in arrayul $error nu trimitem mesajul
        echo 'Mesajul nu a putut fi transmis datorita urmatoarelor erori:<br /><ul>';
        foreach($error as $eroare) {
            echo "<li>$eroare</li>";
        }
        echo '</ul><br /><br />Incercati din nou completand corect campurile din formular.<br />' . $formular;
    } else {
        // Daca nu exista erori continuam trimiterea mesajului
    }

Dupa cum se observa, orice mesaj de eroare a fost salvat ca inregistrare in arrayul $error. Daca exista inregistrari, se va afisa fiecare mesaj de eroare. Daca nu exista scriptul va rula in continuare pentru a livra mesajul. Presupunand ca nu exista nicio eroare se va rula urmatorul cod:

        // Daca nu exista erori continuam trimiterea mesajului
        // 5. Pregatim si trimitem mesajul
        // 5.1 Pregatim metoda de transport
        $transport = Swift_SmtpTransport::newInstance($serverSMTP, 25)
            ->setUsername( $utilizator )
            ->setPassword( $parola );
 
        // 5.2 Pregatim mailerul
        $mailer = Swift_Mailer::newInstance( $transport );
 
        $azi = date("j, M, Y");
 
        // Pregatim mesajul final
        $body = "Azi $azi, ai primit un mesaj din formularul de contact. Datele completate sunt urmatoarele:\n\n";
        $body.= "Nume: $nume\n";
        $body.= "Telefon: $telefon\n";
        $body.= "E-Mail: $email\n";
        $body.= "Mesaj:\n$mesaj\n";
 
        // 5.3 Cream obiectul mesaj
        $mesajObj = Swift_Message::newInstance($subiect)
            ->setFrom( $expeditor )
            ->setTo( $destinatar )
            ->setBody( $body );
 
        // 5.4 Trimitem mesajul
        $result = $mailer->send( $mesajObj );
 
        // 5.5 Afisam un mesaj corespunzator
        if( $result ) {
            // Mesajul a fost trimis
            echo 'Va multumim ca ne-ati contactat. Veti primi un raspuns in cel mai scurt timp.';
        } else {
            echo 'Mesajul nu a putut fi livrat din motive tehnice.';
        }

La pasul 5.1 pregatim un transportor. Transportorul e practic o conexiune la serverul SMTP care urmeaza sa fie folosita pentru livrare. La pasul 5.2 pregatim mailerul, obiectul care se ocupa de partea de protocol pentru livrarea obiectului $mesajObj care urmeaza sa il declaram. In variabila $body vom pastra mesajul asa cum dorim sa apara si adaugam variabilele preluate din formular. Mai jos la pasul 5.3 pregatim obiectul $mesajObj care contine textul mesajului subiectul si headerele. La 5.4 trimitem mesajul.

La prima vedere poate sa para putin incurcat mecanismul de livrare a mesajelor dar daca il urmariti putin e destul de clar structurat. Putin mai complex decat in cazul livrarii mesajelor cu functia mail() dar diferenta de cod merita.

La ultimul pas, 5.5, trebuie sa verificam daca mailul a fost livrat si sa afisam pe ecran un mesaj corespunzator.

Am incercat sa explic cat mai bine modul in care functioneaza formularul de contact si am adaugat comentarii la fiecare pas. Daca totusi va intereseaza doar sa aplicati ceea ce am explicat mai sus puteti descarca formularul de comanda: Download.

Mail

14 Responses so far.

  1. Dumi says:

    Salut am facut to ce scrie aici dar ami da urmatoarea erroare—–
    lib/mailer/classes/Swift/Transport/AbstractSmtpTransport.php on line 416

  2. Sergiu says:

    Salut,

    Asta e tot ce iti apare? Trebuie sa iti apara si un mesaj care sa iti spuna unde e problema. Din ce inteleg din AbstractSmtpTransport.php presupun ca nu comunica corect cu serverul SMTP. Incearca sa te conectezi la un alt server.

  3. Andrea says:

    Salut, ma bucur ca ai scris, ca sunt si de-alde mine… bebelusi la php.
    Poti sa imi spui care e faza cu injectarea e-mailurilor cu Bcc direct in header cand vine vorba de formulare ? Si cum previi asta cu ceea ce ai creat tu ? Multumesc anticipat pt raspuns.

  4. Cornel M says:

    Unde am eu subdomeniu inchiriat free imi spune ca am „PHP Sendmail Enabled”. Cum ma pot folosi de un script scris in PHP ca sa pot primi email dintr-un formular de contact? Te rog da-mi un mail daca ai timp si poti!

  5. Sergiu says:

    Ma bucur ca il gasiti util 😀

    Andreea, presupun ca te referi la adresele injectate de spamerii care folosesc formularele online. Daca folosesti formularul de aici nu trebuie sa iti faci griji pentru ca exista cod CAPTCHA, deci se poate injecta doar cate o adresa pe rand. Ar trebui sa fie masochist spamerul ca sa incerce exploatarea unui formular cu CAPTCHA 🙂

    Daca totusi vrei putina protectie in plus, cel mai simplu ar fi sa te asiguri inainte de a trimite mesajul cu $mailer->send() ca in variabilele $destinatar si $expeditor exista cate o singura adresa de mail. Cel mai simplu se poate face cautand numarul aparitii a caracterului @ (cod ASCII 64):

    < ?php
    $buf = '[email protected]@[email protected]';
    $count = count_chars( $buf, 1 );
    if( $count[64] > 1 ) {
        echo 'Sunt mai multe adrese';
    }
    ?>

    Cornel, in cazul asta ar trebui sa ai functia mail() activa. Daca nu e activa poti trimite mesajele folosind comanda sendmail. Un exemplu asemanator poti gasi in articolul Mail din linia de comanda. E un exemplu in bash, dar poti face ceva asemanator in PHP daca ai active functiile system() sau exec().

  6. Cornel M says:

    Tocmai de aceea Sorin ca am realizat cat de bun este formularul de contact descris de tine in articol si vreau sa il adopt si eu. Dar experienta mea in Unix si in lucrul cu PHP si programele de mail sunt mai slabute si de aceea am si intrebat si am cerut cu oarecare rerzerva asistenta. Ca sa mai castig ceva timp. Dupa cum ai vazut am inceput de la zero un site nou bazat pe noul WP 2.9 si ma straduiesc sa fie cat mai bun din punct de vedere tehnic si dragut ca tema si aspect. Problema e ca unde am eu hostingul ca sa se evite trimiterea de spam si sa se tina sub control fenomenul asta, nu este activat SMTP-ul asa cum imi spune in panelul de control. PHP Sendmail apeleaza SMTP dupa ce trece printr-o multime de filtre si mai trece odata pana sa fie trimis de SMTP. Dupa cum am vazut ca a zis pe forumul de asistenta unul dintre administratori trimiterea unui mesaj poate dura si o ora. Daca dupa 12 ore nu ajunge la destinatar nu mai este nicio sansa ca mesajul sa mai ajunga vreodata. Asta m-a pus pe jar. Si inainte de a ma apuca sa implementez o solutie imi place sa stiu ce fac si sa nu muncesc degeaba. Stii si tu cum e! Am sa revin cu impresii si comentarii.

  7. Sergiu says:

    Cornel, daca ai nevoie de mail doar pentru WordPress ai putea sa folosesti Configure SMTP. E un plugin de WordPress foarte bun care il poti folosi impreuna cu un cont de mail.

    Pe serverul lamp.ro nu am instalat un server de mail ca sa simplific administrarea. Folosesc Configure SMTP si nu am nicio problema 🙂

  8. CaliVita says:

    Multumesc pentru tutorial, eu nu sunt multumit de felul cum este configurata automat pagina de contact din prestashop, o sa incerc sa modific folosindu-ma de ce ai scris tu aici.
    O zi buna

  9. sibel says:

    Atunci cand se incearca trimiterea mesajului apare urmatorul mesaj pagina web contac.php nu poate fi gasita.

  10. Sergiu Tot says:

    Ai redenumit fisierul?

    Cauta linia

    <form method="POST" action="contact.php"></form>

    si asigura-te ca la action e scris corect numele fisierului.

  11. Zoly says:

    Am folosit scriptul de mai sus cu mici modificari. Hosterii din Romania au inceput sa forteze trimitea mailurilor pe SMTP. Dar nu prea te avertizeaza in legatura cu sendmail si ti se dezvaluie userul de cpanel.

  12. Evelina Streescu says:

    Foarte util, multumesc pentru ghidul detaliat!

  13. Nicu says:

    Salutare! am si eu o intrebare pot cumva scoate codul php in afara fisierului cu formular? incerc si eu experimental sa fac un site,si verific tot felu de coduri,sint la inceput si la codul asta bagat cu codul meu iese un spatiu nedorit acuma este drept nu m-am mai uitat in fisierul css,multumesc anticipat.http://85.186.148.122/nicu/files/Contact.php

  14. Sergiu Tot says:

    Salut Nicu,
    Poti pune formularul in orice pagina, atata timp cat atributul ACTION din FORM pointeaza spre pagina care urmeaza sa proceseze mesajul.

    Poate te ajuta:
    http://www.w3schools.com/php/php_forms.asp