#3 — Duplicate prospect handling: add_lead now checks (campaign_id, url) before insert; bulk_add_leads skips existing URLs. #8 — Atomic rate limiting: try_increment_* methods atomically check cap and increment in a single session; router uses these before send. #10 — Reply matching via Message-ID: sender generates Message-ID header, stored on OutreachAttempt; reply monitor parses In-Reply-To/References; poll_replies matches by message_id first, falls back to from_email. #11 — Save-to-campaign uses existing store results instead of re-running expensive deepDiscover. #12 — Lead status Literal type: Pydantic models enforce valid status values; backend validates via LEAD_VALID_STATUSES frozenset; frontend API typed as LeadStatus union.
This commit is contained in:
@@ -10,6 +10,7 @@ from dataclasses import dataclass, field
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from typing import List, Optional, Set
|
||||
from uuid import uuid4
|
||||
from loguru import logger
|
||||
|
||||
|
||||
@@ -35,6 +36,7 @@ class SenderAuthorizationResult:
|
||||
class SendEmailResult:
|
||||
success: bool
|
||||
effective_sender_email: str = ""
|
||||
message_id: str = ""
|
||||
failure_reasons: List[str] = field(default_factory=list)
|
||||
|
||||
|
||||
@@ -116,10 +118,12 @@ class BacklinkOutreachSender:
|
||||
|
||||
sender = sender_validation.effective_sender_email
|
||||
|
||||
msg_id = f"<{uuid4().hex}@{sender.split('@')[-1] if '@' in sender else 'outreach.local'}>"
|
||||
msg = MIMEMultipart("alternative")
|
||||
msg["From"] = sender
|
||||
msg["To"] = to_email
|
||||
msg["Subject"] = subject
|
||||
msg["Message-ID"] = msg_id
|
||||
msg.attach(MIMEText(body, "plain"))
|
||||
|
||||
loop = asyncio.get_running_loop()
|
||||
@@ -149,6 +153,7 @@ class BacklinkOutreachSender:
|
||||
return SendEmailResult(
|
||||
success=success,
|
||||
effective_sender_email=sender,
|
||||
message_id=msg_id if success else "",
|
||||
failure_reasons=[] if success else ["smtp_send_failed"],
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user