Я понимаю о чём ты, но у меня интуитивное ощущение, что тут проблема изначально в том, что эта логика в сущности. Если на основании каких-то свойств сущности мы что-то делаем, то сама сущность уже это не контролирует. Нарушением инкапсуляции в каком-то смысле можно считать признание самого факта, что какое-то свойство существует, ведь по-хорошему мы не знаем каким образом реализовано поведение (логика записи событий). Это покажется странным, но я скорее предпочту геттер, но не у сущности, а у read model, поскольку с моей точки зрения эта логика изначально не относится непосредственно к сущности, она внешняя по отношению к ней.
Вспомни тот пример с отправкой письма: ты ведь не делаешь это через double dispatch? Откуда ты берёшь email? Я либо беру из event'а, если он там есть, либо из read model. Я не считаю это нарушением инкапсуляции, поскольку сущность сама сообщает через события про свой email и это общеизвестное значение для домена.
Дополнительно, я все изменения сущности провожу через транзакцию, поэтому мне некомфортно от самой мысли, что я буду в транзакцию передавать некий сервис, ведь этот сервис либо не будет поддерживать транзакцию, либо я могу как-то нежелательно повлиять на внешние данные (откатить какие-то логи, например). Я хочу иметь детерминированное поведение в рамках транзакции, и некий умный сервис его не гарантирует. Скажем, по этой же причине я никогда не получаю текущее время в самой сущности, я его передаю в саму команду.