Order Confirmation Email in Craft Commerce
To setup/debug email issues in commerce it's easiest to set up the simplest possible email and work your way up from there.


Check your Craft email settings - can you send &amp; receive the test email
successfully?
In Commerce settings, double check you have created your email correctly and that your template exists at the path you set.  To simplify
things initially, avoid using any variables in the subject and hardcode
an address to which the email will be sent
Check your order status and make sure you have assigned your email to it and that a '1' then appears in the 'Has Emails' column for that
status.  It's easiest to start with an email attached to the default
order status so you can be sure orders coming in will trigger the
email.
Create the simplest possible template for the email and just put in it something like Huzzah, my email sent! as an initial end
to end test that the email is being triggered when you submit an order


At that point, your basic email should really send!  

If not, check your commerce.log file for errors.  If you have parsing errors in your email template, they will appear here, or you may get the somewhat obscure [info] [plugin] [Forced] Can't send email if no status or emails exist. which indicates something is wrong with the set up of the status &lt;> email relationship.

Most of the errors typically come from template errors in the actual email - trying to get data not available for example.  commerce.log will help with that, but another handy way of debugging your email templates is to put something like this at the top of them:

{# for debugging! #}
{% if craft.request.getSegment(1)=="order-completed-debug" %}
     {% set order = craft.commerce.orders.id(craft.request.getSegment(2)).first() %}
     {# No order supplied or other issue?  Load latest order by default... #}
     {% if not order %}
         {% set order = craft.commerce.orders.first() %}
     {% endif %}
{% endif %}


Set up a route in Craft settings so that /order-completed-debug/(number) points at your email template and then you will be able to use your browser for much easier testing by going to /order-completed-debug/&lt;someValidOrderID&gt; in your browser rather than having to submit an order each time you change your email template!

Finally, I very strongly recommend you use a transactional email service like mailgun, sparkpost, postmark, mandrill etc. as if you use default phpemail you're very likely to run into email delivery issues.  The logging systems these (often free!) transactional email systems supply are worth their weight in gold as you can see if the email is even being sent or not very simply, which helps with issue diagnosis a LOT.



For completeness, although this is a lot more advanced &amp; less general:

Another gotcha to note is that custom order fields are not necessarily set yet in the order completed email template as it seems this is actually sent out BEFORE the final order save occurs so if you're e.g. setting some data in a plugin method listening to onBeforeOrderComplet=, you'll need to work around this....so to reference those fields you have to use a special approach (currently?)

{% set ISOrderNumber = order.content.ISOrderNumber ?? 'NONE' %}


Not the use of .content there - I need to use this to get at the field that is not yet saved in to the order as such.