Skip to content

Instantly share code, notes, and snippets.

@dullgiulio
Created March 24, 2011 21:13
Show Gist options
  • Save dullgiulio/885906 to your computer and use it in GitHub Desktop.
Save dullgiulio/885906 to your computer and use it in GitHub Desktop.
Trivial mailq output parser in PHP.
<?php
/**
* Simple example PHP code to parse "mailq" output. Useful if you want to show
* the mail queue status through some web service.
*
* Notice that you'll need a mail server (sendmail or, better, postfix) to be
* running on the same machine as your webserver (often that's less that
* optimal.)
*
* If this doesn't work, be sure to check that you have sufficient permissions
* to run mailq succesfully as your webserver user.
*
* - Giulio Iotti <[email protected]>
*/
$results = array();
$current_object = null;
// Get old locale to be later restored. XXX: Changing locale is not thread safe.
$old_locale = getlocale(LC_ALL);
// Set to use no locale.
setlocale(LC_ALL, 'C');
$pipe = popen($mailq_path, 'r');
while($pipe) {
$line = fgets($pipe);
if ($line === false)
break;
// First and last summary lines are the only ones beginning with a dash.
if (strncmp($line, '-', 1) === 0)
continue;
$line = trim();
// Append the current object to the objects list. No last-object problem,
// as we certainly have one empty line before the end.
if (!$line) {
if ($current_object) {
$results[] = $current_object;
$current_object = null;
}
}
// This could be much better so easily (eg: insert months, remove duplications, etc.)
$res = preg_match('/^([A-Z0-9]{1,20})\s+([1-9][0-9]*)\s+((Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s+[A-Za-z]{3}\s+[0-9]{2}\s+[0-9]{2}\:[0-9]{2}\:[0-9]{2})\s+([^ ]+)\s*$/', $line, $matches);
if ($res) {
// Insert message ID and other data into the object.
// It will be competed afterwards.
$current_object = array(
'id' => $matches[1],
'size' => intval($matches[2]),
'date' => strftime($matches[3]),
'sender' => $matches[5],
'failed' => false,
'recipients' => ''
);
} else {
// Parse error lines and recipients in lines following the message ID.
if ($current_object) {
if (strncmp($line, '(host ', 6) === 0) {
$current_object['failed'] = substr($line, 6, strlen($line)-7);
} else {
$current_object['recipients'] .= trim($line);
}
}
}
}
pclose($pipe);
setlocale(LC_ALL, $old_locale);
var_dump($results);
exit(1);
@ywarnier
Copy link

On a typical Linux server, can you automatically "get" the mailq path automatically? I guess you use /var/log/mail.log, right? (it is missing in your script)

@ywarnier
Copy link

Nevermind, it is not functional at all. I didn't get that from the title. Thanks for the concept though.

@fser
Copy link

fser commented Nov 15, 2014

Quoting mailq's manpage:

 The queue ID string is followed by an optional status character:
              *      The message is in the active queue, i.e. the message is selected for delivery.
              !      The message is in the hold queue, i.e. no further delivery attempt will  be  made until the mail is taken off hold.

You don't match those status flags :)

@rich9000
Copy link

rich9000 commented Feb 28, 2018

$mailq = explode("\n",trim(shell_exec("mailq")));

array_shift($mailq);
array_pop($mailq);

foreach ($mailq as $line){
	
	
	if(trim($line) == '') continue;
	
	$line = trim($line);

    // This could be much better so easily (eg: insert months, remove duplications, etc.)
    $res = preg_match('/^([A-Z0-9]{1,20})\s+([1-9][0-9]*)\s+((Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s+[A-Za-z]{3}\s+[0-9]{2}\s+[0-9]{2}\:[0-9]{2}\:[0-9]{2})\s+([^ ]+)\s*$/', $line, $matches);
    if ($res) {
        
        $id = $matches[1];
        $current_object = array(
                'id' => $matches[1],
                'size' => intval($matches[2]),
                'date' => strftime($matches[3]),
                'sender' => $matches[5],
                'failed' => false,
                'recipients' => ''
        );
    } else {
    	
        // Parse error lines and recipients in lines following the message ID.
        if ($current_object) {
                    	
        	if (strpos(">$line", '(')==1) {
        	//if (strncmp($line, '(host ', 6) === 0) {
                $current_object['failed'] = true;
                $current_object['error'] = $line;
            } else {
                $current_object['recipients'][] = $line;
            }
        }
    }
    
    $results[$id] = $current_object;

}
    
    var_dump($results);

@kepon85
Copy link

kepon85 commented Mar 21, 2023

Thank's for this script, it's ok for me :

> $mailq_path='/usr/bin/mailq';
$results = array();
$current_object = null;
...
<    $line = trim();
>    $line = trim($line);

@kepon85
Copy link

kepon85 commented Apr 12, 2023

Thank's
My adaptation :

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment