############################################################################### # Copyright (C) 2006-2025 Jonathan Michaelson # # https://github.com/waytotheweb/scripts # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program; if not, see . ############################################################################### ## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) package ConfigServer::cmqUI; use strict; use Sys::Hostname qw(hostname); use IPC::Open3; use Fcntl qw(:DEFAULT :flock); use Storable(); our ($images, $myv, $script, %FORM, %queue, $expcnt, %cookie, $downloadserver, $script_da, @config, $eximmainlog, $localdomains); # ############################################################################### # start displayUI sub displayUI { my $formref = shift; $script = shift; $script_da = shift; $images = shift; $myv = shift; my $sessioncode = shift; %FORM = %{$formref}; $downloadserver = &getdownloadserver; $eximmainlog = "/var/log/exim_mainlog"; $localdomains = "/etc/localdomains"; if (-e "/usr/local/directadmin/directadmin") { $eximmainlog = "/var/log/exim/mainlog"; $localdomains = "/etc/virtual/domains"; } my $config = ""; my $viewqueue = "Delivery Queue"; if (-e "/usr/msfe/mailscannerq") { if ($FORM{config} !~ /^exim/) { $config = "-qGmailscanner"; push @config, "-qGmailscanner"; $viewqueue = "MailScanner Queue"; } else { $viewqueue = "Delivery Queue"; } } elsif (-e "/etc/exim_outgoing.conf") { if ($FORM{config} !~ /^exim/) { $config = "-C /etc/exim_outgoing.conf"; push @config, "-C", "/etc/exim_outgoing.conf"; $viewqueue = "Delivery Queue"; } else { $viewqueue = "MailScanner Queue"; } } if ($FORM{refresh} == 1 and -e "/etc/cmq/cmqstore") { unlink "/etc/cmq/cmqstore"; } if ($FORM{id} ne "" and $FORM{id} =~ /[^\w\-]/) { print "Invalid email ID [$FORM{id}]"; } elsif ($FORM{bcc} ne "" and $FORM{bcc} =~ /[^a-zA-Z0-9\-\_\.\@\+]/) { print "Invalid email address [$FORM{bcc}]"; } elsif (($FORM{action} eq "View Emails") or ($FORM{action} eq "Delete Emails")) { my $formurl = "?age=$FORM{age}&action=$FORM{action}&subject=$FORM{subject}&links=$FORM{links}&unit=$FORM{unit}&bounce=$FORM{bounce}&frozen=$FORM{frozen}&bool=$FORM{bool}&queue=$FORM{queue}&field=$FORM{field}&config=$FORM{config}&searchtype=$FORM{searchtype}&also=$FORM{also}&text=$FORM{text}&search=$FORM{search}&dir=$FORM{dir}"; if (defined $FORM{page}) {$formurl .= "&page=$FORM{page}"} if (defined $FORM{refresh}) {$formurl .= "&refresh=$FORM{refresh}"} if ($FORM{queue} eq "in") { print "

$viewqueue (Incoming) - $FORM{action}

\n"; } elsif ($FORM{queue} eq "out") { print "

$viewqueue (Outgoing) - $FORM{action}

\n"; } else { print "

$viewqueue - $FORM{action}

\n"; } if ($FORM{page} eq "") {$FORM{page} = 0} if ($FORM{refresh} == 2) {undef $FORM{page}} &getqueue("storable"); open (my $IN, "<",$localdomains); flock ($IN, LOCK_SH); my @confdata = <$IN>; close ($IN); chomp @confdata; $expcnt = 0; my %ldomains; my $total = 0; my $divcnt = 0; foreach my $line (@confdata) {$ldomains{$line} = 1} my @messages; foreach my $key (sort {$queue{$b}{epoch} <=> $queue{$a}{epoch}} keys %queue) { my $show = 0; if ($FORM{queue} ne "inout") { foreach my $address (split(/\,/,$queue{$key}{to})) { my (undef,$domain) = split(/\@/,$address); if (($ldomains{$domain}) and ($FORM{queue} eq "in")) { $show = 1; last; } if (($ldomains{$domain}) and ($FORM{queue} eq "out")) { $show = 0; last; } elsif ((!$ldomains{$domain}) and ($FORM{queue} eq "out")) { $show = 1; last; } } } else {$show = 1} if ($show) { if ($FORM{also}) { if (!$FORM{frozen} and $queue{$key}{frozen} eq "*") {$show = 0} if (!$FORM{bounce} and $queue{$key}{bounce} eq "*") {$show = 0} } else { $show = 0; if ($FORM{frozen} and $queue{$key}{frozen} eq "*") {$show = 1} if ($FORM{bounce} and $queue{$key}{bounce} eq "*") {$show = 1} } if ($FORM{older} and $show) { my $mins = 0; if ($queue{$key}{time} =~ /(\d+)(\w)/) { if ($2 eq "m") {$mins = $1} if ($2 eq "h") {$mins = $1 * 60} if ($2 eq "d") {$mins = $1 * 60 * 24} } my $age = $FORM{age}; if ($FORM{unit} eq "hours") {$age = $age * 60} if ($FORM{unit} eq "days") {$age = $age * 60 * 24} if ($mins > $age) {$show = 1} else {$show = 0} } if ($FORM{search} and $show) { $show = 0; if (($FORM{field} eq "from") and ($FORM{searchtype} eq "contain") and ($FORM{bool}) and ($queue{$key}{from} =~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{field} eq "from") and ($FORM{searchtype} eq "contain") and (!$FORM{bool}) and ($queue{$key}{from} !~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{field} eq "from") and ($FORM{searchtype} eq "begin with") and ($FORM{bool}) and ($queue{$key}{from} =~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{field} eq "from") and ($FORM{searchtype} eq "begin with") and (!$FORM{bool}) and ($queue{$key}{from} !~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{field} eq "from") and ($FORM{searchtype} eq "end with") and ($FORM{bool}) and ($queue{$key}{from} =~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{field} eq "from") and ($FORM{searchtype} eq "end with") and (!$FORM{bool}) and ($queue{$key}{from} !~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{field} eq "from") and ($FORM{searchtype} eq "equal") and ($FORM{bool}) and ($queue{$key}{from} eq $FORM{text})) {$show = 1} elsif (($FORM{field} eq "from") and ($FORM{searchtype} eq "equal") and (!$FORM{bool}) and ($queue{$key}{from} ne $FORM{text})) {$show = 1} if (($FORM{field} eq "ID") and ($FORM{searchtype} eq "contain") and ($FORM{bool}) and ($key =~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{field} eq "ID") and ($FORM{searchtype} eq "contain") and (!$FORM{bool}) and ($key !~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{field} eq "ID") and ($FORM{searchtype} eq "begin with") and ($FORM{bool}) and ($key =~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{field} eq "ID") and ($FORM{searchtype} eq "begin with") and (!$FORM{bool}) and ($key !~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{field} eq "ID") and ($FORM{searchtype} eq "end with") and ($FORM{bool}) and ($key =~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{field} eq "ID") and ($FORM{searchtype} eq "end with") and (!$FORM{bool}) and ($key !~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{field} eq "ID") and ($FORM{searchtype} eq "equal") and ($FORM{bool}) and ($key eq $FORM{text})) {$show = 1} elsif (($FORM{field} eq "ID") and ($FORM{searchtype} eq "equal") and (!$FORM{bool}) and ($key ne $FORM{text})) {$show = 1} if ($FORM{field} eq "to") { foreach my $address (split(/\,/,$queue{$key}{to})) { $address =~ s/D //g; $address =~ s/\+D //g; if (($FORM{searchtype} eq "contain") and ($FORM{bool}) and ($address =~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "contain") and (!$FORM{bool}) and ($address !~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "begin with") and ($FORM{bool}) and ($address =~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "begin with") and (!$FORM{bool}) and ($address !~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "end with") and ($FORM{bool}) and ($address =~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{searchtype} eq "end with") and (!$FORM{bool}) and ($address !~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{searchtype} eq "equal") and ($FORM{bool}) and ($address eq $FORM{text})) {$show = 1} elsif (($FORM{searchtype} eq "equal") and (!$FORM{bool}) and ($address ne $FORM{text})) {$show = 1} if ($show) {last} } } if ($FORM{field} eq "subject") { my $subject = ""; my ($childin, $childout); my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mvh", $key); my @data = <$childout>; waitpid ($cmdpid, 0); chomp @data; foreach my $line (@data) { my (undef,$field,$value) = split(/\s+/,$line,3); if ($field =~ /subject:/i) {$subject = $value;} } if (($FORM{searchtype} eq "contain") and ($FORM{bool}) and ($subject =~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "contain") and (!$FORM{bool}) and ($subject !~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "begin with") and ($FORM{bool}) and ($subject =~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "begin with") and (!$FORM{bool}) and ($subject !~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "end with") and ($FORM{bool}) and ($subject =~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{searchtype} eq "end with") and (!$FORM{bool}) and ($subject !~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{searchtype} eq "equal") and ($FORM{bool}) and ($subject eq $FORM{text})) {$show = 1} elsif (($FORM{searchtype} eq "equal") and (!$FORM{bool}) and ($subject ne $FORM{text})) {$show = 1} } if ($FORM{field} eq "header") { my ($childin, $childout); my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mvh", $key); my @data = <$childout>; waitpid ($cmdpid, 0); chomp @data; my $header = join("\n",@data); if (($FORM{searchtype} eq "contain") and ($FORM{bool}) and ($header =~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "contain") and (!$FORM{bool}) and ($header !~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "begin with") and ($FORM{bool}) and ($header =~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "begin with") and (!$FORM{bool}) and ($header !~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "end with") and ($FORM{bool}) and ($header =~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{searchtype} eq "end with") and (!$FORM{bool}) and ($header !~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{searchtype} eq "equal") and ($FORM{bool}) and ($header eq $FORM{text})) {$show = 1} elsif (($FORM{searchtype} eq "equal") and (!$FORM{bool}) and ($header ne $FORM{text})) {$show = 1} } if ($FORM{field} eq "body") { my ($childin, $childout); my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mvb", $key); my @data = <$childout>; waitpid ($cmdpid, 0); chomp @data; my $body = join("\n",@data); if (($FORM{searchtype} eq "contain") and ($FORM{bool}) and ($body =~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "contain") and (!$FORM{bool}) and ($body !~ /$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "begin with") and ($FORM{bool}) and ($body =~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "begin with") and (!$FORM{bool}) and ($body !~ /^$FORM{text}/i)) {$show = 1} elsif (($FORM{searchtype} eq "end with") and ($FORM{bool}) and ($body =~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{searchtype} eq "end with") and (!$FORM{bool}) and ($body !~ /$FORM{text}$/i)) {$show = 1} elsif (($FORM{searchtype} eq "equal") and ($FORM{bool}) and ($body eq $FORM{text})) {$show = 1} elsif (($FORM{searchtype} eq "equal") and (!$FORM{bool}) and ($body ne $FORM{text})) {$show = 1} } } } if ($show) {push @messages, $key} } if ($FORM{dir} eq "d") {@messages = reverse @messages} my $pagination = ""; my $offsetrows = 50; my $gtotal = scalar(@messages); $formurl = "?age=$FORM{age}&action=$FORM{action}&subject=$FORM{subject}&links=$FORM{links}&unit=$FORM{unit}&bounce=$FORM{bounce}&frozen=$FORM{frozen}&bool=$FORM{bool}&queue=$FORM{queue}&field=$FORM{field}&config=$FORM{config}&searchtype=$FORM{searchtype}&also=$FORM{also}&text=$FORM{text}&search=$FORM{search}&dir=$FORM{dir}"; if ($FORM{action} eq "View Emails" and defined $FORM{page}) { my $from = 0; my $to = $offsetrows - 1; my $offset = $FORM{page}; $from = ($offset) * $offsetrows; $to = (($offset) * $offsetrows) + $offsetrows - 1; if ($to > $gtotal) {$to = $gtotal} @messages = @messages[$from..$to]; my $pages = int( ($gtotal - 1) / $offsetrows); my $start = 0; my $end = 9; if ($pages < 10) {$end = $pages} if ($pages >= 10) { $start = $offset - 4; $end = $offset + 4; } if ($end < 8) {$end = 8} if ($start < 0) {$start = 0} if ($end > $pages) {$end = $pages} $pagination .= "\n"; } if ($FORM{action} eq "View Emails") { print "\n\n"; print "\n"; print "
\n"; # if ($expcnt > 0) { # print "

Expand All\n"; # print " Collapse All

\n"; # } if (defined($FORM{page})) { print "

\n"; print " Refresh Queue Cache \n"; if ($gtotal > $offsetrows) { print " No Pagination\n"; } print "

\n"; print $pagination; } print "\n"; my $formurl = "?age=$FORM{age}&action=$FORM{action}&subject=$FORM{subject}&links=$FORM{links}&unit=$FORM{unit}&bounce=$FORM{bounce}&frozen=$FORM{frozen}&bool=$FORM{bool}&queue=$FORM{queue}&field=$FORM{field}&config=$FORM{config}&searchtype=$FORM{searchtype}&also=$FORM{also}&text=$FORM{text}&search=$FORM{search}"; my $age = ""; if ($FORM{dir} eq "d") {$age = ""} print ""; if ($FORM{subject}) {print ""} print ""; } else { print "
Email ID Age $ageSizeFromToSubject
\n"; print "\n"; } foreach my $key (@messages) { if ($key eq "" or $key eq "0") {next} if (($queue{$key}{time} eq "") or ($queue{$key}{size} eq "")) { if ($FORM{action} eq "View Emails") { print "\n"; print "\n"; } else { print "\n"; print "\n"; } my ($childin, $childout); my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mrm", $key); my @data = <$childout>; waitpid ($cmdpid, 0); next; } if ($FORM{action} eq "View Emails") { my $to = $queue{$key}{to}; if ($to =~ /\,/) { $divcnt++; my @tos = split(/\,/,$to); $to = "$tos[0]\n\n\n"; for (my $x = 1;$x < @tos;$x++) { $to .= "$tos[$x]
\n"; } $to .= "
\n"; } my $frozen; if ($queue{$key}{frozen} eq "*") {$frozen = ""} print "\n"; } else { print "$key $frozen\n"; } print "\n"; } else { print "\n"; } print ""; if ($FORM{subject}) { my $subject = "[no subject/subject not found]"; my ($childin, $childout); my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mvh", $key); my @data = <$childout>; waitpid ($cmdpid, 0); chomp @data; foreach my $line (@data) { my (undef,$field,$value) = split(/\s+/,$line,3); if ($field =~ /subject:/i) {$subject = $value;} } $subject =~ s/>/>/g; $subject =~ s/$subject"; } print "\n"; } elsif ($FORM{action} eq "Delete Emails") { my $cnt = $total + 1; print "\n"; print "\n"; } $total++; } my $span = 7; if ($FORM{subject}) {$span = 8} if ($total == 0) { print "\n"; } elsif ($FORM{action} eq "View Emails") { print ""; if ($FORM{subject}) {print ""} print ""; print "\n"; } print "
 Email IDResponse
 $keyBroken spool file - removed
$keyBroken spool file - removed
".(($total+1) + $FORM{page}*$offsetrows)."\n"; if ($FORM{links}) { print "$key $frozen\n"; if ($FORM{links}) { print " \n"; } else { print " \n"; } if ($FORM{links}) { print " \n"; } else { print " \n"; } if ($FORM{links}) { print "$queue{$key}{time}$queue{$key}{size}$queue{$key}{from}$to
$cnt$key"; my ($childin, $childout); my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mrm", $key); my @data = <$childout>; waitpid ($cmdpid, 0); chomp @data; print $data[-1]; print "
No matching queue entries found
Email ID AgeSizeFromToSubject
\n"; print "\n"; &confirmmodal("do", "Delete Selected", "Are you sure you want to delete these emails?"); print "|
\n"; if ($FORM{action} eq "View Emails") {print $pagination} print "

\n"; print "

\n"; print "\n"; print "\n"; } elsif ($FORM{action} eq "view") { print "
\n"; print "
Headers spool file
\n"; print "
";
		my ($childin, $childout);
		my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mvh", $FORM{id});
		my @data = <$childout>;
		waitpid ($cmdpid, 0);
		chomp @data;
		foreach my $line (@data) {
			$line =~ s/>/>/g;
			$line =~ s/
\n"; print "
\n"; print "
\n"; print "
Data spool file
\n"; print "
";
		$cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mvb", $FORM{id});
		@data = <$childout>;
		waitpid ($cmdpid, 0);
		chomp @data;
		foreach my $line (@data) {
			$line =~ s/>/>/g;
			$line =~ s/
\n"; print "
\n"; } elsif ($FORM{action} eq "viewdelivery") { print "\n"; print "\n"; print "\n"; print "
Delivery Log (Where available - Can take some time depending on the size of the $eximmainlog)
";
		my ($childin, $childout);
		my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exigrep", $FORM{id}, "$eximmainlog");
		my @data = <$childout>;
		waitpid ($cmdpid, 0);
		chomp @data;
		foreach my $line (@data) {
			$line =~ s/>/>/g;
			$line =~ s/
\n"; } elsif ($FORM{action} eq "deliver") { print "\n"; print "\n"; print "\n"; print "
Deliver Email
";
		my ($childin, $childout);
		my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-v", "-M", $FORM{id});
		my @data = <$childout>;
		waitpid ($cmdpid, 0);
		chomp @data;
		foreach my $line (@data) {
			$line =~ s/>/>/g;
			$line =~ s/
\n"; } elsif ($FORM{action} eq "delete") { print "\n"; print "\n"; print "\n"; print "
Delete Email
";
		my ($childin, $childout);
		my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-v", "-Mrm", $FORM{id});
		my @data = <$childout>;
		waitpid ($cmdpid, 0);
		chomp @data;
		foreach my $line (@data) {
			$line =~ s/>/>/g;
			$line =~ s/
\n"; } elsif ($FORM{action} eq "mass") { my $total = 0; my $class = "tdshade2_noborder"; if ($FORM{do} ne "Bcc to:") { print "

Delete Selected

\n"; } else { print "

Bcc Selected to $FORM{bcc}

\n"; } print "\n"; print "\n"; foreach my $key (keys %FORM) { my $id = 0; if ($key =~ /^del_(.*)/) {$id = $1} unless ($id) {next} print "\n"; print "\n"; $total++; if ($class eq "tdshade2_noborder") {$class = "tdshade1_noborder"} else {$class = "tdshade2_noborder"} } print "
Email IDResponse
$id"; my $data; if ($FORM{do} eq "Bcc to:") { my ($childin, $childout); my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mar", $id, $FORM{bcc}); my @data = <$childout>; waitpid ($cmdpid, 0); chomp @data; print $data[-1]; $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mc", $id); @data = <$childout>; waitpid ($cmdpid, 0); chomp @data; print $data[-1]; } else { my ($childin, $childout); my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mrm", $id); my @data = <$childout>; waitpid ($cmdpid, 0); chomp @data; print $data[-1]; } print "
\n"; print "

Total emails: $total

\n"; print "

\n"; } elsif ($FORM{action} eq "Queue Run") { my @cmd; my $flags; if ($config =~ /mailscanner/) {undef @config} if ($FORM{text} ne "" and $FORM{text} =~ /[^a-zA-Z0-9\-\_\.\@\+]/) { print "Invalid data [$FORM{text}]"; } else { if ($FORM{force}) {$flags = "f"} if ($FORM{frozen}) {$flags = "ff"} if ($FORM{search}) { if ($FORM{field} eq "to") { push @cmd, "-R$flags", $FORM{text}; } else { push @cmd, "-S$flags", $FORM{text}; } } else { push @cmd, "-q$flags"; } print "
\n"; print "
Queue Run
\n"; print "
";
			my ($childin, $childout);
			my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-v", @cmd);
			my @data = <$childout>;
			waitpid ($cmdpid, 0);
			chomp @data;
			foreach my $line (@data) {
				$line =~ s/>/>/g;
				$line =~ s/
\n"; print "
\n"; } print "

\n"; } elsif ($FORM{action} eq "Exigrep") { my $cmd; my $flags; if ($FORM{text} eq "") { print "Empty regex"; } else { print "
\n"; print "
Exigrep for $FORM{text}
\n"; print "
";
			my ($childin, $childout);
			my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exigrep", $FORM{text}, "$eximmainlog");
			my @data = <$childout>;
			waitpid ($cmdpid, 0);
			chomp @data;
			foreach my $line (@data) {
				$line =~ s/>/>/g;
				$line =~ s/
\n"; print "
\n"; } print "

\n"; } elsif ($FORM{action} eq "upgrade") { $| = 1; ## no critic print "Retrieving new cmq package...\n"; print "
";
		&printcmd("rm -Rfv /usr/src/cmq* ; cd /usr/src ; wget -q https://$downloadserver/cmq.tgz 2>&1");
		print "
"; if (! -z "/usr/src/cmq.tgz") { print "Unpacking new cmq package...\n"; print "
";
			&printcmd("cd /usr/src ; tar -xzf cmq.tgz ; cd cmq ; sh install.sh 2>&1");
			print "
"; print "Tidying up...\n"; print "
";
			&printcmd("rm -Rfv /usr/src/cmq*");
			print "
"; print "...All done.\n"; } open (my $IN, "<", "/etc/cmq/cmqversion.txt") or die $!; $myv = <$IN>; close ($IN); chomp $myv; print "

\n"; } else { if (-e "/etc/cmq/cmqstore") {unlink "/etc/cmq/cmqstore"} my ($childin, $childout); my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-bpc"); my @output = <$childout>; waitpid ($cmdpid, 0); chomp @output; unless ($output[0]) {$output[0] = 0} my @eximoutput; if ($config) { my ($childin, $childout); my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", "-bpc"); @eximoutput = <$childout>; waitpid ($cmdpid, 0); chomp @eximoutput; unless ($eximoutput[0]) {$eximoutput[0] = 0} } if ($config =~ /mailscanner/) { my @tmp = @eximoutput; @eximoutput = @output; @output = @tmp; } print "
\n"; print "\n"; print ""; if ($config =~ /mailscanner/) { print "\n"; if ($config) { print "\n"; } } elsif ($config =~ /exim/) { print "\n"; if ($config) { print "\n"; } } else { print "\n"; } print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
Mail Queue Queries
Delivery Queue ($output[0] emails)Default queue - email waiting for delivery
MailScanner Queue ($eximoutput[0] emails)Email awaiting processing by MailScanner
Delivery Queue ($output[0] emails)Default queue - email waiting for delivery
MailScanner Queue ($eximoutput[0] emails)Email awaiting processing by MailScanner
Delivery Queue ($output[0] emails)Default queue - email waiting for delivery
All EmailsSelect all email that has been queued
Incoming Emails (may contain outgoing Forwarders)Select incoming email that has been queued
Outgoing EmailsSelect outgoing email that has been queued
Frozen EmailsSelect all frozen email that has been queued
Bounce EmailsSelect all bounce email that has been queued
All Other EmailsSelect all other email that has been queued
Display Email Subject when viewing emailsThis will add load and extend the time it takes to perform the task
Launch links in new windowThis will open links in a new window/tab instead of a modal in View Emails
Emails older than Select email that has been queued by age
Select email that has been queued with specified text
\n"; print " \n"; print "
\n"; &confirmmodal("action", "Delete Emails", "Are you sure you want to delete these emails?"); print "
\n"; print "
\n"; print "\n"; print ""; print "\n"; print "\n"; print "\n"; print "
Exigrep
Perform a pattern match search of $eximmainlog
Regular ExpressionUses exigrep to search $eximmainlog
\n"; print "
\n"; print "\n"; print ""; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
Mail Queue Runs
Performs an exim queue run. These runs can take a long time to complete, so you need to be patient and careful not to spawn multiple queue runs by initiating these options until previous runs have completed.
Force runIgnores retry times for all relevant emails
Frozen Emails (implies Force run)Forces all emails including frozen emails to be retried
contains Selects email based on sender or recipient address text
\n"; my ($status, $text) = &urlget("https://$downloadserver/cmq/cmqversion.txt"); my $actv = $text; my $up = 0; print "\n"; print ""; if ($actv ne "") { if ($actv =~ /^[\d\.]*$/) { if ($actv > $myv) { print "\n"; } else { print "\n"; } $up = 1; } } unless ($up) { print "\n"; } print "
Upgrade
A new version of cmq (v$actv) is available. View ChangeLog
You appear to be running the latest version of cmq
Failed to determine the latest version of cmq: [$status] [$text]
\n"; } print "
cmq: v$myv
"; print "

©2006-2019, ConfigServer Services (Jonathan Michaelson)

\n"; return; } # end displayUI ############################################################################### # start getqueue sub getqueue { my $storable = shift; if ($storable eq "storable" and -e "/etc/cmq/cmqstore") { %queue = %{Storable::retrieve("/etc/cmq/cmqstore")}; return; } my $pos = 0; my $id = 0; my $count = 0; my $queuecnt = 0; my $per = 0; my $oldper = 0; my ($childin, $childout); my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-bpra"); # my $cmdpid = open3($childin, $childout, $childout, "cat /root/tmp/q.txt"); while (my $line = <$childout>) { chomp $line; if ($line eq "") { $queue{$id}{to} =~ s/,$//; if ($queue{$id}{to} =~ /\,/) {$expcnt++} $count++; $pos = 0; $id = 0; next; } if ($pos == 0) { ## if ($line =~ /^\s*(\w+)\s+(\S*)\s+(\w{6}-\w{6}-\w{2})\s+(<.*?>)/) { if ($line =~ /^\s*(\w+)\s+(\S*)\s+(\S+)\s+(<.*?>)/) { my $time = $1; my $size = $2; $id = $3; my $from = $4; if ($from eq "<>") {$from = "[bounce]"; $queue{$id}{bounce} = "*"} $from =~ s/\<|\>//g; my $epoch = time; if ($time =~ /(\d+)(\w)/) { if ($2 eq "m") {$epoch -= $1 * 60} elsif ($2 eq "h") {$epoch -= $1 * 60 * 60} elsif ($2 eq "d") {$epoch -= $1 * 60 * 60 * 24} } $queue{$id}{epoch} = $epoch; $queue{$id}{from} = $from; $queue{$id}{time} = $time; $queue{$id}{size} = $size; $queuecnt++; if ($line =~ /\*\*\* frozen \*\*\*$/) {$queue{$id}{frozen} = "*"} } } else { $queue{$id}{to} .= "$line,"; } $pos++; } waitpid ($cmdpid, 0); if ($storable eq "storable") { Storable::nstore(\%queue, "/etc/cmq/cmqstore"); chmod(0600,"/etc/cmq/cmqstore"); } return; } # end getqueue ############################################################################### # start confirmmodal # print "\n"; # &confirmmodal("submit_name", "submit_value", "display text"); sub confirmmodal { my $name = shift; my $value = shift; my $text = shift; print "\n"; print "\n"; return; } # end confirmmodal ############################################################################### # start urlget (v1.3) sub urlget { my $url = shift; my $file = shift; my $status = 0; my $timeout = 1200; local $SIG{PIPE} = 'IGNORE'; use LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(30); my $req = HTTP::Request->new(GET => $url); my $res; my $text; ($status, $text) = eval { local $SIG{__DIE__} = undef; local $SIG{'ALRM'} = sub {die "Download timeout after $timeout seconds"}; alarm($timeout); if ($file) { $|=1; ## no critic my $expected_length; my $bytes_received = 0; my $per = 0; my $oldper = 0; open (my $OUT, ">", "$file\.tmp") or return (1, "Unable to open $file\.tmp: $!"); binmode ($OUT); print "...0\%\n"; $res = $ua->request($req, sub { my($chunk, $res) = @_; $bytes_received += length($chunk); unless (defined $expected_length) {$expected_length = $res->content_length || 0} if ($expected_length) { my $per = int(100 * $bytes_received / $expected_length); if ((int($per / 5) == $per / 5) and ($per != $oldper)) { print "...$per\%\n"; $oldper = $per; } } else { print "."; } print $OUT $chunk; }); close ($OUT); print "\n"; } else { $res = $ua->request($req); } alarm(0); if ($res->is_success) { if ($file) { rename ("$file\.tmp","$file") or return (1, "Unable to rename $file\.tmp to $file: $!"); return (0, $file); } else { return (0, $res->content); } } else { return (1, "Unable to download: ".$res->message); } }; alarm(0); if ($@) { return (1, $@); } if ($text) { return ($status,$text); } else { return (1, "Download timeout after $timeout seconds"); } } # end urlget ############################################################################### ## start printcmd sub printcmd { my @command = @_; my ($childin, $childout); my $pid = open3($childin, $childout, $childout, @command); while (<$childout>) {print $_} waitpid ($pid, 0); return; } ## end printcmd ############################################################################### ## start getdownloadserver sub getdownloadserver { my @servers; my $downloadservers = "/etc/cmq/downloadservers"; my $chosen; if (-e $downloadservers) { open (my $DOWNLOAD, "<", $downloadservers); flock ($DOWNLOAD, LOCK_SH); my @data = <$DOWNLOAD>; close ($DOWNLOAD); chomp @data; foreach my $line (@data) { if ($line =~ /^download/) {push @servers, $line} } $chosen = $servers[rand @servers]; } if ($chosen eq "") {$chosen = "download.configserver.com"} return $chosen; } ## end getdownloadserver ############################################################################### 1;