You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHPMailer批量发送邮件时服务器卡顿问题求助

Hey there! Let's figure out why your bulk email sender is grinding to a halt after around 100 messages and get it running smoothly for all 6000 recipients.

Problem Diagnosis & Fixes

The server choking without PHP errors is almost always due to gradual resource exhaustion rather than a single crash. Here's what's likely going wrong, and how to fix it:

Core Causes to Blame

  • Resource Leaks: If you're creating a new PHPMailer instance or database connection inside every loop iteration, those unused objects pile up in memory over time, eventually draining server resources.
  • Unclosed SMTP Connections: Each email send might leave an SMTP connection hanging in a TIME_WAIT state, eating up system ports until there are none left for new connections.
  • Memory Bloat: Loading all 6000 email addresses into memory at once can strain PHP's memory limits, even if it doesn't trigger an immediate error.

Step-by-Step Fixes

1. Reuse Connections & Objects (Don't Recreate Them)

The biggest mistake is initializing PHPMailer and database connections inside your loop. Instead, set them up once, then reset only the variable parts (like recipients) each time:

// Initialize database connection ONCE before the loop
$db = new mysqli('your-db-host', 'user', 'password', 'db-name');
if ($db->connect_error) {
    die("DB Connection Failed: " . $db->connect_error);
}

// Initialize PHPMailer ONCE before the loop
require 'PHPMailerAutoload.php';
$mail = new PHPMailer;
$mail->isSMTP();
$mail->Host = 'your-smtp-host';
$mail->SMTPAuth = true;
$mail->Username = 'your-email@domain.com';
$mail->Password = 'your-smtp-password';
$mail->SMTPSecure = 'tls'; // or ssl if needed
$mail->Port = 587;
$mail->setFrom('sender@domain.com', 'Your Brand');

// Fetch recipients in batches (instead of all at once)
$batchSize = 50;
$offset = 0;

while (true) {
    // Get a small batch of emails to avoid memory overload
    $result = $db->query("SELECT email FROM your-recipients-table LIMIT $batchSize OFFSET $offset");
    if ($result->num_rows === 0) break; // Exit loop when no more emails

    while ($row = $result->fetch_assoc()) {
        // Reset only the dynamic parts for each email
        $mail->clearAddresses();
        $mail->addAddress($row['email']);
        $mail->Subject = 'Your Custom Subject';
        $mail->Body = 'Your Email Content Goes Here';

        // Send and log results
        if (!$mail->send()) {
            error_log("Failed to send to {$row['email']}: " . $mail->ErrorInfo);
        } else {
            error_log("Successfully sent to {$row['email']}");
        }

        // Add your delay
        sleep(20);
    }

    // Free up memory from the current batch
    $result->free();
    $offset += $batchSize;
}

// Clean up resources when done
$db->close();
$mail->smtpClose(); // Properly close the SMTP connection

2. Tweak System & PHP Resource Limits

  • Increase PHP Memory: Add this at the top of your script to give PHP more breathing room:
    ini_set('memory_limit', '256M'); // Adjust based on your server's capacity
    
  • Raise Open File Limits: CentOS defaults might restrict the number of open connections. Run ulimit -n to check (default is often 1024). Temporarily raise it with ulimit -n 4096, or set it permanently by editing /etc/security/limits.conf:
    * soft nofile 4096
    * hard nofile 8192
    

3. Add Memory Monitoring

To confirm resource leaks, add a log line inside your loop to track memory usage:

error_log("Current Memory Usage: " . memory_get_usage(true) . " bytes");

If you see the number climbing steadily, you know there's a leak to track down (like unused variables not being cleared). You can force garbage collection with gc_collect_cycles() if needed, but fixing the object reuse is a better long-term fix.

4. Split the Job with Cron (Optional)

For extra reliability, split the 6000 emails into smaller chunks and use a cron job to run them at intervals. For example, create a script that sends 50 emails, then set cron to run it every 20 minutes. This avoids having a single PHP process running for hours straight.


内容的提问来源于stack exchange,提问作者Charith Prabhagya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:34:31