Let me tell you how I answered my questions above.
Why is an online receipt being sent for an offline action?
Typically, this sends the right receipt, as the original action was taken online. However, when the contact makes an EFT contribution, and it is uploaded to CiviCRM, there is no online action (not involving CiviCRM, anyway). So in this case the use of an online receipt introduces the wrinkle that there is no Contribution Page or Event Registration Page, and no Line Items. So details that the online receipt is expecting are missing.
Should I hack the code to use an offline receipt?
For me, no. The workflows in the code were a bit too different for me to easily resolve/refactor. That would be a major project in its own right.
Should I continue using the online receipt but get more data into it?
This is the approach I took. I modified the message template for 'contribution_online_receipt' to include at the bottom of the HTML ...
{if !$contributionPageId}
<no-contribution-page/>
{/if}
... to introduce a HTML element if no Contribution Page was supplied.
My implementation of hook_civicrm_alterMailParams() looks for this element, and if found replaces it with the details I want ...
- Financial Type
- Receipt Date
- Paid By (instrument)
- Custom fields that have visibility 'Public pages' (eg, we want to show people details like 'donation purpose' but not 'internal category X')