# Search

messages.list and threads.list filter by labelIds and by the q operators of Gmail's search box, and leave trash and spam out unless asked.

`GET /gmail/v1/users/me/messages` and `GET /gmail/v1/users/me/threads` take `q`, the grammar of Gmail's search box, and filter the busy inbox the way Gmail does. Find mail by attachment, folder, label, phrase and subject:

```bash
curl -s -X POST "$RYSTIC_URL/_rystic/scenario" -d '{"name":"gmail_busy_inbox"}' -o /dev/null
G=(-H 'Authorization: Bearer ya29.placeholder')
curl -s -G "$RYSTIC_URL/gmail/v1/users/me/messages" --data-urlencode 'q=has:attachment' "${G[@]}" | jq -c '{ids: [.messages[].id], resultSizeEstimate}'
# -> {"ids":["19a4c0d1e2f31003"],"resultSizeEstimate":1}
curl -s -G "$RYSTIC_URL/gmail/v1/users/me/messages" --data-urlencode 'q=in:trash' "${G[@]}" | jq -c '{ids: [.messages[].id], resultSizeEstimate}'
# -> {"ids":["19a4c0d1e2f31009"],"resultSizeEstimate":1}
curl -s -G "$RYSTIC_URL/gmail/v1/users/me/messages" --data-urlencode 'q=invoice label:receipts' "${G[@]}" | jq -c '{ids: [.messages[].id], resultSizeEstimate}'
# -> {"ids":["19a4c0d1e2f31003"],"resultSizeEstimate":1}
curl -s -G "$RYSTIC_URL/gmail/v1/users/me/messages" --data-urlencode 'q="flight ZX4821"' "${G[@]}" | jq -c '{ids: [.messages[].id], resultSizeEstimate}'
# -> {"ids":["19a4c0d1e2f31004"],"resultSizeEstimate":1}
curl -s -G "$RYSTIC_URL/gmail/v1/users/me/threads" --data-urlencode 'q=subject:standup' "${G[@]}" | jq -c '{ids: [.threads[].id], resultSizeEstimate}'
# -> {"ids":["19a4c0d1e2f30004"],"resultSizeEstimate":1}
curl -s -G "$RYSTIC_URL/gmail/v1/users/me/messages" --data-urlencode 'maxResults=100' "${G[@]}" | jq -c '{resultSizeEstimate}'
# -> {"resultSizeEstimate":8}
curl -s -G "$RYSTIC_URL/gmail/v1/users/me/messages" --data-urlencode 'maxResults=100' --data-urlencode 'includeSpamTrash=true' "${G[@]}" | jq -c '{resultSizeEstimate}'
# -> {"resultSizeEstimate":9}
```

### Operators

`q` takes these, joined by an implicit AND:

- bare words, and quoted phrases whose words must appear in order;
- `from:`, `to:`, `cc:`, `bcc:` and `subject:`;
- `label:`, `category:`, `is:` and `in:`;
- `has:attachment`, `filename:`, `larger:` and `smaller:`;
- `after:`, `before:`, `older_than:` and `newer_than:`, read against the simulator's clock;
- `-` for negation, `OR` and `{…}` groups.

Both lists leave trashed and spam mail out unless `includeSpamTrash=true` or the query names it (`in:trash`, `in:spam`, `in:anywhere`).

These readings are unconfirmed, meaning not yet checked against Gmail:

| Query | The simulator reads it as |
|---|---|
| a date in `after:` or `before:` | midnight UTC that day: `after:` matches on or after it, `before:` before it |
| `K` or `M` in `larger:` or `smaller:` | 1,024 or 1,048,576 bytes |
| `has:attachment` or `filename:` | an attachment at most two levels of parts deep, never one below that |

### Filters and pages

`labelIds` keeps only mail that carries every label named, and it combines with `q`. [Pagination](https://www.rystic.ai/docs/simulators/gmail.md#pagination) covers `maxResults` and `pageToken`.

---

Source: https://www.rystic.ai/docs/simulators/gmail/features/search · Markdown: https://www.rystic.ai/docs/simulators/gmail/features/search.md
