Domain Logic and Email Templates

From an email conversation with a reader:

Hi Paul,

I’ve been following your writing and examples about the ADR pattern for some time now. It’s taken me awhile to wrap my head around it but ADR has really added a lot of structure to my code and I’m thankful for your work!

One dilemma that I’ve been struggling with is how to organize emails that are sent out by my service classes. Currently my business logic dictates when to send an email and most of them contain html and text templates. It just feels wrong to include those email templates within the Domain. Do you have any recommendations? Any help you can provide would be greatly appreciated.

In a somewhat related question – Recently I’ve been organizing my “views” folders within the folders of their parents (Http, Mail). I think I based it on your ADR example on github. Do you still prefer this method or do you lean towards organizing within a “resources” folder?

My intuition is that you are right to keep the email templates out of the domain.

In a way, sending an email as part of a web request/response cycle is like sending two responses: the normal HTTP response, and the email response. With that in mind, it might make sense to think of the HTML + Text email templates as part of a presentation layer. Or, as a combination of infrastructure (the email-sending client) plus presentation (the templates). That would be how to think about the separation of concerns there.

Here’s an example of what that separation of concerns might look like in a package directory structure:

            # web page templates
        # ... other domain classes
            # ... mappers, tables, etc
        Emailer.php # implements Domain\EmailInterface

The specifics of directory structure are not important, as long as you see that the Emailer class is separated from the Domain application services (or use cases, or whatever).

The Emailer class, for its part, might be a facade [1] that coordinates between a “real” emailer (e.g. Swiftmailer or PhpMailer) and a template class, to put together and then send the email. You could configure the Emailer class with the template location (resources/templates/email/*) and inject it into your application service (which depends on the EmailInterface).

Now, sending emails inline as part of the web request might be fine in a lower-traffic situation. But as volume scales up, this kind of separation will make it easy to extract all email-sending to a workers. Then the Emailer can queue emails to the workers instead of sending them inline with the web request; the email-sending can become the job of a queue worker, and the template work will go there instead.

As far as where to put templates for views:

The extended example ADR code on GitHub is a few years old at this point. I still think it’s a reasonable setup, especially for people transitioning out of pseudo-MVC toward ADR, but it might do well to receive an update (or some examples of variations).

I don’t prefer any particular method or structure on where to put templates. Sometimes it makes sense to keep templates near the things using them, sometimes it makes sense to collect them all one place. The needs of the system, and the prior experiences of the developer(s), will be the deciding factor as far as I’m concerned. I had PHP-PDS on the brain when I replied, so the pds/skeleton with its “resources” directory was at hand.

[1] A real facade, not a Laravel one. 😉

Are you stuck with a legacy PHP application? You should buy my book because it gives you a step-by-step guide to improving your codebase, all while keeping it running the whole time.

6 thoughts on “Domain Logic and Email Templates

  1. 2 cents on “where to keep the templates”:
    a lot of my projects are for communication agencies. There’s usually a designer there who takes care of most of the html and css. They only know a bit of PHP. Having all (well named) templates in a separate directory has made it a lot easier for them to do their job.
    It’s also like what they’re used too, most of the time. Most of them have experience with wordpress or drupal themes.

  2. I had a similar problem some time ago. I ended up creating some “Definition-Classes” that contain all necessary information (I call them messages). It’s then a one liner to send a mail from your business logic:

    $mailer->send(new RegistrationMessage($user));

    The RegistrationMessage just defines, from where it can load the template and who should receive the email. Afterwards, the mailer is responsible for the loading and rendering of the template and the sending of the email. So you just have to inject the mailer and do not need to care of anything else in your business logic.

    You can find the project with more details and example code here:

    The mailer also cares about multiple locales and different senders. Currently, it loads the mail templates from the Symfony translator and there is no loader for the file system. But it would be easy to add one.

  3. Hey Paul great article as always, I think that application service depends on NotifierInterface is better than EmailInterface like this we can have SmsNotifier, EmailNotifier …etc all of them implements the NotifierInterface in the infrastructure layer, but this is better to be decided depending on the context and the ubiquitous language.

    My opinion about where to put the email templates, I think, a resource folder in the infrastructure is fine since the email is part of it.
    Just I dont like to mix the autoloadable stuff with non-autoloadable ones.

Leave a Reply

Your email address will not be published. Required fields are marked *