Masonite Notifications
Tags: python, masonite, framework, package
Published: 2018-07-29 19:07:25

---
title: Masonite Notifications
published: true
description: Awesome and extendable Masonite notification package to manage both email and Slack notifications.
tags: python, masonite, framework, package
---

# Introduction

[Masonite](https://github.com/masoniteframework/masonite) is an awesome Python web framework that has been picking up a lot of speed in the past few months since the release of Masonite 2.0.

[Masonite](https://github.com/masoniteframework/masonite) Notifications can easily add new notification sending semantics for your Masonite project. These notifications could be sending an email or a slack message. This package is designed to be extremely simple and modular so allow new notification abilities to be added to it through third party integrations.

# Installation

In order to get started using Masonite Notifications, we first have to pip install it:

```
$ pip install masonite-notifications
```

And then add the provider to our PROVIDERS list:

```python
from notifications.providers import NotificationProvider
...
​
PROVIDERS = [
    ...
    NotificationProvider,
    ...
]
```

Thats it! Let's see how it works!

# Usage

There are a few concepts we'll need to cover so you can fully understand how Notifications work. First we will cover the high level stuff and then slowly work down into the lower level implementations. For the purposes of this documentation, we will walk through how to setup a welcome notification so we can send an email when a user signs up.

# Creating a Notification

In order to use it we can create a notification class. We can do this simply with a new craft command.

```python
$ craft notification WelcomeNotification
```

This will create a notification in the `app/notifications` directory. Feel free to move it wherever you like though.

This will create a class like so:

```python
''' A WelcomeNotification Notification '''
from notifications import Notifiable
​
class WelcomeNotification(Notifiable):
​
    def mail(self):
        pass
```

# Building Our Mail Notification

Let's now walk through how to build a notification so we can send the email to our user.

Since our notification inherits from Notifiable,  we have access to a few methods we will use to build the notification. We'll show a final product of what it looks like since it's pretty straight forward but we'll walk through it after:

```python
from notifications import Notifiable
import os
​
​
class WelcomeNotification(Notifiable):
​
    def mail(self):
        return self.subject('New account signup!') \
            .driver('smtp') \
            .panel('GBALeague.com') \
            .heading('You have created a new account!') \
            .line('We greatly value your service!') \
            .line('Attached is an invoice for your recent purchase') \
            .action('Sign Back In', href="http://gbaleague.com") \
            .line('See you soon! Game on!') \
            .view('/notifications/snippets/mail/heading',
                  {'message': 'Welcome To The GBA!'})
```

Notice here we are calling a few methods such as `driver`, `panel`, `line`, etc. If we send this message it will look like:

<img src="https://thepracticaldev.s3.amazonaws.com/i/94ldezlnbtap06p0o97y.png">

Not bad. We can use this logic to easily build up emails into a nice format simply.

## Options

For a full list of notifications, head over to the [Official Documentation](https://docs.masoniteproject.com/official-packages/masonite-notifications#options) page to see a nice table.

# Sending the Notification

Now that we have built our notification above, we can send it in our controller (or anywhere else we like):

```python
from app.notifications.WelcomeNotification import WelcomeNotification
...
​
def show(self, Notify):
​
    Notify.mail(WelcomeNotification, to='user@gmail.com')
```

Notice here we simply specified the Notify class in the parameter list and we are able to pass in our awesome new WelcomeNotification into the mail method.

****
NOTE: The method you should use on the notify class should correspond to the method on the notification class. So for example if we want to execute the slack method on the WelcomeNotification then we would call :

```python
Notify.slack(WelcomeNotification)
```

The method you call should be the same as the method you want to call on the notification class. The Notify class actually doesn't contain any methods but will call the same method on the notification class as you called on the Notify class.
****

# Building Our Slack Notification

Out of the box, Masonite Notifications comes with Slack support as well in case we want to send a message to a specific slack group.

****
NOTE: In order to use this feature fully, you'll need to generate a token from Slack. This token should have at minimum the channels:read, chat:write:bot, chat:write:user and files:write:user permission scopes. If your token does not have these scopes then parts of this feature will not work.
****

Going back to our WelcomeNotification, we can simply specify a new method called slack.

```python
class WelcomeNotification(Notifiable):
​
    def mail(self):
        return self.subject('New account signup!') \
            .driver('smtp') \
            .panel('GBALeague.com') \
            .heading('You have created a new account!') \
            .line('We greatly value your service!') \
            .line('Attached is an invoice for your recent purchase') \
            .action('Sign Back In', href="http://gbaleague.com") \
            .line('See you soon! Game on!') \
            .view('/notifications/snippets/mail/heading',
                  {'message': 'Welcome To The GBA!'})
      
      def slack(self):
          pass
```

Notice the new slack method at the bottom. we will use this method to build our slack notification. Again we will show you a full example and then run through all the methods:

```python
class WelcomeNotification(Notifiable):
​
    def mail(self):
        return self.subject('New account signup!') \
            .driver('smtp') \
            .panel('GBALeague.com') \
            .heading('You have created a new account!') \
            .line('We greatly value your service!') \
            .line('Attached is an invoice for your recent purchase') \
            .action('Sign Back In', href="http://gbaleague.com") \
            .line('See you soon! Game on!') \
            .view('/notifications/snippets/mail/heading',
                  {'message': 'Welcome To The GBA!'})
      
    def slack(self):
        return self.token(os.getenv('BOT')) \
            .text('Masonite Notification: Read The Docs!, https://docs.masoniteproject.com/') \
            .channel('#bot') \
            .as_user('Masonite Bot') \
            .icon(':fire:') \
            .button('Sure!', "https://docs.masoniteproject.com/")
            .button('No Thanks!', "https://docs.masoniteproject.com/" style='danger')

```

This will return a result like this:

<img src="https://thepracticaldev.s3.amazonaws.com/i/7vt0gcyz9hn4attsauuw.png">

## Slack Options

For a full list of notifications, head over to the [Official Documentation](https://docs.masoniteproject.com/official-packages/masonite-notifications#options-1) page to see a nice table.

# Sending a Slack Notification

Now that we have built our notification above, we can send it in our controller (or anywhere else we like):

```python
from app.notifications.WelcomeNotification import WelcomeNotification
...
​
def show(self, Notify):
​
    Notify.slack(WelcomeNotification)
```

Notice here we simply specified the Notify class in the parameter list and we are able to pass in our awesome new WelcomeNotification into the slack method.

# Building Integrations

The Notifiable class is very modular and you are able to build custom integrations if you like pretty simply. In this section we'll walk through how to create what are called Components.

# What are Components?

Components are classes that can be added to a Notification class that extend the behavior of the notification. In fact, the Notifiable class is just a simple abstraction of two different components. Let's look at the signature of the class that we have been inheriting from.

```python
from notifications.components import MailComponent, SlackComponent
​
​
class Notifiable(MailComponent, SlackComponent):
    pass
```

The Component classes are the classes that have our methods we have been using. If you'd like to see the source code on those components you can check them out on GitHub to get a lower level understanding on how they work.

# Creating a Component

Let's walk through a bit on how we created our MailComponent by creating a simplified version of it. First let's create a simple class:

```python
class MailComponent:
    pass
```

Now let's add a line and a subject method to it:

```python
class MailComponent:
    
    def line(self, message):
        pass
    
    def subject(self, subject)
        pass
```

and let's use these two methods to build a template attribute

```python
class MailComponent:
​
    template = ''
    
    def line(self, message):
        self.template += template
        return self
    
    def subject(self, subject)
        self._subject = subject
        return self
```

Since we returned self we can keep appending onto the notification class like we have been.

The actual `MailComponent` class is a bit more complex than this but we'll keep this simple for explanatory purposes.

# The Fire Method

Whenever we insert the notification into the Notify class:

```python
Notify.mail(WelcomeNotification)
```

This will call the mail method on the notification class (or whatever other method we called on the Notify class). 

Once that is returned then it will call the `fire_mail` method which you will specify in your component.

If you have created a discord notification then you should have a `fire_discord` method on your component and you will call it using:

```python
Notify.discord(WelcomeNotification)
```

Since we want to call the mail method on it, we will create a `fire_mail` method:

```python
class MailComponent:
​
    template = ''
    
    def line(self, message):
        self.template += template
        return self
    
    def subject(self, subject)
        self._subject = subject
        return self
    
    def fire_mail(self):
        pass
```

## Protected Members

Sometimes you will want to pass in data into the `fire_mail` method. In order to keep this simple and modular, any keyword arguments you pass into the `Notify` class will be set on the notification class as a protected member. For example if we have this:

```python
Notify.mail(WelcomeNotification, to='admin@site.com')
```

It will set a `_to` attribute on the notification class BEFORE we get to the `fire_x` method.

So using the example above we will be able to do:

```python
def fire_mail(self):
    self._to # admin@site.com
```

We can use this behavior to pass in information into the `fire_mail` method while keeping everything clean.

## Sending The Mail

Ok so finally we have enough information we need to send the actual email. The `fire_mail` method is resolved by the container so we can simply specify what we need to send the email from the parameter list.

Our notification class will look like:

```python
from your.package import MailComponent
​
class WelcomeNotification(Notifiable, MailComponent):
​
    def mail(self):
        return self.subject('New account signup!') \
            .line('We greatly value your service!')
```
     
Our Notify class will look like:

```python
Notify.mail(WelcomeNotification, to='admin@site.com')
```

and our fire method will look like:

```python
class MailComponent:
​
    template = ''
    
    def line(self, message):
        self.template += template
        return self
    
    def subject(self, subject)
        self._subject = subject
        return self
    
    def fire_mail(self, Mail):
        Mail.to(self._to) \
            .subject(self._subject) \
            .send(self.template)
```

Remember the `_to` class attribute that came from the keyword argument in the `Notify` class.

****

If you are curious about sponsoring this package then send an inquiry email over to  joe@masoniteproject.com for more information.

Be sure to give a star on the [GitHub](https://github.com/masoniteframework/masonite) page or join the [Slack](http://slack.masoniteproject.com) channel.