36: subject_set_ids: list = [] 47: subject_rotation: str = "round_robin" 63: "subject_rotation": {"round_robin", "random", "fixed_first"}, 73: "subject_set_ids": c.subject_set_ids or [], 83: "subject_rotation": c.subject_rotation, 118: if data.subject_rotation not in VALID_ENUMS["subject_rotation"]: 119: errors.append("subject_rotation must be round_robin|random|fixed_first") 138: for sid in data.subject_set_ids or []: 142: if not (data.subject_set_ids or []): 143: errors.append("Select at least one subject line") 291: the actual messages (subject + HTML + substituted variables). NOTHING is sent.""" 324: subj = await db.get(SubjectLine, item["subject_id"]) if item.get("subject_id") else None 336: subject = "" 342: subject = subj.subject if subj else (tpl.subject_hint or tpl.name) 348: res_s = engine.substitute(subj.subject, rec, g, 350: subject = res_s.text 352: warn_list.append(f"Unknown variable in subject: {u}") 354: warn_list.append(f"Missing data in subject: {m_}") 359: "subject": subject, 553: """Monitor table: per-recipient status, assigned account, subject/template, errors.""" 570: if cr.generated_subject_id and cr.generated_subject_id not in subj_map: 571: s = await db.get(SubjectLine, cr.generated_subject_id) 572: subj_map[cr.generated_subject_id] = (s.subject[:80] if s else "?") 584: "subject": subj_map.get(cr.generated_subject_id, ""), 608: w.writerow(["seq", "email", "status", "account", "subject", "template", 615: cr.generated_subject_id, cr.generated_template_id, 631:# Wizard options: what lists/subjects/templates/accounts/phones are selectable 640: subjects = (await db.execute(select(SubjectLine).where(SubjectLine.user_id == user.id) 664: "subjects": [{"id": s.id, "subject": s.subject[:160]} for s in subjects], 674: "max_subjects": cfg.MAX_SUBJECTS},