count_emails
Count emails matching specific criteria like sender, date, or keywords to preview results before bulk operations in iCloud Mail.
Instructions
Count how many emails match a set of filters without moving or deleting them. Use this before bulk_move or bulk_delete to preview how many emails will be affected.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| mailbox | No | Mailbox to count in (default INBOX) | |
| sender | No | Match exact sender email address | |
| domain | No | Match any sender from this domain (e.g. substack.com) | |
| subject | No | Keyword to match in subject | |
| before | No | Only emails before this date (YYYY-MM-DD) | |
| since | No | Only emails since this date (YYYY-MM-DD) | |
| unread | No | True for unread only, false for read only | |
| flagged | No | True for flagged only, false for unflagged only | |
| larger | No | Only emails larger than this size in KB | |
| smaller | No | Only emails smaller than this size in KB | |
| hasAttachment | No | Only emails with attachments (client-side BODYSTRUCTURE scan — must be combined with other filters that narrow results to under 500 emails first) | |
| account | No | Account name to use (e.g. 'icloud', 'gmail'). Defaults to first configured account. Use list_accounts to see available accounts. |
Implementation Reference
- lib/imap.js:1793-1808 (handler)The implementation of the `count_emails` tool, which queries IMAP for email counts based on provided filters and an optional mailbox. Includes client-side filtering for attachments when requested.
export async function countEmails(filters, mailbox = 'INBOX', creds = null) { const client = createRateLimitedClient(creds); await client.connect(); await client.mailboxOpen(mailbox); const query = buildQuery(filters); let uids = (await client.search(query, { uid: true })) ?? []; if (filters.hasAttachment) { if (uids.length > ATTACHMENT_SCAN_LIMIT) { await client.logout(); return { count: null, candidateCount: uids.length, mailbox, filters, error: `hasAttachment requires narrower filters first — ${uids.length} candidates exceeds scan limit of ${ATTACHMENT_SCAN_LIMIT}. Add from/since/before/subject filters to reduce the set.` }; } uids = await filterUidsByAttachment(client, uids); } await client.logout(); return { count: uids.length, mailbox, filters }; }