return {"ok": False, "status": "rescheduled", "reason": "cooldown"} # Per-account rate window (0 = disabled; `or` coercion would silently # turn an explicit 0 into 1.0) interval = (float(campaign.send_interval_seconds) if campaign.send_interval_seconds is not None else 1.0) ok, wait = _rate_window(f"acct:{account.id}", interval) if not ok: _reschedule(db, self, campaign.id, cr, job, timedelta(seconds=wait), "rate limit window") return {"ok": False, "status": "rescheduled", "reason": "rate window"} # ------------------------------------------------------------- build message recipient = db.get(Recipient, cr.recipient_id) subject_row = db.get(SubjectLine, cr.generated_subject_id) if cr.generated_subject_id else None template = db.get(EmailTemplate, cr.generated_template_id) if cr.generated_template_id else None subject = subject_row.subject if subject_row else campaign.name if template is None: cr.status = "perm_failed" cr.last_error = "No template assigned" campaign.failed_count += 1 db.commit() return {"ok": False, "status": "perm_failed", "reason": "no template"} var_cfg = dict(campaign.variable_config or {}) engine = VariableEngine(var_cfg) _today = date.today() g = GeneratedValues( invoice_number=cr.generated_invoice_number, amount=cr.generated_amount, shipping=cr.generated_shipping, random_name=engine.generate_random_name(), invoice_date=var_cfg.get("invoice_date") or _today.isoformat(), due_date=var_cfg.get("due_date") or (_effective_invoice_date(var_cfg.get("invoice_date") or _today.isoformat()) + timedelta(days=int(var_cfg.get("due_days", 14)))).isoformat(), phone=cr.generated_phone or var_cfg.get("company_phone", ""), ) unsub_url = _unsubscribe_url(recipient, campaign) rec = _recipient_dict(recipient) cf = (recipient.custom_fields if recipient else None) or {}