Hey Dan,
I’ll get stuck into some idea generation with you, notifications from apps always intrigues me and there doesn’t seem to be much in the way of advice on how it should best be done, even though it’s a really common challenge.
First of all - I love the concept of the interceptor - It’s not something I’ve tried myself but as notifications are a cross cutting concern, it might be well placed. I would try a little proof-of-oncept and see how it feels.
Now, in one of my non-coldbox applications I have a similar setup to you, I send notifications on given events, which then also get saved to the database so we have a record of when and what was sent.
I recently built a model that looks something like this:
MailService - The service responsible for the mail dispatch, using cfmail, rest or whatever.
Message - An ORM entity for the message that contains To, From, Subject, HTML, TEXT etc.
Mailer - A base mailer object, used for establishing different messages.
Now, the clever bit in my opinion is the mailer class. The idea is that it allows me to separate out email generation from the rest of the model, so it’s not sat inside services, this just felt cleaner to me.
Within the application I then have a ‘mailers’ directory, which contains a set of CFC’s - each of which extends the base mailer and contains methods that each define a different message.
So, for instance I would have.
/mailers/user_mailer.cfc
welcome(user)
approved(user)
forgotten_password(user)
Each of the methods, creates, populates and returns a message object. ready for sending through the mail service. So the welcome method might look something like this.
welcome (user) {
local.message = newMessage();
local.message.to = user.getEmail();
local.message.subject = ‘welcome’
local.message.context = {
to = user.getName(),
signature = ‘The Team’
};
return message;
}
Now, each of these mailer classes and their methods has a corresponding set of views, which are located by convention based on the mailers class and method name, something like:
/views/email/user/welcome.html
/views/email/user/welcome.txt
These are templates for the html and plain text versions of the email, in my case these are mustache templates, with placeholders within them for any dynamic context {{To}} or {{Signature}} for instance.
The values for these are put together inside the mailer method we saw above, notice the context?
Also notice there are two templates? one for the HTML format and one for the Plain Text format.
Now, when I want to start sending emails I inject my mailers into my service, so within my registration service I can then do something like this:
public void function register(){
// registration code happens here
// notification
user_mailer.send_welcome(user);
}
Notice that I actually used ‘send_welcome()’ instead of just ‘welcome()’ this is because the mailer class is smart enough to use OMM so I can instantly dispatch the message if I want, or I could just call welcome() and get the mail object for manipulation and dispatch later.
I would then have my mail service save that entity as it was pushed out of the door.
Robert