1. Opening Problem Statement
Meet Alex, an IT security analyst for a mid-sized company. Every day, Alex spends hours manually reviewing suspicious emails to verify their authenticity and trace their origin. Alex struggles with inaccurate sender information, hidden IP addresses, and unclear authentication results, which leads to time wasted, increased risk of phishing threats, and missed malicious activities.
Before discovering this n8n workflow, Alex spent approximately 2 hours daily decoding email headers, often overwhelmed by the complex data and unreliable details embedded within Gmail message headers. False positives and negatives in email validations caused costly errors and jeopardized the company’s email security posture.
2. What This Automation Does
This powerful n8n automation simplifies email header analysis directly for Gmail, delivering precise insights to Alex or any user. When triggered, it:
- Extracts detailed “Received” headers from Gmail emails to find the originating IP address.
- Filters out internal or private IP addresses, isolating the true sender IP for accuracy.
- Queries the IP Quality Score API and IP-API service to assess the reputation, recent spam activity, and geographic information related to the sender IP.
- Checks for key email authentication headers: SPF, DKIM, and DMARC, extracting and interpreting their pass/fail results.
- Compiles all information into a clean, structured JSON output—ready for real-time use or integration with external security tools via webhook.
- Enables API integration through a webhook, letting other platforms submit email data for instant validation and analysis.
By automating this complex process, the workflow can save professionals like Alex several hours per day, drastically reduce human error, and enhance email security by providing actionable intelligence quickly.
3. Prerequisites ⚙️
- n8n account (cloud or self-hosted) 🔌
- Gmail account authorized with OAuth2 credentials for accessing email data 📧
- IP Quality Score API key (free or paid tier) 🔑
- Internet access for HTTP requests to IP reputation and geolocation services
4. Step-by-Step Guide
Step 1: Set Up Gmail Trigger (Testing Only)
Even though the workflow disables the Gmail Trigger node by default, enable it during testing to fetch new emails directly from your Gmail inbox.
- Navigate to the Gmail Trigger node.
- Enable the node by unchecking the “Disabled” option.
- Select OAuth2 credentials linked to your Gmail account.
- Under Poll Times, keep the default “every minute” setting.
- Save and execute the workflow to ensure it triggers on new incoming emails.
Expected outcome: The workflow activates upon new emails, pulling them into n8n for processing.
Common mistake: Forgetting to enable the node results in no triggers firing.
Step 2: Extract and Set Gmail Email Headers
The Set Gmail Headers Here node grabs the raw headers object from the Gmail Trigger output and creates a usable “headers” field for further parsing.
- Click on the node and check its JSON field to confirm the headers array is assigned as
{{ $json.headers }}. - Ensure “Include Other Fields” is enabled to preserve email metadata.
Visual description: You should see a structured object containing the email headers, ready for extraction steps.
Step 3: Extract Received Headers Using Code Node
The Gmail – Extract Received Headers code node filters email headers for all fields labeled “received,” which trace the email’s server route.
Code snippet inside this node is as follows:
// Extract the headers object from the JSON
const headers = $('Gmail - Set Headers').item.json.headers;
// Find all keys named "received" (case-insensitive)
const receivedHeaders = Object.entries(headers)
.filter(([key, value]) => key.toLowerCase() === 'received')
.map(([key, value]) => ({ key, value }));
// Return each header as an object
return receivedHeaders.map(header => ({ json: header }));
This node outputs all “Received” headers for the next node to process.
Step 4: Retain the Most Recent “Received” Header
Gmail – Remove Extra Received Headers is a Limit node that keeps only the most recent “Received” header, which usually contains the originating IP.
Configuration: Set it to keep lastItems, so only the last “received” header passes through.
Step 5: Extract the Original Sender IP Address
Use the Gmail – Extract Original From IP Set node to apply a regular expression that removes internal/local IPs and extracts the true external IP.
Example expression in the node:
= {{ $json.value.replace(/b(127.(?:d{1,3}.){2}d{1,3})|(10.(?:d{1,3}.){2}d{1,3})|(172.(?:1[6-9]|2[0-9]|3[0-1]).d{1,3}.d{1,3})|(192.168.d{1,3}.d{1,3})b/g, "").match(/(s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:)))(%.+)?s*)|(b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)b)/)[0] }}
Expected outcome: The node outputs the cleaned and extracted external IP address as extractedfromip.
Step 6: Conditional Check for Valid IP Address
The Gmail – Original IP Found? If node evaluates if the extracted IP field is neither null nor empty to decide the workflow path.
- If true, it calls IP reputation and geolocation nodes.
- If false, it skips IP checks and moves on to authentication header checks.
Step 7: Query IP Quality Score API
The Gmail – Query IP Quality Score API HTTP Request node queries https://ipqualityscore.com/api to get reputation, recent spam activity, and potential threats linked to the extracted IP address.
Configuration:
- HTTP Method: GET
- URL example:
https://ipqualityscore.com/api/json/ip/YOUR_API_KEY/{extracted_ip}
Response includes: Fraud score, risk assessment, and other indicators.
Step 8: Query Geolocation and Org Info API
The Gmail – Query IP API HTTP Request node calls http://ip-api.com/json/{extracted_ip} to obtain the IP owner’s organization, country, and city.
Simple GET request with the IP embedded in the URL.
Step 9: Evaluate Presence of Authentication-Results Header
The Gmail – Authentication-Results Header? node checks if the email headers contain the “Authentication-Results” field, a key for assessing SPF, DKIM, and DMARC passes or failures.
- If present, the workflow extracts these results.
- If absent, it branches to check these three protocols individually.
Step 10: Extract Authentication-Results Header
The Gmail – Extract Authentication-Results Header Code node filters headers for the “Authentication-Results” field and prepares each for analysis.
Code snippet:
// Extract the headers object from the JSON
const headers = $('Gmail - Set Headers').item.json.headers;
// Filter for "authentication-results"
const results = Object.entries(headers)
.filter(([key, value]) => key.toLowerCase() === 'authentication-results')
.map(([key, value]) => ({ key, value }));
// Return as array of JSON objects
return results.map(header => ({ json: header }));
Step 11: Determine SPF, DKIM, and DMARC Pass/Fail Values
The Gmail – Determine Auth Values Set node interprets the authentication strings to classify the status for each protocol as pass, fail, neutral, error, or unknown.
Example expressions used in this node:
spfvalue = {{ $json.value.toLowerCase().includes('spf=pass') ? "pass" : $json.value.toLowerCase().includes('spf=fail') ? "fail" : $json.value.toLowerCase().includes('spf=neutral') ? "neutral" : "unknown" }}
dkimvalue = {{ $json.value.toLowerCase().includes('dkim=pass') ? "pass" : $json.value.toLowerCase().includes('dkim=fail') ? "fail" : $json.value.toLowerCase().includes('dkim=temperror') ? "error" : "unknown" }}
dmarcvalue = {{ $json.value.toLowerCase().includes('dmarc=pass') ? "pass" : $json.value.toLowerCase().includes('dmarc=fail') ? "fail" : "unknown" }}
Step 12: Handle Cases Where Specific SPFs or Signatures Are Missing
The workflow uses separate If nodes and Set nodes such as Gmail – Received-SPF Header?, Gmail – DKIM-Signature Header?, and Gmail – DMARC Header? to detect if those headers exist.
Based on detection, the workflow either extracts and processes the findings or tags them as “not found”.
Step 13: Combine and Aggregate Results
Multiple Merge and Aggregate nodes combine the authentication results, IP reputation data, spam activity indicators, and geo details.
Format Combined Auth Output1 and Format Individual Auth Outputs1 nodes organize the data fields to produce clean JSON output.
Step 14: Finalize Output and Respond to Webhook
The Gmail – Format Output Set node consolidates all data, and the Gmail – Respond to Webhook node sends the complete response to the calling system.
This allows external platforms to query the webhook with email data and receive detailed trustworthiness analysis.
5. Customizations ✏️
- Adjust IP Reputation Thresholds: In the Gmail – Format Individual Auth Outputs1 node, modify the fraud score cutoffs to customize how spam risk & IP reputation are classified.
- Add Additional Email Headers: Extend the Gmail – Extract Authentication-Results Header code node to capture and analyze further headers as needed.
- Integrate with Slack or Microsoft Teams: Add notification nodes after the Gmail – Respond to Webhook node to send alerts when emails fail authentication.
- Extend IP Info Sources: Incorporate other IP reputation APIs by adding new HTTP Request nodes following the Gmail – Original IP Found? node.
- Customize Webhook Endpoint Path: Change the webhook path in the Gmail – Webhook node parameters to suit your API naming conventions.
6. Troubleshooting 🔧
Problem: “No output from Gmail Trigger node when new emails arrive”
Cause: Gmail Trigger disabled or OAuth2 credentials expired.
Solution: Enable the node and reauthenticate Gmail OAuth2 credentials via Credentials Manager in n8n.
Problem: “Extracted IP is empty or incorrect”
Cause: Private or local IPs not removed properly or headers missing.
Solution: Verify the regular expression in Gmail – Extract Original From IP matches external IPs only; test with multiple email samples.
Problem: “API calls to IP Quality Score fail or return errors”
Cause: Invalid or missing API key; rate limit exceeded.
Solution: Confirm API key is correct; add error handling and retry logic for HTTP nodes.
7. Pre-Production Checklist ✅
- Test with various email samples containing different SPF/DKIM/DMARC configurations.
- Ensure API keys for IP Quality Score are valid and requests succeed.
- Check Gmail OAuth2 credentials for validity and permissions.
- Confirm webhook is active and publicly accessible if integrating externally.
- Backup workflow before major changes.
8. Deployment Guide
After thorough testing, activate the workflow to make the webhook available for production use.
Monitor workflow executions via n8n’s execution logs to track any errors or anomalies.
Regularly update API keys and credentials to maintain uninterrupted service.
9. FAQs
Q: Can I use an alternative email provider instead of Gmail?
A: This workflow is explicitly designed for Gmail and its specific message header format. Using non-Gmail services requires adjustment for header structures.
Q: Does API usage for IP Quality Score incur costs?
A: The IP Quality Score API offers free and paid tiers. Monitor your usage to avoid unexpected fees.
Q: How secure is my email data within this workflow?
A: All email header data stays within your n8n environment. Using self-hosting options enhances security further.
Q: Can this workflow handle large volumes of emails?
A: Yes, but consider API rate limits and n8n execution concurrency settings when scaling.
10. Conclusion
In this tutorial, you have built an advanced n8n workflow that fully automates the extraction, verification, and analysis of Gmail email headers. You learnt to extract sender IP addresses, query IP reputation services, and decode email authentication results for SPF, DKIM, and DMARC with real-time API integration.
This automation saves email security analysts like Alex countless hours, reduces human error, and equips organizations to better identify phishing or spam sources.
Next, consider extending this workflow to:
- Automatically quarantine or label suspicious emails in Gmail.
- Integrate with incident response platforms like PagerDuty or ServiceNow.
- Create dashboards visualizing email threat trends using Google Sheets or Data Studio.
Thanks for following along—let’s keep securing your email communications!