0

This was working.

I was able to create an endpoint, via Google Apps Script, that allow end user to POST a message to me (or another contact), and would also POST copy of that message to them.

The code for the POST request was something like:

function doPost(e) { 
  var response;
  try {
    response = sendContactEmail(e.postData.contents);
  }
  catch (error) { 
    throw JSON.stringify(error, null, '\t');
  }
    return ContentService
      .createTextOutput(JSON.stringify(response))
      .setMimeType(ContentService.MimeType.JSON)
}

Now, when I tried it, I face issue. When I tried it from my Angular site, with service code like :

@Injectable()
export class ContactService implements SenderService {
  constructor(private http: HttpClient) {}

  send(message: EmailMessage): Observable<any> {
    return this.http.post<any>(
      "https://script.google.com/macros/s/AKfycbyEuvROpXUEi4wTX4N06nqF6oHlwihVc9Ut6-OG04zPi5yuOCzn/exec",
      JSON.stringify({ data: message }),
      {
        headers: {
          "Access-Control-Allow-Origin": "*",
        },
      }
    );
  }
}

it doesn't work, and I face issue like

Access to XMLHttpRequest at 'https://script.google.com/macros/s/AKfycbyEuvROpXUEi4wTX4N06nqF6oHlwihVc9Ut6-OG04zPi5yuOCzn/exec' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

In attempt at debugging this issue, I whip open Postman, make the request, only to get back the following HTML response:

<!DOCTYPE html>
<html>

<head>
    <link rel="shortcut icon" href="//ssl.gstatic.com/docs/script/images/favicon.ico">
    <title>Error</title>
    <style type="text/css">
        body {
            background-color: #fff;
            margin: 0;
            padding: 0;
        }

        .errorMessage {
            font-family: Arial, sans-serif;
            font-size: 12pt;
            font-weight: bold;
            line-height: 150%;
            padding-top: 25px;
        }
    </style>
</head>

<body style="margin:20px">
    <div><img alt="Google Apps Script" src="//ssl.gstatic.com/docs/script/images/logo.png"></div>
        <div style="text-align:center;font-family:monospace;margin:50px auto 0;max-width:600px">Authorization is
            required to perform that action.</div>
</body>

</html>

I don't know that much about using Google Apps Script as a backend.

Should I set up OAuth token for this type of stuff, and if so, how? Else, what should I do about this issue?

Right now, there is no backend, other than my legacy Google Apps Script.

Marios
  • 26,333
  • 8
  • 32
  • 52
Mike Warren
  • 3,796
  • 5
  • 47
  • 99
  • I proposed a modification point as an answer. Could you please confirm it? In my environment, I could confirm that the script worked by the modification. But in your environment, when it didn't work, I apologize for this. – Tanaike Jul 14 '20 at 05:00
  • Does this answer your question? [XMLHttpRequest blocked by CORS policy when posting data to a Web App](https://stackoverflow.com/questions/62587453/xmlhttprequest-blocked-by-cors-policy-when-posting-data-to-a-web-app) – TheMaster Jul 14 '20 at 05:02
  • @TheMaster In the case of `axios.post`, it was found that `Content-Type` was not required. [Ref](https://github.com/tanaikech/taking-advantage-of-Web-Apps-with-google-apps-script#script-for-javascript) But in my environment, it seems that in the case of angular, when `Content-Type` is not used, the error related to CORS occurs. – Tanaike Jul 14 '20 at 05:07
  • 1
    @Tanaike As said in that answer, I believe the essence of the answer is "to avoid preflight". Different libraries may set different headers as default. But as long as `Content-type` is set to "text/plain" or any of the other mime types, which make the requests "simple requests", it should avoid cors errors. That's why I'm linking that answer here. – TheMaster Jul 14 '20 at 05:19
  • 1
    @TheMaster Thank you for replying. I forgot that the request header might depend on each library. In that case, I could understand that it was required to fix the content type. When I think about OP's situation, I thought that the content type might have already been set. By this, the content type is required to be used. Also, I could modify [this](https://github.com/tanaikech/taking-advantage-of-Web-Apps-with-google-apps-script#removing-this-error). Thanks for the additional information. – Tanaike Jul 14 '20 at 05:43

1 Answers1

1

In this case, how about using "Content-Type": "text/plain" instead of "Access-Control-Allow-Origin": "*" as follows?

From:

headers: {
  "Access-Control-Allow-Origin": "*",
},

To:

headers: {
  "Content-Type": "text/plain"
},

Note:

  • In this case, it supposes that doPost(e) of your Google Apps Script side works fine. When the your Google Apps Script occurs an error, the error might not be able to be removed. Please be careful this.

References:

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • Sadly, it didn't work. I confirmed it on both the Angular app and Postman... – Mike Warren Jul 14 '20 at 05:02
  • @Mike Warren Thank you for replying. I apologize for the inconvenience. I would like to confirm your situation. Your Google Apps Script has no error. Is my understanding correct? When an error occurs at the Google Apps Script, the error cannot be removed. Please be careful this. – Tanaike Jul 14 '20 at 05:04
  • @Mike Warren By the way, from `Authorization is required to perform that action.` in your question, in this case, please test your script for the Web Apps with `Execute the app as: Me` and `Who has access to the app: Anyone, even anonymous` as the simple situation. And when you could confirm that your Google Apps Script has no errors, please redeploy the Web Apps as new version. By this, the latest script is reflect to the Web Apps. Please be also careful this. – Tanaike Jul 14 '20 at 05:12
  • @Mike Warren When `Who has access to the app:` is `Anyone` and `Only myself` and/or `Execute the app as:` is `User accessing the web app`, the access token is required to access to Web Apps, and also, in your case, the Google Apps Script project is required to be shared with each user. So please be also careful this. – Tanaike Jul 14 '20 at 05:13
  • OK, so when I run a test function I left in the code, I see authorization screens. When I accept them all, and continue, I face the following error: ` Exception: You do not have permission to call Session.getActiveUser. Required permissions: https://www.googleapis.com/auth/userinfo.email (line 1, file "Code") ` I double-checked and made sure to `Execute the app as: Me` and `Who has access to the app: Anyone, even anonymous ` – Mike Warren Jul 14 '20 at 05:20
  • UPDATE: I found the cause. I just had to add that permission to the appsscript.json file... That being said, I still face the issue from the front end – Mike Warren Jul 14 '20 at 05:25
  • @Mike Warren Thank you for replying. From your replying, it was found that the modified request could run the Google Apps Script. And, from the error message, in your case, do you set the scopes by using the manifest file (`appsscript.json`)? If it's so, please remove `oauthScopes[]` and redeploy the Web Apps as new version again. By this, the authorization can be done for the new scopes. – Tanaike Jul 14 '20 at 05:26
  • @Mike Warren If the authorization screen is not opened when the Web Apps is redeployed, please directly run the function of `doPost` at the script editor. By this, I think that the authorization screen is opened. At that time, please permit the scopes. – Tanaike Jul 14 '20 at 05:29
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/217774/discussion-between-mike-warren-and-tanaike). – Mike Warren Jul 14 '20 at 05:36
  • Thought Javascript Fetch API `no-cors` mode would resolve this (as it does 'bypass' CORS) as it seemed to be the only official way to get away with it, but it only returns `opaque` response which doesn't return the data. Normal request used to work for me as well, but this didn't work neither. I still wonder why it stopped working all of a sudden. – Iorippi Dec 16 '20 at 23:13
  • Sorry for bump: @Tanaike san, "If the authorization screen is not opened when the Web Apps is redeployed, please directly run the function of doPost at the script editor. By this, I think that the authorization screen is opened. At that time, please permit the scopes." - This isn't working out for me but do you have any idea on this? I fired up new project with the same code, and it showed up, and I didn't need to do any CORS fiddling (as it were before). I'm guessing the hiccup is happening at those permission related stuff, but I've got no chance fixing them in any ways. – Iorippi Dec 16 '20 at 23:47
  • @Iorippi Thank you for your comment. Unfortunately, from your comment, I cannot understand about your current situation. I apologize for my poor English skill. But I would like to support you. So, in order to correctly understand about your current situation, can you post it as new question by including more information? By this, I would like to confirm it and try to understand about it. If you can cooperate to resolve your issue, I'm glad. Can you cooperate to resolve your issue? – Tanaike Dec 17 '20 at 00:58
  • Thank you for reply, @Tanaike. I'm also bad at English as I'm also Japanese, but only for the sake of readability, I'm sticking to my second language haha Anyhow, I figured my case is rather the edge case with bug, so I reported to google. If you had any insight then that certainly helps! I'm in very weird situation. I can't even recreate the environment so I think I'd just make clone project and work from there. https://issuetracker.google.com/issues/175811869 – Iorippi Dec 17 '20 at 13:50
  • @Tanaike FYI: I have been working on that issue, and it turned out to be the now old runtime (Rhino) is causing (seemingly authorization related) issue that are triggering CORS and 500 error. I got them temporarily resolved by moving onto the new V8 runtime, but someone who needs to stick to the old runtime environment might find this inconvenient. Someone at Google is actually listening to my bug report, so hopefully it'll be fixed in future! – Iorippi Dec 17 '20 at 15:54
  • @Iorippi Thank you for replying. From your replying, unfortunately, I cannot still understand about your current situation and your goal. When I could correctly understand about it, I would like to think of the issue and solution. I apologize I cannot resolve your issue soon. This is due to my poor English skill. I deeply apologize for this. – Tanaike Dec 18 '20 at 00:41
  • @Tanaike No need to apologize, I mean thanks for heads up! Like I said, I found the work around so I'm fine. I suck at English so let me put it in this way if that helps: 今まで動いてたデプロイメントがある日を堺にAJAXリクエストに対して急に CORS と 500 エラーを返してきたので、それを解決しようとしてました。パーミッションとグーグル側の旧実行環境絡みのバグみたいですが(報告中なのでまだ未承認) V8 にアプデしたら解決されたので、一応もう大丈夫です。いろいろ質問しておきつつ結局自分で完結してまいました、すみません笑 – Iorippi Dec 18 '20 at 16:07
  • @Iorippi Thank you for replying. By releasing V8 runtime, several bugs have already been reported. Although I cannot understand about your actual situation, that might have been one of them. But I'm glad your issue was resolved. – Tanaike Dec 19 '20 at 00:09
  • @Tanaike Oddity was that the environment that caused the issue was actually the old runtime that has been working stably, not the V8. So it happened all of a sudden despite I didn't touch anything at all. (And what it does was simply reading text from Google Docs and return the data.) I thought this was going to be a big hiccup for many users, but seems like it's edge case somehow. Anyhow, thanks again for checking! – Iorippi Dec 20 '20 at 03:22
  • @Iorippi Thank you for the additional information. – Tanaike Dec 20 '20 at 08:16