You have a few options.
First of all, make the use-case explicit. You can, for example, add a bool to the UserRegistered
event indicating that the user was registered as part of creation of an order. This would allow the email handlers to send appropriate emails.
Another option is to create a handler which sends emails for both events. Since emails shouldn't be sent immediately anyway have the handler, upon commit, determine which events have arrived during a given unit of work and in this way, determine the type of email to send. If both events have arrived, send a single email, otherwise send the email corresponding to the event received. For this to work, you have to make sure the handlers have a per-unit-of-work lifetime.
Finally, digging deeper, observe that you have to aggregates at play, a User
and an Order
. Ideally, especially in distributed scenarios, you shouldn't modify to aggregates within a single transaction. To implement a use-case requiring modification of to aggregates, create a saga also known as a process manager. With a saga, each aggregate gets modified in its own transaction and as part of the transaction and a message is sent to advance to the next step (in this case there are 2 steps). The saga would receive an initiating message called something like RegisterUserAndCreateOrder
. It would then register the user, then the order, and upon completion of both, it would send an appropriate email. Note the user and order can even be created concurrently. Take a look here for more on this event driven approach.