I have a similar issue with a 1.6.1.18 installation.
It sends the normal mails but not the mail with the downloadable file. Another issue is that it asks you to select a carrier instead of saying that no carrier is needed when there are only virtual products.
It had a look in the source code:
There is a javascript variable isVirtualCart that is set to 0 where it should be 1.
This variable is set in OrderOPCController.php with:
if ($this->nbProducts) {
$this->context->smarty->assign('virtual_cart', $this->context->cart->isVirtualCart());
}
And this is where it gets strange: $this->nbProducts is true so the assignment runs. However, if you put debug code in the isVirtualCart() function in the Cart class you see that it is never called. Somehow this function is masked and returns an empty string.
Still stranger is that the version I have running on my localhost is working ok. But the copy of it on the server of the customer gives the problem.
It becomes yet stranger when you have a look at the content of the Cart object near this operation in OrderOPCController.php. Normally Cart->_products is an array of the products in the products in the cart. However, on the localhost (so when it is behaving correctly) this array is empty when the cart contains only a virtual product.