dwyl / learn-to-send-email-via-google-script-html-no-server

:email: An Example of using an HTML form (e.g: "Contact Us" on a website) to send Email without a Backend Server (using a Google Script) perfect for static websites that need to collect data.
GNU General Public License v2.0
3.12k stars 911 forks source link

No 'Access-Control-Allow-Origin' header is present #154

Closed ghost closed 6 years ago

ghost commented 7 years ago

Hello!

First of all, I wanted to thank you for this tool - it's great! I am having some trouble with one particular problem, however. When I go to submit the form, I get my "submission successful" prompt on my webpage but notice no e-mail is sent and nothing is logged on the excel sheet. I checked the console and found this:

image

I am working on a work network so I'm thinking there might be trouble with a Google Apps Script trying to communicate with my CalendarTest.html - any easy way around this or will I have to setup a local server?

ghost commented 7 years ago

After further research, I believe my initial suspicion is correct - I had forgot to mention in my initial post that I am viewing this webpage locally (i.e. by opening a tab through my text editor) and that, combined with the fact I am on a work domain/network, is the reason why I expect that error to be thrown.

For anybody else who stumbles across this issue and still has difficulty understanding why, I'd recommend looking up CORS

iteles commented 7 years ago

@mskusek Thanks for updating! Glad you were able to figure it out.

I think it might be worth adding a troubleshooting section to this tutorial to capture all the great content from the issues that have been solved. What do you reckon @mckennapsean ?

mckennapsean commented 6 years ago

Many people have had CORS issues over the years.

@mskusek thanks for posting an update! what was your final solution? did you just host the index.html file on a server and run from there, or...?

@iteles I made a PR for improving the tutorial a while back, adding a section on FAQ's. If we can pinpoint the proper solution, we can post this in there too! #148 Feel free to take a look & review! I was waiting a bit to hear from others, but may pull in soon otherwise.

ghost commented 6 years ago

@mckennapsean For a temporary fix, I simply created another Google account that wasn't part of my work's domain and am doing my testing/debugging through that.

Once I have additional access at my work, I'll try linking my web app and google work domain - I will post updates when I get any!

sebalaini commented 6 years ago

same here, I have the exact problem when I implement the ajax request and I'm trying the functionality from local. I tried with GH pages and I have the same error, @mskusek how can you solve the problem ?

ghost commented 6 years ago

same here, I have the exact problem when I implement the ajax request and I'm trying the functionality > from local. I tried with GH pages and I have the same error, @mskusek how can you solve the problem ?

@sebalaini If you're working on a work network like I am, the only way around it is working with your network administrator and everything that entails.

You could look up additional information on CORS but for some of the solutions I've found, they pose security threats and the last thing I would want to do is put my workplace at risk.

bluenashty commented 6 years ago

I have encountered this one but the cause of the error was the handler is looking for the id="thankyou_message" so what i did is put the code stated referring to id="thankyou_message" and the error is gone. Hopefully it helps for an idea. Thank you!

sebalaini commented 6 years ago

@mskusek Thanks, I solved :) was an error with the permission of Google sheets and I didn't copy the exact code as in the html here in the repo.

mckennapsean commented 6 years ago

For the OP & others with the issue, I have a work GSuite domain now, so I can test this in the near future. I plan to do so. I will keep others posted of any updates, solutions, and gotchas as I go.

mckennapsean commented 6 years ago

For those with GSuite or Google Enterprise accounts, I could not replicate these issues locally with my account.

As a note, the script URL that is given when you have multiple accounts signed in (e.g. a GSuite and a personal Google account) includes a /u/#, which is not applicable when running the URL anonymously. So you would need to remove this additional info from the URL in order to use it correctly. May have to add this info to that step.

padmanabhkulkarni18 commented 6 years ago

401_failed_to_load

I am having the same issue, Could anyone help?

mckennapsean commented 6 years ago

I have tested some more and found this error when:

A) you have improper permissions set. check step # 5 again, it absolutely must be set to "Anyone, even anonymous" or this cannot work.

-or-

B) when you have multiple google accounts logged in when publishing the form, the URL given will include the user id in it, i.e. /u/# where the # corresponds to the user id, it starts at 0 and goes up for each google account. you have to remove that string from the publish URL in order for it to work properly (this is really a google bug).

Lastly, we need to fix the form, since the form happily submits (and has a thank you page) even when these errors occur which is not good.

padmanabhkulkarni18 commented 6 years ago

I hadn't specified the data attribute in html, now m getting the console of success, but not getting email or a response for the data sent. Any help would be appreciated..

mckennapsean commented 6 years ago

Which data attribute was that? This issue sounds tangential to the one here, and not really easy to reproduce without an example. I would suggest looking back at the steps, especially the ones highlighted above, watch your console for errors, and use sites like StackOverflow to your advantage.

antoc0d3 commented 6 years ago

https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi

Slals commented 6 years ago

I had the issue, I will tell you why the issue was raised in my case and how I fixed it :

I was sending data using application/json header with POST method. This kind of request will first send an OPTIONS method (it's called a pre-flight request), since Google script doesn't allow this method, the CORS error was returned. BTW this behavior is in the CORS specification.

How to fix this :

Simply sets the following header Content-Type: application/x-www-form-urlencoded and make sure you send formatted data. For example by using FormData in JavaScript.

var formData = new FormData();

formData.append("email", "test@example.com");
formData.append("message", "Hello"); 

// Send formData as the body with your HTTP library (JQuery, XMLHttpRequest, or wathever)
// Dont forget to set the header Content-Type: application/x-www-form-urlencoded
mckennapsean commented 6 years ago

thanks for posting that @Slaals ! that is very insightful and useful.

is this a result from not using our provided clientside JS?

we have the XMLHttpRequest header set to that in our code. perhaps the main issue is that people using the site without the Javascript (or if there are errors in the Javascript console causing it to never run - aka, same as not having it loaded) --> thus they are submitting the form with a json header in the POST request?

mckennapsean commented 6 years ago

The OP was posting a CORS issue from the Google script... not the GitHub script we provide. This is an important distinction if you have a similar problem, which script is causing it?

I recently discovered that we are actually hosting the GitHub file from another site (RawGit) that corrects CORS headers on GitHub files. So I would be baffled if you are using our script and getting that.

I am less certain on the Google side unless you are sending a mangled/incorrect header to the Google Script in the first place (as mentioned above).

4edorov commented 6 years ago

hi! i use a Google Script with React got a CORS error:

Failed to load https://script.google.com/macros/s/---------/exec: 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:3000' is therefore not allowed access.

my solution is to create a new copy and deploy it, you will recieve a new link, it works again

mckennapsean commented 6 years ago

Glad to hear you found a solution - thanks for posting @4edorov !

mckennapsean commented 6 years ago

this thread has varied from one issue to the next, with large variability of the underlying issue. is it a CORS issue from Google's side? from a local JS script? is it limited to a GSuite account? I have tried to reproduce and only seen errors which I posted fixes for above. in all of those cases, it was the result of someone not following the tutorial correctly.

if there are still problems let's make new, more specific issues to which of those cases above it affects.

mckennapsean commented 6 years ago

oh and I did just require people copying the repo to use their own local JS instead of loading one from Git, which could solve one of these cases. #240

wntiv-main commented 3 years ago

hi! i use a Google Script with React got a CORS error:

Failed to load https://script.google.com/macros/s/---------/exec: 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:3000' is therefore not allowed access.

my solution is to create a new copy and deploy it, you will recieve a new link, it works again

I have the same problem, tried this but it didn't work for me.

DamirMakhmudov commented 3 years ago

just add to request: mode: 'no cors' for ex:

 async function sendRequest(){
      const url = 'https://';
      const requestOptions = {
        method: "POST",
        mode: 'no-cors',
        headers: {
           "Content-Type": "application/json",
        },
        body: JSON.stringify({ title: "some data" })
      };
      let response = await fetch(url, requestOptions);
      let data = await response.text(); //or .json()
      console.log(data);
oseias-costa commented 1 year ago

basta adicionar ao pedido: mode:'no cors' para ex:

 async function sendRequest(){
      const url = 'https://';
      const requestOptions = {
        method: "POST",
        mode: 'no-cors',
        headers: {
           "Content-Type": "application/json",
        },
        body: JSON.stringify({ title: "some data" })
      };
      let response = await fetch(url, requestOptions);
      let data = await response.text(); //or .json()
      console.log(data);

Thank you