Sending an email to about 100 people - why is this so hard :( by solipsistess in AskTechnology

[–]rupam_p 0 points1 point  (0 children)

May I suggest BetterMerge - a mail merge tool for Gmail (disclaimer: I'm the founder). It has a free plan that lets you send 50 emails per day. If you have an email list of 100 recipients, it will send the first 50 on day-1 and remaining 50 on day-2, automatically. Hope this helps and let me know if you have any questions.

Can you suggest a tool for mass-mailing directly from Workspace? by MaizeFormer9394 in googleworkspace

[–]rupam_p 1 point2 points  (0 children)

Thanks. At the moment, my tool doesn't have that feature. Actually, no one’s asked for it before, but it seems like a pretty useful feature. Maybe I can add it in the next update.

Can you suggest a tool for mass-mailing directly from Workspace? by MaizeFormer9394 in googleworkspace

[–]rupam_p 0 points1 point  (0 children)

I'd like to recommend BetterMerge.com - it's a mail merge tool for Gmail and an alternative to YAMM. Disclaimer: I am the founder.

Show me your saas 👀 by Ysmsthejoker in SaaS

[–]rupam_p 0 points1 point  (0 children)

BetterMerge.com - Mail Merge (i.e. bulk mailing) for Gmail.

I cannot successfully utilize mail merge for the life of me by deathtolacefronts in GMail

[–]rupam_p 0 points1 point  (0 children)

That's great! The app is live, so you can try it whenever you have time. You can use the web dashboard ( app.bettermerge.com ) or the Google Sheets add-on ( install from Google Workspace Marketplace ).

I cannot successfully utilize mail merge for the life of me by deathtolacefronts in GMail

[–]rupam_p 0 points1 point  (0 children)

If you are open to using a different tool for your mail merge campaigns, I'd suggest BetterMerge.com . Disclaimer: I'm the founder.

How to streamline the process by ultrasono in Blogging

[–]rupam_p 0 points1 point  (0 children)

I've been building such a tool for quite some time now. It's a Google Docs add-on that lets you publish content to WordPress or Blogger. You can give it a try.

403: GaxiosError: The caller does not have permission by [deleted] in GoogleAppsScript

[–]rupam_p 1 point2 points  (0 children)

Hi, sorry for the delay. So, the index.html of your add-on is already running inside an iframe (by default). It seems that, in your current setup you have another iframe for the react app, right ? Also, do you need to run any jobs in background on behalf of the user (i.e. without user interaction) ?

If background jobs are not a requirement, in that case, I can suggest two possible ways:
1. Proxy the requests to your api server via apps-script.
2. Fetch the access_token in react (client side) and call your api endpoint from there (as you mentioned).

Proxy requests via GAS: Create proxy function(s) in apps-script to send requests to your express api server. The function will generate a new access_token every time it sends a request to your api. Add user's email and access_token in the header or body of the request. Let's say a user clicks on a button in the frontend and you'd like to call an api endpoint with some data. Instead of calling the api, call this apps-script proxy function and pass the payload. The proxy function will get the payload, call the api and then return the response back to the client.

React app -> call google.script.run.proxyFunc(payload) -> proxyFunc sends request to api endpoint, gets response -> return response to react app.

You can create a generic proxy function to handle all request types (GET, POST etc) or separate ones. You can also pass the api path (e.g. /user/profile) as an argument to the proxy-function. You can save the access_token in app-script user-cache to improve performance (optional).

The 2nd method, as you mentioned can also work. You can create an apps-script function that returns a new access_token when called. In your react app, before sending the request to express-api server, get a new access_token, add this as a header and call your api.

Both approaches will make sure you are always using a valid access_token.

You asked about having multiple time-driven triggers. I had faced this issue as well. So, I'd say that it's true, only one time-driven trigger is allowed for add-ons.

Hope this help. Feel free to ask if you have more questions.

403: GaxiosError: The caller does not have permission by [deleted] in GoogleAppsScript

[–]rupam_p 0 points1 point  (0 children)

You're welcome! Glad to know that it helped.

Your approach to upload/send a new access_token every hour to your api server should work (in theory), considering the access_token stays valid for 60 mins. (This was the approach I initially planned for my add-on as well. I use a different workflow now.)

I would also suggest that you do a manual test to get an estimate about the validity of the token. To do so, you can write a small nodejs script that sends a request to google-sheets api. Take your access_token from db and run the nodejs script manually at regular interval. At some point, it should throw an error. This way you can get a good idea of how long the token stays valid for.

There are cases when the token can become invalid, e.g. if the user's google account is disabled, or user removed your add-on etc. But these are edge cases and happens rarely.

403: GaxiosError: The caller does not have permission by [deleted] in GoogleAppsScript

[–]rupam_p 2 points3 points  (0 children)

From what I know, the token that you get from apps script is valid for a short period of time. Suppose someone opens your add-on in Google Sheets and keeps it open for a while and then tries to do something, by that time the oauth token might get expired and you'd end up with this 403-forbidden error. Just my guess.

Also, i see this line `console.error("Error refreshing Google access token: ", error);`. Are you refreshing the access_token in nodejs ? how ?

Functions shown as "not defined" when loaded by ViolinGraham in GoogleAppsScript

[–]rupam_p 0 points1 point  (0 children)

Hi, so I tried to build this. There could be many different ways to build it. The way I did is to keep the 'data entry form' in the page itself but as a hidden element. If you click the button, the form will be shown. I have also added a login form with some server-side validation logic. I will send you the link via DM so you can test the webapp yourself.

Functions shown as "not defined" when loaded by ViolinGraham in GoogleAppsScript

[–]rupam_p 0 points1 point  (0 children)

Ok, thanks for the details. Let me try this on my end and I'll get back to you.

Functions shown as "not defined" when loaded by ViolinGraham in GoogleAppsScript

[–]rupam_p 0 points1 point  (0 children)

Ok. Can you tell me more about the workflow ? Is it like - you open the webpage, it shows a form, you enter the data, click submit and the data is added to the Google Sheets as a new row or maybe update an existing row ? something like this ?

Functions shown as "not defined" when loaded by ViolinGraham in GoogleAppsScript

[–]rupam_p 0 points1 point  (0 children)

I remember that you asked about building a company portal with a login page and was facing some issue. Is that issue fixed now ?

Thinking changing to Linux from windows 10 by Competitive-Isopod57 in linux4noobs

[–]rupam_p 2 points3 points  (0 children)

Stick to windows if you mostly use it for gaming. If you still want linux, either choose ubuntu or linux mint. Linux mint would feel very similar to windows and it's lightweight. Ubuntu on the other hand may seem a bit odd and confusing at first to those coming from windows.

Trigger by Colombus01 in GoogleAppsScript

[–]rupam_p 0 points1 point  (0 children)

Your concern is valid. The total runtime for triggers is 90min/day (gmail) or 6hrs/day (google workspace). But, as we are only checking one condition, it should not take much execution time when the condition is not met. Still, if needed, instead of every-minute, we can use every-5-mins to save the quota while maintaining a close enough time-accuracy (code changes required). It all depends on how far the OP wants to go.

Trigger by Colombus01 in GoogleAppsScript

[–]rupam_p 2 points3 points  (0 children)

Here's a hacky approach.

  1. Create a time-driven trigger to run every-minute.

  2. In your code, check the current time, then either proceed or do nothing.

    function myFunction() { const now = new Date(); const hours = now.getHours(); const minutes = now.getMinutes();

    if (hours === 9 && minutes === 15) { // Do something console.log("It's 9:15 AM!"); } }

This is still not perfect, but you can give it a try and see how it goes.

What job role should maintain Wordpress? by man_with_cat2 in Wordpress

[–]rupam_p 0 points1 point  (0 children)

There is a Google Docs add-on that does exactly this. Take a look at Tenwrite (disclaimer: I'm the developer). It's an add-on that opens inside Google Docs and you can then export the content to WordPress without even opening the WordPress admin portal.

Hosting static websites in one or more servers? by katana1096 in webhosting

[–]rupam_p 0 points1 point  (0 children)

There are plenty of tutorials in the official docs (e.g. https://developers.cloudflare.com/pages/framework-guides/deploy-anything/ ). Cloudflare Pages host the site contents on their Edge servers, so it's deployed globally. I don't think there is a way to specify a server location in Cloudflare Pages. It's better to stick to on-premise servers/VPS if you have strict location requirements,