跳到正文
DEV Community· Ujjwal Dubey·· 3 小時前AI 評分47

在 AI 處理前,如何將地產平台客戶查詢電郵解析成結構化紀錄

Parsing Property Portal Lead Emails Into Clean Records Before Any AI Touches Them

AI 導讀

小型地產代理應先把地產平台發來的客戶查詢通知電郵解析成結構化紀錄,再加入 AI 處理跟進,讓後續去重和跟進計時器更易管理。每個寄件地址使用獨立解析器,儲存前檢查物業參考編號及電話或電郵;資料不合格便交由人員處理。AI 只用於從電郵自由文字中擷取資訊,結果另存欄位,避免覆蓋按固定規則解析的資料。

正文

Ujjwal Dubey

Many property portals still deliver leads to small agencies as notification emails. Before you add an AI assistant to the follow-up, turn those emails into clean, structured records. Clean input makes everything downstream simpler, from dedupe to follow-up timers.

This intake step is the unglamorous start of real estate lead automation for small agencies, and it is worth getting right.

The shape you want

{"source": "portal_a", "received_at": "2026-10-19T09:12:00+05:30",
 "name": "...", "phone": "...", "email": "...",
 "listing_ref": "...", "message": "...", "raw_id": "<message-id>"}

One parser per sender

Each portal formats its emails differently, so write one small parser per sender address and route by the From header.

import re

def parse_portal_a(body: str) -> dict:
    def grab(pattern):
        m = re.search(pattern, body)
        return m.group(1).strip() if m else None
    return {
        "name": grab(r"Name:\s*(.+)"),
        "phone": grab(r"Phone:\s*([+\d][\d\s-]+)"),
        "email": grab(r"Email:\s*(\S+@\S+)"),
        "listing_ref": grab(r"Ref(?:erence)?:\s*(\S+)"),
        "message": grab(r"Message:\s*([\s\S]+?)\n\s*\n"),
    }

PARSERS = {"leads@portal-a.example": parse_portal_a}

def parse(email):
    parser = PARSERS.get(email.sender)
    if parser is None:
        return route_to_human(email, reason="unknown_sender")
    record = parser(email.text_body)
    record.update(source=email.sender, raw_id=email.message_id,
                  received_at=email.date)
    return record

Validate before you store

REQUIRED = ("listing_ref",)
ONE_OF = ("phone", "email")

def validate(r):
    problems = [f for f in REQUIRED if not r.get(f)]
    if not any(r.get(f) for f in ONE_OF):
        problems.append("no_contact")
    return problems

If validate returns anything, send the email to a person with the reason attached. Do not guess.

Rules that save pain later

  • Keep the raw email ID so you can re-parse when a portal changes its format, which happens without notice.
  • Normalise phone numbers to one format before matching against existing contacts.
  • Fail loudly. A parser that silently returns None for the phone number creates leads nobody can call.
  • Use AI only for the free-text message. Pulling budget, move-in date or "wants to view this weekend" from the message is a good AI job. Store that output in separate fields so it never overwrites what you parsed deterministically.
  • Write a test per portal using a saved real email with personal details removed.

Dedupe and follow-up timers come after this step. They are much easier when every lead arrives in the same shape.

Disclosure: I run NxFlowAI, an AI automation agency. Mapping intake like this is part of our first audit, which takes 72 hours for one workflow.

來源:DEV Community · dev.to