PHPackages                             jeffersongoncalves/laravel-newsletter - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Mail &amp; Notifications](/categories/mail)
4. /
5. jeffersongoncalves/laravel-newsletter

ActiveLibrary[Mail &amp; Notifications](/categories/mail)

jeffersongoncalves/laravel-newsletter
=====================================

Compose, schedule and send double opt-in email newsletters with open/click tracking for Laravel applications.

v1.0.0(1mo ago)101MITPHPPHP ^8.2CI passing

Since Jul 14Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/jeffersongoncalves/laravel-newsletter)[ Packagist](https://packagist.org/packages/jeffersongoncalves/laravel-newsletter)[ Docs](https://github.com/jeffersongoncalves/laravel-newsletter)[ GitHub Sponsors](https://github.com/jeffersongoncalves)[ RSS](/packages/jeffersongoncalves-laravel-newsletter/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (1)Dependencies (14)Versions (2)Used By (1)

[![Laravel Newsletter](https://raw.githubusercontent.com/jeffersongoncalves/laravel-newsletter/master/art/jeffersongoncalves-laravel-newsletter.png)](https://raw.githubusercontent.com/jeffersongoncalves/laravel-newsletter/master/art/jeffersongoncalves-laravel-newsletter.png)

Laravel Newsletter
==================

[](#laravel-newsletter)

[![Latest Version on Packagist](https://camo.githubusercontent.com/c460b263fc40ae5c929d243a97d95b461321fa4d98a788884208fff5b5f762da/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6a6566666572736f6e676f6e63616c7665732f6c61726176656c2d6e6577736c65747465722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/jeffersongoncalves/laravel-newsletter)[![GitHub Tests Action Status](https://camo.githubusercontent.com/c72de98665f5934c2cf125dc9daa865d811676fe7fcd5623d13be0be782544d6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6a6566666572736f6e676f6e63616c7665732f6c61726176656c2d6e6577736c65747465722f72756e2d74657374732e796d6c3f6272616e63683d6d6173746572266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/jeffersongoncalves/laravel-newsletter/actions?query=workflow%3Arun-tests+branch%3Amaster)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/74b375e84769fe3b1a2ac029fe5d784d58e7653281f5ff2f97825f57d06a30f9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6a6566666572736f6e676f6e63616c7665732f6c61726176656c2d6e6577736c65747465722f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d6173746572266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/jeffersongoncalves/laravel-newsletter/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amaster)[![Total Downloads](https://camo.githubusercontent.com/fac44254aae736e66023e42c88dfa9c4f4fa25648cc41b8136448c12f4e50e27/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6a6566666572736f6e676f6e63616c7665732f6c61726176656c2d6e6577736c65747465722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/jeffersongoncalves/laravel-newsletter)[![License](https://camo.githubusercontent.com/44e45bb490348800f6eee18e36a680e9daa63513b263031e7f73503eb45aa504/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6a6566666572736f6e676f6e63616c7665732f6c61726176656c2d6e6577736c65747465722e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)

Compose, schedule and send double opt-in email newsletters with open/click tracking for Laravel applications.

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11, 12, or 13

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require jeffersongoncalves/laravel-newsletter
```

The package uses Laravel's auto-discovery, so the service provider and facade are registered automatically.

### Publish Configuration

[](#publish-configuration)

```
php artisan vendor:publish --tag=newsletter-config
```

### Publish Migrations

[](#publish-migrations)

```
php artisan vendor:publish --tag=newsletter-migrations
```

### Run Migrations

[](#run-migrations)

```
php artisan migrate
```

### Publish Translations (optional)

[](#publish-translations-optional)

```
php artisan vendor:publish --tag=newsletter-translations
```

Configuration
-------------

[](#configuration)

The configuration file is located at `config/newsletter.php`:

```
return [
    // URI prefix for subscribe/confirm/unsubscribe/tracking/webview routes
    'route_prefix' => 'newsletter',

    // Email group used when a subscription request does not specify one
    'default_email_group' => 'Website',

    // Registers `newsletter:send-scheduled` on the schedule (hourly)
    'schedule_enabled' => true,

    // Tag outgoing links with UTM parameters and inject the open-tracking pixel
    'tracking_enabled' => true,
];
```

Usage
-----

[](#usage)

### Composing a Newsletter

[](#composing-a-newsletter)

```
use JeffersonGoncalves\Newsletter\Models\Newsletter;
use JeffersonGoncalves\Newsletter\Enums\NewsletterContentType;

$newsletter = Newsletter::create([
    'subject' => 'Monthly Update',
    'sender_name' => 'Example Co',
    'sender_email' => 'news@example.com',
    'content' => 'Hello there!',
    'content_type' => NewsletterContentType::Html,
    'send_unsubscribe_link' => true,
    'send_webview_link' => true,
    'route' => 'monthly-update',
    'published' => true,
    'utm_campaign' => 'monthly-update',
]);

$emailGroup = \JeffersonGoncalves\Newsletter\Models\EmailGroup::firstOrCreate(['title' => 'Website']);

$newsletter->emailGroups()->attach($emailGroup);
```

Attachments can be added through the `attachments` media collection (powered by `spatie/laravel-medialibrary`):

```
$newsletter->addMedia($uploadedFile)->toMediaCollection('attachments');
```

### Subscribing (Double Opt-in)

[](#subscribing-double-opt-in)

```
use JeffersonGoncalves\Newsletter\Facades\Newsletter;

$member = Newsletter::subscribe('subscriber@example.com', 'Website');
// $member->confirmed_at is null until the confirmation link is clicked
```

A confirmation email with a signed link is queued automatically. Once the subscriber clicks it (`GET /newsletter/confirm/{emailGroupMember}`), `confirmed_at` is set. Unsubscribing works the same way via `GET /newsletter/unsubscribe/{emailGroupMember}`.

### Sending

[](#sending)

```
use JeffersonGoncalves\Newsletter\Facades\Newsletter;

Newsletter::send($newsletter);
```

This resolves every confirmed, non-unsubscribed member of the newsletter's email groups (excluding anyone it was already sent to), dispatches one queued job per recipient inside a batch, and marks the newsletter as `sent` once the batch completes. Delivery outcomes are recorded per recipient in `NewsletterSentRecipient`.

### Sending a Test Copy

[](#sending-a-test-copy)

```
Newsletter::sendTest($newsletter, 'preview@example.com');
```

Renders and sends synchronously to a single address without touching delivery tracking.

### Scheduling

[](#scheduling)

```
use JeffersonGoncalves\Newsletter\Enums\NewsletterStatus;

$newsletter->update([
    'status' => NewsletterStatus::Scheduled,
    'scheduled_at' => now()->addDay(),
]);
```

The `newsletter:send-scheduled` command runs hourly by default (disable via `NEWSLETTER_SCHEDULE_ENABLED=false`) and sends every newsletter whose `scheduled_at` is due.

### Tracking

[](#tracking)

When `tracking_enabled` is on, every external link in the rendered email is tagged with `utm_source`, `utm_medium` and `utm_campaign`. When a newsletter has `send_webview_link` enabled, a 1x1 open-tracking pixel is appended, incrementing `total_views` on each open.

### Detecting Broken Links

[](#detecting-broken-links)

```
use JeffersonGoncalves\Newsletter\Actions\FindBrokenNewsletterLinksAction;

$broken = app(FindBrokenNewsletterLinksAction::class)->handle($newsletter);
```

Returns a collection of `['url' => ..., 'status' => int|null, 'error' => string|null]` for every link/image that returned an error status or could not be reached.

Events
------

[](#events)

`NewsletterSent`, `NewsletterScheduled`, `EmailGroupMemberSubscribed`, `EmailGroupMemberConfirmed`, `EmailGroupMemberUnsubscribed`.

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Jefferson Gonçalves](https://github.com/jeffersongoncalves)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance93

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

44d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/411493?v=4)[Jefferson Gonçalves](/maintainers/jeffersongoncalves)[@jeffersongoncalves](https://github.com/jeffersongoncalves)

---

Top Contributors

[![jeffersongoncalves](https://avatars.githubusercontent.com/u/411493?v=4)](https://github.com/jeffersongoncalves "jeffersongoncalves (9 commits)")

---

Tags

composerdouble-opt-inemailemail-marketingjeffersongoncalveslaravellaravel-packagemailing-listnewsletterphplaravelemailemail marketingmailing listnewsletterdouble-opt-in

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/jeffersongoncalves-laravel-newsletter/health.svg)

```
[![Health](https://phpackages.com/badges/jeffersongoncalves-laravel-newsletter/health.svg)](https://phpackages.com/packages/jeffersongoncalves-laravel-newsletter)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

265.2k](/packages/aedart-athenaeum)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.5k31.8M163](/packages/laravel-cashier)[laravel/ai

The official AI SDK for Laravel.

1.1k4.6M342](/packages/laravel-ai)[spatie/laravel-health

Monitor the health of a Laravel application

88412.7M191](/packages/spatie-laravel-health)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45844.8k1](/packages/pressbooks-pressbooks)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
