why i still getting spam emails after installing reCaptcha v3 - html

I have installed google recaptcha v3 in my html form but i'm still getting spam emails, what should i do next to prevent spams ? Any way without using php code only js scripts ?
My code is using this one :
<script src="https://www.google.com/recaptcha/api.js"></script>
Add a callback function to handle the token.
<script>
function onSubmit(token) {
document.getElementById("demo-form").submit();
}
</script>
Add attributes to your html button.
<button class="g-recaptcha"
data-sitekey="reCAPTCHA_site_key"
data-callback='onSubmit'
data-action='submit'>Submit</button>

You have to verify the captcha request server side. You are likely getting hit with spambots. Having only client side validation will only work against most humans, not bots.
Bots do not care if your client side has reCAPTCHA as they likely reading your HTML form's action URL and directly sending a POST request to it without your validation script - in short they are bypassing reCAPTCHA and other client side validation.
You should also be warry of posting your email address directly on your site as they often get scraped and spammed as well. Here is an old post that talks about obfuscation of on site email address to prevent spam.

Try this
function submit(e) {
e.preventDefault();
var response = grecaptcha.getResponse();
if (response.length == 0) {
//reCaptcha not verified
} else {
//reCaptch verified
document.getElementById("demo-form").submit();
}
}
<script src="https://www.google.com/recaptcha/api.js"></script>
<form onsubmit="submit();">
<input type="text" name="name">
<button class="g-recaptcha" data-sitekey="reCAPTCHA_site_key" data-callback='submit' data-action='submit'>Submit</button>
</form>
Change the right key in there !

Related

Keep same web page after POST request on iOS devices (Django sending 204 status response)

My Django project has a number of buttons on the web page that do POST requests to the main view.py which in turn handles the action and returns a 204 No content response. The results of the action show up asynchronously later on the web page (at the time the response is generated there's nothing new to show).
On any non-iOS based browser the 204 response works fine and the web page remains in the browser, as expected from RFC 7231.
Unfortunately all iOS based browsers I've tried (Safari, Firefox, Chrome) navigate to a blank page after the POST, which is not what I want (see this question). Apparently this is a long standing bug in WebKit.
Is there any way to achieve the same thing across all browsers? ie. Click button, POST, web page stays as is, change appears later. I've looked at this but no sure it's really what I'm after. Changing the response code is possible but I don't see a viable alternative that doesn't navigate away from the current page. My current hacky fix is to reload the whole page for an iOS device, but this moves the page if the user had scrolled down earlier so looks pretty janky.
The solution for this is contained in this question and the answer by Terry. Plus some other info about handling the CSRF protection in Django.
The short answer is to override the regular form submit with event.preventDefault()
in your own onsubmit function for each form. Then do the POST asynchronously with JQuery. This avoids the server having to return an HttpResponse with status 204, or anything really, beyond an empty JsonResponse.
There are several forms on my web page so I don't have a single function assigned to each button, like in the above linked answer, but several that change individual button behaviour. Also for Django there's the added consideration of including the CSRF token in the POST request.
So, for example, some html with two buttons;
<form id="form-a" onsubmit="submit_form_a(event)">{% csrf_token %}
<input type="hidden" name="button-a" value="some_value_for_a">
<button type="submit" class="w3-button">Button A</button>
</form>
<form id="form-z" onsubmit="submit_form_z(event)">{% csrf_token %}
<input type="hidden" name="button-z" value="some_value_for_z">
<button type="submit" class="w3-button">Button Z</button>
</form>
Then Javascript, where the first form submit callback, for example, disables the button;
function submit_form_a(e){
e.preventDefault();
var url = "/main/a"
var formData = $(e.target).serialize();
var btn = $(e.target).find("button");
btn.prop("disabled", true);
myPost(url, formData);
}
And the second submit callback that does some animation, using the excellent W3.CSS;
function submit_form_z(e){
e.preventDefault();
var url = "/main/z"
var formData = $(e.target).serialize();
var btn = $(e.target).find("button");
btn.toggleClass("w3-animate-fading").toggleClass("w3-text-red")
myPost(url, formData);
}
Both of those scripts call a common script mypost, which sets up the XMLHttpResponse header with the CSRF token, then POSTs it;
// Make sure any AJAX POST requests are not going off-site. Prevents
// leaking the CSRF token.
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); }
function myPost(url, data) {
var csrftoken = $("[name=csrfmiddlewaretoken]").val();
// Set the header on the AJAX POST request with the CSRF token
$.ajaxSetup({beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}});
$.post(url, data);
}
Back at the Django views.py side of things, look at the <input> data from the form and do what you need to do. I only just discovered on iOS the buttons themselves don't get included in the POST form data, like they seem to with other platforms, making hidden text input elements necessary;
if request.is_ajax() and request.method == 'POST':
if 'button-a' in request.POST:
# do something for A
elif 'button-z' in request.POST:
# do something for Z
return JsonResponse({})
And voila! Buttons can be clicked, background stuff happens and the page doesn't move. You could return something other than an empty JSON response and handle it back in the form callbacks, such as re-enabling the button, but I don't need that. See earlier linked answer for details there.

Redirecting from doPost() in Google Web App, HTML form with App script

Say I have an HTML file with various inputs. According to these inputs I would like to send an email and then display a thank you message or redirect to a thank you page.
I am loading the index.html file in the doGet() as below:
function doGet(){
var template = HtmlService.createTemplateFromFile('index');
template.action = ScriptApp.getService().getUrl();
return template.evaluate();
}
After adding the implementation which I require in doPost(e) function, deploying the code into a web app, filling in the form and submitting, everything seems to be working perfectly apart from the last bit. I want to show an output message or redirect to a thank you page, or something of the sort, but all I am seeing is a blank page, where there would have been the HTML form.
I have tried:
function doPost(e) {
//all logic
return ContentService.createTextOutput("Thank you");
}
And..
function doPost(e) {
//all logic
return ContentService.createTextOutput(JSON.stringify(e.parameter));
}
And..
function doPost(e) {
//all logic
var htmlBody = "<h1>Thank you.</h1>";
return HtmlService.createHtmlOutput(htmlBody);
}
And..
function doPost(e) {
//all logic
var template = HtmlService.createTemplateFromFile('Thanks');
return template.evaluate();
}
In all the listed cases the HTML form simply seems to disappear and I can only see a blank screen.
Any ideas?
In GAS, sending a POST request via web app is not as simple as it seems. Go ahead and try a little experiment: add the following JS code to the HTML page served by the doGet() function just before the closing <body> tag:
...
<script>
console.log(window.location);
</script>
</body>
When inspecting the output in the console, you'll likely get something like:
The issue is that the web app URL ending with '/exec' doesn't actually link to self. Ratner, the googleusercontent.com link is the URL you'll be redirected to when opening links and forms. However, in order to get the form submit to work, the POST request should be sent to the "published" URL of your web app (the one ending with '/exec').
You must therefore override the defaults by implementing your own routing. There are many ways to achieve this result - here's the easiest one:
<form method="post" action="<?!= ScriptApp.getService().getUrl() ?>">
<input type="submit" value="submit">
</form>
If the <?!= ?> notation looks unfamiliar to you, please check the section on scriptlets and HTML templates in GAS https://developers.google.com/apps-script/guides/html/templates
Basically, what happens is that the web app URL is force-printed to the template before raw HTML is sent to your browser for rendering. This makes sure you'll hit the correct URL when 'submit' event occurs.

HTML Forms post redirect

I've got an HTML form that I'm posting to a url successfully. However, I need to have the page be redirected after I've posted the form. I'm not able to use ajax because CORS is not enabled. When I post to the url I'm getting a success message, and a redirect link in json format. This seems much easier than it's proving to be.
What I know is, when I post to the original url, a cookie is created, and when I go to the url that the page is returning, I am an authenticated user. So, it seems that I need to capture that cookie, and then redirect, but I could be off base.
This can be achieved using custom scripting.
The script waits for the input button to be clicked and sets up a listener that checks to see if the div that holds the confirmation text is visible and then sends the user to the destination page.
Add this to the code injection point for the page that holds the form:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
var eventposted=0;
$(document).ready(function(){
$('input.button').click(function() {
window.setInterval(foo, 100);
});
});
function foo(){
if(($(".form-submission-text").is(':visible')) && (eventposted==0)){
window.location = "http://www.something.com/destinationpage";
eventposted=1;
}
}
</script>

Multiple instances of Google reCaptcha

I used google reCaptcha for my website and my login and register form are in same page and when I use reCaptcha twice, the second captcha doesn't work.
I used this code for login and register form:
<div class="g-recaptcha" data-sitekey="********"></div>
Any body can help me to solve it ?
https://www.google.com/recaptcha/
Only Answer: You can't.
It's not possible to do that with reCAPTCHA. Only one CAPTCHA is supported in a page at any time. It seems that multiple forms on the same page must share a CAPTCHA, unless you're willing to use a different CAPTCHA.
You can just put login on one page and register on another, because that's all you can do. Or you can use more JavaScript and load another CAPTCHA after the form is loaded.
By using the following code I fixed that problem:
form:
<div id="captcha"></div>
head:
var captchaCallback = function() {
grecaptcha.render('captcha', {
'sitekey' : ''
});
};
</script>
<script src="//www.google.com/recaptcha/api.js?onload=captchaCallback&render=explicit&hl=en" async defer></script>

Posting data to HtmlService from separate form

I recently noticed that you cannot embed a HtmlService app in a non Google Sites site.
What I was wanting to do is have a chrome extension which was a simple form to capture feedback from users. The form would be powered by HtmlService and the data from the form captured in a spreadsheet. I know, you could do this with Google Forms, but the design and layout are not good enough to encourage users to complete the form as regularly as we wish.
As I can't embed the HtmlService apps as an iframe in the popup.html in my extension I'm wondering if I can simple have a form with a post action back to the HtmlService app.
Is this possible to have the post go back to the app? If so what would the post look like and what would the function look like to capture this data?
I have done this a couple of ways, but I ended up doing a simple local html page with a form:
<form action="yourScriptURL" method="get">
<input type="text" name="firstName" />
<input type="text" name="lastName" />
</form>
And then in your apps script:
function doGet(GETVARS){
var firstName = GETVARS.parameters.firstName;
var lastName = GETVARS.parameters.lastName;
Logger.log(firstName + " " + lastName);
//return Whatever you want here, HtmlService, UiApp, ContentService, etc
}
If you wanted, you can set the correct SCP info in your Chrome Extension/App and use JSONP to do this via AJAX. Works pretty well actually - you just need to plan out how the script is authorized, how the user is authenticated (or not) to use it, etc. It's really not as bad as it sounds.