locked
Using Web Helpers Captcha on Email Contact Form RRS feed

  • Question

  • User-871665172 posted

    Hi,

    I'm trying to add Captcha to my email form to stop spam, but I'm struggling.  There's no Web Pages tutorials that I can find which combine Captcha with email, so I'm trying to achieve this by combining the information from the two Web Pages tutorials on Captcha below:

    https://docs.microsoft.com/en-us/aspnet/web-pages/overview/security/16-adding-security-and-membership

    https://docs.microsoft.com/en-us/aspnet/web-pages/overview/security/using-a-catpcha-to-prevent-automated-programs-bots-from-using-your-aspnet-web-site

    I can get the tutorial 'Using a CAPTCHA to Prevent Bots from Using Your ASP.NET Web Razor) Site ' working and I know my email form works. The issues I'm having relate to combining the validation for Captcha with the validation for email along with using multiple if else statements.

    I stopped trying to combine the Captcha validation messages, instead I decided to just add Captcha validation to the email sending code, because if that code is not validated a message is shown anyway.

    But, no matter what I try, if the form fields are filled in correctly, but Captcha 'is not' filled in correctly, the email still sends OK when the form is submitted.  I cannot get the form 'not to send' when Captcha is not validated and 'to send' when it is. 

    I've had too many different attempts to list;  so , here are just two versions of the code I've tried. If you are kind enough to help get this working, please treat me like a dummy when you reply.  

    This could help others too, if working. Thanks.

    1st Method, using the Starter template 'adding security and membership tutorial'.

    @using Microsoft.Web.Helpers;
    @{
        Page.Title = "";
    
        var message = "";
        var emailAddress = Request.Form["emailAddress"];
        var emailSubject = Request.Form["emailSubject"];
        var emailBody = Request.Form["emailBody"];
    
    
       try{
            if (IsPost && Validation.IsValid()) {
    
            // Captcha code added from - https://docs.microsoft.com/en-us/aspnet/web-pages/overview/security/16-adding-security-and-membership
    
            if (!ReCaptcha.Validate("PRIVATE_KEY")) {
                ModelState.AddFormError("Captcha response was not correct.");
            }
                        
                // Send email
                WebMail.Send(to:"MY_EMAIL_ADDRESS",
                subject: Request.Form["emailSubject"],
             
                body: "Help request from -   " + Request.Form["customerName"] + " <br/>" + "Email Subject -   " + Request.Form["emailSubject"]  + " <br/> " + "Customer email -   " + Request.Form["emailAddress"]  + " <br/> " + "Request -   " + Request.Form["emailBody"]
               );
               message = "Thank you, Email sent!";
            }
        }
        catch(Exception ex){
            message = "Email could not be sent!";
        }
    }
    
    
    @section AdditionalMeta
    {
    <!-- Meta -->
       <meta name="robots" content="index, follow">
       <meta name="description" content="" />   
    }
    
    
    <div class="container">
    
        <div class="row" style="margin-top: 20px; margin-bottom: 20px;">
    
            <div class='well col-xs-12 col-sm-12 col-md-6'>
     
                <form role="form" method="post">
     
                @if(IsPost){
                <span class="alert alert-success">@message</span>
                }
        
                <h3>Email Contact Form</h3>
     
                <div class="form-group">
                <label for="customerName">Full Name:</label>
                <input  type="text" class="form-control" name="customerName" id="customerName" placeholder="Name" required="">
                </div>
     
                <div class="form-group">
                <label for="emailSubject">Subject:</label>
                <input  type="text" class="form-control" name="emailSubject"  id="emailSubject"  placeholder="e.g. Quote" required="">
                </div>
     
    
                <div class="form-group">
                <label for="emailAddress">Email Address:</label>
                <input  type="email" class="form-control" name="emailAddress"  id="emailAddress"  placeholder="e.g. me@me.com" required="">
                </div>
     
     
                <div class="form-group">
                <label for="emailBody">Text Area:</label>
                <textarea  class="form-control" name="emailBody" rows="10" id="emailBody"  placeholder="Enter Details" required=""></textarea>
                </div>
    
               <!-- Captcha code added from - https://docs.microsoft.com/en-us/aspnet/web-pages/overview/security/16-adding-security-and-membership -->
                @ReCaptcha.GetHtml("PUBLIC_KEY", theme: "white")
    
                <p class="form-actions">
                    <input type="submit" value="Register" title="Register" />
                </p>
     
                </form>
    
            </div><!--/well -->
        </div><!--/row-->
    </div><!--/container -->


    Here's the second using the 'Use Captcha to prevent bots tutorial' 

    App Start Page:

    @{
    
    //Mailbox
         WebMail.SmtpServer = "host";
         WebMail.SmtpPort = 25;
         WebMail.EnableSsl = true;
         WebMail.UserName = "email address";
         WebMail.Password = "password";
         WebMail.From = "from email address";
    
    
    }
    
    @using Microsoft.Web.Helpers;
    @{
      // Add the PublicKey and PrivateKey strings with your public
      // and private keys. Obtain your PublicKey and PrivateKey
      // at the ReCaptcha.Net (http://recaptcha.net) website.
      ReCaptcha.PublicKey = "PUBLIC_KEY";
      ReCaptcha.PrivateKey = "PRIVATE_KEY";
    }

    Email form page

    @using Microsoft.Web.Helpers;
    @{
        Page.Title = ";
    
        var message = "";
        var emailAddress = Request.Form["emailAddress"];
        var emailSubject = Request.Form["emailSubject"];
        var emailBody = Request.Form["emailBody"];
        
        // Added captcha code from - https://docs.microsoft.com/en-us/aspnet/web-pages/overview/security/using-a-catpcha-to-prevent-automated-programs-bots-from-using-your-aspnet-web-site
        var showRecaptcha = true;
        
    
        try{
            if (IsPost && Validation.IsValid()) {
               
                // Added captcha code
               if (ReCaptcha.Validate()) {
               
                
                // Send email
                WebMail.Send(to:"MY_Email_Address",
                subject: Request.Form["emailSubject"],
             
                body: "Help request from -   " + Request.Form["customerName"] + " <br/>" + "Email Subject -   " + Request.Form["emailSubject"]  + " <br/> " + "Customer email -   " + Request.Form["emailAddress"]  + " <br/> " + "Request -   " + Request.Form["emailBody"]
               );
               message = "Thank you, Email sent!";
            } }
        }
        catch(Exception ex){
            message = "Email could not be sent!";
        }
    }
    
    
    @section AdditionalMeta
    {
    <!-- Meta -->
       <meta name="robots" content="index, follow">
       <meta name="description" content="" />   
    
    }
    
    
    
    <div class="container">
        <div class='row'>
        <div class='well col-xs-12 col-sm-12 col-md-6'>
     
            <form role="form" method="post">
     
            @if(IsPost){
            <span class="alert alert-success">@message</span>
            }
        
            <h3>Email Contact Form</h3>
     
            <div class="form-group">
              <label for="customerName">Full Name:</label>
              <input  type="text" class="form-control" name="customerName" id="customerName" placeholder="Name" required="">
            </div>
     
            <div class="form-group">
              <label for="emailSubject">Subject:</label>
              <input  type="text" class="form-control" name="emailSubject"  id="emailSubject"  placeholder="e.g. Quote" required="">
            </div>
     
    
            <div class="form-group">
              <label for="emailAddress">Email Address:</label>
              <input  type="email" class="form-control" name="emailAddress"  id="emailAddress"  placeholder="e.g. me@me.com" required="">
            </div>
     
     
            <div class="form-group">
              <label for="emailBody">Text Area:</label>
              <textarea  class="form-control" name="emailBody" rows="10" id="emailBody"  placeholder="Enter Details" required=""></textarea>
            </div>
    
            <!-- Added captcha code-->
            @if(showRecaptcha == true){
                if(ReCaptcha.PrivateKey != ""){
                <p>@ReCaptcha.GetHtml()</p>
                <input type="submit" value="Submit" title="Send" />      
                }
            }
    
    
            <br />
     
            </form>
        </div><!--/well -->
       </div><!--/row -->
     </div><!--/container -->
    Tuesday, August 8, 2017 7:07 AM

All replies

  • User-871665172 posted

    The following which includes the Captcha error messages again, seems pretty close. The email is being sent when the form is completed correctly and the Captcha messages are working correctly, but if Captcha is 'not completed', the email is still sent.

    I have tried to replicate the registration Captcha logic in the correct order from the add security and membership tutorial, but failure to complete Captcha is not stopping the form from being submitted.

    I cannot understand why the email 'try, if validation is valid' statement is not depending on the ' if Captcha is validated' statement.  Isn't the code saying, 'if Captcha is validated', 'try (if form is valid) to send the email'?

    UPDATE: JQuery validate was missing from my code, but adding it has not made a difference.

    @using Microsoft.Web.Helpers;
    @{
        Page.Title = "";
    
        var message = "";
        var emailAddress = Request.Form["emailAddress"];
        var emailSubject = Request.Form["emailSubject"];
        var emailBody = Request.Form["emailBody"];
    
            if (IsPost) {
    
            if (!ReCaptcha.Validate("PRIVATE_KEY")) {
                ModelState.AddError("recaptcha", "Captcha response was not correct");
            }
    
             try{
                 
                 if (Validation.IsValid()) {
               
                // Send email
                WebMail.Send(to:"EMAIL_ADDRESS",
                subject: Request.Form["emailSubject"],
             
                body: "Help request from -   " + Request.Form["customerName"] + " <br/>" + "Email Subject -   " + Request.Form["emailSubject"]  + " <br/> " + "Customer email -   " + Request.Form["emailAddress"]  + " <br/> " + "Request -   " + Request.Form["emailBody"]
               );
               message = "Thank you, Email sent!";
            } 
        }
        catch(Exception ex){
            message = "Email could not be sent!";
        }
    }
    }
    
    @section AdditionalMeta
    {
    <!-- Meta -->
       <meta name="robots" content="index, follow">
       <meta name="description" content="" />   
    
    }
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.6/jquery.validate.unobtrusive.js"></script>
    
    
    <div class="container">
    <div class='row'>
            <div class='well col-xs-12 col-sm-12 col-md-6'>
     
            <form role="form" method="post">
     
            @if(IsPost){
            <span class="alert alert-success">@message</span>
            }
        
            <h3>Email Contact Form</h3>
     
            <div class="form-group">
              <label for="customerName">Full Name:</label>
              <input  type="text" class="form-control" name="customerName" id="customerName" placeholder="Name" required="">
            </div>
     
            <div class="form-group">
              <label for="emailSubject">Subject:</label>
              <input  type="text" class="form-control" name="emailSubject"  id="emailSubject"  placeholder="e.g. Quote" required="">
            </div>
     
    
            <div class="form-group">
              <label for="emailAddress">Email Address:</label>
              <input  type="email" class="form-control" name="emailAddress"  id="emailAddress"  placeholder="e.g. me@me.com" required="">
            </div>
     
     
            <div class="form-group">
              <label for="emailBody">Text Area:</label>
              <textarea  class="form-control" name="emailBody" rows="10" id="emailBody"  placeholder="Enter Details" required=""></textarea>
            </div>
    
                    @ReCaptcha.GetHtml("PUBLIC_KEY, theme: "white")
                    @Html.ValidationMessage("recaptcha")
           
      <input type="submit" value="Submit" title="Send" />      
    
            <br />
     
            </form>
        </div><!--/well -->
       </div><!--/row -->
     </div><!--/container -->
    
    Tuesday, August 8, 2017 9:10 AM
  • User347430248 posted

    Hi DaniB,

    instead of using nested if condition.

    you can try to make a test with flag variables.

    store the flag value of captcha validation and if it is validated then send the mail otherwise try to inform the user that captcha validation failed and perform it again.

    Regards

    Deepak 

    Wednesday, August 9, 2017 6:11 AM
  • User-871665172 posted

    Hi Deepak,

    Thanks for getting back to me; your help is appreciated.

    I’ve been wanting to add captcha to the contact form on this site for a long time, but I’m not very good with ASP Razor, as you can see.  I have not used ASP Razor since the site was built, which was years ago when I was in higher education and then I only used ASP Razor for a few months.

    When I began the other day, I thought there would be a tutorial on how to add Captcha when sending mail, because it is so necessary.  Believe it or not, I’ve already used up my full 2-day holiday on this, so I’m out of time.

    With regard to your approach, I think I understood what you were saying, but I wasn’t sure how I could use a variable for the Captcha HTML because it is ready-made by a helper.  I tried to research this, but maybe I was looking in the wrong place.  I may try to look into your approach in future.

    Regarding the approach I was taking, after looking at a page on Razor logic, I noticed statements could be reversed using a ‘!’.  So, I added a ‘!’ in front of the if statement to reverse it, saying, if Captcha is not validated show the Captcha error and Captcha HTML again, else send the email.

    It seems I managed to get everything working except combining the form validation with the Captcha validation.

    Because the whole statement is now wrapped in ‘Try’, the original form error message of "Email could not be sent!" tried to show, as well as the Captcha error message (ModelState.AddError("recaptcha", "Captcha response was not correct") if Captcha was not completed correctly.  I say tried to show, because the try catch error text ("Email could not be sent!") didn't show, but the Bootstrap alert box the text is inside did.

    I've tried all ways to get the Captcha validation to work with the form Try Catch validation, including giving all 3 messages different variable names, E.G. If Captcha is not valid show message1, if form is valid show message2 and if form is not valid show message3 - still no joy.

    I don’t have more time to figure out the validation correctly, so in the end I managed to just use the original form validation error message (message = "Email could not be sent!") for the Captcha message too, so both error messages still show, just in the same place.  This sort of plasters over the problem, but doesn’t fix the underlying issue. 

    From the user’s perspective, everything appears to work; however, I know this isn’t the right way to handle the validation.  Maybe somebody else who knows more can finish off the validation properly.  If they do, I’m sure it will be a big help to others like me.

    There was another issue, the form fields did not retain the form data if the form was submitted but failed validation; instead, users had to re-enter the form data.

    I thought that there must be a better way of handling this.  After doing a little more research I found a post on ‘Working with HTML Forms in ASP.NET Web Pages (Razor) Sites’, which included a section on ‘Restoring Form Values After Postbacks’

    But, it didn’t cover the textarea.  After more research, I found a post by Mike which shows how to do this too.

    Finally, I could not find a post or tutorial on adding Captcha to a web pages email form, so I think this post still has potential to help others if the validation gets finished off correctly – although it does somewhat work as it is.

    Thanks again Deepak.

    Here’s what I ended up with:

    Code for _AppStart.cshtml

    @{
     
    //Mailbox
         WebMail.SmtpServer = "";
         WebMail.SmtpPort = 25;
         WebMail.EnableSsl = true;
         WebMail.UserName = "ADD_YOUR_EMAIL_ADDRESS_HERE";
         WebMail.Password = "EMAIL_PASSWORD";
         WebMail.From = "ADD_YOUR_EMAIL_ADDRESS_HERE";
     
     
    }
     
    @using Microsoft.Web.Helpers;
    @{
      // Add the PublicKey and PrivateKey strings with your public
      // and private keys. Obtain your PublicKey and PrivateKey
      // at the Google Captcha site
      ReCaptcha.PublicKey = "ADD_YOUR_GOOGLE_CAPTCHA_PUBLIC_KEY_HERE";
      ReCaptcha.PrivateKey = "ADD_YOUR_GOOGLE_CAPTCHA_PRIVATE_KEY_HERE";
    }

    Code for _Contact-Us.cshtml (or whatever page is called)

    @using Microsoft.Web.Helpers;
    @{
        Page.Title = "";
        var message = "";
        var emailAddress = Request.Form["emailAddress"];
        var emailSubject = Request.Form["emailSubject"];
        var emailBody = Request.Form["emailBody"];
    
        var showRecaptcha = true;
    
          try{
    
          if (IsPost) {
            if (!ReCaptcha.Validate()) {
                message = "Email could not be sent, please check form fields and captcha!";
                showRecaptcha = true;
            }
            else{
    
            if (Validation.IsValid()) {
    
                WebMail.Send(to:"ADD_YOUR_EMAIL_ADDRESS_HERE",
                subject: Request.Form["emailSubject"],
             
                body: "Help request from -   " + Request.Form["customerName"] + " <br/>" + "Email Subject -   " + Request.Form["emailSubject"]  + " <br/> " + "Customer email -   " + Request.Form["emailAddress"]  + " <br/> " + "Request -   " + Request.Form["emailBody"]
               );
               message = "Thank you, Email sent!";
               }
           }
       }
    }
        catch(Exception ex){
            message = "Email could not be sent!";
        }
    }
            
    
    <div class="container">
    <div class='row'>
            <div class='well col-xs-12 col-sm-12 col-md-6'>
     
            <form role="form" method="post">
     
            @if(IsPost){
            <span class="alert alert-success">@message</span>
            }
        
            <h3>Email Contact Form</h3>
     
            <div class="form-group">
              <label for="customerName">Full Name:</label>
              <input  type="text" class="form-control" name="customerName" value="@Request.Form["customerName"]" id="customerName" placeholder="Name" required="">
            </div>
     
            <div class="form-group">
              <label for="emailSubject">Subject:</label>
              <input  type="text" class="form-control" name="emailSubject" value="@Request.Form["emailSubject"]"  id="emailSubject"  placeholder="e.g. Quote" required="">
            </div>
     
            <div class="form-group">
              <label for="emailAddress">Email Address:</label>
              <input  type="email" class="form-control" name="emailAddress" value="@Request.Form["emailAddress"]" id="emailAddress"  placeholder="e.g. me@me.com" required="">
            </div>
     
     
            <div class="form-group">
              <label for="emailBody">Text Area:</label>
              <textarea  class="form-control" name="emailBody" rows="10" id="emailBody"  placeholder="Enter Details" required="">@Request["emailBody"]</textarea>
            </div>
    
     @if(showRecaptcha == true){
            if(ReCaptcha.PrivateKey != ""){
                <p>@ReCaptcha.GetHtml()</p>
                <input type="submit" value="Submit" />
            }
          
        }
            <br />
     
            </form>
        </div><!--/well -->
       </div><!--/row -->
     </div><!--/container -->

    Footnote:

    In case anyone tries to use some of what I posted and the page won’t run.

    My earlier example included the code from ‘section A’ below.  The code in ‘section A’ is used in conjunction with the code in ‘section B’, which goes in the ‘_SiteLayout’ page, in order to add different ‘Meta tags’ for each page on the site. 

    So, if you include ‘section A’, you will need to use ‘section B too’.  Although, none of this is anything to do with sending email or Captcha, so for this example there’s no need to use either.

    Section A

    @section AdditionalMeta
    {
    <!-- Meta -->
       <meta name="robots" content="index, follow">
       <meta name="description" content="" />   
    }

    Section B (goes in _SiteLayout)

    @RenderSection("AdditionalMeta", false)

    Also, the form error message alert box and columns classes are Twitter Bootstrap v03, to get those to work you will need to reference them in the head section of your _SiteLayout page.

    Wednesday, August 9, 2017 10:23 AM
  • User-871665172 posted

    Hi,

    Does anyone know how to upgrade to Google ReCaptcha version 2.0 please?

    I'm getting the error message "recaptcha v1 is shutdown, direct site owners to g.co/recaptcha/upgrade".

    I have registered and obtained keys for version 2.0, but I'm not sure how to do the server side validation. I presume the web helpers library is now out of date.  Does anyone have ASP.NET Web Pages Razor CSHTML ReCaptcha v 2.0 example.code please or can suggest an edit to the above?

    Thanks.

    Saturday, June 2, 2018 11:26 AM
  • User-871665172 posted

    In case somebody else’s Captcha v1 has shutdown and they need a solution to get Captcha back up and running, I thought I’d answer my own question.

    Because Webmatrix 3 on my PC will no longer connect to the NuGet Gallery, I opened up the website in Visual Studio 2017 Community, then saved the site as a solution, which must be done before VS allows you to access NuGet, then I installed BotDetect CAPTCHA 4.4.1 instead.

    After removing the _AppStart.cshtml code containing the site and secret key for the old web helpers Captcha, I had to uncomment the new entries in the web.config file for registering the HttpHandler used for BotDetect ‘Traditional’ API requests.  However, you may not need to do this.

    Then, I implemented Captcha in my email contact form sort of like below, slightly differently from the tutorial guidance here and here. Don't forget to use the BotDetect.Web package at the top of the page.

    @using BotDetect.Web;
    @{
    Layout = "/shared/_SiteLayout.cshtml";
     
    var message = "";
    var message2 = "";
     
    Captcha exampleCaptcha = new Captcha("ExampleCaptcha"); 
    exampleCaptcha.UserInputID = "CaptchaCode"; 
     
                if ((Request.HttpMethod == "POST")) 
                { 
                bool isHuman = exampleCaptcha.Validate();
                if (isHuman) 
                {
                WebMail.Send(to:"**** ADD YOUR EMAIL ADDRESS HERE ****",
                subject: Request.Form["emailSubject"],
                body: "<h3>Help request from</h3> -   " + Request.Form["customerName"] + " <br><br> " + "<h3>Email Subject</h3> -   " + Request.Form["emailSubject"]  + " <br><br> " + "<h3>Customer email</h3> -   " + Request.Form["emailAddress"]  + " <br><br>  " + "<h3>Request</h3> -   " + Request.Form["emailBody"]
                );
                message = "Email sent! Thank you."; 
                }
                else
                {
                message2 = "Send failure. Retype code & try again!";
            }
        }
    }
    <style>
        .incorrect {
            color: red;
            font-weight: 600;
        }
        #CaptchaCode {
            margin: 15px 30px 15px 30px;
        }
    </style>
     
        <br>
            <br>
                <br>
            <br>
        <br>
     
        <form role="form" method="post">
                
            <h2><strong>Email Contact Form</strong></h2>    
            <div class="form-group">
                <label for="customerName">Full Name:</label>
                <input  type="text" class="form-control" name="customerName" value="@Request.Form["customerName"]" id="customerName" placeholder="Name" required="">
            </div>
     
            <div class="form-group">
                <label for="emailSubject">Subject:</label>
                <input  type="text" class="form-control" name="emailSubject" value="@Request.Form["emailSubject"]"  id="emailSubject"  placeholder="e.g. Quote" required="">
            </div>
     
            <div class="form-group">
                <label for="emailAddress">Email Address:</label>
                <input  type="email" class="form-control" name="emailAddress" value="@Request.Form["emailAddress"]" id="emailAddress"  placeholder="e.g. me@me.com" required="">
            </div>
     
     
            <div class="form-group" style="margin-bottom: 5px;">
                <label for="emailBody">Text Area:</label>
                <textarea style="margin-bottom: 15px;" class="form-control" name="emailBody" rows="10" id="emailBody" placeholder="Enter Details" required="">@Request["emailBody"]</textarea>
            </div>
     
            @Html.Label("Retype the code from the picture:", "CaptchaCode") 
     
            @Html.Raw(exampleCaptcha.Html)
                <div class="validationDiv"> 
            @Html.TextBox("CaptchaCode")
     
                <br>
     
                <input type="submit" class="btn btn-info" value="Send" style="margin: 5px 30px 10px 30px;" />
     
            @if(IsPost){
                <h3>@message <span class="incorrect">@message2</span></h3>  
            }   
                <br>
     
                </div><!--./validationDiv-->
        </form>
     
    

    Thursday, April 18, 2019 6:38 AM