NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

The published config/campaigns.php in full:

return [
    'store' => env('CAMPAIGNS_STORE', \RoundlyConsulting\Campaigns\Stores\InMemoryCampaignStore::class),
    'from-name' => env('CAMPAIGNS_FROM_NAME', ''),
    'from-address' => env('CAMPAIGNS_FROM_ADDRESS', ''),
    'recipients' => [
        'only-verified' => env('CAMPAIGNS_ONLY_VERIFIED', false),
        'contact-type' => env('CAMPAIGNS_RECIPIENT_CONTACT_TYPE', 'email'),
    ],
    'sending-queue' => env('CAMPAIGNS_SENDING_QUEUE', 'default'),
    'process-recipient-job' => \RoundlyConsulting\Campaigns\Jobs\SendCampaignEmail::class,
    'notification' => env('CAMPAIGNS_NOTIFICATION'),
    'notification-channel' => env('CAMPAIGNS_NOTIFICATION_CHANNEL', 'mail'),
];

Every key

KeyDefaultEnvPurpose
storeInMemoryCampaignStore::classCAMPAIGNS_STOREWhere campaigns and recipients are kept — a Contracts\CampaignStore. DatabaseCampaignStore::class persists them; or point at your own. Any value that isn’t a CampaignStore class throws InvalidConfigurationException — it never falls back to the in-memory store.
from-name''CAMPAIGNS_FROM_NAMEDefault sender name when a campaign is dispatched without ->from(). Seeds the DefaultFromName option.
from-address''CAMPAIGNS_FROM_ADDRESSDefault sender address when a campaign is dispatched without ->from(). Seeds the DefaultFromAddress option. Left blank, SendCampaignEmail sends from your mailer’s global mail.from address and name.
recipients.only-verifiedfalseCAMPAIGNS_ONLY_VERIFIEDSkip owners and contacts without a verified contact when resolving recipients. Seeds OnlyVerifiedRecipients. Read strictly: true/1/on/yes or false/0/off/no; anything else throws InvalidConfigurationException.
recipients.contact-typeemailCAMPAIGNS_RECIPIENT_CONTACT_TYPEContact kind resolved for an owner when ->viaContactType() is unset — a ContactType value: email, phone, address, url, social or custom. Seeds DefaultRecipientContactType. A typo throws InvalidConfigurationException instead of reading as email.
sending-queuedefaultCAMPAIGNS_SENDING_QUEUEQueue every per-recipient delivery job runs on — point a worker at it. The campaign’s job batch is opened on it when the campaign is prepared. Seeds the DefaultSendingQueue option. A blank value is not set (default); a non-string value throws.
process-recipient-jobSendCampaignEmail::class—Job dispatched once per recipient. Must implement Contracts\ProcessesCampaignRecipient — any other value throws InvalidConfigurationException when the campaign starts, while it is still Pending.
notificationnullCAMPAIGNS_NOTIFICATIONA Notifications\CampaignNotification subclass delivered by SendCampaignNotification. Any other class fails the send, recording the InvalidConfigurationException message on the recipient.
notification-channelmailCAMPAIGNS_NOTIFICATION_CHANNELRoute channel of SendCampaignNotification’s on-demand notifiable. Seeds the DefaultChannel option. A blank value is not set (mail); a non-string value throws.

Environment

Every key except process-recipient-job reads an env variable, so you rarely need to publish the config at all:

CAMPAIGNS_STORE='RoundlyConsulting\Campaigns\Stores\DatabaseCampaignStore'
CAMPAIGNS_FROM_NAME="Example Shop"
CAMPAIGNS_FROM_ADDRESS=[email protected]
CAMPAIGNS_ONLY_VERIFIED=false
CAMPAIGNS_RECIPIENT_CONTACT_TYPE=email
CAMPAIGNS_SENDING_QUEUE=campaigns
CAMPAIGNS_NOTIFICATION='App\Notifications\ProductLaunchNotification'
CAMPAIGNS_NOTIFICATION_CHANNEL=mail

Wrap class names in single quotes. Inside double quotes phpdotenv reads each backslash as the start of an escape sequence — \C, \S and \N are not valid ones — and refuses to load the .env file.

Strict values

A key that is not set — absent, null, or blank like a host’s CAMPAIGNS_SENDING_QUEUE= — takes its default. For the sender fields that default is '', which keeps the mailer’s own from; for notification it is none. A value that is set but unusable throws RoundlyConsulting\PackageToolkit\Exceptions\InvalidConfigurationException naming the key, instead of quietly falling back: a store or job class that doesn’t implement its contract, a contact type that isn’t a ContactType value, a non-string queue, channel or sender, a verified-only switch outside true/1/on/yes and false/0/off/no.

Config vs stored options

The send defaults — sender, recipient rules, sending queue and notification channel — are also runtime-editable options. The config value is only the seed: a stored option overrides it, and an explicit builder call overrides both. See Send defaults.

Campaigns without a sender

from-address is blank by default. A campaign with neither ->from() nor a from-address default (or a stored DefaultFromAddress option) still sends: SendCampaignEmail leaves the From header to your mailer, so the email goes out from the global mail.from address and name. Set CAMPAIGNS_FROM_ADDRESS, or call ->from(), only when campaigns should use a different sender.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.