You've just installed postfix, badly, and emails to your users are not
being delivered, but rather deferred.
You are stuck in the meantime until you can figure out how to get the
email to deliver, and meanwhile you
have emails pending to be delivered to users. You'd rather not make them
wait.
*resurrection* to the rescue. I wrote this quickly as a band-aid, but my
config is still messed up and I'm
still using this tool to purge "deferred"s until I can get my config
rectified.
As written, you can use this from "cron" if you like!
The program takes no arguments. It scans the postfix queue looking for
reason=deferred, and (added today)
reason = User unknown in virtual alias table, and for each item found,
converts the queue item into a valid email
and appends it directly to the intended recipient's spool file. (Run
"resurrection" as root.)
If it cannot open the spool file, it instead appends the content to a
file SPOOL/username. You can hack the code
to put that directory where you like.
If the operation was successful, the spool file is moved out of
/var/spool/postfix to a directory STASH, similar to
SPOOL. This removes the item from the postfix queue.
===
Here the code is (php7.)
The postfix guys can carp at my stupidisms, fair game. Meanwhile, this
tool is helping save my ass.
If you want to use this, eyeball all the paths used to insure they match
use on your system.
*#!/usr/local/bin/php**
**<?php**
**// "resurrection" by Eric Dynamic, April 2019.**
**
**// items in STASH cannot be processed this way, as we must "postcat
-hb STASH/$QID" and do not know the recipient,**
**// we would have to get that from the "xpq" phase; the email can only
be for one person; and other possible missing values.**
**// (probably untrue: the source location differs, but -vq will return
the same information no matter where the file comes from.)**
**// postcat -vq gives recipient information (aliases translated.)
postcat -hbq does not dress the output and we'd have to map aliases.**
**
**$QENTRY = array();**
**exec("postqueue -j",$QENTRY);**
**if(!count($QENTRY)) return;**
**$line_number = 0;**
**foreach($QENTRY as $J) {**
** // one item in the postfix queue:**
** ++$line_number; $L = "($line_number)";**
** $QITEM = json_decode($J,TRUE);**
** if(!is_array($QITEM)) { echo "$L QITEM is not an array.\n";
return; }**
** if(!isset($QITEM)) { echo "$L no QITEM.\n"; continue; }**
** if(!isset($QITEM['queue_name'])) { echo "$L no qname.\n";
continue; }**
** if($QITEM['queue_name'] != 'deferred') continue;**
** if(!isset($QITEM['queue_id'])) { echo "$L no QID.\n"; continue; }**
** $QID = $QITEM['queue_id'];**
**
**// for each recip w/delay. decode msg once, send mult.**
**
** if(!isset($QITEM['recipients'])) { echo "$L no recipient
array.\n"; continue; }**
** $USER = array();**
** $uline_number = 0; $dunno = 1;**
** foreach( $QITEM['recipients'] as $RCP ) {**
** ++$uline_number; $U = "($uline_number)";**
**echo "\nobject $L$U\n";**
**var_dump($RCP);**
** if($dunno) { // we'll assume the reason is always given
with the first user**
** if(!isset($RCP['delay_reason'])) continue;**
** if(**
** !preg_match("/^temporary failure/",$RCP['delay_reason'])**
** && !preg_match("/^User unknown in virtual alias
table/",$RCP['delay_reason'])**
** ) continue;**
** // added 'unknown', note that this may deliver to a spool
file for a nonexistent user**
** // and you need to clean that up manually after this runs.**
** $dunno = 0;**
** }**
** // ['sender']=> 'bou...@mcsv.net'**
** if(!isset($RCP['address'])) continue;**
** $u = strtok($RCP['address'],'@');**
** if(!$u) continue;**
** echo "$L$U user $u.\n";**
** $USER[] = $u;**
** }**
** if(!count($USER)) { echo "$L no users for a temporary failure or
unknown alias.\n"; continue; }**
**
** echo "postcat -hbq $QID\n";**
** $fd = popen("postcat -vq $QID","r");**
** if(!$fd) { echo "$L no QF results.\n"; continue; }**
**////////////////////////////////////////////**
**// xpq**
**////////////////////////////////////////////**
** $recipient = $from = $date = $BODY = ''; $token = array();**
** while( $line = fgets($fd) ) {**
** $line = rtrim($line);**
**//echo "line\t".substr($line,0,13)." = $line\n";**
** if( substr($line,0,10) == "recipient:" ) { $recipient =
substr($line,11); continue; }**
** if( substr($line,0,13) != "regular_text:" ) continue;**
** $line = substr($line,14);**
**//echo "frag\t\t".substr($line,0,6)."\n";**
** if(substr($line,0,6) == "Date: ") $date = substr($line,6);**
** else if(substr($line,0,6) == "From: ") $from = substr($line,6);**
** $BODY .= "$line\n"; // actually, this contains the headers too**
** }**
** fclose($fd);**
** if(!$recipient || !$from || !$date) { fprintf(STDERR,"missing
recipient($recipient), from($from) or date($date).\n"); continue; }**
**
** //regular_text: Date: 11 Apr 2019 19:02:05 -0000**
** //regular_text: From: "Reader Supported News"
<do-not-re...@inbound.readersupportednews.org>**
** //From e...@transbay.net Sun Apr 7 15:11:13 2013**
**
**if(preg_match("/<(.*)>/",$from,$token)) $from = $token[1]; else { $j =
strpos($from,' '); if($j) $from = substr($from,0,$j); }**
**
** // we have to recreate the leading "^From " line to make mail
programs happy**
** if(!preg_match("/([ 0-9][0-9]) ([ADFJMNOS][a-z][a-z])
(2[01][0-9][0-9]) ([0-9]{2}:[0-9]{2}:[0-9]{2})/",$date,$token))**
** { fprintf(STDERR,"bad date format.\n"); return; }**
** $date = $token[2].' '.$token[1].' '.$token[3].' '.$token[4];**
** $DOW = date_parse_from_format("M j H:i:s
Y",$date); // format expected**
** $DOW =
date('D',mktime(0,0,0,$DOW['month'],$DOW['day'],$DOW['year']));**
** $date = "$DOW $date";***// all that to get the day of the week***
** $EMAIL = "From $from
$date\n$BODY\n"; // add a blank line
in case mail programs need it**
**////////////////////////////////////////////**
** // do xpq here into outfile $SPOOLFILE. once satisfied this works
we will append to user's real spool file**
** foreach($USER as $u) {**
** $u = strtolower($u);**
** //$F = "/usr/local/etc/postfix/SPOOL/$u";**
** $F = "/var/mail/$u";**
** $fp = fopen($F,"a"); if(!$fp) {**
** echo "$L can't open $F for $QID output to $u. Fallback to
SPOOL.\n";**
** $F = "/usr/local/etc/postfix/SPOOL/$u";**
** $fp = fopen($F,"a"); if(!$fp) { echo "$L can't open $F for
$QID output to $u.\n"; continue; }**
** }**
** flock($fp,LOCK_EX);**
**fprintf($fp,"\n%s",$EMAIL); // a leading blank too to be paranoid**
** flock($fp,LOCK_UN);**
** fclose($fp);**
** }**
**////////////////////////////////////////////**
** // if we were happy, move the spool file out of postfix space**
** $Q0 = substr($QID,0,1);**
** $F = "/var/spool/postfix/deferred/$Q0/$QID";**
** $S = "/usr/local/etc/postfix/STASH/$QID";**
** @unlink($S);**
** rename($F,$S); // assuming postfix does not record the existence
of the file thus needing to be told this was done**
**////////////////////////////////////////////**
** }**
**?>**
*