# 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.
