Recruiter email parser — auto-populate Contacts from inbox #102

Open
opened 2026-04-15 09:52:41 -07:00 by pyr0ball · 0 comments
Owner

Summary

Contacts view currently shows emails logged by the user or seeded into the DB. We need an email parser that automatically detects and imports recruiter emails from a connected inbox (IMAP or Gmail API).

What it should do

  • Connect to IMAP / Gmail (user-configured in Settings)
  • Scan inbox for job-related emails: recruiter outreach, interview confirmations, offer letters, rejection notices
  • Parse: sender, subject, date, stage signal (interview_scheduled, offer_received, rejected, positive_response, etc.)
  • Insert into job_contacts with direction=inbound and the detected stage_signal
  • Optionally attempt to match against an existing job in the pipeline (by company name / job title from subject)
  • Deduplicate on (job_id, from_addr, received_at)

Classifier labels available

Avocet already defines 9 labels that map directly to stage signals:
interview_scheduled, offer_received, rejected, positive_response, survey_received, neutral, event_rescheduled, unrelated, digest

Use the classifier pipeline from scripts/classifier_adapters.py for detection.

Notes

  • Gmail OAuth path requires Google Cloud project setup — start with IMAP (less friction)
  • IMAP credentials stored in config/email.yaml (gitignored), same pattern as config/notion.yaml
  • Email sync can be a background task dispatched from Settings → Integrations
  • The demo hint on Contacts says "Peregrine logs every recruiter email automatically" — this is the feature that makes that true
  • Contacts view: web/src/views/ContactsView.vue
  • Email sync stub: GET /api/email/sync already exists in dev-api.py
  • Avocet classifier: /Library/Development/CircuitForge/avocet/
## Summary Contacts view currently shows emails logged by the user or seeded into the DB. We need an email parser that automatically detects and imports recruiter emails from a connected inbox (IMAP or Gmail API). ## What it should do - Connect to IMAP / Gmail (user-configured in Settings) - Scan inbox for job-related emails: recruiter outreach, interview confirmations, offer letters, rejection notices - Parse: sender, subject, date, stage signal (interview_scheduled, offer_received, rejected, positive_response, etc.) - Insert into `job_contacts` with direction=`inbound` and the detected `stage_signal` - Optionally attempt to match against an existing job in the pipeline (by company name / job title from subject) - Deduplicate on (job_id, from_addr, received_at) ## Classifier labels available Avocet already defines 9 labels that map directly to stage signals: `interview_scheduled`, `offer_received`, `rejected`, `positive_response`, `survey_received`, `neutral`, `event_rescheduled`, `unrelated`, `digest` Use the classifier pipeline from `scripts/classifier_adapters.py` for detection. ## Notes - Gmail OAuth path requires Google Cloud project setup — start with IMAP (less friction) - IMAP credentials stored in `config/email.yaml` (gitignored), same pattern as `config/notion.yaml` - Email sync can be a background task dispatched from Settings → Integrations - The demo hint on Contacts says "Peregrine logs every recruiter email automatically" — this is the feature that makes that true ## Related - Contacts view: `web/src/views/ContactsView.vue` - Email sync stub: `GET /api/email/sync` already exists in dev-api.py - Avocet classifier: `/Library/Development/CircuitForge/avocet/`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Circuit-Forge/peregrine#102
No description provided.