IntegrationsAdvanced

How to sync AI-extracted tasks from email to your calendar with n8n

Self-host an n8n workflow that reads email, extracts deadlines with AI, and creates calendar events, all under your own control.

11 minAdvanced

If you want full control and no per-task fees, n8n is an open-source automation tool you can self-host. This guide builds a workflow that watches an inbox, sends each email to an AI node to pull out any deadline, and creates a calendar event when it finds one. Everything runs on your own server.

  • n8n installed (Docker is easiest) and reachable in a browser
  • Gmail or IMAP credentials, plus Google or CalDAV calendar credentials
  • An AI provider credential (OpenAI, Anthropic, or a local model)
  • About 12 minutes

Step 1: Run n8n locally

The quickest start is Docker. This command runs n8n and stores its data in a named volume so your workflows survive restarts. Open the printed URL and create your owner account.

zsh - run n8n
$docker volume create n8n_data
$docker run -d --name n8n -p 5678:5678 \
$ -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n
n8n ready on http://localhost:5678
$

Step 2: Add the email trigger

Create a new workflow. Add a Gmail Trigger node (or Email Trigger IMAP for non-Gmail) set to poll every minute. Connect your credentials. This node outputs the subject and body of each new message into the workflow.

n8n - workflow canvas
[ Gmail Trigger ] --> [ OpenAI: extract deadline ]
|
v
[ IF has_deadline ]
true | false (do nothing)
v
[ Google Calendar: Create ]
Trigger, AI extraction, an IF gate, then create event.

Step 3: Extract the deadline with an AI node

Add an OpenAI (or AI Agent) node. Prompt it to return strict JSON describing any deadline. The key trick is to return a clear empty signal when there is no deadline, so the next step can branch cleanly.

AI node prompt
Read this email. If it contains a deadline or due date, return:
{ "has_deadline": true, "title": "...", "datetime": "YYYY-MM-DDTHH:mm:ss" }
If there is no deadline, return:
{ "has_deadline": false }
Return JSON only.

Subject: {{ $json.subject }}
Body: {{ $json.textPlain }}
Branch on the boolean
Add an IF node after the AI step that checks has_deadline is true. Only the true branch connects to the calendar node, so emails without dates are quietly ignored instead of creating junk events.

Step 4: Create the calendar event

On the true branch, add a Google Calendar node set to Create an event. Map the title and use the AI datetime for the start, with an expression to add an hour for the end. Activate the workflow with the toggle in the top right.

end time expression
{{ $json.datetime
   ? new Date(new Date($json.datetime).getTime() + 60*60*1000).toISOString()
   : '' }}

Result: a vendor emails that the signed contract is due June 30 at noon. Within a minute n8n parses it and a one-hour Contract due block appears on your calendar at the right time, with no SaaS subscription and no data leaving your server except the AI call you chose.

Watch related tutorials

Tags
#n8n#self-hosted#calendar#email