Apparently, there is a GAM solution to this, which is
gam update group nameofgroup who_can_leave_group ALL_MANAGERS_CAN_LEAVE
I did a quick test, and it appears to work. Users will still see the option to "unsubscribe," but after they do, they'll still be subscribed anyway.
Thanks to Zack McCauley for the tip.
What's the problem?
We used to have students come in and say they'd accidentally unsubscribed from an important school mailing list and needed to be resubscribed. This confused us, because we didn't think students could unsubscribe themselves. Turns out not only can they (click on the arrow at the top of the email and then select Unsubscribe from this mailing-list), but we contacted Google directly, and they confirmed there isn't a way for Google Apps admins to prevent users from unsubscribing (and apparently this issue goes back at least as far as 2012, if not longer).
I get that people in general should be able to unsubscribe from mailing lists, but this is a controlled environment. These are email addresses provided by the institution (school, organization, company) and so the institution should be able to decide what mailing lists its own employees and students are on, right? Well, apparently not.
Fortunately, we don't have a ton of people who make it a habit of unsubscribing themselves from mailing lists. Most of the time when students do unsubscribe, they soon realize they're missing important messages, and then they ask to resubscribe.
Nevertheless, it can be handy to find which students are unsubscribed from the lists they should be subscribed to.
This is something I thought GAM should be able to handle, and I even got some suggested commands from another Mac admin. Unfortunately, I couldn't get gam to work. I followed all the instructions and still ended up with this error, no matter how much "coffee" I got and despite enabling access to the suggested scopes:
Are you ready to authorize GAM to manage G Suite user data and settings? (yes or no) Y
Great! Checking service account scopes.This will fail the first time. Follow the steps to authorize and retry. It can take a few minutes for scopes to PASS after they've been authorized in the admin console.
Scope: https://mail.google.com/ FAIL
Scope: https://www.googleapis.com/auth/activity FAIL
Scope: https://www.googleapis.com/auth/calendar FAIL
Scope: https://www.googleapis.com/auth/drive FAIL
Scope: https://www.googleapis.com/auth/gmail.settings.basic FAIL
Scope: https://www.googleapis.com/auth/gmail.settings.sharing FAIL
Scope: https://www.googleapis.com/auth/plus.me FAIL
ERROR: Some scopes failed! Please go to:
and grant Client name:
Access to scopes:
Service account authorization failed. Confirm you entered the scopes correctly in the admin console. It can take a few minutes for scopes to PASS after they are entered in the admin console so if you're sure you entered them correctly, go grab a coffee and then hit Y to try again. Say N to skip admin authorization.
Google Apps Script
I started looking into Google Apps Script, which is pretty cool, except the documentation isn't comprehensive enough to suggest all the steps involved to find unsubscribed users.. For example, there isn't any documentation on how to construct a query that has two parts to it. Frankly, I couldn't even find official Google documentation on how to include a query—I had to find that on Stack Overflow.
In addition to missing pieces in the documentation, Google Apps Script also suffers from arbitrarily imposed limits to what you can do. For example, you can't fetch more than 500 user records at once. Also, even though there's a function to check if a user is a member of a group, if you run that in a loop over several hundred users at once, you'll get this error:
Service invoked too many times in a short time: groups read. Try Utilities.sleep(1000) between calls.
I played around with scripting putting users back into groups, but it gave uneven results (some of that was our own fault—we had a couple of users in the incorrect organizational units, but it also seemed to sometimes not actually put users in groups successfully).
The working script
So ultimately, I didn't script this in the "ideal" way (due to limitations put in place by Google), but the script basically works. For each grade level, it will find all the students who aren't suspended users, put them into an array, find all the members of the appropriate mailing list, and then take each of those members out of the original array. Anyone still left in the array is potentially unsubscribed to a list she should be subscribed to.
Finally, an email is sent to specified recipients to let them know either everything's okay or something has to be investigated. You can script this to run every day or every week and then make fixes yourself afterwards.
Google Groups / mailing list quirk
I also found one quirk to Google Groups. There was one student I had trouble adding back to a group. It would seem I could add the student in the admin console, but then the student still wouldn't be added (no error message). It was only when I went to Google Groups itself (not the admin console) and tried to add the student directly that I saw a message saying I couldn't add the student because the student already had an pending request that needed approval (the student had asked to re-join the mailing list). Once I approved that request, the student was back in.