Add a From-address dropdown to the mail-merge tool

Replaces the free-text From field with a select of real working addresses
(mblack@txproducts.de, now the default; mckinley@mckinleyblack.com kept for
internal test sends), deduplicating the 8 render_template("index.html", ...)
call sites into a single render_index() helper along the way. Also picks up
today's real outreach-log entry from testing the reconnect_message send to
Peter's actual address.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
beantownbabeandClaude Sonnet 5 committed 2026-08-17 15:16:47 +02:00
1 parent 5b4918d2af
commit 95abe3b167
4 files changed
+32 -29

No files matched your search

@@ -44,7 +44,7 @@ OUTPUT_DIR = HERE / "output_drafts"
# Default sender for .eml drafts, so Mail.app picks the right account when
# more than one is configured. --send overrides this with SMTP_USER instead.
DEFAULT_FROM = "mckinley@mckinleyblack.com"
DEFAULT_FROM = "mblack@txproducts.de"
PLACEHOLDER_RE = re.compile(r"\{\{\s*([^}]+?)\s*\}\}")
@@ -60,7 +60,11 @@
{% endfor %}
<h2 style="margin-top:18px;">From address</h2>
<input type="text" name="from_address" value="{{ default_from }}">
<select name="from_address">
{% for addr in from_addresses %}
<option value="{{ addr }}" {% if addr == default_from %}selected{% endif %}>{{ addr }}</option>
{% endfor %}
</select>
</div>
<button type="submit" formaction="/open_in_mail">Open in Mail.app</button>
+20 -26
View File
@@ -32,6 +32,8 @@ DEFAULT_ATTACHMENTS = [
app = Flask(__name__)
FROM_ADDRESSES = ["mblack@txproducts.de", "mckinley@mckinleyblack.com"]
def get_contacts():
if not mm.CONTACTS_FILE.exists():
@@ -88,14 +90,22 @@ def smtp_configured():
return all(os.environ.get(k) for k in ("SMTP_HOST", "SMTP_USER", "SMTP_PASS"))
@app.route("/")
def index():
def render_index(error=None, preselect_email=""):
return render_template(
"index.html",
contacts=get_contacts(),
templates=get_templates(),
attachments=get_attachment_options(),
default_from=mm.DEFAULT_FROM,
from_addresses=FROM_ADDRESSES,
error=error,
preselect_email=preselect_email,
)
@app.route("/")
def index():
return render_index(
error=request.args.get("error"),
preselect_email=(request.args.get("email") or "").strip().lower(),
)
@@ -109,25 +119,19 @@ def generate():
from_address = request.form.get("from_address") or mm.DEFAULT_FROM
if not selected:
return render_template("index.html", contacts=get_contacts(), templates=get_templates(),
attachments=get_attachment_options(), default_from=mm.DEFAULT_FROM,
error="Check at least one contact first.")
return render_index(error="Check at least one contact first.")
try:
full_df = pd.read_excel(mm.CONTACTS_FILE, sheet_name="Contacts")
except Exception as exc:
return render_template("index.html", contacts=get_contacts(), templates=get_templates(),
attachments=get_attachment_options(), default_from=mm.DEFAULT_FROM,
error=f"Close the Excel file and try again. ({exc})")
return render_index(error=f"Close the Excel file and try again. ({exc})")
if "Draft File" not in full_df.columns:
full_df["Draft File"] = ""
try:
rows = rows_for_selection(selected, template_name)
except ValueError as exc:
return render_template("index.html", contacts=get_contacts(), templates=get_templates(),
attachments=get_attachment_options(), default_from=mm.DEFAULT_FROM,
error=str(exc))
return render_index(error=str(exc))
lines = []
warnings = []
@@ -155,25 +159,19 @@ def open_in_mail():
from_address = request.form.get("from_address") or mm.DEFAULT_FROM
if not selected:
return render_template("index.html", contacts=get_contacts(), templates=get_templates(),
attachments=get_attachment_options(), default_from=mm.DEFAULT_FROM,
error="Check at least one contact first.")
return render_index(error="Check at least one contact first.")
try:
full_df = pd.read_excel(mm.CONTACTS_FILE, sheet_name="Contacts")
except Exception as exc:
return render_template("index.html", contacts=get_contacts(), templates=get_templates(),
attachments=get_attachment_options(), default_from=mm.DEFAULT_FROM,
error=f"Close the Excel file and try again. ({exc})")
return render_index(error=f"Close the Excel file and try again. ({exc})")
if "Draft Opened" not in full_df.columns:
full_df["Draft Opened"] = ""
try:
rows = rows_for_selection(selected, template_name)
except ValueError as exc:
return render_template("index.html", contacts=get_contacts(), templates=get_templates(),
attachments=get_attachment_options(), default_from=mm.DEFAULT_FROM,
error=str(exc))
return render_index(error=str(exc))
lines = []
warnings = []
@@ -206,16 +204,12 @@ def preview():
from_address = request.form.get("from_address") or mm.DEFAULT_FROM
if not selected:
return render_template("index.html", contacts=get_contacts(), templates=get_templates(),
attachments=get_attachment_options(), default_from=mm.DEFAULT_FROM,
error="Check at least one contact first.")
return render_index(error="Check at least one contact first.")
try:
rows = rows_for_selection(selected, template_name)
except ValueError as exc:
return render_template("index.html", contacts=get_contacts(), templates=get_templates(),
attachments=get_attachment_options(), default_from=mm.DEFAULT_FROM,
error=str(exc))
return render_index(error=str(exc))
table_rows = [{"email": r["Email"], "subject": s, "body": b} for r, s, b in rows]
+6 -1
View File
@@ -3825,7 +3825,12 @@
"time": "3:40 PM - 5:10 PM"
}
],
"outreach_log": [],
"outreach_log": [
{
"date": "17.08.26",
"note": "Draft opened in Mail.app (reconnect_message.txt), 17.08.26 14:52"
}
],
"notes": "",
"value_tags": [
"money"