Google Workspace CLI
Setup
1. Install dependencies
pip install google-api-python-client google-auth-httplib2 google-auth-oauthlib
2. Create Google Cloud Project
- Go to Google Cloud Console
- Create a new project
- Enable APIs: Gmail, Calendar, Sheets, Docs, People API
- Create OAuth 2.0 credentials (Desktop app)
- Download
credentials.jsonto your working directory
3. Authentication helper
Save as google_auth.py:
import os
import pickle
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
SCOPES = [
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/calendar',
'https://www.googleapis.com/auth/contacts',
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/documents',
'https://www.googleapis.com/auth/drive'
]
def get_credentials():
creds = None
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
return creds
def get_service(api, version):
return build(api, version, credentials=get_credentials())
First run will open browser for OAuth authorization.
Gmail
List recent emails
python3 -c "
from google_auth import get_service
gmail = get_service('gmail', 'v1')
results = gmail.users().messages().list(userId='me', maxResults=10).execute()
messages = results.get('messages', [])
for msg in messages:
m = gmail.users().messages().get(userId='me', id=msg['id'], format='metadata').execute()
headers = {h['name']: h['value'] for h in m['payload']['headers']}
print(f\"From: {headers.get('From', 'N/A')}\")
print(f\"Subject: {headers.get('Subject', 'N/A')}\")
print(f\"Date: {headers.get('Date', 'N/A')}\")
print('-' * 50)"
Read email by ID
python3 -c "
from google_auth import get_service
import base64
gmail = get_service('gmail', 'v1')
msg = gmail.users().messages().get(userId='me', id='MESSAGE_ID', format='full').execute()
headers = {h['name']: h['value'] for h in msg['payload']['headers']}
print(f\"From: {headers.get('From')}\")
print(f\"Subject: {headers.get('Subject')}\")
print(f\"Date: {headers.get('Date')}\")
if 'data' in msg['payload']['body']:
body = base64.urlsafe_b64decode(msg['payload']['body']['data']).decode()
print(f\"\nBody:\n{body}\")"
Send email
python3 -c "
from google_auth import get_service
import base64
from email.mime.text import MIMEText
gmail = get_service('gmail', 'v1')
message = MIMEText('Hello! This is a test email.')
message['to'] = 'recipient@example.com'
message['subject'] = 'Test Email'
raw = base64.urlsafe_b64encode(message.as_bytes()).decode()
result = gmail.users().messages().send(userId='me', body={'raw': raw}).execute()
print(f\"Email sent! ID: {result['id']}\")"
Search emails
python3 -c "
from google_auth import get_service
gmail = get_service('gmail', 'v1')
# Search queries: from:, to:, subject:, after:, before:, has:attachment, is:unread
results = gmail.users().messages().list(userId='me', q='is:unread subject:invoice', maxResults=5).execute()
for msg in results.get('messages', []):
m = gmail.users().messages().get(userId='me', id=msg['id'], format='metadata').execute()
headers = {h['name']: h['value'] for h in m['payload']['headers']}
print(f\"• {headers.get('Subject', 'No subject')}\")"
List labels
python3 -c "
from google_auth import get_service
gmail = get_service('gmail', 'v1')
results = gmail.users().labels().list(userId='me').execute()
for label in results.get('labels', []):
print(f\"{label['id']}: {label['name']}\")"
Google Calendar
List upcoming events
python3 -c "
from google_auth import get_service
from datetime import datetime, timezone
calendar = get_service('calendar', 'v3')
now = datetime.now(timezone.utc).isoformat()
events = calendar.events().list(
calendarId='primary',
timeMin=now,
maxResults=10,
singleEvents=True,
orderBy='startTime'
).execute()
for event in events.get('items', []):
start = event['start'].get('dateTime', event['start'].get('date'))
print(f\"{start}: {event['summary']}\")"
Create event
python3 -c "
from google_auth import get_service
calendar = get_service('calendar', 'v3')
event = {
'summary': 'Meeting with Team',
'location': 'Conference Room A',
'description': 'Weekly sync',
'start': {
'dateTime': '2025-02-03T10:00:00',
'timeZone': 'America/New_York',
},
'end': {
'dateTime': '2025-02-03T11:00:00',
'timeZone': 'America/New_York',
},
'attendees': [
{'email': 'colleague@example.com'},
],
'reminders': {
'useDefault': False,
'overrides': [
{'method': 'email', 'minutes': 24 * 60},
{'method': 'popup', 'minutes': 10},
],
},
}
result = calendar.events().insert(calendarId='primary', body=event).execute()
print(f\"Event created: {result.get('htmlLink')}\")"
Delete event
python3 -c "
from google_auth import get_service
calendar = get_service('calendar', 'v3')
calendar.events().delete(calendarId='primary', eventId='EVENT_ID').execute()
print('Event deleted')"
List calendars
python3 -c "
from google_auth import get_service
calendar = get_service('calendar', 'v3')
calendars = calendar.calendarList().list().execute()
for cal in calendars.get('items', []):
print(f\"{cal['id']}: {cal['summary']}\")"
Google Contacts (People API)
List contacts
python3 -c "
from google_auth import get_service
people = get_service('people', 'v1')
results = people.people().connections().list(
resourceName='people/me',
pageSize=20,
personFields='names,emailAddresses,phoneNumbers'
).execute()
for person in results.get('connections', []):
names = person.get('names', [{}])
emails = person.get('emailAddresses', [{}])
phones = person.get('phoneNumbers', [{}])
print(f\"Name: {names[0].get('displayName', 'N/A')}\")
print(f\"Email: {emails[0].get('value', 'N/A') if emails else 'N/A'}\")
print(f\"Phone: {phones[0].get('value', 'N/A') if phones else 'N/A'}\")
print('-' * 30)"
Create contact
python3 -c "
from google_auth import get_service
people = get_service('people', 'v1')
contact = {
'names': [{'givenName': 'John', 'familyName': 'Doe'}],
'emailAddresses': [{'value': 'john.doe@example.com'}],
'phoneNumbers': [{'value': '+1234567890'}]
}
result = people.people().createContact(body=contact).execute()
print(f\"Contact created: {result['resourceName']}\")"
Search contacts
python3 -c "
from google_auth import get_service
people = get_service('people', 'v1')
results = people.people().searchContacts(
query='John',
readMask='names,emailAddresses'
).execute()
for result in results.get('results', []):
person = result.get('person', {})
names = person.get('names', [{}])
print(f\"Found: {names[0].get('displayName', 'N/A')}\")"
Google Sheets
Read spreadsheet
python3 -c "
from google_auth import get_service
sheets = get_service('sheets', 'v4')
SPREADSHEET_ID = 'your-spreadsheet-id'
RANGE = 'Sheet1!A1:D10'
result = sheets.spreadsheets().values().get(
spreadsheetId=SPREADSHEET_ID,
range=RANGE
).execute()
for row in result.get('values', []):
print('\t'.join(row))"
Write to spreadsheet
python3 -c "
from google_auth import get_service
sheets = get_service('sheets', 'v4')
SPREADSHEET_ID = 'your-spreadsheet-id'
RANGE = 'Sheet1!A1'
values = [
['Name', 'Email', 'Phone'],
['John Doe', 'john@example.com', '+1234567890'],
['Jane Smith', 'jane@example.com', '+0987654321']
]
body = {'values': values}
result = sheets.spreadsheets().values().update(
spreadsheetId=SPREADSHEET_ID,
range=RANGE,
valueInputOption='RAW',
body=body
).execute()
print(f\"Updated {result.get('updatedCells')} cells\")"
Append rows
python3 -c "
from google_auth import get_service
sheets = get_service('sheets', 'v4')
SPREADSHEET_ID = 'your-spreadsheet-id'
RANGE = 'Sheet1!A:D'
values = [['New Entry', 'data1', 'data2', 'data3']]
body = {'values': values}
result = sheets.spreadsheets().values().append(
spreadsheetId=SPREADSHEET_ID,
range=RANGE,
valueInputOption='RAW',
body=body
).execute()
print(f\"Appended {result.get('updates', {}).get('updatedRows')} row(s)\")"
Create new spreadsheet
python3 -c "
from google_auth import get_service
sheets = get_service('sheets', 'v4')
spreadsheet = {
'properties': {'title': 'My New Spreadsheet'},
'sheets': [{'properties': {'title': 'Data'}}]
}
result = sheets.spreadsheets().create(body=spreadsheet).execute()
print(f\"Created: {result['spreadsheetUrl']}\")"
Google Docs
Read document
python3 -c "
from google_auth import get_service
docs = get_service('docs', 'v1')
DOCUMENT_ID = 'your-document-id'
doc = docs.documents().get(documentId=DOCUMENT_ID).execute()
print(f\"Title: {doc.get('title')}\")
content = doc.get('body', {}).get('content', [])
for element in content:
if 'paragraph' in element:
for text_run in element['paragraph'].get('elements', []):
if 'textRun' in text_run:
print(text_run['textRun']['content'], end='')"
Create document
python3 -c "
from google_auth import get_service
docs = get_service('docs', 'v1')
doc = docs.documents().create(body={'title': 'My New Document'}).execute()
print(f\"Created document: {doc.get('documentId')}\")"
Insert text
python3 -c "
from google_auth import get_service
docs = get_service('docs', 'v1')
DOCUMENT_ID = 'your-document-id'
requests = [
{
'insertText': {
'location': {'index': 1},
'text': 'Hello, this is inserted text!\n\n'
}
}
]
result = docs.documents().batchUpdate(
documentId=DOCUMENT_ID,
body={'requests': requests}
).execute()
print('Text inserted')"
Replace text
python3 -c "
from google_auth import get_service
docs = get_service('docs', 'v1')
DOCUMENT_ID = 'your-document-id'
requests = [
{
'replaceAllText': {
'containsText': {'text': '{{PLACEHOLDER}}', 'matchCase': True},
'replaceText': 'Actual Value'
}
}
]
result = docs.documents().batchUpdate(
documentId=DOCUMENT_ID,
body={'requests': requests}
).execute()
print(f\"Replaced {result.get('replies', [{}])[0].get('replaceAllText', {}).get('occurrencesChanged', 0)} occurrences\")"
Google Drive (File Operations)
List files
python3 -c "
from google_auth import get_service
drive = get_service('drive', 'v3')
results = drive.files().list(
pageSize=10,
fields='files(id, name, mimeType)'
).execute()
for f in results.get('files', []):
print(f\"{f['name']} ({f['mimeType']})\")"
Upload file
python3 -c "
from google_auth import get_service
from googleapiclient.http import MediaFileUpload
drive = get_service('drive', 'v3')
file_metadata = {'name': 'example.txt'}
media = MediaFileUpload('example.txt', mimetype='text/plain')
file = drive.files().create(
body=file_metadata,
media_body=media,
fields='id'
).execute()
print(f\"Uploaded file ID: {file.get('id')}\")"
Download file
python3 -c "
from google_auth import get_service
import io
from googleapiclient.http import MediaIoBaseDownload
drive = get_service('drive', 'v3')
FILE_ID = 'your-file-id'
request = drive.files().get_media(fileId=FILE_ID)
file = io.BytesIO()
downloader = MediaIoBaseDownload(file, request)
done = False
while not done:
status, done = downloader.next_chunk()
print(f\"Download {int(status.progress() * 100)}%\")
with open('downloaded_file', 'wb') as f:
f.write(file.getvalue())
print('Download complete')"
Common IDs & URLs
| Service | ID Location |
|---|---|
| Gmail Message | URL: mail.google.com/mail/u/0/#inbox/MESSAGE_ID |
| Calendar Event | From API response event['id'] |
| Spreadsheet | URL: docs.google.com/spreadsheets/d/SPREADSHEET_ID/ |
| Document | URL: docs.google.com/document/d/DOCUMENT_ID/ |
| Drive File | URL: drive.google.com/file/d/FILE_ID/ |
Notes
- First run requires browser-based OAuth authorization
token.picklestores credentials for subsequent runs- Scopes can be limited based on needed functionality
- Rate limits apply; implement exponential backoff for production
- Use service accounts for server-to-server authentication
- Keep
credentials.jsonsecure and never commit to version control