Bounce Manager v2.1
Part of CloudWizard Email Suite
Bounce Manager connects to your bounce mailbox via IMAP, reads delivery failure notifications, classifies them as hard bounces, soft bounces, IP blocks, or spam rejects, and automatically suppresses hard-bounced addresses from future campaigns.
Requirements
| Requirement | Detail |
|---|---|
| PHP | 8.1 or higher |
| PHP IMAP extension | php-imap — must be installed and enabled. See below → |
| MariaDB / MySQL | 5.7+ / 10.3+ |
| Web server | Nginx or Apache |
| Bounce mailbox | Any IMAP-accessible mailbox. Dedicated address recommended. |
| Outbound HTTPS | Server must reach cloudwizard.eu for license verification |
Verify the IMAP extension before proceeding:
php -r "echo extension_loaded('imap') ? 'IMAP OK' : 'IMAP missing';"
If it reports missing, install it first — the module will not function without it.
Step 1 — Install the Controller
Bounce Manager is a module that runs inside the CloudWizard Controller. The controller handles authentication, shared database config, and module detection. Install it first.
Upload the controller
Extract cw_controller_core.zip and upload the contents of cw_controller/ to a directory on your server — typically public_html/CW/:
public_html/CW/
bootstrap.php
index.php
admin/
setup.php
login.php
style.css
...
Run the setup wizard
Visit https://yourdomain.com/CW/. The wizard runs automatically. Fill in:
- Database — host, name, username, password, table prefix
- SMTP — outgoing mail server for admin notifications
- Admin password — minimum 8 characters
Click Complete setup. The config file is written outside your webroot automatically.
Log in
You're redirected to the login page. Enter your admin password. You should see the CloudWizard Email Suite dashboard with four empty module slots.
Step 2 — Install Bounce Manager
Upload the module
Extract cw_module_bouncemanager.zip and upload the BounceManager/ folder inside your controller directory:
public_html/CW/BounceManager/
bouncemanager.php
bm_config.php
module.php
admin/
index.php
Verify detection
Reload the controller dashboard. The Bounce Manager card should show Open →. If it still shows "Not installed", confirm BounceManager/module.php is on the server and readable by PHP.
Step 3 — Activate your license
Register at CloudWizard
Go to cloudwizard.eu/register. Enter your name, email, select Bounce Manager, and submit.
Confirm your email
Click the confirmation link in the email you receive. Your license key is shown on screen and emailed to you. Format: XXXX-XXXX-XXXX.
Enter the key
In the controller go to Settings → License, paste the key, click Save settings. The key is verified immediately.
Step 4 — Add a bounce mailbox
Bounce Manager supports unlimited IMAP accounts — one per sending domain or a single shared address.
Open Mailbox settings
From the Bounce Manager page click Mailbox settings in the left panel.
Fill in account details
Enter a label, IMAP host, port, username, password, and mailbox folder (default: INBOX). Click Add Account.
Test the connection
Click Test next to the account. A green confirmation shows the message count. See the IMAP settings table if you get an error.
Enable the account
Confirm the account shows ACTIVE. Inactive accounts are skipped during scans.
IMAP settings by provider
| Provider | Host | Port | SSL |
|---|---|---|---|
| Gmail | imap.gmail.com | 993 | Yes |
| Outlook / Microsoft 365 | outlook.office365.com | 993 | Yes |
| Self-hosted (Dovecot) | your mail server hostname | 993 or 143 | 993=Yes, 143=No |
| cPanel / Plesk / Virtualmin | mail.yourdomain.com | 993 | Yes |
Running a scan
Select the mailboxes to scan using the checkboxes, then click Run bounce scan →. A progress bar tracks the scan in real time. The page reloads automatically when finished and shows updated bounce counts. Full history is available via ↗ Scan history.
What happens during a scan
- Connects to each selected IMAP account
- Fetches up to 500 messages per account per chunk
- Applies pattern matching to classify each bounce
- Records classified bounces in
cw_bounces - Deletes matched bounce messages from the IMAP server
- Non-bounce messages are never touched
What gets deleted vs. what stays
| Message type | Action |
|---|---|
| Hard bounce notification | Classified, recorded, deleted from IMAP |
| Soft bounce notification | Classified, recorded, deleted from IMAP |
| IP block notification | Classified, recorded, deleted from IMAP |
| Spam reject notification | Classified, recorded, deleted from IMAP |
| Unrecognised message | Left in mailbox — not touched |
| Non-bounce email | Left in mailbox — not touched |
Bounce types
| Type | Meaning | Suppress? |
|---|---|---|
| Hard | Permanent failure — address doesn't exist, domain invalid, mailbox permanently closed | Yes — always |
| Soft | Temporary failure — mailbox full, server busy, quota exceeded. Soft count increments on each bounce. | After repeated bounces |
| IP Block | Your sending IP was rejected. The recipient address is valid — the rejection is about your IP, not the address. | No — address is valid |
| Spam Reject | Message rejected as spam. Address is valid — review content and sending reputation. | No — address is valid |
How addresses are detected
Bounce Manager uses pattern matching on the email subject line and body text to identify and classify bounce messages. See the Patterns section for details on how to view and customise the matching rules.
Suppression list
Hard-bounced addresses are written to cw_mail_suppression — a shared table that Mail Engine checks before every send. Suppressed addresses are skipped automatically across all campaigns and lists.
You can also import external suppression lists (legacy unsubscribes, complaint lists) using the import_suppression.php utility included with the Email Suite.
Patterns
Bounce classification is driven by pattern rules stored in the database. The Patterns tab shows all rules in three categories:
| Category | Where it matches | Default count |
|---|---|---|
| Subject rules | Email subject line | 23 |
| IP Block rules | Email body text | 15 |
| Spam Reject rules | Email body text | 13 |
Match types
| Type | Behaviour |
|---|---|
starts_with | Pattern must appear at the start of the subject (case-insensitive) |
contains | Pattern can appear anywhere in the subject or body |
regex | Full PHP regular expression, e.g. /^Delivery (Failure|Error)/i |
Result types for subject rules
| Result | Meaning |
|---|---|
hard | Classify as hard bounce immediately |
soft | Classify as soft bounce immediately |
parse | Match confirmed as a bounce — parse body to determine hard vs soft from the SMTP code |
Adding a custom pattern
If you encounter bounce messages that are not being classified, go to Bounce Manager → Patterns, click Add Pattern, and enter the matching text from the unrecognised bounce subject or body. Set the category and result type, then save. The new rule applies on the next scan.
Exporting bounces
Export buttons at the bottom of the bounce list produce a CSV with columns: email, bounce_type, soft_count, reason, source_account, bounce_date.
| Export | Contents | Use for |
|---|---|---|
| Exclude list (hard+soft) | All hard and soft bounces | Main suppress list for sending |
| Hard | Hard bounces only | Permanent removes |
| Soft | Soft bounces only | Review and retry decisions |
| All | Everything including IP blocks and spam rejects | Full audit export |
Using the exclude list in PHP
// Load hard+soft bounces from exported CSV into an array
$exclude = [];
if (($fh = fopen('bounces_exclude_2026-07-01.csv', 'r')) !== false) {
fgetcsv($fh); // skip header
while (($row = fgetcsv($fh)) !== false) {
$exclude[] = strtolower(trim($row[0]));
}
fclose($fh);
}
// Filter your list before sending
$toSend = array_filter($myList, fn($email) => !in_array(strtolower($email), $exclude));
Using the exclude list with SQL
-- Mark bounced addresses in your subscribers table
UPDATE subscribers s
JOIN cw_bounces b ON LOWER(s.email) = LOWER(b.email)
AND b.bounce_type IN ('hard', 'soft')
SET s.emails_ok = 'N', s.bounce = 1;
Audit log
The Audit Log tab in Bounce Manager shows two tables:
Scan history
Every scan run is recorded with: date and time, account scanned, emails scanned, bounces found, IP/spam blocks, failures, messages deleted from IMAP, and duration in seconds.
Processing failures
Messages that matched a bounce subject rule but could not be fully parsed are logged here with the subject line, a body snippet, and the failure reason. Review these occasionally — they often indicate a bounce format from a new provider that needs a custom pattern added.
Cron automation
To scan automatically without manual intervention, add a cron job in Virtualmin → Scheduled Cron Jobs:
0 * * * * curl -s "https://yourdomain.com/CW/BounceManager/bouncemanager.php?action=cron_scan&key=YOURCRONKEY" > /dev/null 2>&1
Use your controller's cron_secret value as the key. The example runs every hour — adjust to match your sending volume. Once or twice daily is sufficient for low-volume senders.
PHP IMAP extension
Ubuntu / Debian with PHP-FPM
apt install php8.3-imap
systemctl restart php8.3-fpm
Virtualmin
Go to System Settings → PHP Configuration, enable the imap extension for your PHP version, restart PHP-FPM.
cPanel
Go to WHM → PHP Extensions and Applications and enable imap.
Verify
php -m | grep imap
Security
- Always use HTTPS. Bounce Manager handles IMAP passwords — never run it over plain HTTP.
- The controller admin is protected by your admin password. Use a strong password (the setup wizard enforces minimum 8 characters).
- Use a dedicated bounce mailbox where possible — not your main inbox. The scan deletes matched messages permanently.
- Restrict admin access by IP if possible. In Nginx, inside the
locationblock for your CW directory:
allow 1.2.3.4; deny all; - Rotate your IMAP password periodically and update it in Bounce Manager → Mailbox settings.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| Cannot connect to account | Wrong host, port, or credentials | Use the Test button. Check that IMAP is enabled on the mail server and the port is reachable. |
| Unable to negotiate TLS | Server doesn't support STARTTLS on port 143 | Uncheck SSL and use port 143, or switch to port 993 with SSL checked. |
| SECURITY PROBLEM: AUTH=PLAIN in logs | PHP IMAP library warning on plain-text auth | Harmless — connection still works. Use SSL (port 993) to eliminate the warning. |
| 0 bounces found after scan | Subject patterns don't match your bounce format | Check the mailbox folder setting. Copy an unrecognised bounce subject and add a custom pattern. |
| Module not detected on dashboard | module.php missing or not readable | Confirm CW/BounceManager/module.php exists. Restart PHP-FPM: systemctl restart php8.3-fpm |
| License key not accepted | Unconfirmed email, wrong key format, or server can't reach cloudwizard.eu | Confirm your registration email first. Key format: XXXX-XXXX-XXXX. Check outbound HTTPS from server. |
| 500 error on admin pages | IMAP extension missing, DB error, or file permissions | tail -20 /home/yourusername/logs/php_log |
CloudWizard Email Suite — Bounce Manager v2.1
cloudwizard.eu —
support@cloudwizard.eu