How to Track PHP mail() Logs via Sendmail/Exim for Duplicate Email Prevention


2 views

When our PHP configuration got reset during a server migration, a critical mass email campaign timed out after approximately 4,000 sends. Now we need to determine exactly which emails were successfully sent to avoid duplicate deliveries, but we're missing proper logging.

The PHP mail() function ultimately routes through sendmail (Exim in our case). While sendmail -bp shows some queued messages, it doesn't provide the comprehensive log we need. Here are better approaches:


# Check Exim's main log (common locations)
grep "mail()" /var/log/exim_mainlog
grep "PHP" /var/log/exim_rejectlog

# Alternative log locations
/var/log/exim4/mainlog
/var/log/maillog
/var/log/syslog | grep exim

To prevent this issue in future, implement logging directly in your PHP script:


function logged_mail($to, $subject, $message) {
    $log_entry = date('Y-m-d H:i:s') . " | TO: $to | SUBJECT: $subject\n";
    file_put_contents('/var/log/php_mail.log', $log_entry, FILE_APPEND);
    
    // Send the actual email
    return mail($to, $subject, $message);
}

If you're using WHM:

  1. Navigate to WHM > Service Configuration > Exim Configuration Manager
  2. Enable "Log Verbosity" to increase detail
  3. Check "Log File Path" for custom log locations

For large campaigns, consider this MySQL approach:


CREATE TABLE email_log (
    id INT AUTO_INCREMENT PRIMARY KEY,
    recipient VARCHAR(255) NOT NULL,
    subject TEXT,
    sent_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    status ENUM('queued','sent','failed') DEFAULT 'queued'
);

// PHP insertion example
$stmt = $pdo->prepare("INSERT INTO email_log (recipient, subject) VALUES (?, ?)");
foreach ($recipients as $email) {
    $stmt->execute([$email, $campaign_subject]);
    logged_mail($email, $campaign_subject, $message);
}

If logs aren't where expected:

  • Check Exim's config: exim -bP configure_file
  • Verify rsyslog config: grep -R "exim" /etc/rsyslog.*
  • Search all possible locations: find /var/log -name "*mail*" -o -name "*exim*"

When PHP's mail() function fails during bulk email operations, tracking successful deliveries becomes critical. The standard approach using sendmail -bp (which lists the mail queue) often proves insufficient because:

  • It only shows pending/queued messages, not already-sent ones
  • The output format isn't optimized for programmatic parsing
  • Historical data isn't preserved in the queue

Since you're using Exim as the MTA, these log locations typically contain delivery records:

/var/log/exim_mainlog
/var/log/exim_rejectlog
/var/log/maillog

For WHM/cPanel servers, try:

/usr/local/cpanel/logs/exim_mainlog
/var/cpanel/easy/apache/rawlog/exim_mainlog

This PHP script extracts successful deliveries from Exim logs:

<?php
function parseEximLogs($logPath, $originalRecipients) {
    $sentEmails = [];
    $handle = fopen($logPath, 'r');
    
    if ($handle) {
        while (($line = fgets($handle)) !== false) {
            if (strpos($line, '=>') !== false) {
                foreach ($originalRecipients as $email) {
                    if (strpos($line, $email) !== false) {
                        $sentEmails[] = $email;
                        break;
                    }
                }
            }
        }
        fclose($handle);
    }
    
    return array_unique($sentEmails);
}

// Usage example:
$originalList = ['user1@domain.com', 'user2@domain.com'];
$sentList = parseEximLogs('/var/log/exim_mainlog', $originalList);
$unsentList = array_diff($originalList, $sentList);

print_r($unsentList);
?>

For future mailings, implement a logging wrapper around mail():

function logged_mail($to, $subject, $message, $headers = '') {
    static $logFile = '/path/to/mail_delivery.log';
    
    $result = mail($to, $subject, $message, $headers);
    
    $logEntry = sprintf(
        "[%s] To: %s | Status: %s\n",
        date('Y-m-d H:i:s'),
        $to,
        $result ? 'SENT' : 'FAILED'
    );
    
    file_put_contents($logFile, $logEntry, FILE_APPEND);
    return $result;
}

In WHM, you can access email logs through:

  1. WHM > Home > Email > Track Delivery
  2. WHM > Home > Service Configuration > Exim Configuration Manager
  3. WHM > Home > Server Status > Mail Queue