Coder Social home page Coder Social logo

subscribable-notifications's Introduction

Subscribable Notifications for Laravel

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads Laravel Compatibility

This package has been designed to help you handle email unsubscribes with as little as 5 minutes setup. After installing your notifications sent over email should now be delivered with unsubscribe links in the footer and as a mail header which email clients can present to the user for quicker unsubscribing. It can also handle resolving the unsubscribing of the user through a signed route/controller.

Installation

You can install the package via composer:

composer require ylsideas/subscribable-notifications

Optionally to make use of the built in unsubscribing handler you can publish the application service provider. If you wish to implement your own unsubscribing process and only insert unsubscribe links into your notifications, you can forgo doing this.

php artisan vendor:publish --tag=subscriber-provider

This will create a \App\Providers\SubscriberServiceProvider class which you will need to register in config/app.php.

'providers' => [
    ...
    
    /*
     * Package Service Providers...
     */
     \App\Providers\SubscribableServiceProvider::class,
     
     ...
]

After this you can configure your unsubscribe handlers quickly as methods within the service provider that return the closures.

The package itself does not determine how you store or evaluate your users' subscribed state. Instead it provides hooks in which to handle that.

Usage

First off you must implement the YlsIdeas\SubscribableNotifications\Contracts\CanUnsubscribe interface on your notifiable User model. You can also apply the YlsIdeas\SubscribableNotifications\MailSubscriber trait which will implement this for you to automatically provide signed urls for the unsubscribe controller provided by this library.

use YlsIdeas\SubscribableNotifications\MailSubscriber;
use YlsIdeas\SubscribableNotifications\Contracts\CanUnsubscribe;

class User implements CanUnsubscribe
{
    use Notifiable, MailSubscriber;
}

Implementing your own unsubscribe links

If you wish to implement your own completely different unsubscribeLink() method you can.

use YlsIdeas\SubscribableNotifications\Contracts\CanUnsubscribe;

class User implements CanUnsubscribe
{
    use Notifiable;
    
    public function unsubscribeLink(?string $mailingList = ''): string
    {
        return URL::signedRoute(
            'sorry-to-see-you-go',
            ['subscriber' => $this, 'mailingList' => $mailingList],
            now()->addDays(1)
        );
    }
}

Implementing notifications as part of a mailing list

If you wish to apply specific mailing lists to notifications you need to implement the YlsIdeas\SubscribableNotifications\Contracts\AppliesToMailingList on those notifications. This will put two unsubscribe links into your emails generated from those notifications. One for all emails and one for only that type of email.

use YlsIdeas\SubscribableNotifications\Contracts\AppliesToMailingList;

class Welcome extends Notification implements AppliesToMailingList
{
    ...
    
    public function usesMailingList(): string
    {
        return 'weekly-updates';
    }
    
    ...
}

Using the full unsubscribing workflow

Using the App\Providers\SubscriberServiceProvider you can set up simple hooks to handle unsubscribing the user from all future emails. This package doesn't determine how you should store that record of opting out of future emails. Instead you provide functions in the provider which will be called. The following are just examples of what you can do.

Implementing an unsubscribe hook for a specific mailing list

This handler will be called if a user links a link through to unsubscribe for a specific mailing list.

public class SubscriberServiceProvider
{
    ...
    
    public function onUnsubscribeFromMailingList()
    {
        return function ($user, $mailingList) {
            $user->mailing_lists = $user->mailing_lists->put($mailingList, false);
            $user->save();
        };
    }
    
    ...
}

Implementing an unsubscribe hook for all emails

This handler will be called if the user has clicked through to the link to unsubscribe from all future emails.

public class SubscriberServiceProvider
{
    ...
    
    public function onUnsubscribeFromAllMailingLists()
    {
        return function ($user) {
            $user->unsubscribed_at = now();
            $user->save();
        };
    }
    
    ...
}

Implementing an unsubscribe response

The completion handler will be called after a user is unsubscribed, allowing you to customise where the user is redirected to or if you want to maybe show a further form even.

public class SubscriberServiceProvider
{
    ...
    
    public function onCompletion()
    {
        return function ($user, $mailingList) {
            return view('confirmation')
                ->with('alert', 'You\'re not unsubscribed');
        };
    }
    
    ...
}  

Dedicated handler

You may also provide a string in the format of class@method that the subscriber class will use to grab the class from the service container and then call the specified method on if you want to do something more custom.

public class SubscriberServiceProvider
{
    ...
    
    public function onUnsubscribeFromAllMailingLists()
    {
        return '\App\UnsubscribeHandler@handleUnsubscribing';
    }
    
    ...
}

Checking if a notification should be sent per the subscription

You can also add hooks to check if a user should receive notifications for a mailing list or for all mail notifications.

To do this you need to make sure your user has the YlsIdeas\SubscribableNotifications\Contracts\CheckSubscriptionStatusBeforeSendingNotifications interface implemented. The YlsIdeas\SubscribableNotifications\MailSubscriber trait will implement this for you to use the built in Subscriber handlers.

If you want to implement a method yourself to check the subscription you could also just implement the method yourself like in the example below.

use YlsIdeas\SubscribableNotifications\Contracts\CanUnsubscribe;
use YlsIdeas\SubscribableNotifications\Contracts\CheckSubscriptionStatusBeforeSendingNotifications;
use YlsIdeas\SubscribableNotifications\Facades\Subscriber;

class User implements CanUnsubscribe, CheckSubscriptionStatusBeforeSendingNotifications
{
    use Notifiable;
    
    
    public function mailSubscriptionStatus(Notification $notification) : bool
    {
        return Subscriber::checkSubscriptionStatus(
            $this,
            $notification instanceof AppliesToMailingList
                ? $notification->usesMailingList()
                : null
        );
    }
}

Then you need to implement the YlsIdeas\SubscribableNotifications\Contracts\CheckNotifiableSubscriptionStatus interface on the notifications that should trigger a check of the subscription status of the user it's being sent to. Then you just need to return true if the subscription status should be checked.

use YlsIdeas\SubscribableNotifications\Contracts\CheckNotifiableSubscriptionStatus;

class Welcome extends Notification implements CheckNotifiableSubscriptionStatus
{
    ...
    
    public function checkMailSubscriptionStatus() : bool
    {
        return true;
    }
    
    ...
}

To use the functionality you then need to add your own Subscription check hooks. These hooks can be implemented as you see fit.

public class SubscriberServiceProvider
{
    ...

    public function onCheckSubscriptionStatusOfMailingList()
    {
        return function ($user, $mailingList) {
            return $user->mailing_lists->get($mailingList, false);
        };
    }

    public function onCheckSubscriptionStatusOfAllMailingLists()
    {
        return function ($user) {
            return $user->unsubscribed_at === null;
        };
    }
    
    ...
}  

Customising the email templates

Out of the box the emails generated use the same templates except that they inject a small bit of text into the footer of the emails. If you wish you customise the templates further you may publish the views.

php artisan vendor:publish --tag=subscriber-views

This will create a resources/views/vendor/subscriber folder containing both html.blade.php and text.blade.php which can be customised. These will then be the defaults used by the notification mail channel.

Customising the User Model

If you are using a different User model than the one found in app/Models/User.php or app/Users.php for Laravel 7 and earlier you can change this by calling. It's suggested you do this in the boot method of the SubscriberServiceProvider.

Subscriber::userModel('App\Models\User');

Testing

composer test

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

Laravel Package Boilerplate

This package was generated using the Laravel Package Boilerplate.

subscribable-notifications's People

Contributors

peterfox avatar dependabot[bot] avatar github-actions[bot] avatar arjasco avatar gavinservai avatar laravel-shift avatar trkyshorty avatar

Stargazers

P Rijal avatar Tibor (Tee) avatar Talk is cheap show me the code  avatar  avatar Sefer Demirci avatar Luca Patera avatar  avatar Enver Arslan avatar Dheia avatar Brian Barthold avatar Ankh avatar Diego Pronesti avatar Dajan Vulaj avatar Bruce Lam avatar Muhammed Cetin avatar Hoàng Vũ avatar Bas van Dinther avatar vincenzo vecchio avatar Lamkateh avatar John Bacon avatar  avatar Zach Schneider avatar  avatar 咸鱼 avatar Lucas Yang avatar moneya avatar Csaba Kissi avatar Mikhail Sarazhin avatar Aivaras avatar Burak BOZ avatar Luca Trevisani avatar Razik avatar Asok avatar AriaieBOY avatar Hassan Kerdash avatar Ryan Stefan avatar Hosein avatar Ruslan Voroshchuk avatar Martin Lechêne avatar Omar Alalwi avatar Mohamed Hassan avatar Miftah Shidiq avatar Matt Sims avatar Nguyen Quang Truong avatar Hungokata avatar Md Rafsan Jani Rafin avatar Carlos Cativo avatar Leandro Marcolin avatar Wong Ban Korh avatar David Lonjon avatar laurent Beauvisage avatar Olivier Grenet avatar Parables Boltnoel avatar Phillip Fickl avatar Kadir Melih Can avatar Mario Linguito avatar Simon Hartcher avatar Felice Ostuni avatar Musa Kurt avatar  avatar Mike Trummer avatar Ganesh Ghalame avatar Hesham Fouda avatar Isyak Rizqi avatar Erik Berkun-Drevnig avatar Marijn Bent avatar SANKAR SUDA avatar pherum avatar David Pella avatar Alessandro Tesoro avatar  avatar Thiago Vieira  avatar LogikIO avatar Kslr avatar Basil K avatar Muh Ghazali Akbar avatar Isern Palaus avatar Balasubramani avatar  avatar Andre Sayej avatar Bagaskara Wisnu Gunawan avatar guanguans avatar Thallis Ferreira Soares Casemiro avatar  avatar baijunyao avatar  avatar  avatar Tom White avatar Maxim Babichev avatar Krystian Duma avatar Lee Overy avatar Kevs avatar Brian Faust avatar maxtc avatar Mehmet Çınar avatar Spacetum Co avatar Can Evgin avatar Daniel Gräfe avatar Nikolas Evers avatar Noah Halstead avatar

Watchers

 avatar Leandro Marcolin avatar  avatar Scrutinizer Auto-Fixer avatar David Pella avatar Jozef Barca avatar saidjon avatar

subscribable-notifications's Issues

Laravel 10 release

Discussed in #49

Originally posted by dbhynds January 16, 2024
Hello.

I notice the composer.json on main has been updated to support Laravel 10, but a release hasn't been made. Would it be possible to have a release tagged, please?

Not working with 5.8 - email gets sent but no Unsubscribe url in footer

Hi Peter as discussed via email.

I download the package using composer and did these few steps.

Added App\Providers\SubscriberServiceProvider to my config/app.php also published it and changed the dummyuser to my User model as App\User

In my user Model i did the following

 `        
         use YlsIdeas\SubscribableNotifications\MailSubscriber;
         use YlsIdeas\SubscribableNotifications\Contracts\CanUnsubscribe;
      class User extends Authenticatable implements CanUnsubscribe
        {
               use HasApiTokens;
              use  Notifiable, Rewardable, MailSubscriber;

  `

In my notification file I did this

  `            use YlsIdeas\SubscribableNotifications\Contracts\AppliesToMailingList;

              use YlsIdeas\SubscribableNotifications\Contracts\AppliesToMailingList;
             class SendReceipts extends Notification implements AppliesToMailingList
         {
                 use Queueable;
               protected $receiptRequest;
/**
 * Create a new notification instance.
 *
 * @return void
 */
            public function __construct(array $receiptRequest)
            {
                   $this->receiptRequest = $receiptRequest;
          }
            public function usesMailingList(): string
          {
              return 'receipts-list';
             }`

The email goes through, but no unsubscribe url in footer.

Unable to use toMail from my notification

Hey please guide me for this
I am using default notification mail function as given below but it never gets called now Please help me out of this. I have my own content in rate_your_experience mail blade file but that is not being use.
Check my screenshot this is what my email is looking in Inbox which should not look like. rate_your_experience blade file has my custom content,

Screenshot 2021-07-08 at 20-41-29 Mailtrap - Safe Email Testing

It seems that my markdown template is not in use when triggering email using below syntax.

public function toMail($notifiable)
{
    return (new MailMessage)
            ->subject("Rate Your Experience")
            ->markdown(
                'emails.rate_your_experience',
                [
                    'source' => $this->source,
                    'user' => $notifiable
                ]
            );
}

Hardcoded User model

Issue is here:

public $userModel = '\App\User';

You are using a hardcoded user model class App\User even tho that's not a give. Lots of us use App\Models\User and if I'm not mistaken this is becoming the new standard.

You should probably use auth.php config, specifically providers.users.model where everyone configures their user model.

Workflows are referencing vulnerable actions

Hello, there!

As part of the university research we are currently doing regarding the security of Github Actions, we noticed that one or many of the workflows that are part of this repository are referencing vulnerable versions of the third-party actions. As part of a disclosure process, we decided to open issues to notify GitHub Community.

Please note that there are could be some false positives in our methodology, thus not all of the open issues could be valid. If that is the case, please let us know, so that we can improve on our approach. You can contact me directly using an email: ikoishy [at] ncsu.edu

Thanks in advance

  1. The workflow run-tests.yml is referencing action shivammathur/setup-php using references v1. However this reference is missing the commit 7163319 which may contain fix to the vulnerability.

The vulnerability fix that is missing by actions' versions could be related to:
(1) CVE fix
(2) upgrade of vulnerable dependency
(3) fix to secret leak and others.
Please consider updating the reference to the action.

If you end up updating the reference, please let us know. We need the stats for the paper :-)

Laravel 7 release

Hey,

Looks like the composer has been updated but a release hasnt been made.

Would it be possible to do a tag & release please?

Thanks!!!!
Lee

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.