DocsAutoResponderProcess

Salesforce CRM (REST API)#

Purpose: Contacts and Leads lookup; status updates; email/title updates where business rules allow.

Code: src/auto_responder/services/databases/salesforce.py

Configuration#

SettingNotes
SALESFORCE_DOMAINLogin, test, custom domain, or full instance URL.
SALESFORCE_ACCESS_TOKENBearer token auth when set.
SALESFORCE_CLIENT_IDOAuth client id (simple-salesforce flows).
SALESFORCE_USERNAME, SALESFORCE_PASSWORD, SALESFORCE_SECURITY_TOKENUsername/password flow when not using access token.

See config.py for the full set and validation. Initialization failures fall back to MockSalesforceDatabase in main.py (live mode still attempts the real connector first).

Contact lookup#

CallPurpose
lookup_by_email(email)Returns list of ContactRecord (Contacts and/or Leads)

Action engine touches#

Salesforce writes follow the same active-only CUPOLA gate as Hodor. Email / title updates run only when _handle_title_update confirms an active CUPOLA row; otherwise the row routes to Human Review. CUPOLA-side reactivation is disabled; Salesforce Lead / non-Multipub Contact reactivation on ACTIVE still runs when mirroring applies. OUT_OF_OFFICE does not touch Salesforce.

INACTIVE (_handle_inactive)#

For each Salesforce record on the contact:

RuleAction
Multipub subscriber exists and record is a ContactSkip status update ("Multipub-related")
Otherwise (Lead or non–Multipub-tied Contact)update_lead_status(id, False) or update_contact_status(id, False)

Reads:

CallPurpose
check_active_subscription(contact_id)For Contacts only — subscription warning list

ACTIVE (_handle_active)#

Same Multipub-related Contact skip rule. For eligible records with is_active=False:

CallPurpose
update_lead_status(id, True)Reactivate Lead
update_contact_status(id, True)Reactivate Contact

If already active, logged as "already active". Note that this path does not imply a CUPOLA reactivation — CUPOLA stays inactive and a reactivation candidate is routed to IP4 Human Review.

OUT_OF_OFFICE#

Handled by _handle_out_of_office. The entire Salesforce loop is skipped; a Human Review row is emitted (HUMAN_REVIEW_REASON_OUT_OF_OFFICE).

Changed email / updated title#

Runs only when the CUPOLA active-only gate in _handle_title_update passes. After the gate, loops contact.records:

If the CUPOLA gate fails (no row, or inactive row), Salesforce is not updated — the row goes to Human Review with HUMAN_REVIEW_REASON_UPDATE_ON_INACTIVE or HUMAN_REVIEW_REASON_ACTIVE_NEW_CONTACT.

Note: Replacement flows add the new person in Cupola; action_engine.py does not call Salesforce add_contact for replacements.

Read-only / dry-run#

Output artifacts#

Salesforce IDs captured on inactive-person records in OutputDocumentCollector.