This workflow corresponds to n8n.io template #12069 — we link there as the canonical source.
This workflow follows the Gmail → Postgres recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Abandoned Signup Recovery Automation",
"tags": [],
"nodes": [
{
"id": "235e1c65-4c7b-486c-8c82-1a8701a9cc5e",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-336,
-80
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24
}
]
}
},
"typeVersion": 1.1
},
{
"id": "1eda6ee0-8f8a-466e-a5ca-90ce12ba5acb",
"name": "Find Abandoned Users",
"type": "n8n-nodes-base.postgres",
"position": [
-112,
-80
],
"parameters": {
"query": "SELECT *\nFROM public.\"Users\"\nWHERE \"Status\" = 'Incomplete'\n AND last_activity < NOW() - INTERVAL '24 hours'\n AND recovery_email_sent = FALSE;",
"options": {},
"operation": "executeQuery"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.4
},
{
"id": "0b77e61d-2f82-4fd7-962d-ee714ac7f981",
"name": "Alert Sales Team",
"type": "n8n-nodes-base.slack",
"position": [
1680,
-80
],
"parameters": {
"text": "=Recovery Email Sent to:\nID: {{ $json.ID }}\nName: {{ $json.Name }}\nEmail: {{ $json.Email }}\n--",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SLACK_CHANNEL_ID",
"cachedResultName": "general"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "607c2651-d22a-4a82-b9d6-fbe16181a120",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
112,
-80
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1463d610-6161-4ee2-a589-990f7e2d8df8",
"operator": {
"type": "number",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.ID }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2.3
},
{
"id": "bcb6f17b-75c0-4298-9a69-272aa0ffda76",
"name": "Loop Over Items",
"type": "n8n-nodes-base.splitInBatches",
"position": [
336,
-80
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "3c960e40-70de-446b-9a72-7763a3289c13",
"name": "PrepareEmail email",
"type": "@itechnotion/n8n-nodes-inboxplus.inboxPlus",
"position": [
560,
-80
],
"parameters": {
"templateId": "YOUR_EMAIL_TEMPLATE_ID",
"recipientEmail": "={{ $json.Email }}"
},
"credentials": {
"inboxPlusApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "18d25a98-ccc6-4138-8780-11f2bee671e2",
"name": "Send a message",
"type": "n8n-nodes-base.gmail",
"position": [
784,
-80
],
"parameters": {
"sendTo": "={{ $json.recipientEmail }}",
"message": "={{ $json.body }}",
"options": {},
"subject": "={{ $json.subject }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "6f26a2b4-84b9-421b-b0c2-98694208f854",
"name": "Get a message",
"type": "n8n-nodes-base.gmail",
"position": [
1008,
-80
],
"parameters": {
"messageId": "={{ $json.id }}",
"operation": "get"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "210bd1ef-b47f-4c47-ac70-1b7290ab3d4c",
"name": "StartSequence email",
"type": "@itechnotion/n8n-nodes-inboxplus.inboxPlus",
"position": [
1232,
-80
],
"parameters": {
"subject": "={{ $json.Subject }}",
"threadId": "={{ $json.threadId }}",
"messageId": "={{ $json.id }}",
"operation": "startSequence",
"sequenceId": "YOUR_SEQUENCE_ID",
"trackingId": "={{ $('PrepareEmail email').item.json.trackingId }}",
"sequenceSenderEmail": "={{ $json.From }}",
"sequenceRecipientEmail": "={{ $json.To }}"
},
"credentials": {
"inboxPlusApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "48468632-7376-46c7-83e5-6324a4d3fa35",
"name": "Update rows in a table",
"type": "n8n-nodes-base.postgres",
"position": [
1456,
-80
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "Users",
"cachedResultName": "Users"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"columns": {
"value": {
"ID": "={{ $('Loop Over Items').item.json.ID }}",
"recovery_email_sent": true
},
"schema": [
{
"id": "ID",
"type": "number",
"display": true,
"removed": false,
"required": false,
"displayName": "ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "last_activity",
"type": "dateTime",
"display": true,
"removed": true,
"required": false,
"displayName": "last_activity",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "recovery_email_sent",
"type": "boolean",
"display": true,
"required": false,
"displayName": "recovery_email_sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"ID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.6
},
{
"id": "b3ee6a42-c4a6-4b40-9831-eb2343cb1db3",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-912,
-320
],
"parameters": {
"width": 512,
"height": 560,
"content": "## Automated User Recovery Email Workflow\nThis workflow identifies inactive users who abandoned onboarding, sends automated recovery emails, updates their status, and alerts the sales team\u2014ideal for SaaS user reactivation without manual follow-up.\n\n### How It Works\n\u2022 A scheduled trigger runs every 24 hours\n\u2022 The workflow queries Postgres for users marked as incomplete and inactive\n\u2022 Results are validated to ensure users exist\n\u2022 Users are processed one by one to avoid rate limits\n\u2022 A personalized recovery email is prepared using InboxPlus\n\u2022 The email is sent via Gmail and tracked in a sequence\n\u2022 The user record is updated to prevent duplicate emails\n\u2022 The sales team is notified in Slack after completion\n\n### Setup Steps\n1. Configure the Schedule Trigger to run at your preferred interval\n2. Connect Postgres credentials and verify the Users table schema\n3. Update the SQL query conditions if your inactivity logic differs\n4. Add InboxPlus credentials and select the correct email template\n5. Connect Gmail credentials for sending recovery emails\n6. Set the correct Slack channel and connect Slack credentials\n7. Run a test with a sample inactive user and activate the workflow\n"
},
"typeVersion": 1
},
{
"id": "ecc7088d-34af-47ab-95d9-efaf202a516b",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-384,
-320
],
"parameters": {
"color": 7,
"width": 640,
"height": 560,
"content": "## Step 1: Start the check and find inactive users\nThe workflow runs automatically on a schedule and queries your database to find users who abandoned onboarding and have been inactive for more than 24 hours."
},
"typeVersion": 1
},
{
"id": "10a8ec77-68a4-4359-88db-696ea421ef4b",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
272,
-320
],
"parameters": {
"color": 7,
"width": 1104,
"height": 560,
"content": "## Step 2: Prepare users and generate recovery emails\nInactive users are validated and processed one by one. A personalized recovery email is prepared using a predefined template and sent via Gmail, with tracking enabled for follow-up sequences."
},
"typeVersion": 1
},
{
"id": "872f488d-a292-48f8-aca0-5d30a34d8c77",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1392,
-320
],
"parameters": {
"color": 7,
"width": 480,
"height": 560,
"content": "## Step 3: Update records and notify the sales team\nHere the user record is updated to prevent duplicate outreach, and a notification is posted to Slack for the sales team"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"connections": {
"If": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Get a message": {
"main": [
[
{
"node": "StartSequence email",
"type": "main",
"index": 0
}
]
]
},
"Send a message": {
"main": [
[
{
"node": "Get a message",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[],
[
{
"node": "PrepareEmail email",
"type": "main",
"index": 0
}
]
]
},
"Alert Sales Team": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Find Abandoned Users",
"type": "main",
"index": 0
}
]
]
},
"PrepareEmail email": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
},
"StartSequence email": {
"main": [
[
{
"node": "Update rows in a table",
"type": "main",
"index": 0
}
]
]
},
"Find Abandoned Users": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"Update rows in a table": {
"main": [
[
{
"node": "Alert Sales Team",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2inboxPlusApipostgresslackOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automatically identifies users who started but did not complete the signup process. It runs on a fixed schedule, checks your database for inactive and incomplete users, and validates the results before proceeding. Each user is then processed individually to send a…
Source: https://n8n.io/workflows/12069/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow transforms raw SaaS metrics into a fully automated Product Health Monitoring & Incident Management system.
This workflow continuously validates data quality using rules stored in Notion, runs anomaly checks against your SQL database, generates AI-powered diagnostics, and alerts your team only when real iss
This workflow monitors customer health by combining payment behavior, complaint signals, and AI-driven feedback analysis. It runs on daily and weekly schedules to evaluate risk levels, escalate high-r
This workflow automatically monitors and reports data quality for any SQL table using configurable checks and thresholds. It evaluates key metrics—including null values, duplicate records, row count a
Continuous monitoring: Real-time surveillance of supplier performance, financial health, and operational status Risk scoring: AI-powered assessment of supplier risks across multiple dimensions (financ