"Yesterday's emails." "This week's events." "Anything since the script last ran." Real automations care about recent, not all. Two pieces: (1) compute the date threshold in Python, (2) inject it into Gmail's query parameter so the filter happens server-side.
from datetime import datetime, timedelta
cutoff = datetime.now() - timedelta(days=1)
yyyy_mm_dd = cutoff.strftime("%Y/%m/%d")
result = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {
"query": f"after:{yyyy_mm_dd}",
"max_results": 50,
})
print(len(result.get("messages", [])))from datetime import datetime, timedelta — that's an import. New territory.
Python's standard library is huge; you reach for it constantly. datetime covers calendar math: datetime.now() for now, timedelta(days=1) for an offset, .strftime(format) to render as a string. Gmail's query syntax wants YYYY/MM/DD — the format string "%Y/%m/%d" produces exactly that.
Server-side filter — that's the same thing as day 4 but using the API instead of Python?
Right. Day 4 was Python-side filter (over-fetch, then filter locally). Today's lesson is the better default: push the filter to Gmail. Less network, less quota, faster.
Two halves: compute the threshold, inject it into the API call.
Python's datetime module:
from datetime import datetime, timedelta
cutoff = datetime.now() - timedelta(days=1) # 24h ago
cutoff = datetime.now() - timedelta(hours=6) # 6h ago
cutoff = datetime.now() - timedelta(days=7) # a week agodatetime.now() returns the current time. timedelta(days=N) is an offset you can add or subtract.
Format for the target API:
gmail_format = cutoff.strftime("%Y/%m/%d") # "2026/05/04"
iso_format = cutoff.isoformat() # "2026-05-04T10:30:00"Gmail's query syntax expects YYYY/MM/DD. ISO 8601 is the universal format for most APIs.
query operators| Operator | Meaning |
|---|---|
after:2026/05/04 | sent on or after 2026-05-04 |
before:2026/05/04 | sent on or before 2026-05-04 |
is:unread | unread messages |
from:user@domain.com | from a specific sender |
subject:invoice | subject contains "invoice" |
has:attachment | has any attachment |
Combine with spaces (which mean AND): "is:unread after:2026/05/04 from:boss@co.com" matches unread messages from boss sent after May 4.
# Bad: over-fetch then Python-filter
result = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {"max_results": 500})
recent = [m for m in result["messages"] if recent_enough(m)]Fetching 500 messages to filter down to 5 is 100× the network and 100× the quota cost. The server-side filter does the same thing in one call.
# Good: push the filter to Gmail
result = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {
"query": f"after:{cutoff_str}",
"max_results": 50,
})strftime format codes| Code | Means |
|---|---|
%Y | 4-digit year (2026) |
%m | 2-digit month (05) |
%d | 2-digit day (04) |
%H | 24-hour hour (14) |
%M | 2-digit minute (30) |
%S | 2-digit second (05) |
A full reference is at the Python docs; the codes above cover 90% of what you'll need.
"Yesterday's emails." "This week's events." "Anything since the script last ran." Real automations care about recent, not all. Two pieces: (1) compute the date threshold in Python, (2) inject it into Gmail's query parameter so the filter happens server-side.
from datetime import datetime, timedelta
cutoff = datetime.now() - timedelta(days=1)
yyyy_mm_dd = cutoff.strftime("%Y/%m/%d")
result = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {
"query": f"after:{yyyy_mm_dd}",
"max_results": 50,
})
print(len(result.get("messages", [])))from datetime import datetime, timedelta — that's an import. New territory.
Python's standard library is huge; you reach for it constantly. datetime covers calendar math: datetime.now() for now, timedelta(days=1) for an offset, .strftime(format) to render as a string. Gmail's query syntax wants YYYY/MM/DD — the format string "%Y/%m/%d" produces exactly that.
Server-side filter — that's the same thing as day 4 but using the API instead of Python?
Right. Day 4 was Python-side filter (over-fetch, then filter locally). Today's lesson is the better default: push the filter to Gmail. Less network, less quota, faster.
Two halves: compute the threshold, inject it into the API call.
Python's datetime module:
from datetime import datetime, timedelta
cutoff = datetime.now() - timedelta(days=1) # 24h ago
cutoff = datetime.now() - timedelta(hours=6) # 6h ago
cutoff = datetime.now() - timedelta(days=7) # a week agodatetime.now() returns the current time. timedelta(days=N) is an offset you can add or subtract.
Format for the target API:
gmail_format = cutoff.strftime("%Y/%m/%d") # "2026/05/04"
iso_format = cutoff.isoformat() # "2026-05-04T10:30:00"Gmail's query syntax expects YYYY/MM/DD. ISO 8601 is the universal format for most APIs.
query operators| Operator | Meaning |
|---|---|
after:2026/05/04 | sent on or after 2026-05-04 |
before:2026/05/04 | sent on or before 2026-05-04 |
is:unread | unread messages |
from:user@domain.com | from a specific sender |
subject:invoice | subject contains "invoice" |
has:attachment | has any attachment |
Combine with spaces (which mean AND): "is:unread after:2026/05/04 from:boss@co.com" matches unread messages from boss sent after May 4.
# Bad: over-fetch then Python-filter
result = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {"max_results": 500})
recent = [m for m in result["messages"] if recent_enough(m)]Fetching 500 messages to filter down to 5 is 100× the network and 100× the quota cost. The server-side filter does the same thing in one call.
# Good: push the filter to Gmail
result = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {
"query": f"after:{cutoff_str}",
"max_results": 50,
})strftime format codes| Code | Means |
|---|---|
%Y | 4-digit year (2026) |
%m | 2-digit month (05) |
%d | 2-digit day (04) |
%H | 24-hour hour (14) |
%M | 2-digit minute (30) |
%S | 2-digit second (05) |
A full reference is at the Python docs; the codes above cover 90% of what you'll need.
Create a free account to get started. Paid plans unlock all tracks.