Step 1 — Email parser
Resend inbound webhook that parses Bayut/PF emails into structured lead data.
2 min read
Setting up the email parser
Step 1: Get a Resend inbound domain
- Sign up at resend.com
- Buy
leads@yourdomain.com(or use a subdomain likeleads.steinhoff.systems) - Configure DNS: MX record pointing to Resend, SPF/DKIM for deliverability
- In Resend dashboard: enable inbound email, set webhook URL
Step 2: The parser script
# scripts/parse-lead-email.py
import re
import json
from email import message_from_string
from bs4 import BeautifulSoup
def parse_bayut_email(raw_email):
msg = message_from_string(raw_email)
payload = msg.get_payload()
if msg.is_multipart():
html = ""
for part in payload:
if part.get_content_type() == "text/html":
html = part.get_payload(decode=True).decode()
break
soup = BeautifulSoup(html, "html.parser")
# Bayut email structure (inspected — 2026 version)
lead = {
"source": "bayut",
"name": soup.find("span", {"class": "lead-name"}).text,
"phone": soup.find("span", {"class": "lead-phone"}).text,
"budget": soup.find("span", {"class": "lead-budget"}).text,
"area": soup.find("span", {"class": "lead-area"}).text,
"timeline": soup.find("span", {"class": "lead-timeline"}).text,
"property_ref": soup.find("span", {"class": "property-ref"}).text,
"message": soup.find("div", {"class": "lead-message"}).text,
}
# Extract budget number from string like "AED 1.5M" or "1,000,000"
budget_match = re.search(r'([\d,]+)', lead["budget"])
if budget_match:
lead["budget_num"] = int(budget_match.group(1).replace(",", ""))
return lead
Step 3: The webhook endpoint
# scripts/server.py (Flask)
from flask import Flask, request, jsonify
from parse_lead_email import parse_bayut_email
import json
app = Flask(__name__)
@app.route("/webhook/resend", methods=["POST"])
def handle_lead_email():
data = request.json
raw_email = data["email"]["raw"]
lead = parse_bayut_email(raw_email)
# Save to database
save_lead(lead)
# Trigger qualification flow
qualify_lead(lead)
return jsonify({"status": "ok", "lead_id": lead["id"]})
def qualify_lead(lead):
# Hot: budget > 1M AND timeline < 1 month
# Warm: budget > 500k AND timeline < 2 months
# Cold: everything else
...
Gotchas
- Bayut emails use inline CSS tables — BeautifulSoup handles this but be prepared for weird nesting
- Arabic text — make sure you decode UTF-8 properly:
raw_email.decode('utf-8') - Multiple properties in one email — some portal emails contain 2–3 leads. Parse them all.
- Property ref format — Bayut uses
BPT1234567, PF usesPF-789012, Dubizzle usesDUB-3456. Your parser needs to handle all three.
Real-world test
After building this, send yourself a test email from Bayut Pro (request a test lead through the portal). Verify the parser extracts correctly. You will find 3 things wrong with your first regex. Fix them, then re-test.
AI Lead Automation · progress saved in this browser · sign in to sync across devices
Up next
Step 2 — WhatsApp integration
Twilio WhatsApp Business API for instant first-touch messages with read receipts.
1 min