Still open, so here’s the actual mechanism. An order email can only render data that’s saved on the order itself. Your app’s date lives in a front-end widget, so there’s nothing on the order for the email to read — that’s why it’s not showing, and why typing it in by hand breaks the automated send like you found.
The native fix is to write the date to a cart attribute, which does save on the order and is available in notification templates. Two steps:
1. Capture it near the add-to-cart / cart form (theme code):
<input type="hidden" name="attributes[Estimated Delivery]"
value="{{ 'now' | date: '%s' | plus: 432000 | date: '%B %d, %Y' }}">
432000 is 5 days in seconds — swap in your lead time. (Note: plus only adds numbers, so you convert to a timestamp with %s first, add seconds, then reformat. The | plus: 5 version that gets posted around doesn’t render, because after date: you’re adding to a string.)
2. Print it in Settings → Notifications → Order confirmation:
{% for attribute in attributes %}
{% if attribute.first == 'Estimated Delivery' %}
<p>Estimated delivery: {{ attribute.last }}</p>
{% endif %}
{% endfor %}
Note there’s no order. prefix inside email templates — it’s just attributes.
That gives every order a stored date, shown consistently on the order page and the email, with zero manual entry. The catch is it’s a flat lead time; if you need real per-product/destination logic, holidays or weekend skips, you’re maintaining a lot more Liquid.
(Full disclosure, I build one of the apps in this space — Estimated Delivery Date ‑ ETA — which does the calculation + email piece if you’d rather not maintain the code. But the two snippets above solve it natively and cost nothing, so start there.