Troubleshooting Guide #
Common issues and solutions for the Message plugin.
🚨 Email Delivery Issues #
Emails Not Sending #
Symptoms:
- Messages stuck in "Processing" status
- No emails received by subscribers
- Dashboard shows 0 sent
Diagnosis Steps:
-
Check Cron Job
# Verify cron is configured crontab -l | grep artisan # Test manually php artisan campaign:run -
Check SMTP Configuration
# Test SMTP connection php artisan tinker >>> Mail::raw('Test', function($message) { >>> $message->to('test@example.com')->subject('Test'); >>> }); -
Review Queue Status
# Check for failed jobs php artisan queue:failed # Retry failed jobs php artisan queue:retry all
Solutions:
-
Cron not running: Add to crontab:
* * * * * cd /path/to/project && php artisan schedule:run >> /dev/null 2>&1 -
SMTP misconfigured:
- Verify credentials in Settings → Email Settings
- Test connection with "Test Connection" button
- Check firewall allows outbound SMTP
-
Queue workers stopped:
php artisan queue:restart php artisan queue:work --daemon
Low Delivery Rate #
Symptoms:
- High bounce rate (>5%)
- Many emails marked as spam
- Delivery rate below 95%
Solutions:
-
Verify SPF/DKIM/DMARC
v=spf1 include:sendgrid.net ~all -
Check Sender Reputation
- Use tools like MXToolbox
- Review blacklist status
- Monitor complaint rates
-
Improve Email Content
- Avoid spam trigger words
- Balance text-to-image ratio
- Include unsubscribe link
Delayed Email Delivery #
Symptoms:
- Emails arrive hours late
- Queue backlog growing
- Processing takes too long
Solutions:
-
Optimize Batch Size
// config/campaign.php 'batch_size' => 50, // Reduce for faster processing -
Add Queue Workers
# Run multiple workers php artisan queue:work --queue=campaigns --tries=3 & php artisan queue:work --queue=campaigns --tries=3 & -
Use Redis Queue
QUEUE_CONNECTION=redis
📊 Dashboard & Analytics Issues #
Dashboard Not Loading #
Symptoms:
- Blank dashboard
- Spinning loader
- Error messages
Solutions:
-
Clear Cache
php artisan cache:clear php artisan view:clear php artisan config:clear -
Check Permissions
- Verify user has
manage_messagespermission - Confirm organization assignment
- Verify user has
-
Database Optimization
OPTIMIZE TABLE campaign_messages; OPTIMIZE TABLE campaign_subscribers;
Incorrect Statistics #
Symptoms:
- Open rates showing 0%
- Click tracking not working
- Wrong subscriber counts
Solutions:
-
Rebuild Statistics
// Via tinker $message = Message::find(1); $message->rebuildStats(); -
Verify Tracking Pixel
- Check email HTML includes tracking pixel
- Confirm tracking domain is accessible
-
Process Webhooks
php artisan campaign:process-webhooks
Missing Performance Data #
Symptoms:
- No data in last 30 days
- Charts showing empty
- KPIs displaying zero
Solutions:
-
Check Date/Timezone
// config/app.php 'timezone' => 'America/New_York', -
Verify Data Collection
- Ensure webhooks are configured
- Check webhook delivery logs
- Confirm tracking is enabled
🔌 SMTP & Server Issues #
SMTP Connection Failed #
Error Messages:
Connection could not be established with host smtp.example.com
Failed to authenticate on SMTP server
Solutions:
-
Test with Telnet
telnet smtp.sendgrid.net 587 -
Common Fixes
- Use correct port (587 for TLS, 465 for SSL)
- Try authentication with base64 encoding
- Check IP whitelisting requirements
-
Firewall Issues
# Check if port is open nc -zv smtp.sendgrid.net 587
SMTP Rate Limit Exceeded #
Symptoms:
- 429 Too Many Requests errors
- Temporary sending failures
- Automatic failover triggered
Solutions:
-
Implement Sending Windows
'sending_window' => [ 'start' => '09:00', 'end' => '17:00' ] -
Reduce Sending Rate
'rate_limit' => 100, // per hour 'batch_delay' => 10 // seconds -
Distribute Across Servers
- Configure multiple SMTP servers
- Enable load balancing mode
All SMTP Servers Failing #
Symptoms:
- Test mode activated
- No emails being sent
- Multiple failover attempts
Emergency Steps:
-
Quick Diagnostic
# Test all servers php artisan campaign:test-smtp --all -
Common Causes
- Account suspended
- Credit/quota exhausted
- IP blacklisted
- Network outage
-
Recovery Actions
- Contact SMTP providers
- Check account status
- Review recent changes
- Enable test mode temporarily
👥 Subscriber Issues #
Duplicate Subscribers #
Symptoms:
- Same email appears multiple times
- Import creates duplicates
- Statistics inflated
Solutions:
-
Clean Database
-- Find duplicates SELECT email, COUNT(*) FROM campaign_subscribers GROUP BY email HAVING COUNT(*) > 1; -- Remove duplicates (keep oldest) DELETE s1 FROM campaign_subscribers s1 INNER JOIN campaign_subscribers s2 WHERE s1.id > s2.id AND s1.email = s2.email; -
Add Unique Constraint
Schema::table('campaign_subscribers', function($table) { $table->unique(['email', 'organization_id']); });
Subscribers Not Receiving Emails #
Symptoms:
- Specific subscribers never get emails
- No bounce or error messages
- Status shows as sent
Diagnosis:
-
Check Subscriber Status
SELECT * FROM campaign_subscribers WHERE email = 'user@example.com'; -
Review Send Logs
SELECT * FROM campaign_messages_subscribers WHERE subscriber_id = 123; -
Common Issues
- Subscriber unsubscribed
- Email in suppression list
- Invalid email format
- Blocked by provider
Import Failures #
Symptoms:
- CSV import shows errors
- Subscribers not added
- Timeout during import
Solutions:
-
Check CSV Format
- UTF-8 encoding required
- Proper column headers
- No special characters in headers
-
Reduce Batch Size
'import_batch_size' => 100, // Smaller batches -
Use Command Line
php artisan campaign:import subscribers.csv --list=1
🔑 API Issues #
Authentication Failed #
Error:
{
"error": "Invalid or expired token"
}
Solutions:
-
Verify Token
- Check token hasn't expired
- Confirm token is active
- Verify correct header format
-
Check IP Restrictions
- Review allowed IPs in API settings
- Confirm request from whitelisted IP
-
Test with Curl
curl -H "Authorization: Bearer YOUR_TOKEN" \ https://domain.com/api/campaign/subscribers
Rate Limit Exceeded #
Error:
{
"error": "Too many requests",
"retry_after": 3600
}
Solutions:
-
Implement Exponential Backoff
let delay = 1000; for (let i = 0; i < maxRetries; i++) { try { return await makeRequest(); } catch (e) { await sleep(delay); delay *= 2; } } -
Request Rate Limit Increase
- Contact support
- Provide use case justification
-
Optimize API Usage
- Batch operations when possible
- Cache responses
- Use webhooks instead of polling
🔄 Webhook Issues #
Webhooks Not Triggering #
Symptoms:
- No webhook deliveries logged
- Events not being tracked
- Missing email statistics
Solutions:
-
Verify Webhook URL
curl -X POST https://your-domain.com/webhook \ -H "Content-Type: application/json" \ -d '{"test": true}' -
Check Provider Configuration
- SendGrid: Event Webhook settings
- Mailgun: Webhook configuration
- Ensure events selected
-
Review Webhook Logs
SELECT * FROM webhook_delivery_logs ORDER BY created_at DESC LIMIT 10;
Webhook Signature Validation Failed #
Error:
Webhook signature verification failed
Solutions:
-
Verify Secret Key
- Match provider's signing key
- Check for trailing spaces
- Ensure proper encoding
-
Debug Signature
$calculated = hash_hmac('sha256', $payload, $secret); $received = $_SERVER['HTTP_X_SIGNATURE']; Log::info('Signatures', compact('calculated', 'received'));
🎨 Template Issues #
Broken Email Layout #
Symptoms:
- CSS not rendering
- Images not showing
- Mobile display issues
Solutions:
-
Inline CSS
'inline_css' => true, // config/campaign.php -
Use Absolute URLs
<!-- Wrong --> <img src="/images/logo.png"> <!-- Correct --> <img src="https://domain.com/images/logo.png"> -
Test Email Clients
- Use Litmus or Email on Acid
- Check Gmail, Outlook, Apple Mail
- Verify mobile rendering
💾 Database Issues #
Migration Errors #
Error:
SQLSTATE[42S01]: Base table or view already exists
Solutions:
-
Reset Migrations
php artisan plugin:refresh Albrightlabs.Campaign -
Manual Cleanup
DROP TABLE IF EXISTS campaign_messages; DROP TABLE IF EXISTS campaign_subscribers; -- etc for all campaign tables -
Fresh Migration
php artisan october:migrate --force
Database Connection Timeout #
Symptoms:
- Slow page loads
- Random timeouts
- Connection pool exhausted
Solutions:
-
Optimize Queries
-- Add indexes ALTER TABLE campaign_subscribers ADD INDEX idx_email (email); ALTER TABLE campaign_messages_subscribers ADD INDEX idx_sent (sent_at); -
Increase Connection Pool
// config/database.php 'mysql' => [ 'max_connections' => 150, ]
📅 Message Schedule Issues #
Schedule Not Running #
Symptoms:
- Next run time passed but message not sent
- Schedule shows active but no sends occurring
Diagnosis:
-
Check Cron Job
crontab -l | grep artisan php artisan schedule:list -
Verify Schedule Status
$schedule = MessageSchedule::find($id); echo "Active: " . ($schedule->is_active ? 'Yes' : 'No'); echo "Next run: " . $schedule->next_run_at; echo "Runs: {$schedule->run_count}/{$schedule->max_runs}"; -
Check Message Status
SELECT * FROM campaign_messages WHERE id = X; -- Status should be 'scheduled' (code 7)
Solutions:
- Ensure cron job runs every minute
- Verify schedule
is_active = true - Check
max_runsnot exceeded - Confirm message status is 'scheduled'
Wrong Send Time #
Symptoms:
- Messages sent at incorrect hour
- Time off by several hours
Solutions:
- Verify schedule timezone matches desired timezone
- Check server timezone:
date - Account for Daylight Saving Time transitions
- Test with
php artisan campaign:runmanually
👤 Sender Profile Issues #
Profile Not in Dropdown #
Symptoms:
- Sender profile missing from selection
- Empty dropdown on message form
Solutions:
// Check profile exists for organization
$profiles = SenderProfile::where('organization_id', $orgId)->get();
if ($profiles->isEmpty()) {
// Create a profile first
}
Cannot Delete Profile #
Symptoms:
- Error when trying to delete sender profile
Cause: Profile is used in messages
Solution:
// Check usage
$messageCount = $profile->messages()->count();
if ($messageCount > 0) {
// Reassign messages to different profile first
// Or mark profile as inactive instead of deleting
}
✉️ Email Validation Issues #
Disposable Email False Positives #
Symptoms:
- Legitimate emails blocked as disposable
Solutions:
// Check disposable list
$checker = new DisposableEmailChecker();
$domains = $checker->getDisposableDomains();
// Whitelist specific domain
// Or disable disposable checking temporarily
Import Validation Failures #
Symptoms:
- CSV import rejecting valid emails
Solutions:
-
Check validation settings
// Disable strict validation temporarily config(['campaign.validation.check_mx_records' => false]); -
Review failed emails
tail -f storage/logs/campaign.log | grep validation -
Test individual email
$validator = new EmailValidator(); $result = $validator->validate('user@example.com'); print_r($result);
🔍 Debug Mode #
Enable Detailed Logging #
// config/campaign.php
'debug' => true,
'log_level' => 'debug',
Check Log Files #
# Campaign specific logs
tail -f storage/logs/campaign.log
# Laravel logs
tail -f storage/logs/laravel.log
# Mail logs
tail -f storage/logs/mail.log
Use Debug Commands #
# Test configuration
php artisan campaign:test-config
# Test SMTP
php artisan campaign:test-smtp
# Debug subscriber
php artisan campaign:debug-subscriber user@example.com
# Process queue manually
php artisan campaign:process-queue --verbose
📞 Getting Support #
Before Contacting Support #
-
Gather Information
- Error messages
- Log files
- Steps to reproduce
- System information
-
Try Common Fixes
- Clear cache
- Restart services
- Check documentation
-
Prepare Details
php artisan campaign:diagnostic > diagnostic.txt
Contact Methods #
- Email: support@albrightlabs.com
- Phone: (610) 756-5060
- Documentation: Check relevant guides
- Community: Forum and discussions
Information to Provide #
- October CMS version
- Campaign plugin version
- PHP version
- Error messages
- Recent changes
- Diagnostic output
Need more help? Contact support at support@albrightlabs.com