68:def send_one(self, campaign_id: int, campaign_recipient_id: int):
69-    """Process one recipient: build message, send through Gmail, record real outcome."""
70-    with SyncSession() as db:
71-        campaign = db.get(Campaign, campaign_id)
72-        if campaign is None:
73-            return {"ok": False, "status": "cancelled", "reason": "campaign deleted"}
74-        if campaign.status in ("paused", "cancelled", "completed"):
75-            return {"ok": False, "status": "cancelled", "reason": f"campaign {campaign.status}"}
76-
77-        cr = db.get(CampaignRecipient, campaign_recipient_id)
78-        if cr is None:
79-            return {"ok": False, "status": "cancelled", "reason": "campaign_recipient deleted"}
80-        if cr.status in ("sent", "suppressed", "perm_failed"):
81-            return {"ok": True, "status": cr.status, "reason": "already finalized"}
82-
83-        job = (db.execute(select(SendJob)
84-                          .where(SendJob.campaign_recipient_id == cr.id,
85-                                 SendJob.campaign_id == campaign.id))).scalar_one_or_none()
86-
87-        # Re-check suppression at send time (recipient may have unsubscribed since enqueue)
88-        sup = (db.execute(select(SuppressionEntry)
89-                          .where(SuppressionEntry.email == cr.email))).scalar_one_or_none()
90-        if sup:
91-            cr.status = "suppressed"
92-            campaign.suppressed_count += 1
93-            cr.last_error = "Suppressed at send time"
94-            db.add(EmailEvent(campaign_id=campaign.id, campaign_recipient_id=cr.id,
95-                              event_type="suppressed", detail="Suppressed at send time"))
96-            db.commit()
97-            _publish_progress(campaign.id)
98-            return {"ok": True, "status": "suppressed", "reason": "suppression hit"}
99-
100-        account = db.get(GmailAccount, cr.assigned_account_id) if cr.assigned_account_id else None
101-        if account is None or not account.is_active or account.status != "authorized":
102-            cr.status = "skipped"
103-            campaign.skipped_count += 1
104-            cr.last_error = "Assigned account unavailable/unauthorized"
105-            db.commit()
106-            _publish_progress(campaign.id)
107-            return {"ok": False, "status": "skipped", "reason": "account unavailable"}
108-
