title: Google App Script Web App GET and POST request blocked by CORS policy
body: <p>I created a Google Web script app that adds a user's name and email to a spreadsheet. This works fine when accessing the web page from directly in the browser, but both GET and POST requests from a website returns the error "Access to fetch at '<a href="https://script.google.com/macros/s/AKfycbxkG5hM6MMswwHdzWSJKwutMYsOZRT3zjC7jFti0sDvJ47bWB4BTsHPhvbyEVGSsSc5/exec" rel="noreferrer">https://script.google.com/macros/s/AKfycbxkG5hM6MMswwHdzWSJKwutMYsOZRT3zjC7jFti0sDvJ47bWB4BTsHPhvbyEVGSsSc5/exec</a>' from origin '' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled."</p>
  
  <p>I don't necessarily need a response from the POST request, but using 'no-cors' doesn't actually update the spreadsheet (I tested to make sure it worked outside of website)</p>
  
  <p>I've used both XMLHttpRequest and the fetch method, with both GET and POST requests and a variety of the settings changed to try to get this to work but no luck so far.</p>
  
  <p>I've tried to modify settings in the Google Apps Script Project (Set to execute as me, anyone can access even anonymous) and the manifest (not much here, <a href="https://developers.google.com/apps-script/concepts/manifests" rel="noreferrer">documentation reference</a>).</p>
  
  <p>I've looked at these stack overflow posts to try to help, but their solution didn't work for me (any didn't exactly apply to my situation)</p>
  
  <p><a href="https://stackoverflow.com/questions/44910180/app-script-sends-405-response-when-trying-to-send-a-post-request">App Script sends 405 response when trying to send a POST request</a></p>
  
  <p><a href="https://stackoverflow.com/questions/29525860/google-apps-script-cross-domain-requests-stopped-working">Google Apps Script cross-domain requests stopped working</a></p>
  
  <p>Here's my fetch method (most recent attempt)</p>
  
  <pre><code>fetch("https://script.google.com/macros/s/AKfycbxkG5hM6MMswwHdzWSJKwutMYsOZRT3zjC7jFti0sDvJ47bWB4BTsHPhvbyEVGSsSc5/exec", {
      method: 'POST',
      data: data,
      mode: 'cors',
      credentials: 'include', // include, *same-origin, omit
      redirect: 'follow',
      headers: {
          'Content-Type': 'text/plain;charset=utf-8',
      }
  }).then(response =&gt; {
      console.log("success:", response);
  });
  </code></pre>
  
  <p>Right now the server should return a string that says "Success" but instead I get the error I mentioned before.</p>
  
  <p><strong>Edit</strong>
  I forgot to include the doGet and doPost methods on the Google App Script:</p>
  
  <pre><code>
  var emailRegex = /^(([^&lt;&gt;()\[\]\\.,;:\s@"]+(\.[^&lt;&gt;()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  
  function doPost (e){
    if(!e) return ContentService.createTextOutput("No e");
    if(!e.parameters) return ContentService.createTextOutput("No params");
    if(!e.parameters.email) return ContentService.createTextOutput("No email");
    if(!e.parameters.name) return ContentService.createTextOutput("No name");
    if(!emailRegex.test(e.parameters.email)) return ContentService.createTextOutput("Wrong email format"); // if the email is not in proper format, return
  
    return addToDoc(e.parameters);
  }
  
  function doGet (e){
  
    if(!e) return ContentService.createTextOutput("No e");
    if(!e.parameters) return ContentService.createTextOutput("No params");
    if(!e.parameters.email) return ContentService.createTextOutput("No email");
    if(!e.parameters.name) return ContentService.createTextOutput("No name");
    if(!emailRegex.test(e.parameters.email)) return ContentService.createTextOutput("Wrong email format"); // if the email is not in proper format, return
  
    return addToDoc(e.parameters);
  }
  
  function addToDoc (params){
    var email = params.email;
    var name = params.name;
  
    var sheet = SpreadsheetApp.openById("1X0sUNSFcv-phGbGy7jeo9K5WLEX5cxyh_1_X6kSPjPs").getSheets()[0];
  
    var dataRange = sheet.getDataRange();
    var values = dataRange.getValues();
  
    // If we already have the email in the system, return
    for(var x = 0; x &lt; values.length; x++){
      for(var y = 0; y &lt; values[x].length; y++){
        if(values[x][y].indexOf(email) &gt; -1) return ContentService.createTextOutput("Already have email");
      }
    }
  
    // Gets current row index and updates
    var scriptProps = PropertiesService.getScriptProperties();
    var nextDataIndex = parseInt(scriptProps.getProperty("NEXT_DATA_INDEX"));
    scriptProps.setProperty("NEXT_DATA_INDEX", ""+(nextDataIndex+1));
  
    var insertRange = sheet.getRange(nextDataIndex, 1, 1, 2);
    insertRange.setValues([[name, email]]);
  
    return ContentService.createTextOutput("Success");
  }
  </code></pre>
  
  <hr>
  
  <h2>Solution</h2>
  
  <p>So it turns out my doPost request was failing (doGet was working) because I was using <code>e.parameters</code> and not <code>e.postData</code>. When I got the error message I assumed it was a problem with my website, not the web app.</p>
  
  <p>Thank you Tanaike! I would've spent forever trying to fix the website</p>