This is not hard to implement in Commerce if you're ok with all the content going in one email (which I think is a better approach from the customer's point of view - we used to do this as separate emails years ago but customers got irritated that one order results in a whole bunch of emails). If you do want to trigger multiple separate emails, that's a tiny bit harder - but would not be difficult to implement in a plugin.
(Sketch of that approach - listen to onOrderComplete
and loop through cart items. For any that match your desired triggers, parse a template and then email it off with Craft's email functions - simple stuff as far as plugins go - let me know if you want me to expand on this).
But back to the one email approach - your order emails (receipts or any triggered by any other status) - are full twig templates - that means you can use conditionals, includes etc, to achieve what you want.
Basically, in your email template, you can loop through the products in the order and set content into some 'storage' variables (with the content being directly written in that template, or stored in fields on your products, or stored in entries in a section, or using include of other templates - anything really!).... and then output that content later in the email.
We do this to produce a 'Super Receipt' - basically a receipt that includes a whole lot of additional 'How To Get The Best From Your XXX' type content. This content comes, in our case, from 3 levels - the product category for stuff that applies to e.g. all monitors, the brand, for brand specific stuff (how to get support from NEC, for example), and finally from product specific content. This allows for very quickly building up libraries of this content, and a nice hierarchy of concerns. Categories, Brands and Products each have a field autoResponder
that holds this content.
Clients love it.
Here's the code.
{# Store items we've seen already so we don't get duplicate AR content #}
{% set seenItems = [] %}
{% set seenProductCategories = [] %}
{% set seenProductBrands = [] %}
{# And store the actual content we need to print out at the end in groups #}
{% set arProductContent = {} %}
{% set arBrandContent = {} %}
{% set arCatgeoryContent = {} %}
{% for lineItem in order.lineItems %}
{# No need to look at the same products twice... #}
{% if lineItem.purchasable.product.id not in seenItems %}
{% set seenItems = seenItems|merge([lineItem.purchasable.product.id]) %}
{# Category AR content #}
{% if lineItem.purchasable.product.id not in suppressedIds %}
{% for category in lineItem.purchasable.product.categories %}
{% if category.autoResponder|length %}
{% set arCatgeoryContent = arCatgeoryContent|merge({(category.title):category.autoResponder}) %}
{% endif %}
{% endfor %}
{% endif %}
{# Brand AR Content #}
{% set brand = lineItem.purchasable.product.brand.first() %}
{% if brand|length %}
{% if brand.id not in seenProductBrands %}
{% if brand.autoResponder|length %}
{% set seenProductBrands = seenProductBrands|merge([brand.id]) %}
{% set arBrandContent = arBrandContent|merge({(brand.title):brand.autoResponder}) %}
{% endif %}
{% endif %}
{% endif %}
{# Product AR Content #}
{% set product = lineItem.purchasable.product %}
{% if product.autoResponder|length and product.type != "service" %}
{% set preamble = '<small>See also: <a href="' ~ product.url ~ '#wiki">' ~ product.title ~ ' wiki</a></small>' %}
{% set arProductContent = arProductContent|merge({(product.title): preamble|raw ~ product.autoResponder}) %}
{% endif %}
{% endif %}
{% endfor %}
{# Now, print it all out, most general & needed to most specific #}
{% for key, content in arCatgeoryContent %}
{{ emailLib.paraWithHeader ( key, content|raw )}}
{% endfor %}
{% for key, content in arBrandContent %}
{{ emailLib.paraWithHeader ( key, content|raw )}}
{% endfor %}
{% for key, content in arProductContent %}
{{ emailLib.paraWithHeader ( key, content|raw )}}
{% endfor %}