A lightweight, self-hosted mailing list manager built with pure PHP 8 and SQLite. Perfect for small to medium organizations who want full control over their mailing lists without complex dependencies.
This tool runs on any standard PHP web hosting and relies on a dedicated IMAP mailbox that centralizes all mailing list traffic.
┌─────────────────────────────────────────┐
│ Your Mail Server │
│ │
geeks@domain.com ─┼──► alias ──┐ │
admin@domain.com ─┼──► alias ──┼──► listes@domain.com ◄─────┼─── IMAP/SMTP
news@domain.com ─┼──► alias ──┘ (main mailbox) │
└─────────────────────────────────────────┘
▲
│
▼
┌─────────────────────────────────────────┐
│ PHP Web Hosting │
│ │
│ ┌─────────┐ ┌─────────────────┐ │
│ │ cron.php│───►│ KList Manager │ │
│ └─────────┘ │ (this tool) │ │
│ ▲ └─────────────────┘ │
└────────┼────────────────────────────────┘
│
Scheduled task (every 5-15 min)
-
Dedicated Mailbox
You need to have a dedicated email account (e.g.,listes@yourdomain.com) with IMAP access. This mailbox:- Receives all incoming list emails
- Sends all outgoing emails to subscribers
- Stores processed messages in IMAP folders
-
Email Aliases (
⚠️ Manual Setup Required)
Each mailing list needs a corresponding email alias pointing to the main mailbox.List Name Alias to Create Points To geeksgeeks@yourdomain.comlistes@yourdomain.comnewsnews@yourdomain.comlistes@yourdomain.comteamteam@yourdomain.comlistes@yourdomain.com⚠️ Important: Creating email aliases must be done manually in your mail server/hosting panel (cPanel, Plesk, etc.). This tool does not create aliases automatically! -
Periodic Processing
The tool processes emails by callinghttps://yourdomain.com/listes/cron.php?key=YOUR_CRON_KEY. This can be:- Automated via a cron job / scheduled task
- Triggered manually for testing
You can find the actual URL with the CRON_KEY in Settings → Cron Configuration
Each run: fetches new emails → identifies target list → applies moderation → forwards to subscribers
- 📋 Multiple mailing lists - Create unlimited lists with individual settings
- 👥 Subscriber management - Add, remove, search, and export subscribers
- 🛡️ Moderation - Optional moderation for each list before forwarding
- 🚫 Blocklist - Automatic blocking of bouncing emails
- 📧 Discussion lists - Reply-to-all mode (expose recipients) or broadcast mode (BCC)
- 🔍 Subscriber search - Find subscribers across all lists with partial matching
- ⚡ Live search - Real-time filtering as you type
- 📊 Dashboard - Overview with cron status, subscriber counts, and last activity
- 🌙 Dark theme - Modern, eye-friendly interface
- 🔐 Secure - CSRF protection, prepared statements, session security
- PHP 8.0+ with extensions:
imap(for email fetching)sqlite3orpdo_sqliteopenssl(for SMTP/IMAP TLS)mbstring(recommended)
- Web server with
.htaccesssupport (Apache/LiteSpeed) or equivalent nginx config - IMAP/SMTP access to a dedicated email account for the lists
git clone https://github.com/KomplexKapharnaum/KList.git listes
cd listesOr download and extract the ZIP file.
Upload the entire folder to your web hosting (via FTP, SFTP, or SSH).
Example structure:
public_html/
└── listes/ ← Upload here
├── index.php
├── config.php
├── cron.php
├── assets/
├── data/
├── lib/
├── src/
├── templates/
└── tmp/
# Ensure data and tmp directories are writable
chmod 755 data/
chmod 755 tmp/
chmod 644 data/.htaccess
chmod 644 tmp/.htaccessNavigate to your installation URL (e.g., https://yourdomain.com/listes/)
On first access, the setup wizard will guide you through:
- Admin account - Create your email/password (also used for moderation notifications)
- IMAP configuration - Connect to your dedicated mailbox
- SMTP configuration - Configure email sending (a test email will be sent)
The database is only created after all settings are validated and connections tested.
The cron job processes incoming emails and forwards approved messages.
Using cPanel Cron:
*/5 * * * * curl -s "https://yourdomain.com/listes/cron.php?key=YOUR_CRON_KEY" > /dev/nullUsing wget:
*/5 * * * * wget -q -O /dev/null "https://yourdomain.com/listes/cron.php?key=YOUR_CRON_KEY"Find your cron key: Settings → Cron Configuration
💡 Tip: Run every 5 minutes for near real-time processing, or every 15-30 minutes for lower priority lists.
- Click "Nouvelle liste" in the sidebar
- Enter a name (lowercase, no spaces - becomes the email prefix)
- Configure options:
- Modération - Require approval before forwarding
- Liste de Discussion - Recipients see each other (reply-to-all works)
- Active - Enable/disable the list
- Add subscribers (one per line, or comma/semicolon separated)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ INBOX │ ──▶ │ PENDING │ ──▶ │ APPROVED │
│ (incoming) │ │ (moderated) │ │ (ready) │
└─────────────┘ └─────────────┘ └─────────────┘
│ │
│ (auto-approved) │
└───────────────────┐ │
▼ ▼
┌─────────────────────────────┐
│ Forward to │
│ subscribers │
└─────────────────────────────┘
│
▼
┌─────────────┐
│ DONE │
│ (archived) │
└─────────────┘
Special IMAP folders created automatically:
INBOX- Incoming messagesPENDING- Awaiting moderationAPPROVED- Ready to forwardDONE- Successfully sentDISCARDED- Rejected by moderator or unauthorizedERRORS- Bounce messages / errorsARCHIVE- Round-back preventionOTHERS- No matching list
Users can unsubscribe by sending an email to the list with STOP as the subject.
Example: Send to mylist@yourdomain.com with subject STOP
The Subscriber Search page lets you:
- Find subscribers by partial email match
- See all lists a subscriber belongs to
- Unsubscribe from individual lists or all at once
listes/
├── index.php # Main entry point & router
├── config.php # Configuration & helpers
├── cron.php # Email processing endpoint
├── .htaccess # Security rules
├── .gitignore # Git ignore rules
│
├── data/ # SQLite database (protected)
│ ├── .htaccess # Deny all access
│ └── listes.db # Database file (auto-created)
│
├── src/ # PHP classes (protected)
│ ├── Auth.php # Authentication
│ ├── Database.php # SQLite wrapper
│ ├── ListManager.php # List operations
│ ├── BlocklistManager.php
│ └── MailProcessor.php # Email logic
│
├── templates/ # HTML templates (protected)
│ ├── layout.php # Base layout
│ ├── dashboard.php
│ ├── login.php
│ ├── list-edit.php
│ ├── subscribers.php
│ ├── moderation.php
│ ├── errors.php
│ └── settings.php
│
├── assets/ # Public CSS/JS/images
│ └── css/
│ └── style.css # Dark theme
│
├── lib/ # Third-party libraries
│ ├── PHPMailer/ # Email sending
│ └── Fetch/ # IMAP fetching
│
└── tmp/ # Temporary files (attachments)
└── .htaccess # Deny all access
| Feature | Implementation |
|---|---|
| SQL Injection | All queries use PDO prepared statements |
| XSS Protection | All output escaped with htmlspecialchars() |
| CSRF Protection | Token validation on all forms |
| Session Security | HttpOnly, Secure, SameSite flags |
| Password Hashing | bcrypt via password_hash() |
| Directory Protection | .htaccess blocks data/, src/, templates/, tmp/ |
| Cron Security | Secret key required for cron endpoint |
| Setting | Description |
|---|---|
site_title |
Application title |
admin_email |
Login email |
admin_password |
Hashed password |
imap_host |
IMAP server hostname |
imap_port |
IMAP port (usually 993) |
smtp_host |
SMTP server hostname |
smtp_port |
SMTP port (usually 587) |
domains |
Allowed domains (comma-separated) |
cron_key |
Secret key for cron URL |
| Issue | Solutions |
|---|---|
| IMAP connection failed | Verify credentials in Settings • Check IMAP is enabled on mail server • Try mail.domain.com vs domain.com • Ensure firewall allows port 993 |
| Cron not running | Verify cron key in Settings → Cron Configuration • Test URL in browser • Check server cron logs |
| Emails not sending | Check SMTP settings • Verify SPF/DKIM for sender email • Check ERRORS folder on IMAP |
| Memory exhausted | Reduce $maxMessagesPerRun in MailProcessor.php • Large attachments (>10MB) auto-skipped • Increase PHP memory limit |
GPLv3 License - See LICENSE file
Thomas BOHL (@maigre)
KomplexKapharnaüm – Arts numériques & Spectacle vivant
- PHPMailer – Email sending library
- Fetch – IMAP library
- Material Icons – UI icons