実アカウントでのライブデモ — サインアップ不要、クレジットカード不要。キャンペーンを作り、自動化を実行し、分析が動くのを見る。
開発者向け
AcelleMail は Laravel 11+ のメールマーケティング基盤で、暗号化されていない PHP ソース一式と型付き Hook システムを同梱しています。送信ドライバ、決済ゲートウェイ、AI、カスタム UI、さらには REST API まで、コアを fork せずにプラグインで追加できます。
実運用中のプラグイン
開発者が AcelleMail を選ぶ理由
全ライセンスに暗号化なしの PHP ソース一式が同梱されます。任意のクラスを書き換え、任意のサービスを上書きし、自分の namespace に fork してください。コードはあなたのもの、ルールもあなたのもの。Laravel 11+ ベースなので、すでに知っているフレームワークが重い処理を担います。
Composer 形式のフォルダを storage/app/plugins/<vendor>/<name>/ に配置するだけでアプリが autoload します。ServiceProvider が routes / views / migrations / hooks を注入。有効化・無効化・削除をクリーンに行えます。
storage/app/plugins/<vendor>/<name>/
キャンペーン、リスト、購読者、テンプレート、オートメーション用の CRUD エンドポイント。ドメインレベルの出来事ごとに発火する webhook イベント。SaaS フロントエンド、モバイルアプリ、他の Laravel サービスにそのまま組み込めます。プラグインが使う API と外部クライアントが使う API は同一 — 二級市民のエンドポイントはありません。
あなたのサーバー、あなたの DB、あなたの購読者データ。ベンダーロックインなし。ライセンスは買い切り。送信コストは基盤の SMTP 実費のみ(例: Amazon SES は 1,000 通あたり $0.10)。PHP が動く環境ならどこへでも展開可能 — ベアメタル、Kubernetes、Forge、Laravel Vapor。スタックに応じて自由にスケールします。
プラグインで作れるもの
プラグインはディスク上に存在する自己完結型の Laravel パッケージです。独自の namespace、独自のデータベーステーブル、routes、views、controllers、models を持ち、include ハックではなく型付き Hook システム経由でコアと統合します。
include
rencontru/postal
athena/evs
acelle/ai
page.maillist.show.body
page.campaign.index.sidebar
/rui/admin/ai-usage
/rui/admin/ai-audit
/rui/admin/ai-conversations
/plugins/acelle/ai/dashboard
/api/v1/ai/*
customer_added
plan_changed
subscription_terminated
dispatch_list_import_job
sidebar-menu-items
一つのプラグインで複数のサーフェスを組み合わせ可能 — acelle/ai は 14 のうち 7 を 1 パッケージで使用しています。
Hook システム
コアはプラグインのコードを import しません — 拡張ポイントを宣言するだけです。プラグインは listen して反応します。4 パターンそれぞれに明確な役割があり、競合は即座に例外を投げます。
add() + collect()
プラグインがリストに項目を追加します。コアが「送信ドライバを持っているのは誰?」と問い合わせると、あなたのプラグインが「私が持っています」と応答します。
Hook::add('register_sending_server_driver', fn () => [ 'type' => 'myvendor-foo', 'driver' => \MyVendor\Foo\Driver::class, ]); $drivers = Hook::collect('register_sending_server_driver');
on() + fire()
プラグインが発生した事象に反応します。戻り値は破棄されます。
Hook::on('customer_added', function ($customer) { LoyaltyPoints::award($customer, 100, 'welcome'); }); Hook::fire('customer_added', [$customer]);
set() + perform()
プラグインがコアロジックの一部を完全に置き換えます。一つの挙動は一つのプラグインしか主張できず、競合すれば即座に例外が投げられます。
Hook::set('dispatch_list_import_job', fn ($list, $f) => new MyFasterImportJob($list, $f)); Hook::setIfEmpty('dispatch_list_import_job', fn ($list, $f) => new DefaultImportJob($list, $f)); $job = Hook::perform('dispatch_list_import_job', [$list, $f]); dispatch($job);
modify() + filter()
プラグインがコールバックチェーンを通じて値を変換します。各コールバックは現在の値を受け取り、変更後の値を返します。
Hook::modify('sidebar-menu-items', function (array $items) { $items[] = [ 'label' => 'Loyalty', 'url' => route('lp.dashboard'), ]; return $items; }); $menu = Hook::filter('sidebar-menu-items', $defaultMenu);
5 分で Hello World
scaffold がすべて生成します — Composer メタデータ、ServiceProvider、サンプルモデル、サンプル migration、サンプルルート、サンプルビュー。そこから先はあなたの自由に拡張できます。
標準フォルダ構造と inactive 状態の DB 行を生成します。
$ php artisan plugin:init myvendor/loyalty ✓ Created storage/app/plugins/myvendor/loyalty/ ✓ DB row inserted (status: inactive) ✓ index.json + ServiceProvider autoloaded
namespace と ServiceProvider を Composer に伝えます。
{ "name": "myvendor/loyalty", "description": "Award points on signup", "version": "1.0.0", "autoload": { "psr-4": { "MyVendor\\Loyalty\\": "src/" } }, "extra": { "laravel": { "providers": [ "MyVendor\\Loyalty\\ServiceProvider" ] } } }
プラグイン専用テーブル、vendor 接頭辞付きの名前。activate 時に実行、delete 時にロールバックします。
Schema::create('myvendor_loyalty_accounts', function (Blueprint $t) { $t->id(); $t->foreignId('customer_id')->constrained()->cascadeOnDelete(); $t->integer('points')->default(0); $t->timestamps(); });
あなたの namespace 配下の標準的な Eloquent モデルです。
namespace MyVendor\Loyalty\Models; use Illuminate\Database\Eloquent\Model; class Account extends Model { protected $table = 'myvendor_loyalty_accounts'; protected $fillable = ['customer_id', 'points']; }
普通の Laravel controller — view namespace はプラグイン名です。
namespace MyVendor\Loyalty\Controllers; use Acelle\Http\Controllers\Controller; class DashboardController extends Controller { public function index() { return view('loyalty::dashboard', [ 'accounts' => \MyVendor\Loyalty\Models\Account::orderByDesc('points')->take(10)->get(), ]); } }
いつも使っている Route::group と同じ。ServiceProvider::boot() で読み込みます。
Route::group([ 'middleware' => ['web', 'auth'], 'namespace' => '\MyVendor\Loyalty\Controllers', 'prefix' => 'plugins/myvendor/loyalty', ], function () { Route::get('/', 'DashboardController@index')->name('lp.dashboard'); Route::get('/{account}', 'DashboardController@show'); });
views と routes をロードし、activate_plugin_… にフックして有効化時に migration を実行します。
activate_plugin_…
public function boot(): void { $this->loadViewsFrom (__DIR__.'/../resources/views', 'loyalty'); $this->loadRoutesFrom(__DIR__.'/../routes.php'); Hook::on('activate_plugin_myvendor/loyalty', fn () => \Artisan::call('migrate', [ '--path' => 'storage/app/plugins/myvendor/loyalty/database/migrations', '--force' => true, ]) ); Hook::on('customer_added', fn ($customer) => Models\Account::create(['customer_id' => $customer->id, 'points' => 100]) ); }
/rui/admin/plugins にアクセス。migration が自動実行され、プラグインは指定の prefix で動作します。
/rui/admin/plugins
✓ activated myvendor/loyalty v1.0.0 → migrations: 1 ran (myvendor_loyalty_accounts) → routes: 2 registered under /plugins/myvendor/loyalty → hooks: 2 listening (activate, customer_added) → status: active → visit /plugins/myvendor/loyalty/ ← live
動くプラグインが完成しました。あとは機能に応じて models / controllers / hooks を好きなだけ追加してください。テストは tests/ に置き、php artisan test --testsuite='Plugin: myvendor/loyalty' で実行できます。正式な仕様はナレッジベースを参照してください。
tests/
php artisan test --testsuite='Plugin: myvendor/loyalty'
プラグインライフサイクル
すべてのプラグインは正確に 4 つの状態のいずれか一つに存在します。現在の状態が、どの hook が発火するか、どの migration が実行済みか、次の遷移で何が起きるかを規定します。docs/plugin/SOURCE_OF_TRUTH.md に基づいたソース・グラウンディング。
docs/plugin/SOURCE_OF_TRUTH.md
プラグインフォルダ存在、index.json がインデックス化済み、DB 行は inactive。ServiceProvider の register() は実行済みですが、boot() の hook は有効化をクリックするまでゲートで遮断されています。
index.json
inactive
register()
boot()
初回の有効化で activate_plugin_<name> が一度発火 — ここで migration が実行されます。以降は無効化されるまで、REGISTRY / EVENT / FILTER / BEHAVIOR の全 hook が稼働します。
activate_plugin_<name>
Routes はアンマウント、hook はゲートで遮断されますが、フォルダと DB テーブルは残存。再有効化しても migration や activate hook は再実行されない — 本番でのトグルが安全です。
フォルダ削除、DB 行も消去。$keepData = false ならプラグインの migration がロールバック — vendor 接頭辞付きテーブルは drop されます。コアのテーブルには一切手を加えません。
$keepData = false
実プラグインショーケース
acelle/ai プラグインは完全な AI アシスタント層を同梱しています: 全ページに浮かぶエージェントチャットボックス、リッチテキストフィールドでの ✨ sparkle 書き換え、ナレッジベース基盤の coach ペルソナ(Deliverability, Segments, Campaigns, Forms)、5 つのルートにまたがる管理側の可観測性サーフェス。3 つのレイアウト hook 経由でマウントされ、コアの変更はゼロです。
3 つのレイアウト REGISTRY hook — それだけです。加えてページ単位の注入、ライフサイクルイベントリスナー、/api/v1/ai/* 配下の名前空間化されたカスタム REST API。コアの変更はゼロで、プラグインフォルダはドロップインで配布可能です。
REST API
REST API を使えば AcelleMail を自社の SaaS フロントエンド、モバイルアプリ、Laravel サービスに統合できます。プラグインが使う API と外部クライアントが使う API は同一 — 二級市民のエンドポイントはありません。
GET/POST/PATCH/DELETE /api/v1/lists[/:uid]
/api/v1/subscribers
/api/v1/campaigns[/:uid]
/api/v1/automations[/:uid]
/api/v1/sending_servers[/:uid]
/api/v1/customers[/:uid]
/api/v1/subscriptions[/:uid]
ライフサイクル(Admin → Webhooks で設定): new_customer, new_subscription, change_plan, cancel_subscription, terminate_subscription, automation_webhook。受信者単位のトラッキング(キャンペーン単位): open, click, unsubscribe。
new_customer
new_subscription
change_plan
cancel_subscription
terminate_subscription
automation_webhook
open
click
unsubscribe
# Create a list $ curl -X POST \ https://your-acelle.example.com/api/v1/lists \ -H "Authorization: Bearer $ACELLE_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Newsletter", "from_email": "hi@example.com", "from_name": "Hi Team", "subject": "Weekly digest" }' # Add a subscriber $ curl -X POST \ .../api/v1/lists/:uid/subscribers \ -H "Authorization: Bearer $ACELLE_TOKEN" \ -d '{"EMAIL":"alice@example.com"}' # Send a campaign $ curl -X POST \ .../api/v1/campaigns/:uid/send \ -H "Authorization: Bearer $ACELLE_TOKEN" # Receive a webhook POST /your-webhook-endpoint { "event": "campaign.sent", "campaign_uid": "abc123", "list_uid": "xyz789", "sent_at": "2026-05-06T12:34:56Z" }
オープンソースの理念
サーバー上で動く PHP のすべての行を確認できます。ionCube も SourceGuardian も難読化もありません。カスタマイズは git diff で追跡、何でも grep で見つかります。
git diff
grep
2016 年以降の AcelleMail の全リリースが CodeCanyon のダウンロード履歴に残ります。必要なときに必要なものを取得できます。サブスク圧力なし。
プラグインは MyVendor\MyPlugin\ 配下に存在し、Acelle\* コアから完全に隔離されます。Composer 経由でチームやマーケットプレイスに配布可能です。
MyVendor\MyPlugin\
Acelle\*
$80 (Regular) または $199 (SaaS 向け Extended) を一度支払うだけ。サブスクなし、購読者課金なし、メール課金なし。事業が成長しても計算式は変わりません。
リソースとコミュニティ
ソースに根ざした 11 本の深掘り解説。必要なページへ直接ジャンプ:
ホスト側の 5 ファイル、boot-and-load フロー、4 つのライフサイクル状態、2 つの注入レイヤー — 他のドキュメントが前提とするメンタルモデル。
認証、エンドポイントカタログ、webhook ペイロード、エラー形状 — サンプル付きのネイティブランディングページ。
REGISTRY / EVENT / BEHAVIOR / FILTER — プラグインが使う 4 つの拡張形状を、コアから grep した実呼び出し箇所、競合セマンティクス、6 つのアンチパターンとともに解説。
コアを fork せずに新しい MTA バックエンドを提供。register_sending_server_driver 契約、9 つのケイパビリティマーカー、Postal プラグインで踏んだ 5 つの落とし穴。
register_sending_server_driver
正典級の複雑プラグインをエンドツーエンドで解説。8 モデル、14 migrations、18 ロケール、全 hook サーフェス、チャットボックス UI、加えて 4 ステップの学習レシピ。
Hook 契約やプラグインライフサイクルで詰まりましたか? メールでご連絡ください — 24 時間以内に返信します。
基礎、実装、品質、リファレンス — 全ページを 1 箇所にまとめ、storage/app/plugins/acelle/ai/ と正典のプラグインドキュメントに対してソース・グラウンディング。
storage/app/plugins/acelle/ai/
開発者向け FAQ
可能ですが、最もクリーンなパターンはプラグインです。プラグインはコアの namespace の外で動作し、アップグレードを自動的に生き延びます。コアを直接編集することもできますが、リリースごとに upstream の変更を手動でマージする必要があります。プラグインシステムはまさにそうした苦行を避けるために存在します。
はい、設計上そうなっています。コアが hook ポイントを宣言し、プラグインが反応します。hook の名前とシグネチャが安定している限り(破壊的変更にはバージョンスタンプを付けます)、プラグインは動き続けます。リリースごとに AI プラグイン(acelle/ai)でテストしています。
はい。Extended ライセンスは自作プラグインを自分のライセンスで配布する権利を付与します。プラグインは独自の namespace に存在し、そのコードは 100 % あなたのものです。複数のチームが社内プラグインエコシステム向けにプライベートマーケットプレイスを運営しています。
REGISTRY hook はマージ(各プラグインが寄与)、EVENT hook はすべて発火(競合不可)、FILTER チェーンは累積、BEHAVIOR のみが「排他的」パターン — 2 つのプラグインが同じ挙動を主張しようとすると即座に例外が投げられます。サイレント上書きの不意打ちはありません。
はい、同じ Hook システム経由で可能です。プラグイン A がイベントを発火し、プラグイン B が listen できます。または public クラスを公開する — MyVendor\PluginA\Service は通常の PHP クラスなので、他と同じく import できます。acelle/ai プラグインは、他のプラグインがカスタム AI ツールを登録できるよう hook を公開しています。
Regular ($80) は単一ドメインでの自社利用をカバーします。Extended ($199) はエンドユーザーへの課金(SaaS としての再販)、ホワイトラベルクローンの配布、自作プラグインの販売権を追加します。両方とも同じソースコードを同梱しています。
同じデータベースに書き込みますが、vendor 名で接頭辞を付けたテーブル(例: myvendor_loyalty_accounts)に書き込みます。Migration はプラグインの activate 時に実行され、$keepData = false での delete 時にロールバックします。コアテーブルへのリスクはゼロです。
プラグインのランタイムは PHP / Laravel です。ただしプラグインから何にでもシェルアウト可能 — Node サービス、Python ML、Go バイナリ、外部 HTTP API。複数のチームが外部ツールをラップするプラグインを提供しています。プラグインは統合シェル、重い処理はどこにでも置けます。
acelle/ai は、他のプラグインがカスタム AI ツールを登録したり、エンジンを差し替えたり、可観測性レイヤーにフックしたりするための hook を公開します。契約は AI プラグインのソースを参照してください。あなたのプラグインから AI エージェントがコンテキストとして拾うイベントを発火することも可能です。
現時点ではありません。プラグインは直接販売、GitHub、プライベートレジストリで配布されています。コミュニティマーケットプレイスはロードマップにあり、十分な数のサードパーティプラグインが揃った段階で立ち上げる予定です。
PHP ソース一式。永続アップデート。Hook システム。コピーできる実運用例。Extended ライセンス(商用プラグイン再配布 + SaaS 利用)は買い切り $199。
フルソースコード、定期課金なし、無制限送信で Email マーケティングを掌握した何千もの企業に加わりませんか。一度の $80 ライセンス、永続アップデート。
おかえりなさい。サインインしていいね・コメントしましょう。
はじめての方は アカウントを作成 — 10秒で完了、メール認証は不要です。
簡単サインアップ — メール認証なし、すぐにご利用いただけます。
8文字以上で入力してください。
すでにアカウントをお持ちですか? サインイン.