4

Is there a simple command to find out the current number of messages per domain in the linux sendmail queue? mailq dumps out a verbose list, but it's not convenient for a quick overview.

I'm using Centos and sendmail.

mailq -v | egrep -v '^-' | get_domains.pl | sort | uniq -c
But the above command output is as following:
1 domain.com>

Above command did not fulfill my requirement, any help in this regard please.

Here is updated output:

domain.com> has 5 message(s)
domain.com.pk> has 1 message(s)
abc.com.pk> has 2 message(s)
xyz.coinfo.net.cn> has 1 message(s)
mmm.com> has 1 message(s)
User4283
  • 781
  • 3
  • 10
  • 27

3 Answers3

3

Try this:

# mailq -v | awk 'BEGIN { FS = "@" } \
!/^[a-zA-Z0-9-]|^[ \t]+(\(|\/|Total requests:)/ { print $2 }' | sort | uniq -c
quanta
  • 51,413
  • 19
  • 159
  • 217
  • 1
    sed and egrep are unnecessary since awk can also do the selection; alternatively, use grep -o to extract the email address domains and omit the sed and awk. – ramruma Sep 18 '11 at 21:06
  • Thanks for your comment. Could you please show us your solution with `grep -o`? – quanta Sep 19 '11 at 02:13
  • 1
    This is a very elegant solution and preferable to the Perl ones as some systems may not have perl installed (but everything that can pretend to be unix-like should have awk, sort and uniq) – voretaq7 Sep 19 '11 at 03:40
  • I agree. This will work as well. – Rilindo Sep 19 '11 at 14:29
  • 2
    mailq -v |grep -o '@.*' |sort |uniq -c |sort -nr – ramruma Sep 21 '11 at 03:15
  • @quanta -- above is grep -o solution as requested. @.* to get the domain is not foolproof but will work well over 99 per cent of the time, and be obvious when it fails. I have not excluded the sending address as that provides an easy way to get the total number of messages. – ramruma Sep 21 '11 at 03:18
  • If you don't exclude the sending address, it will not fit with the OP's requirement. – quanta Sep 21 '11 at 03:25
  • 1
    OP can recognise his own sending domain but if not, it will be the one at the top with the total number of messages. Excluding it is trivial (|grep -v OPdomain) but pointless. – ramruma Sep 21 '11 at 08:04
2

Well, if you are going to use perl, might as well go all the way.

The following is a fairly imperfect way of counting the number of messages per domain:

#!/usr/bin/perl

use strict;

my @mailq = `cat /home/users/rilindo/mailq`; #Had to simulate the output of the mail command here. Change this to the actual mailq path, e.g. /usr/bin/mailq
my %domains = ();

foreach my $m (@mailq) {
    $m =~ s/^\s+//;
    $m =~ s/\s+$//;
    $m =~ s/>//;
    next if $m =~ /Queue/;
    if ($m =~ /\d\d:\d\d:\d\d/) {
        $domains{(split(/@/,$m))[1]}++;
    }
    else {
        $domains{(split(/@/,$m))[1]}++;
    }
}

foreach my $d (keys %domains) {
    print $d . " has $domains{$d} message(s)" . "\n";
}

Essentially, we send an output of the mailq command into an array and iterate. For each record in the array, we strip the leading and trailing spaces/newlines, and then split at the "@" sign. Then we insert domain as a key (if it doesn't exist) and then increment it in a hash. On the next try, it will simply increment the value if the same domain was found. From there, we loop through the hash and then print out the domain with the total number of matches.

The result:

[rilindo@localhost ~]$ ./parsemail.pl 
domain.com has 6 message(s)
domain3.com has 2 message(s)
domain1.com has 2 message(s)

Like I said, its not perfect, but it does the job. If nothing else, it will give you an idea of where to go from here.

Incidentally, since it appears you know perl, review of Perl's hash data structures will prove to be very useful:

http://www.cs.mcgill.ca/~abatko/computers/programming/perl/howto/hash/

Or:

http://perldoc.perl.org/perldsc.html

Rilindo
  • 5,078
  • 5
  • 28
  • 46
1

"simple" is relative. mailq's output is a royal pain to parse, but it can be done. Typical mailq verbose output is something like:

-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
637F5CFF9C*    1497 Sat Dec 18 21:40:34  sender@domain.com 
                                         recepient@domain.com

637F5CFF9d*    1497 Sat Dec 18 21:40:35  sender@domain.com 
                                         recepient@domain2.com

Some creative hackery can get you what you need:

First, you want to strip out that top line - it's useful to a human but not relevant to our parsing goals.
Easiest way: mailq -v | egrep -v '^-'

Now you want to grab the recipient information and extract the domain name. Perl is your friend here - Pipe the output through this handy script (let's call it get_domains.pl):

#!/usr/bin/perl
$/ = "\n\n";                                    # Use a blank line as the separator.
while (<>) {
        ($x,$recip) = split(/\n/, $_);          # Extract the recipient line
        ($user,$domain) = split(/@/, $recip);   # Get the domain.
        print "$domain\n";                      # Print Recipient Domain
}

This just leaves the easy part - counting the domains (pipe through sort | uniq -c).

So mailq -v | egrep -v '^-' | get_domains.pl | sort | uniq -c will give you output something like:

    1 domain.com
    1 domain2.com
voretaq7
  • 79,879
  • 17
  • 130
  • 214
  • it only print single domain. Output is as following. 1 domain.com> – User4283 Sep 15 '11 at 18:16
  • Did you remember the `-v` flag to mailq (which I left out of my examples)? – voretaq7 Sep 15 '11 at 18:19
  • I've executed the same command. > mailq | egrep -v '^-' | get_domains.pl | sort | uniq -c – User4283 Sep 15 '11 at 18:21
  • Read my comment again. Also see the most recent edit to the answer. – voretaq7 Sep 15 '11 at 18:24
  • Dear i've read and now executed the command " mailq -v | egrep -v '^-' | get_domains.pl | sort | uniq -c " results are same with this command too. – User4283 Sep 15 '11 at 18:27
  • If it doesn't work your `mailq -v` output is atypical (perhaps you have delivery status messsages floating around?) - You will need to look at your `mailq` output and may need to modify this solution to fit your specific needs. System administration is not a field that lends itself to "I can haz teh c0dez?"… – voretaq7 Sep 15 '11 at 18:32
  • Your solution didn't work because queue messages doesn't separated by a blank line. – quanta Sep 18 '11 at 17:59
  • @quanta they were in my output (and at least one other example I looked at), but that's no guarantee of output consistency: It's possible my setup is funky. Your awk solution is more elegant though (it gives me "blank domain" artifacts, but those are easy to discard). – voretaq7 Sep 19 '11 at 03:39