anti-spam form mailer

hjuw 15.01.05 16:40

Lähetä postia sivustolta formista. Varmistuskoodi jolla postin saa lähetettyä näkyy kuvana.

 Tekstiversio  Arvo: 3 (3 ääntä)  Äänestä: +  -
Saat sivullesi yhteydenottoformin joka lähettää formin sisällön sähköpostiisi/sähköposteihin. "Salasana varmennettu".

Jonkin aikaa etsin formi-postinlähettäjää jossa olisi koodivarmistus, eli sivua olisi skriptin kautta vaikeampi hyödyntää väärin.
Enpä äkkiseltään löytänyt joten tein itse, arvatenkin joku linkkaa sekunnissa vastaavan. Jonkin aikaa ainakin malli
nähtävissä osoitteessa: http://netti.nic.fi/~052972/mailer/mailer.php Malli ei lähetä oikeasti mitään.

Mureakuhan ohje 80 merkkiä leveyttä ylittyy monin paikoin, mutta jos on hankaluuksia lukea ja silti koodi kiinnostaa,
koodin voi noutaa: http://netti.nic.fi/~052972/mailer/mailer.zip

Palautetta olisi suotavaa antaa. Varsinkin jos koodissa on selkeästi jokin toteutettu typerästi.

Ensimmäinen koodivinkkini.


TIEDOSTO mailer.php alkaa:
<?php
//      Published by hjuw under free for anyone to use everywhere in anyway anyone likes -license.
//      Function section begins

/*** basicXhtmlStart
*       Returns standards-compliant xhtml-page start.
*       $title = html title.
*       $cssfile = css-stylesheet file name.
*/

function basicXhtmlStart($title = "", $cssfile = "") {
        return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
                <head>
                <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1" />
                <title>'
. $title .'</title>
                <link rel="stylesheet" href="'
. $cssfile .'" type="text/css" />
                </head> 
                <body>'
;
}

/***    basicXhtmlEnd
*       Returns standards-compliant xhtml-page end.
*/

function basicXhtmlEnd() {
        return '</body></html>';
}       

/*** showMailForm
*       Returns a string containing html form inside a table.
*       $heading = heading text
*       $name = value for input field name
*       $email = value for input field email
*       $subject = value for input field subject
*       $message = value for textarea
*       $error = message to be displayed in a case of an error.
*
*/
     
function showMailForm($heading, $name = "", $email = "", $subject = "", $message = "", $error = "") {
        if ($error != "") {
                $error = '<tr><td class="errcode">'. $error .'</td></tr>';
        }

        return '
                <p>'
. $heading .'</p>
                <table cellspacing="0"><tr><td>Your Anti-spam code is:</td><td><img src="image.php" alt="" /></td></tr></table>
                <br/>
                <form action="'
. $_SERVER['PHP_SELF'] .'" method="post">
                <table cellspacing="0">
                <tr><td class="up"></td></tr>
                <tr><td class="head">Anti-spam code:</td></tr>
                <tr><td class="desc"><input type="text" name="spamcode" size="40" value=""/></td></tr>
                <tr><td class="down"></td></tr>
                <tr><td class="up"></td></tr>
                <tr><td class="head">Your name:</td></tr>
                <tr><td class="desc"><input type="text" name="name" size="40" value="'
. $name .'"/></td></tr>
                <tr><td class="down"></td></tr>
                <tr><td class="up"></td></tr>
                <tr><td class="head">Your email address:</td></tr>
                <tr><td class="desc"><input type="text" name="email" size="40" value="'
. $email .'"/></td></tr>
                <tr><td class="down"></td></tr>
                <tr><td class="up"></td></tr>
                <tr><td class="head">Subject:</td></tr>
                <tr><td class="desc"><input type="text" name="subject" size="40" value="'
. $subject .'"/></td></tr>
                <tr><td class="down"></td></tr>
                <tr><td class="up"></td></tr>
                <tr><td class="head">Message:</td></tr>
                <tr><td class="desc">
                <textarea name="message" rows="10" cols="60">'
. $message .'</textarea></td></tr>
                <tr><td class="down"></td></tr>'
.
                $error .'</table><p><input type="submit" name="submit" value="Send"/></p></form>';
}

/***    getIp
*       Returns ip-address
*/

function getIp() {
        if ($_SERVER['HTTP_X_FORWARDED_FOR']) {
                $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif ($_SERVER['HTTP_CLIENT_IP']) {
                $ip = $_SERVER['HTTP_CLIENT_IP'];
        } else {
                $ip = $_SERVER['REMOTE_ADDR'];
        }
        return $ip;
}

/***    isValidEmail
*       Returns true if given email address is considered valid. In other case returns false.
*       $email = emails address to be checked.
*/

function isValidEmail($email) {
        return (eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $email)) ? true : false
}

/***    isValidSpamCode
*       Returns true if user-given anti-spam code equals with $_SESSION['spamcode']. In other case returns false.
*       $formcode = anti-spam code to be checked.
*/

function isValidSpamCode($formcode) {
        return ($formcode == $_SESSION['spamcode']) ? true : false;
}

/***    newSpamCode
*       Generates new 5 characters long anti-spam code
*       If you change the length of the anti-spam code, you also have to change the image dimensions in image.php
*/

function newSpamCode() {
        $_SESSION['spamcode'] = substr(md5(uniqid(rand(), true)), 0, 5);
}
//            Function section ends


//##### You propably want to change at least some of these
//      Text before the form
$heading = "Welcome to my plah plah plaa... Your IP address will also be submitted.";
//      Page title
$pagetitle = "Contact Page";
//      Css-filename
$cssfilename = "mailer.css";
//      Insert one or more email recipients here
//      one: array("xxx@yyy.zzz");
//      many: array("xxx@xxx.xx", "yyy@yyy.yy", "zzz@zzz.zz");
$emails = array("");   
//#####

session_start();
header("Cache-control: private");

if (isset($_POST['submit'])) { 
       
        //      Checking fields
        $error = "Please check your ";
        //      Checking anti-spam code
        if (isValidSpamCode($_POST['spamcode'])) {
                $errorend = ". Rewrite your anti-spam code.";
        } else {
                $error .= "anti-spam code, ";
                $errorend = ".";
        }
       
        //      Checking name, email, subject and message
        $error .= ($_POST['name'] != "" && strlen($_POST['name']) < 50) ? "" : "name, ";
        $error .= (isValidEmail($_POST['email']) && strlen($_POST['email']) < 50) ? "" : "email address, ";
        $error .= ($_POST['subject'] != ""  && strlen($_POST['name']) < 100) ? "" : "subject, ";
        $error .= ($_POST['message'] != "" && strlen($_POST['name']) < 100000) ? "" : "message, ";
       
        //      No errors == no comma in the error string.
        if ($lastcomma = strrpos ($error, ",") === false) {     
                //      Everything is just fine, trying to send mail
                $mail = "\nSending moment: ". date("l dS of F Y H:i:s") .
                                "\nSender IP-address: ". getIp() .
                                "\n\nName: " . $_POST['name'] .
                                "\nEmail: " . $_POST['email'] .
                                "\nSubject: " . $_POST['subject'] .
                                "\n\nMessage: \n" . $_POST['message'] . "\n";
                               
                $from"From: contactpage@{$_SERVER['SERVER_NAME']}\r\n" .
                                "Reply-To: ". $_POST['email'] ."\r\n" .
                                "MIME-Version: 1.0\r\n" .
                                "X-Mailer: PHP/" . phpversion() ."\r\n" .
                                "Content-type: text/plain; charset=\"iso-8859-1\"\r\n";
               
                $mailcount = 0;
                //      Loop for sending mail
                foreach ($emails as $email) {
                        if (@mail($email, $_POST['subject'], $mail, $from)) {
                                $mailcount++;
                        } else {
                                $mailcount--;
                        }
                }
               
                $_SESSION=array();
                if (isset($_COOKIE[session_name()])) {
                        setcookie(session_name(), '', time()-42000, '/');
                }
                session_destroy();
               
                echo basicXhtmlStart($pagetitle, $cssfilename);
               
                $addressCnt = count($emails);
                if ($addressCnt + $mailcount == 0) {
                        $sendsucc = "There were some major difficulties with the server, please try again later.";
                } elseif ($addressCnt == $mailcount) {
                        $sendsucc = "Your Mail Was Succesfully Sent! Thank You.";
                } else {
                        $sendsucc = "There was a small problem with the server, you could try again later.";
                }
               
                echo "<h1>". $sendsucc ."</h1>";
       
        //      There is something wrong with the fields, showing prefilled form with an error message       
        } else {       
                //      Cleaning the error message
                $error = substr($error, 0, $lastcomma-2);
                $error = preg_replace("/,\s*([a-zA-Z_0-9 ]+)$/", " and \\1", $error) . $errorend;
                newSpamCode();
               
                echo basicXhtmlStart($pagetitle, $cssfilename);
                echo showMailForm($heading, $_POST['name'], $_POST['email'], $_POST['subject'], $_POST['message'], $error);
        }
} else {
        newSpamCode();
       
        echo basicXhtmlStart($pagetitle, $cssfilename);
        echo showMailForm($heading);
}       

echo basicXhtmlEnd();   
?>



TIEDOSTO image.php alkaa:
<?php
        session_start();
        header("Cache-control: private");
        header("Content-type: image/png");
        $im = @imagecreate(74, 30)
           or die("Unable to create new image");
        $background_color = imagecolorallocate($im, 180, 200, 150);
        $text_color = imagecolorallocate($im, 12, 14, 91);
        imagestring($im, 5, 15, 8, $_SESSION['spamcode'], $text_color);
        imagepng($im);
        imagedestroy($im);
?>



TIEDOSTO mailer.css alkaa:
body {
        background-color:#FAEBD7;
}

p{
        font-family:Verdana,Arial,Courier,Times New Roman,Comic Sans MS,Serif;
        font-size:80%;
        font-style:normal;
        font-weight:500;
        color:#222222;
}

h1{
        font-family:Verdana,Arial,Courier,Times New Roman,Comic Sans MS,Serif;
        font-size:120%;
        font-style:normal;
        font-weight:900;
        color:#aa6644;
}

TABLE{
        width: 400px;
        border-style: outset;
        border-color: #8A7E5E;
        border-width: 3px;
}

TD{
        background-color:#fafafa;
        font-family:Verdana,Arial,Courier,Times New Roman,Comic Sans MS,Serif;
        text-align:left;
        font-size:70%;
}

TD.down{
        background-color:#AAAAAA;
}
TD.up{
        background-color:#CCCCCC;
}

TD.head{
        background-color:#DDDEDD;
        letter-spacing:1px;
        font-style:normal;
        font-weight:900;
        color:#222222;
        text-align:left;
        padding-left:1em;
}

TD.desc{
        background-color:#EADECE;
        text-align:right;
}

TD.errcode{
        background-color:#EADECE;
        letter-spacing:1px;
        font-style:normal;
        font-weight:100;
        color:#cc2222;
        text-align:left;
}

TEXTAREA{
        width: 395px;
        height: 120px;
}

 

uffis 14:56 16.1.05 
Muuten hyvä, mutta asettaa ylitsepääsemättömiä esteitä mm. näkövammaisille.

Sen sijaan, että kirjoittaisit
function isValidSpamCode($formcode) {
    return ($formcode == $_SESSION['spamcode']) ? true : false;
}
voisit kirjoittaa
function isValidSpamCode($formcode) {
    return ($formcode == $_SESSION['spamcode']);
}
hjuw 16:36 16.1.05 
Totta. En omaa kyllä mitään tietämystä millaiset laitteet näkövammaisilla on sivujen ymmärtämiseen. Samoin asia on ilmeisesti silloin, jos sivulla esitetään sähköpostiosoitteet kuvina.

Esittämäsi funktion palautus oli hyvä huomautus, varmaan nopeampi tapa. Käyttöönottajat(?) saavat vapaasti muokata koodia, koodivinkiksi moisen toteuttamiselle tämä oli tarkoitettukin. Samoin $muuttuja != "" kohdat kannattanee muuttaa empty($muuttuja) muotoon.
editoitu: 22:47 16.1.05
uffis 22:47 16.1.05 
Karkeasti näkövammaisten laitteita voi jäljitellä siten, että katsoo sivuja lynxillä tai linksillä. Kuvia tai niissä olevaa informaatiota ei siis näe, ja siitä syystä onkin tärkeää antaa kuvien alt-attribuuteille sisältö, joka kertoo, mitä kuvassa näkyy. Tarkempia tietoja ruudunlukijoista saa googlettamalla hakusanoilla "screen reader" tai esim. sivulta http://www.kolumbus.fi/vesa.huotari/esitykset/saavutettavuus/saavutettava_palvelu.htm.

Samoin $muuttuja != "" kohdat kannattanee muuttaa empty($muuttuja) muotoon.
Yleensä ei kannata, jos on tarkoitus sallia merkkijonot, joiden sisältö on esim. numero nolla ("0"), koska empty katsoo sen tyhjäksi. Mieluummin käyttää samaa tapaa kuin mitä itsekin olet käyttänyt, tai tarkistaa merkkijonon pituuden strlen-funktiolla nollaa vastaan.
hjuw 12:28 17.1.05 
Alt-attribuuttiin spam-koodin sijoittaminen vain pilaa tämän skriptini idean, eli lomaketta skriptin kautta hyödyntävällä tulisi olla ocr-tekniikkaa käytössään.

Yleissäännöksi empty:n käyttö ei käy, mutta tässä nimenomaisessa skriptissä empty-funktiota(tai pituutta tosiaan verraten nollaan) voisi mielestäni käyttää, ainoat johon nolla sopisi edes auttavasti, ovat aihe ja viesti, eivätkä ole kovin kuvaavia kummassakaan tapauksessa sivupalautteeksi.
Ztane 00:22 20.1.05 
hjuw kirjoitti:
Alt-attribuuttiin spam-koodin sijoittaminen vain pilaa tämän skriptini idean, eli lomaketta skriptin kautta hyödyntävällä tulisi olla ocr-tekniikkaa käytössään.
Sun pitää laittaa sokeille avautuun puhuttuna :d
kpl 01:06 23.1.05 
Moro,
Väsäsin koodinpätkän joka lukee kuvasta merkkijonon ja tulostaa sen:
http://mureakuha.com/koodikirjasto/685

Eli on varsin helppoa ohittaa tuo tarkistus, josta esimerkkinä lähettämäni koodinpätkä.
hjuw 15:57 23.1.05 
kpl kirjoitti:
Moro,
Väsäsin koodinpätkän joka lukee kuvasta merkkijonon ja tulostaa sen:
http://mureakuha.com/koodikirjasto/685

Eli on varsin helppoa ohittaa tuo tarkistus, josta esimerkkinä lähettämäni koodinpätkä.


hjuw kirjoitti:
...eli lomaketta skriptin kautta hyödyntävällä tulisi olla ocr-tekniikkaa käytössään.


Moro.

Joten? Ei tarkoitus ollutkaan ettei juuri tuota olisi mahdollista ohittaa, ja jopa veikkasinkin jonkun tuon vetävän ns. lyttyyn hienolla tunnistusskriptillä. Mutta tätä versiotani voi muokata vapaasti, laitetaan hieman erivärisiä viivoja, kulmioita ja palloja sekaisin päälle, fonttikoot arvotaan, muutetaan kirjainväliä ja värejä, sekä sijaintia kuvassa joka merkille erikseen. Samoin tietty taivutetaan ja käännetään kirjainmallia. Koodivinkki = ei valmis toteutus, vaan muokkaamiskelponen. Katso esim. M$ passport palveluun rekisteröitymiskuvaa, ja rakenna siihen tunnistusskipti. Siitä ei tosin meinaa saada silmälläkään selvää.
hjuw 21:01 23.1.05 
Höh, ei sauniksen serverillä ollutkaan freetypelle ymmärrystä. Php:n fontteja on pelkällä gd:llä hieman huono muokata jotta merkeistä vielä saisi selvää, mutta kevyesti muokattu image.php löytyy käytöstä osoitteesta: http://netti.nic.fi/~052972/mailer/mailer2.php

Jos skriptini idea olisi ollut esitellä gd-kirjastoa, olisi se saattanut viedä suuremman osan koodista kuin muu tauhka.