ai newsFr., 23. Okt.
EilmeldungGoogle Maps für CarPlay: Mit Gemini sprechen bei der Fahrt

Track job applications from Gmail automatically with n8n and AI

After the twentieth job application, nobody remembers which company replied, which one sent a coding test with a Friday deadline, and which one quietly rejected you three weeks ago. The usual advice is "keep a spreadsheet". The problem is that keeping the spreadsheet is a second job. But almost eve

dev.toFreitag 15:49 · 23.10.6 Min. Lesezeit
Bild: dev.to

After the twentieth job application, nobody remembers which company replied, which one sent a coding test with a Friday deadline, and which one quietly rejected you three weeks ago. The usual advice is "keep a spreadsheet". The problem is that keeping the spreadsheet is a second job.

But almost every update in a job search already arrives as an email: the "thanks for applying" confirmation, the assessment link, the interview invite, the rejection. So the spreadsheet can maintain itself. This post walks through an n8n workflow that watches Gmail, uses Google Gemini (free tier) to recognise emails about your applications, and keeps one row per application in Google Sheets with the latest status, next step and deadline.

A Google Sheet like this, updated every hour:

application _ key | company | role | status | next _ step | deadline | last _ update | last _ subject | from | gmail _ link Enter fullscreen mode Exit fullscreen mode Statuses: applied, assessment, interview, offer, rejected, recruiter_outreach, other. Add conditional formatting on the status column and you have a colour-coded board.

Gmail Trigger (every hour, filtered search) -> Code: keep sender, subject, date, first 3,000 chars -> Basic LLM Chain + Gemini + Structured Output Parser -> IF is_job_application -> Set: build application_key + Gmail link -> Google Sheets: append or update by application_key Enter fullscreen mode Exit fullscreen mode Six working nodes. The interesting decisions are in the filter, the prompt and the key.

You don't want to send every newsletter and receipt to an LLM. The Gmail Trigger node accepts a normal Gmail search query, so let Gmail do the first pass:

-category:promotions -category:social (application OR applying OR applied OR interview OR candidacy OR position OR role OR offer OR assessment) Enter fullscreen mode Exit fullscreen mode This is deliberately broad: a missed interview invite is far worse than a wasted AI call. The model does the precise filtering in the next step.

Set the trigger to Simple: off so you get the full message (body text and HTML), and Read status: both, because you may already have opened the email on your phone before the workflow sees it.

Rejection emails are short, but some ATS emails come with 40 KB of HTML. A Code node keeps only what the model needs:

return $input. all (). map ( i => { const m = i. json; const body = ( m. text || ( m. html || '' ). replace ( /< [^ > ] +>/g, ' ' ) || m. snippet || '' ). replace ( / \s +/g, ' ' ). trim (); return { json: { message_id: m. id, thread_id: m. threadId, from: m. from?. text || m. from?. value?.[ 0 ]?. address || '', subject: m. subject || '', date: m. date || '', body: body. slice ( 0, 3000 ) } }; }); Enter fullscreen mode Exit fullscreen mode 3,000 characters is enough for every status email I've seen, and it keeps each call small on the free tier.

The prompt does two jobs at once: decide whether this email is about your application at all, and if so extract the details.

You read one email from a job seeker's inbox and decide whether it is about one of their own job applications. From: {{ $json.from }} Subject: {{ $json.subject }} Date: {{ $json.date }} Body: {{ $json.body }} Rules: - is_job_application is true only for emails about an application this person made or a recruiter contacting them about a specific role. Newsletters, job alerts, marketing and course emails are false. - status is one of: applied (confirmation received), assessment (test or task), interview (invite or scheduling), offer, rejected, recruiter_outreach, other. - company and role: use the hiring company (not the ATS such as Workday or Greenhouse).

Use "Unknown" if not stated. - deadline: an ISO date (YYYY-MM-DD) if the email names one, otherwise an empty string. - next_step: under 12 words, empty string if none. Enter fullscreen mode Exit fullscreen mode The line about the ATS matters more than you'd think. Lots of confirmation emails come from no-reply@myworkday.com or greenhouse.io, and without that instruction you end up with a tracker full of "Workday".

Job alerts are the other big false positive: "10 new Data Analyst jobs in London" contains every keyword in the Gmail filter. The rule explicitly marks them false.

A Structured Output Parser pins the shape:

{ "is_job_application": true, "company": "Acme Ltd", "role": "Data Analyst", "status": "interview", "next_step": "Video interview on Tuesday", "deadline": "2026-10-21", "confidence": "high" } Enter fullscreen mode Exit fullscreen mode In the LLM Chain node, use batching (5 items, 5-second delay). When you first activate and a burst of emails arrives, this keeps you under the free tier's requests-per-minute limit.

This is the part that turns a log into a tracker. Each email produces a key from company and role:

{{ ( $json. output. company + '|' + $json. output. role ). toLowerCase (). replace (/[ ^ a-z0-9 |] + / g, ' ' ). trim () }} Enter fullscreen mode Exit fullscreen mode Acme Ltd | Data Analyst and ACME LTD | Data Analyst. both become acme ltd|data analyst. The Google Sheets node uses Append or Update with application_key as the matching column, so the confirmation creates the row, and the assessment, the interview invite and the offer all update the same row.

The row also stores a direct Gmail link to the thread:

https://mail.google.com/mail/u/0/#all/{{ thread_id }} Enter fullscreen mode Exit fullscreen mode so you can jump from the sheet to the email in one click.

The free version gives you a self-updating tracker. When I used it myself, the things I wanted next were: an instant ping when an interview or offer lands (rather than finding it in the sheet), a weekly view of how the search is going, and a nudge for applications that went quiet. Those are in a Pro version: a History tab with every status change, instant Telegram alerts for interviews, assessments and offers, a Monday report (applications, response rate, interviews, offers, rejections), and polite follow-up emails written by Gemini for applications with no reply after N days, saved as Gmail drafts (never sent automatically). It's $15 on Payhip: Job application tracker Pro.

If you're earlier in the search, there's also a free template on n8n.io that scores remote job listings against your CV and alerts you on Telegram. The rest of my templates are on the store and my n8n creator profile.

Good luck with the search. If an email type confuses the classifier, paste the subject line in the comments and I'll tune the prompt.

Quelle: dev.to (dev.to). Original öffnen