简单的 PHP 联系表与垃圾邮件

问题描述 投票:0回答:1

我意识到这可能是不好的做法,但是......我使用了一个简单的 php 脚本,这是我在多年前阅读的一本教程书的帮助下编写的。我已经尽可能多地对其进行了调整以用于多个站点,但它在各个站点之间基本相同。我已经尝试并尝试消除垃圾邮件类型的消息,但可惜我无法弄清楚我还能做什么/可以做什么。我敢肯定有人会提到这一点,例如Javascript 会更好,但我现在没有时间或动力去学习它,所以请坚持使用 PHP。具体代码如下,对于如何在未来证明这一点以消除垃圾邮件的建议将不胜感激。

联系方式:

<?php 

    define ('SITE_KEY', '...');
    define ('SECRET_KEY', '...');

if (array_key_exists('send', $_POST)) {
    
    function getCaptcha($SecretKey) {
        $Response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".SECRET_KEY."&response={$SecretKey}");
        $Return = json_decode($Response);
        return $Return;
    }
    $Return = getCaptcha($_POST['g-recaptcha-response']);
    //var_dump($Return);
    
    // mail processing script
    $to = 'email1';
    $me = 'email2';
    $subject = 'Feedback From Website';
    
    // list expected fields
    $expected = array('name', 'email', 'question');
    // set required fields
    $required = array('name', 'email', 'question');
    
    // set additional headers
    $headers = 'From: Megan Roth<[email protected]>';

    // set the include
    $process = 'includes/process.inc.php';
    if (file_exists($process) && is_readable($process)) {
        include($process);
    }
    else {
        $mailSent = false;
        mail($me, 'Server Problem', "$process cannot be read", $headers);
    }
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:title" content="Megan Roth, Mezzo-Soprano - Contact">
<meta property="og:type" content="website">
<meta property="og:image" content="http://www.meganroth.com/EditedImages/index.jpg">
<meta property="og:url" content="http://www.meganroth.com/contact.php">
<meta property="og:description" content="Mezzo-soprano Megan Roth enjoys a career as a soloist in opera and oratorio as well as with prestigious chamber ensembles around the country.">
<title>Megan Roth, Mezzo-Soprano - Contact</title>
<meta name="description" content="Mezzo-soprano Megan Roth enjoys a career as a soloist in opera and oratorio as well as with prestigious chamber ensembles around the country.">
<meta name="author" content="Nathan Roth" >
<link href="css/w3_parallax_template.css" type="text/css" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Crimson+Pro">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=EB+Garamond">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Domine">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="css/parallax12.css" type="text/css" rel="stylesheet">
<style>


/************* ABOVE THIS LINE GLOBAL ***************/

form { width: 100%; }
form p { margin: 0px 0px 25px 20px; }
textarea {
    width: 380px;
    height: 150px;
}
@media screen and (max-width: 400px) { textarea {
            width: 240px;
            height: 120px;
} }
.textInput { width: 300px; }
@media screen and (max-width: 400px) { .textInput { width: 125px; } }
.sendButton { border:1px solid #000000!important; color: #000; background-color: #FAC41E; }
.sendButton:hover { border:1px; color:#000000; background-color: #08748F; }
form .website{ display:none; } /* hide because is spam protection */
.conStudio {
    font-family: "EB Garamond", Times, "Times New Roman", serif;
    font-size: 1.4em;
    line-height: 1.68em;
    color: #FAC41E;
    font-weight: bold;
    margin: 0px 0px 0px 0px;
}
</style>
<script>
    <!--
    function MM_validateForm() { //v4.0
      if (document.getElementById){
        var i,p,q,nm,test,num,min,max,errors='',args=MM_validateForm.arguments;
        for (i=0; i<(args.length-2); i+=3) { test=args[i+2]; val=document.getElementById(args[i]);
          if (val) { nm=val.name; if ((val=val.value)!="") {
            if (test.indexOf('isEmail')!=-1) { p=val.indexOf('@');
              if (p<1 || p==(val.length-1)) errors+='- '+nm+' must contain an e-mail address.\n';
            } else if (test!='R') { num = parseFloat(val);
              if (isNaN(val)) errors+='- '+nm+' must contain a number.\n';
              if (test.indexOf('inRange') != -1) { p=test.indexOf(':');
                min=test.substring(8,p); max=test.substring(p+1);
                if (num<min || max<num) errors+='- '+nm+' must contain a number between '+min+' and '+max+'.\n';
        } } } else if (test.charAt(0) == 'R') errors += '- '+nm+' is required.\n'; }
        } if (errors) alert('The following error(s) occurred:\n'+errors);
        document.MM_returnValue = (errors == '');
    } }
    //-->
    </script>
    <script src="https://www.google.com/recaptcha/api.js?render=6LcEl-8UAAAAAMlzOfIDXmnooj34lkDNfKDTxN2m"></script>
    <!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-34193066-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-34193066-1');
</script>
</head>
<body>

<?php include("includes/new_navigation12.inc.php"); ?>

<!-- Container  -->
<div class="w3-content w3-container w3-padding-64">
  <div class="w3-row">
            <div class="hdquote">
                &quot;…(her) soaring mezzo-soprano is clean and clear and her vocal glissandos precise and near perfect.&quot;<br>
                - <em>Asheville Citizen-Times</em><br>
                <strong>The Barber of Seville</strong>, Brevard Music Center.
                    <div class="decLine"></div>
            </div>
     </div>
            
        <div class="w3-row">
                    
         <div class="w3-col m9 w3-padding-large">  
            <?php 
            if ($_POST && isset($missing) && !empty($missing)) {
            ?>
            <p class="warning">Please complete the missing item(s) indicated.</p>
            <?php
            }
            elseif ($_POST && $linkOne) {
            ?>
            <p class="warning">Sorry, Messages that contain inappropriate data will not be sent.</p>
            <?php
            }
            elseif ($_POST && $linkTwo) {
            ?>
            <p class="warning">Sorry, Messages that contain inappropriate data will not be sent.</p>
            <?php
            }
            elseif ($_POST && $linkThree) {
            ?>
            <p class="warning">Sorry, Messages that contain inappropriate data will not be sent.</p>
            <?php
            }
            elseif ($_POST && !$mailSent) {
            ?>
            <p class="warning">Sorry, there was a problem sending your message. Please try again later.</p>
            <?php
            }
            elseif ($_POST && $Return->success == true && $Return->score > 0.5 && $mailSent) {
            ?>
            <p class="success">Your message has been sent. Thank you for your comments/questions!</p>
            <?php } ?>           
            <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="contact" id="contact" class="w3-container w3-card-4" onSubmit="MM_validateForm('name','','R','email','','RisEmail','comments','','R');return document.MM_returnValue">
            <p><input name="website" type="text" class="website"></p>
              <p>
                <label for="name">Name: <?php
                if (isset($missing) && in_array('name', $missing)) { ?>
                <span class="warning">Please enter your name</span><?php } ?>
                </label>
                <input name="name" type="text" class="textInput" id="name" 
                <?php if (isset($missing)) {
                    echo 'value="'.htmlentities($_POST['name'], ENT_QUOTES).'"';
                    } ?>
                >
              </p>
              <p>
                <label for="email">Email: <?php
                if (isset($missing) && in_array('email', $missing)) { ?>
                <span class="warning">Please enter your email address</span><?php } ?>
                </label>
                <input name="email" type="text" class="textInput" id="email"
                <?php if (isset($missing)) {
                    echo 'value="'.htmlentities($_POST['email'], ENT_QUOTES).'"';
                    } ?>
                >
              </p>
              <p>
                <label for="question">Comments:<?php
                if (isset($missing) && in_array('question', $missing)) { ?>
                <span class="warning">Please enter your comments</span><?php } ?>
                </label>
                <textarea name="question" id="question" cols="25" rows="5"><?php 
                    if (isset($missing)) {
                        echo htmlentities($_POST['question'], ENT_QUOTES);
                    } ?></textarea>
              </p>
              <p>
                        <input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response">              
              </p>
              <p>
                <input class="sendButton" type="submit" name="send" id="send" value="Click to Submit Comments">
              </p>
            </form>
            <script>
                    grecaptcha.ready(function() {
                        grecaptcha.execute('<?php echo SITE_KEY; ?>', {action: 'homepage'}).then(function(token) {
                           //console.log(token);
                           document.getElementById('g-recaptcha-response').value=token;
                        });
                    });
            </script>
            <p class="welcome">Please take this time to send comments and your email address so we can stay in touch with you!</p><br><br>
    </div>
    <div class="w3-col m3 w3-padding-large">
      <img class="border" src="EditedImages/Contact.jpg" alt="Headshot for Megan Roth's Contact Webpage">
   </div>
   </div>
        
   <div class="w3-row w3-center">
            <span class="conStudio">Interested in private lessons? Please visit my <a href="http://studio.meganroth.com/" onclick="window.open(this.href, '_blank');return false;">studio site!</a></span>
   </div>
  
</div>

<!-- Footer -->
<?php include("includes/new_footer12.inc.php"); ?>

<script>
// Change style of navbar on scroll
window.onscroll = function() {myFunction()};
function myFunction() {
    var navbar = document.getElementById("myNavbar");
    if (document.body.scrollTop > 100 || document.documentElement.scrollTop > 100) {
        navbar.className = "w3-bar" + " w3-card" + " w3-animate-top" + " w3-white";
    } else {
        navbar.className = navbar.className.replace(" w3-card w3-animate-top w3-white", "");
    }
}

// Used to toggle the menu on small screens when clicking on the menu button
function toggleFunction() {
    var x = document.getElementById("navDemo");
    if (x.className.indexOf("w3-show") == -1) {
        x.className += " w3-show";
    } else {
        x.className = x.className.replace(" w3-show", "");
    }
}

// Toggle between showing and hiding the sidebar, and add overlay effect
function w3_open() {
  if (mySidebar.style.display === 'block') {
    mySidebar.style.display = 'none';
    overlayBg.style.display = "none";
  } else {
    mySidebar.style.display = 'block';
    overlayBg.style.display = "block";
  }
}

// Close the sidebar with the close button
function w3_close() {
  mySidebar.style.display = "none";
  overlayBg.style.display = "none";
}

/* When the user clicks on the button, 
toggle between hiding and showing the dropdown content */
function myFunction() {
  document.getElementById("myDropdown").classList.toggle("w3-show");
}

// Close the dropdown if the user clicks outside of it
window.onclick = function(e) {
  if (!e.target.matches('.dropbtn')) {
  var myDropdown = document.getElementById("myDropdown");
    if (myDropdown.classList.contains('w3-show')) {
      myDropdown.classList.remove('w3-show');
    }
  }
}
</script>

</body>
</html>

现在是实际的邮件处理脚本:

<?php

        # spam protection
        if (isset($_POST["website"]) && $_POST["website"] == "") {      
        
        if (isset($_SERVER['SCRIPT_NAME']) && strpos($_SERVER['SCRIPT_NAME'], 'inc.php')) exit;
    
        // remove escape characters from POST array
        if (get_magic_quotes_gpc()) {
            function stripslashes_deep($value) {
                $value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value);
                return $value;
            }
          $_POST = array_map('stripslashes_deep', $_POST);
        }
    
        // create empty array for any missing fields
        $missing = array();
        
        // assume that there is nothing suspect
        $suspect = false;
        // create a pattern to locate suspect phrases
        $pattern = '/Content-Type:|Bcc:|CC:/i';
        // function to check for suspect phrases
        function isSuspect($val, $pattern, &$suspect) {
        // if the variable is an array, loop through each element
        // and pass it recursively back to the same function
        if (is_array($val)) {
          foreach ($val as $item) {
            isSuspect($item, $pattern, $suspect);
            }
        }
        else {
          // if one of the suspect phrases is found, set Boolean to true
          if (preg_match($pattern, $val)) {
            $suspect = true;
            }
          }
        }
        
        // check the $_POST array and any subarrays for suspect content
        isSuspect($_POST, $pattern, $suspect);
        
        if ($suspect ) {
            $mailSent = false;
            unset($missing);
        }
        else {
        // process the $_POST variables
            foreach ($_POST as $key => $value) {
                // assign to temporary variable and strip whitespace if not an array
                $temp = is_array($value) ? $value : trim($value);
                // if empty and required, add to $missing array
                if (empty($temp) && in_array($key, $required)) {
                    array_push($missing, $key);
                }
                // otherwise, assign to a variable of the same name as $key
                elseif (in_array($key, $expected)) {
                    ${$key} = $temp;
                }
            }
        }
        
        // validate the email address
        if (!empty($email)) {
            // regex to identify illegal characters in email address
            $checkEmail = '/^[^@]+@[^\s\r\n\'";,@%]+$/';
            // reject the email address if it doesn't match
            if (!preg_match($checkEmail, $email)) {
                $suspect = true;
                $mailSent = false;
                unset($missing);
            }
        }
        
        // validate the comments
        // regex to identify html links
        $linkOne = false;
        $checkCommentsLinks = '/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i'; // '/(http:\/\/|www)/';
        if(preg_match($checkCommentsLinks, stripcslashes($question))){
            $linkOne = true;
            $suspect = true;            
            $mailSent = false;
            unset($missing);
        }
        
        //validate comments against email addresses
        $linkTwo = false;
        $checkCommentsEmail = '/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/';
        if(preg_match($checkCommentsEmail, stripcslashes($question))){
            $linkTwo = true;
            $suspect = true;            
            $mailSent = false;
            unset($missing);
        }
        
        //look for links in comments
        $linkThree = false;
        if(preg_match('/http|www/i',$question)) {
            $linkThree = true;
            $suspect = true;            
            $mailSent = false;
            unset($missing);
        }
        
        // go ahead only if not suspect and all required fields OK
        if (!$suspect && empty($missing)) {
            // initialize the $message variable
            $message = '';
            // loop through the $expected array
            foreach($expected as $item) {
                // assign the value of the current item to $val
                if (isset(${$item})) {
                    $val = ${$item};
                }
                // if it has no value, assign 'Not Selected'
                else {
                    $val = 'Not selected';
                }
                // if an array, expand as comma-separated string
                if (is_array($val)) {
                    $val = implode(', ', $val);
                }
                // add label and value to the message body
                $message .= ucfirst($item).": $val\n\n";
                }
        
            // limit line length
            $message = wordwrap($message, 70);
            
            // create Reply-To header
            if (!empty($email)) {
                $headers .= "\r\nReply-To: $email";
            }
        
            // send it
            $mailSent = mail($to, $subject, $message, $headers);
            if ($mailSent) {
                // $missing is no longer needed if the email is sent, so unset it
                unset($missing);
            }
        }
        } 
        else {
            http_response_code(400);
            exit;
        }
?>

最近我真正反对的是最新的垃圾邮件实际上是在发送一封主题行(不知道主题从哪里来)以“SPAM”开头的电子邮件。任何帮助将不胜感激!感谢阅读!

php email spam-prevention email-spam
1个回答
0
投票

没有防止垃圾邮件的未来证据,您已经使用三种方法来防止它

  1. 验证码
  2. 在发送的数据中匹配某些垃圾词,您可以添加更多垃圾词
  3. 蜜罐

可以添加

  1. CSRF 代币
  2. 测量发送表格所需的时间,例如。如果表格在不到 30 秒内发送,则值得怀疑
  3. 生成动态输入名称
  4. 在客户端使用 javascript 验证数据

在你的

isSuspect
函数中,你应该在
$suspect
为真时中断,这样你就不必检查所有其他值

//...
foreach ($val as $item) {
   isSuspect($item, $pattern, $suspect);
   if ($suspect)
       break;
}
//...

测量时间的例子

生成表格时节省时间

session

session_start();
$_SESSION['form_time'] = time();

提交表格时检查时间:

session_start();
$time_limit = 30; 
$suspect = false;

if (isset($_SESSION['form_time']) && is_numeric($_SESSION['form_time'])) {
    $seconds_passed = time() - $_SESSION['form_time'];
    if ($seconds_passed < $time_limit) {
       $suspect = true;
    } 
} else {
    $suspect = true;
}

注意: 如果用户打开多个表单,值将被覆盖,将使用最后一个值,之前打开的表单将失效

这只是基本方法,有很多方法可以实现,30秒只是我选择的任意值

© www.soinside.com 2019 - 2024. All rights reserved.