Factories
Create multiple similar emails
Imagine you want to inform a couple of users about something that happened in your system, for example a successful transaction or a report generated by your application. You would have a very similar mail body except for the salutation or one or two minor differences. Handling this with the single email class from above feels a little off.
That is why this package provides a mail factory! This factory is a wrapper for creating similar emails and providing the email class shown above with recipient-specific content.
Look at this example:
class MyFancyMail(BaseEmailService):
subject = _('I am a great email!')
template_name = 'email/my_fancy_email.html'
class MyFancyMailFactory(BaseEmailServiceFactory):
service_class = MyFancyMail
def __init__(self, action_id: int, recipient_email_list: list = None):
super().__init__(recipient_email_list)
self.action = Action.objects.filter(id=action_id).first()
def get_recipient_list(self) -> list:
return self.action.fetch_recipients_for_this_action()
def get_email_from_recipient(self, recipient) -> str:
if isinstance(recipient, User):
return recipient.email
return recipient
def is_valid(self):
if not self.action:
raise EmailServiceConfigError('No action provided.')
return super().is_valid()
def get_context_data(self):
context = super().get_context_data()
context.update({
'action': self.action,
})
return context
This is only one of many (!) possibilities to handle a case like described above. We pass a custom action id to the factory and fetch the given action (this might be a project, a report, a record…) and set it to a class attribute.
The get_recipient_list() method fetches the recipients based on the action we are looking at right now.
Because we might get mixed results (mostly not, but just to show what is possible), we overwrite the method
get_email_from_recipient() to be able to handle simple email addresses as a string or user objects. If you pass only
strings, overwriting this method can be omitted.
We added a sanity check in the is_valid() method to be sure that nobody tries to create emails like this without an
action being set.
Finally, we add the action to the context data get_context_data() so the MyFancyMail() class can use it.
Now for every recipient an instance of MyFancyMail() will be created. Now it is no problem, handling the salutation
or any other recipient-specific content within the “real” mail class. Only make sure that the factory provides all the
required data.