1#
2# Monitorix - A lightweight system monitoring tool.
3#
4# Copyright (C) 2005-2017 by Jordi Sanfeliu <jordi@fibranet.cat>
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc.,
18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19#
20
21package mail;
22
23use strict;
24use warnings;
25use Monitorix;
26use RRDs;
27use POSIX qw(strftime);
28use Exporter 'import';
29our @EXPORT = qw(mail_init mail_update mail_cgi);
30
31
32sub mail_init {
33	my $myself = (caller(0))[3];
34	my ($package, $config, $debug) = @_;
35	my $rrd = $config->{base_lib} . $package . ".rrd";
36	my $mail = $config->{mail};
37
38	my $info;
39	my @rra;
40	my @tmp;
41	my $n;
42
43	my @average;
44	my @min;
45	my @max;
46	my @last;
47
48	if(-e $rrd) {
49		$info = RRDs::info($rrd);
50		for my $key (keys %$info) {
51			if(index($key, 'rra[') == 0) {
52				if(index($key, '.rows') != -1) {
53					push(@rra, substr($key, 4, index($key, ']') - 4));
54				}
55			}
56		}
57		if(scalar(@rra) < 12 + (4 * $config->{max_historic_years})) {
58			logger("$myself: Detected size mismatch between 'max_historic_years' (" . $config->{max_historic_years} . ") and $rrd (" . ((scalar(@rra) -12) / 4) . "). Resizing it accordingly. All historical data will be lost. Backup file created.");
59			rename($rrd, "$rrd.bak");
60		}
61	}
62
63	if(!(-e $rrd)) {
64		logger("Creating '$rrd' file.");
65		for($n = 1; $n <= $config->{max_historic_years}; $n++) {
66			push(@average, "RRA:AVERAGE:0.5:1440:" . (365 * $n));
67			push(@min, "RRA:MIN:0.5:1440:" . (365 * $n));
68			push(@max, "RRA:MAX:0.5:1440:" . (365 * $n));
69			push(@last, "RRA:LAST:0.5:1440:" . (365 * $n));
70		}
71		eval {
72			RRDs::create($rrd,
73				"--step=60",
74				"DS:mail_in:GAUGE:120:0:U",
75				"DS:mail_out:GAUGE:120:0:U",
76				"DS:mail_recvd:GAUGE:120:0:U",
77				"DS:mail_delvd:GAUGE:120:0:U",
78				"DS:mail_bytes_recvd:GAUGE:120:0:U",
79				"DS:mail_bytes_delvd:GAUGE:120:0:U",
80				"DS:mail_rejtd:GAUGE:120:0:U",
81				"DS:mail_spam:GAUGE:120:0:U",
82				"DS:mail_virus:GAUGE:120:0:U",
83				"DS:mail_bouncd:GAUGE:120:0:U",
84				"DS:mail_queued:GAUGE:120:0:U",
85				"DS:mail_discrd:GAUGE:120:0:U",
86				"DS:mail_held:GAUGE:120:0:U",
87				"DS:mail_forwrd:GAUGE:120:0:U",
88				"DS:mail_queues:GAUGE:120:0:U",
89				"DS:mail_val01:GAUGE:120:0:U",
90				"DS:mail_val02:GAUGE:120:0:U",
91				"DS:mail_val03:GAUGE:120:0:U",
92				"DS:mail_val04:GAUGE:120:0:U",
93				"DS:mail_val05:GAUGE:120:0:U",
94				"DS:mail_val06:GAUGE:120:0:U",
95				"DS:mail_val07:GAUGE:120:0:U",
96				"DS:mail_val08:GAUGE:120:0:U",
97				"DS:mail_val09:GAUGE:120:0:U",
98				"DS:mail_val10:GAUGE:120:0:U",
99				"RRA:AVERAGE:0.5:1:1440",
100				"RRA:AVERAGE:0.5:30:336",
101				"RRA:AVERAGE:0.5:60:744",
102				@average,
103				"RRA:MIN:0.5:1:1440",
104				"RRA:MIN:0.5:30:336",
105				"RRA:MIN:0.5:60:744",
106				@min,
107				"RRA:MAX:0.5:1:1440",
108				"RRA:MAX:0.5:30:336",
109				"RRA:MAX:0.5:60:744",
110				@max,
111				"RRA:LAST:0.5:1:1440",
112				"RRA:LAST:0.5:30:336",
113				"RRA:LAST:0.5:60:744",
114				@last,
115			);
116		};
117		my $err = RRDs::error;
118		if($@ || $err) {
119			logger("$@") unless !$@;
120			if($err) {
121				logger("ERROR: while creating $rrd: $err");
122				if($err eq "RRDs::error") {
123					logger("... is the RRDtool Perl package installed?");
124				}
125			}
126			return;
127		}
128	}
129
130	# check dependencies
131	if(lc($mail->{alerts}->{delvd_enabled}) eq "y") {
132		if(! -x $mail->{alerts}->{delvd_script}) {
133			logger("$myself: ERROR: script '$mail->{alerts}->{delvd_script}' doesn't exist or don't has execution permissions.");
134		}
135	}
136	if(lc($mail->{alerts}->{mqueued_enabled}) eq "y") {
137		if(! -x $mail->{alerts}->{mqueued_script}) {
138			logger("$myself: ERROR: script '$mail->{alerts}->{mqueued_script}' doesn't exist or don't has execution permissions.");
139		}
140	}
141	if(!$mail->{stats_rate}) {
142		$mail->{stats_rate} = "per_second";
143	}
144
145	# Since 3.6.0 all DS changed from COUNTER to GAUGE
146	RRDs::tune($rrd,
147		"--data-source-type=mail_val01:GAUGE",
148		"--data-source-type=mail_val02:GAUGE",
149		"--data-source-type=mail_val03:GAUGE",
150		"--data-source-type=mail_val04:GAUGE",
151		"--data-source-type=mail_val05:GAUGE",
152	);
153
154	$config->{mail_hist} = 0;
155	$config->{mail_hist_alert1} = 0;
156	$config->{mail_hist_alert2} = 0;
157	push(@{$config->{func_update}}, $package);
158	logger("$myself: Ok") if $debug;
159}
160
161sub mail_update {
162	my $myself = (caller(0))[3];
163	my ($package, $config, $debug) = @_;
164	my $rrd = $config->{base_lib} . $package . ".rrd";
165	my $mail = $config->{mail};
166
167	my $in_conn;
168	my $out_conn;
169	my $recvd;
170	my $delvd;
171	my $bytes_recvd;
172	my $bytes_delvd;
173	my $rejtd;
174	my $spam;
175	my $virus;
176	my $bouncd;
177	my $queued;
178	my $discrd;
179	my $held;
180	my $forwrd;
181	my $queues;
182	my $spf_none;
183	my $spf_pass;
184	my $spf_softfail;
185	my $spf_fail;
186	my $rbl;
187	my $gl_records;		# means 'passed' in Postgrey
188	my $gl_greylisted;
189	my $gl_whitelisted;
190	my $gl_delayed;		# specific for Postgrey
191	my @mta = (0) x 15;
192	my @gen = (0) x 10;
193	my @mta_h = (0) x 15;
194	my @gen_h = (0) x 10;
195
196	my $n;
197	my $first_read;
198	my $mail_log_seekpos;
199	my $mail_log_size = 0;
200	my $sa_log_seekpos;
201	my $sa_log_size = 0;
202	my $clamav_log_seekpos;
203	my $clamav_log_size = 0;
204	my $rrdata = "N";
205
206	# Read last MAIL data from historic
207	($mail_log_seekpos, $sa_log_seekpos, $clamav_log_seekpos, @mta_h[0..15-1], @gen_h[0..10-1]) = split(';', $config->{mail_hist});
208	$mail_log_seekpos = defined($mail_log_seekpos) ? int($mail_log_seekpos) : 0;
209	$sa_log_seekpos = defined($sa_log_seekpos) ? int($sa_log_seekpos) : 0;
210	$clamav_log_seekpos = defined($clamav_log_seekpos) ? int($clamav_log_seekpos) : 0;
211	$first_read = $mail_log_seekpos ? 0 : 1;
212
213	$recvd = $delvd = $bytes_recvd = $bytes_delvd = 0;
214	$in_conn = $out_conn = $rejtd = 0;
215	$bouncd = $discrd = $held = $forwrd = 0;
216	$queued = $queues = 0;
217	if(lc($mail->{mta}) eq "sendmail") {
218		if(open(IN, "mailstats -P |")) {
219			while(<IN>) {
220				if(/^ T\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/) {
221					$recvd = $1;
222					$bytes_recvd = $2;
223					$delvd = $3;
224					$bytes_delvd = $4;
225				}
226				if(/^ C\s+(\d+)\s+(\d+)\s+(\d+)/) {
227					$in_conn = $1;
228					$out_conn = $2;
229					$rejtd = $3;
230				}
231			}
232			close(IN);
233			$bytes_recvd *= 1024;
234			$bytes_delvd *= 1024;
235		}
236		if(open(IN, "mailq |")) {
237			while(<IN>) {
238				my ($tmp) = ($_ =~ m/^\w{14}[ *X-]\s*(\d{1,8}) /);
239				$queues += $tmp if $tmp;
240				if(/^\s+Total requests: (\d+)$/) {
241					$queued = $1;
242				}
243			}
244			close(IN);
245		}
246	} elsif(lc($mail->{mta}) eq "postfix") {
247		my @data;
248
249		for my $path (split /:/, $ENV{PATH}) {
250			if(-f "$path/pflogsumm" && -x _) {
251				if(open(IN, "pflogsumm -d today -h 0 -u 0 --smtpd_stats --no_bounce_detail --no_deferral_detail --no_reject_detail --no_no_msg_size --no_smtpd_warnings $config->{mail_log} 2>/dev/null |")) {
252					@data = <IN>;
253					close(IN);
254					last;
255				}
256			}
257			if(-f "$path/pflogsumm.pl" && -x _) {
258				if(open(IN, "pflogsumm.pl -d today -h 0 -u 0 --smtpd_stats --no_bounce_detail --no_deferral_detail --no_reject_detail --no_no_msg_size --no_smtpd_warnings $config->{mail_log} 2>/dev/null |")) {
259					@data = <IN>;
260					close(IN);
261					last;
262				}
263			}
264		}
265
266		logger("$myself: 'pflogsumm' returned empty data. Is it really installed?")
267			if !@data;
268
269		foreach(@data) {
270			if(/^\s*(\d{1,7})([ km])\s*received$/) {
271				$recvd = $1;
272				$recvd = $1 * 1024 if $2 eq "k";
273				$recvd = $1 * 1024 * 1024 if $2 eq "m";
274			}
275			if(/^\s*(\d{1,7})([ km])\s*delivered$/) {
276				$delvd = $1;
277				$delvd = $1 * 1024 if $2 eq "k";
278				$delvd = $1 * 1024 * 1024 if $2 eq "m";
279			}
280			if(/^\s*(\d{1,7})([ km])\s*forwarded$/) {
281				$forwrd = $1;
282				$forwrd = $1 * 1024 if $2 eq "k";
283				$forwrd = $1 * 1024 * 1024 if $2 eq "m";
284			}
285			if(/^\s*(\d{1,7})([ km])\s*bounced$/) {
286				$bouncd = $1;
287				$bouncd = $1 * 1024 if $2 eq "k";
288				$bouncd = $1 * 1024 * 1024 if $2 eq "m";
289			}
290			if(/^\s*(\d{1,7})([ km])\s*rejected \(/) {
291				$rejtd = $1;
292				$rejtd = $1 * 1024 if $2 eq "k";
293				$rejtd = $1 * 1024 * 1024 if $2 eq "m";
294			}
295			if(/^\s*(\d{1,7})([ km])\s*held/) {
296				$held = $1;
297				$held = $1 * 1024 if $2 eq "k";
298				$held = $1 * 1024 * 1024 if $2 eq "m";
299			}
300			if(/^\s*(\d{1,7})([ km])\s*discarded \(/) {
301				$discrd = $1;
302				$discrd = $1 * 1024 if $2 eq "k";
303				$discrd = $1 * 1024 * 1024 if $2 eq "m";
304			}
305			if(/^\s*(\d{1,7})([ km])\s*bytes received$/) {
306				$bytes_recvd = $1;
307				$bytes_recvd = $1 * 1024 if $2 eq "k";
308				$bytes_recvd = $1 * 1024 * 1024 if $2 eq "m";
309			}
310			if(/^\s*(\d{1,7})([ km])\s*bytes delivered$/) {
311				$bytes_delvd = $1;
312				$bytes_delvd = $1 * 1024 if $2 eq "k";
313				$bytes_delvd = $1 * 1024 * 1024 if $2 eq "m";
314			}
315		}
316		if(open(IN, "mailq |")) {
317			while(<IN>) {
318				if(/^-- (\d+) Kbytes in (\d+) Request/) {
319					$queues = $1;
320					$queued = $2;
321				}
322			}
323			close(IN);
324		}
325	}
326
327	$gl_records = $gl_greylisted = $gl_whitelisted = $gl_delayed = 0;
328	if(lc($mail->{greylist}) eq "milter-greylist") {
329		if(-r $config->{milter_gl}) {
330			open(IN, $config->{milter_gl});
331			if(!seek(IN, -80, 2)) {
332				logger("Couldn't seek to the end ($config->{milter_gl}): $!");
333				return;
334			}
335			while(<IN>) {
336				if(/^# Summary:\s+(\d+) records,\s+(\d+) greylisted,\s+(\d+) whitelisted/) {
337					$gl_records = $1;
338					$gl_greylisted = $2;
339					$gl_whitelisted = $3;
340				}
341			}
342			close(IN);
343		}
344	}
345
346	$spam = $virus = 0;
347	$spf_none = $spf_pass = $spf_softfail = $spf_fail = 0;
348	$rbl = 0;
349	if(-r $config->{mail_log}) {
350		my $date = strftime("%b %e", localtime);
351		open(IN, $config->{mail_log});
352		if(!seek(IN, 0, 2)) {
353			logger("Couldn't seek to the end ($config->{mail_log}): $!");
354			return;
355		}
356		$mail_log_size = tell(IN);
357		if($mail_log_size < $mail_log_seekpos) {
358			$mail_log_seekpos = 0;
359		}
360		if(!seek(IN, $mail_log_seekpos, 0)) {
361			logger("Couldn't seek to $mail_log_seekpos ($config->{mail_log}): $!");
362			return;
363		}
364		while(<IN>) {
365			my @line;
366			if(/^$date/) {
367				if(/MailScanner/ && /Spam Checks:/ && /Found/ && /spam messages/) {
368					@line = split(' ', $_);
369					$spam += int($line[8]);
370				}
371				if(/MailScanner/ && /Virus Scanning:/ && /Found/ && /viruses/) {
372					@line = split(' ', $_);
373					$virus += int($line[8]);
374				}
375				if(/amavis\[.* SPAM/) {
376					$spam++;
377				}
378				if(/amavis\[.* INFECTED|amavis\[.* BANNED/) {
379					$virus++;
380				}
381				# postfix-policyd-spf-perl
382				if (/policy-spf/) {
383					if(/: pass/) {
384						$spf_pass++;
385					} elsif(/: none/) {
386						$spf_none++;
387					} elsif(/ action=550 /) {
388						$spf_fail++;
389					} else {
390						# There one line per spf check, so it gets here, we'll consider it is a softfail
391						$spf_softfail++;
392					}
393				# for other SPF handlers (smf-spf)
394				} else {
395					if(/ SPF none/) {
396						$spf_none++;
397					} elsif(/ SPF pass/) {
398						$spf_pass++;
399					} elsif(/ SPF softfail/) {
400						$spf_softfail++;
401					} elsif(/ SPF fail/) {
402						$spf_fail++;
403					}
404				}
405				# postfix RBL
406				if(/ postfix\/smtpd\[\d+\]: NOQUEUE: reject: RCPT from /) {
407					# postgrey
408					if(lc($mail->{greylist}) eq "postgrey") {
409						if(/ Recipient address rejected: Greylisted, /) {
410							next;	# ignored
411						}
412					}
413					$rbl++;
414				}
415				# postgrey
416				if(lc($mail->{greylist}) eq "postgrey") {
417					if(/ action=greylist, reason=new, /) {
418						$gl_greylisted++;
419					}
420					if(/ action=greylist, reason=early-retry /) {
421						$gl_delayed++;
422					}
423					if(/ action=pass, reason=triplet found, /) {
424						$gl_records++;
425					}
426					if(/ action=pass, reason=client (whitelist|AWL), /) {
427						$gl_whitelisted++;
428					}
429				}
430			}
431		}
432		close(IN);
433	}
434
435	if(-r $config->{spamassassin_log}) {
436		my $date = strftime("%b %e", localtime);
437		open(IN, $config->{spamassassin_log});
438		if(!seek(IN, 0, 2)) {
439			logger("Couldn't seek to the end ($config->{spamassassin_log}): $!");
440			return;
441		}
442		$sa_log_size = tell(IN);
443		if($sa_log_size < $sa_log_seekpos) {
444			$sa_log_seekpos = 0;
445		}
446		if(!seek(IN, $sa_log_seekpos, 0)) {
447			logger("Couldn't seek to $sa_log_seekpos ($config->{spamassassin_log}): $!");
448			return;
449		}
450		while(<IN>) {
451			if(/^$date/ && /spamd: identified spam/) {
452				$spam++;
453			}
454		}
455		close(IN);
456	}
457
458	if(-r $config->{clamav_log}) {
459		my $date = strftime("%a %b %e", localtime);
460		open(IN, $config->{clamav_log});
461		if(!seek(IN, 0, 2)) {
462			logger("Couldn't seek to the end ($config->{clamav_log}): $!");
463			return;
464		}
465		$clamav_log_size = tell(IN);
466		if($clamav_log_size < $clamav_log_seekpos) {
467			$clamav_log_seekpos = 0;
468		}
469		if(!seek(IN, $clamav_log_seekpos, 0)) {
470			logger("Couldn't seek to $clamav_log_seekpos ($config->{clamav_log}): $!");
471			return;
472		}
473		while(<IN>) {
474			if(/^$date/ && / FOUND/) {
475				$virus++;
476			}
477		}
478		close(IN);
479	}
480
481	$mta[0] = int($in_conn) - ($mta_h[0] || 0);
482	$mta[0] = 0 unless $mta[0] != int($in_conn);
483	$mta[0] /= 60 if lc($mail->{stats_rate}) eq "per_second";
484	$mta_h[0] = int($in_conn);
485
486	$mta[1] = int($out_conn) - ($mta_h[1] || 0);
487	$mta[1] = 0 unless $mta[1] != int($out_conn);
488	$mta[1] /= 60 if lc($mail->{stats_rate}) eq "per_second";
489	$mta_h[1] = int($out_conn);
490
491	$mta[2] = int($recvd) - ($mta_h[2] || 0);
492	$mta[2] = 0 unless $mta[2] != int($recvd);
493	$mta[2] /= 60 if lc($mail->{stats_rate}) eq "per_second";
494	$mta_h[2] = int($recvd);
495
496	$mta[3] = int($delvd) - ($mta_h[3] || 0);
497	$mta[3] = 0 unless $mta[3] != int($delvd);
498	$mta[3] /= 60 if lc($mail->{stats_rate}) eq "per_second";
499	$mta_h[3] = int($delvd);
500
501	$mta[4] = int($bytes_recvd) - ($mta_h[4] || 0);
502	$mta[4] = 0 unless $mta[4] != int($bytes_recvd);
503	$mta[4] /= 60 if lc($mail->{stats_rate}) eq "per_second";
504	$mta_h[4] = int($bytes_recvd);
505
506	$mta[5] = int($bytes_delvd) - ($mta_h[5] || 0);
507	$mta[5] = 0 unless $mta[5] != int($bytes_delvd);
508	$mta[5] /= 60 if lc($mail->{stats_rate}) eq "per_second";
509	$mta_h[5] = int($bytes_delvd);
510
511	$mta[6] = int($rejtd) - ($mta_h[6] || 0);
512	$mta[6] = 0 unless $mta[6] != int($rejtd);
513	$mta[6] /= 60 if lc($mail->{stats_rate}) eq "per_second";
514	$mta_h[6] = int($rejtd);
515
516	# avoid initial peak
517	$mta_h[7] = 0;
518	if(!$first_read) {
519		$mta[7] = int($spam);
520		$mta[7] /= 60 if lc($mail->{stats_rate}) eq "per_second";
521	}
522	# avoid initial peak
523	$mta_h[8] = 0;
524	if(!$first_read) {
525		$mta[8] = int($virus);
526		$mta[8] /= 60 if lc($mail->{stats_rate}) eq "per_second";
527	}
528
529	$mta[9] = int($bouncd) - ($mta_h[9] || 0);
530	$mta[9] = 0 unless $mta[9] != int($bouncd);
531	$mta[9] /= 60 if lc($mail->{stats_rate}) eq "per_second";
532	$mta_h[9] = int($bouncd);
533
534	$mta[10] = int($queued) || 0;
535	$mta_h[10] = 0;
536
537	$mta[11] = int($discrd) - ($mta_h[11] || 0);
538	$mta[11] = 0 unless $mta[11] != int($discrd);
539	$mta[11] /= 60 if lc($mail->{stats_rate}) eq "per_second";
540	$mta_h[11] = int($discrd);
541
542	$mta[12] = int($held) - ($mta_h[12] || 0);
543	$mta[12] = 0 unless $mta[12] != int($held);
544	$mta[12] /= 60 if lc($mail->{stats_rate}) eq "per_second";
545	$mta_h[12] = int($held);
546
547	$mta[13] = int($forwrd) - ($mta_h[13] || 0);
548	$mta[13] = 0 unless $mta[13] != int($forwrd);
549	$mta[13] /= 60 if lc($mail->{stats_rate}) eq "per_second";
550	$mta_h[13] = int($forwrd);
551
552	$mta[14] = int($queues) || 0;
553	$mta_h[14] = 0;
554
555	# avoid initial peak
556	$gen_h[0] = 0;
557	if(!$first_read) {
558		$gen[0] = int($spf_none);
559	}
560	# avoid initial peak
561	$gen_h[1] = 0;
562	if(!$first_read) {
563		$gen[1] = int($spf_pass);
564	}
565	# avoid initial peak
566	$gen_h[2] = 0;
567	if(!$first_read) {
568		$gen[2] = int($spf_softfail);
569	}
570	# avoid initial peak
571	$gen_h[3] = 0;
572	if(!$first_read) {
573		$gen[3] = int($spf_fail);
574	}
575	# avoid initial peak
576	$gen_h[4] = 0;
577	if(!$first_read) {
578		$gen[4] = int($rbl);
579		$gen[4] /= 60 if lc($mail->{stats_rate}) eq "per_second";
580	}
581
582	if(lc($mail->{greylist}) eq "milter-greylist") {
583		$gen_h[5] = $gen[5] = 0;
584		$gen_h[6] = $gen[6] = int($gl_records) || 0;
585		$gen_h[7] = $gen[7] = int($gl_greylisted) || 0;
586		$gen_h[8] = $gen[8] = int($gl_whitelisted) || 0;
587		$gen_h[9] = $gen[9] = int($gl_delayed) || 0;
588	}
589	if(lc($mail->{greylist}) eq "postgrey") {
590		$gen_h[5] = $gen[5] = 0;
591		$gen_h[6] = $gen[6] = 0;
592		$gen_h[7] = $gen[7] = 0;
593		$gen_h[8] = $gen[8] = 0;
594		$gen_h[9] = $gen[9] = 0;
595		# avoid initial peak
596		if(!$first_read) {
597			$gen[6] = int($gl_records);
598			$gen[6] /= 60 if lc($mail->{stats_rate}) eq "per_second";
599		}
600		# avoid initial peak
601		if(!$first_read) {
602			$gen[7] = int($gl_greylisted);
603			$gen[7] /= 60 if lc($mail->{stats_rate}) eq "per_second";
604		}
605		# avoid initial peak
606		if(!$first_read) {
607			$gen[8] = int($gl_whitelisted);
608			$gen[8] /= 60 if lc($mail->{stats_rate}) eq "per_second";
609		}
610		# avoid initial peak
611		if(!$first_read) {
612			$gen[9] = int($gl_delayed);
613			$gen[9] /= 60 if lc($mail->{stats_rate}) eq "per_second";
614		}
615	}
616
617	$config->{mail_hist} = join(";", $mail_log_size, $sa_log_size, $clamav_log_size, @mta_h, @gen_h);
618	for($n = 0; $n < 15; $n++) {
619		$rrdata .= ":" . $mta[$n];
620	}
621	for($n = 0; $n < 10; $n++) {
622		$rrdata .= ":" . $gen[$n];
623	}
624
625	# MAIL alert
626	if(lc($mail->{alerts}->{delvd_enabled}) eq "y") {
627		my $val = int($mta[3]);
628		$val *= 60 + 0.5 if lc($mail->{stats_rate}) eq "per_second";
629		if(!$mail->{alerts}->{delvd_threshold} || $val < $mail->{alerts}->{delvd_threshold}) {
630			$config->{mail_hist_alert1} = 0;
631		} else {
632			if(!$config->{mail_hist_alert1}) {
633				$config->{mail_hist_alert1} = time;
634			}
635			if($config->{mail_hist_alert1} > 0 && (time - $config->{mail_hist_alert1}) >= $mail->{alerts}->{delvd_timeintvl}) {
636				if(-x $mail->{alerts}->{delvd_script}) {
637					logger("$myself: ALERT: executing script '$mail->{alerts}->{delvd_script}'.");
638					system($mail->{alerts}->{delvd_script} . " " .$mail->{alerts}->{delvd_timeintvl} . " " . $mail->{alerts}->{delvd_threshold} . " " . $val);
639				} else {
640					logger("$myself: ERROR: script '$mail->{alerts}->{delvd_script}' doesn't exist or don't has execution permissions.");
641				}
642				$config->{mail_hist_alert1} = time;
643			}
644		}
645	}
646	if(lc($mail->{alerts}->{mqueued_enabled}) eq "y") {
647		my $val = $mta[10];
648		if(!$mail->{alerts}->{mqueued_threshold} || $val < $mail->{alerts}->{mqueued_threshold}) {
649			$config->{mail_hist_alert2} = 0;
650		} else {
651			if(!$config->{mail_hist_alert2}) {
652				$config->{mail_hist_alert2} = time;
653			}
654			if($config->{mail_hist_alert2} > 0 && (time - $config->{mail_hist_alert2}) >= $mail->{alerts}->{mqueued_timeintvl}) {
655				if(-x $mail->{alerts}->{mqueued_script}) {
656					logger("$myself: ALERT: executing script '$mail->{alerts}->{mqueued_script}'.");
657					system($mail->{alerts}->{mqueued_script} . " " .$mail->{alerts}->{mqueued_timeintvl} . " " . $mail->{alerts}->{mqueued_threshold} . " " . $val);
658				} else {
659					logger("$myself: ERROR: script '$mail->{alerts}->{mqueued_script}' doesn't exist or don't has execution permissions.");
660				}
661				$config->{mail_hist_alert2} = time;
662			}
663		}
664	}
665
666	RRDs::update($rrd, $rrdata);
667	logger("$myself: $rrdata") if $debug;
668	my $err = RRDs::error;
669	logger("ERROR: while updating $rrd: $err") if $err;
670}
671
672sub mail_cgi {
673	my ($package, $config, $cgi) = @_;
674	my @output;
675
676	my $mail = $config->{mail};
677	my @rigid = split(',', ($mail->{rigid} || ""));
678	my @limit = split(',', ($mail->{limit} || ""));
679	my $tf = $cgi->{tf};
680	my $colors = $cgi->{colors};
681	my $graph = $cgi->{graph};
682	my $silent = $cgi->{silent};
683	my $zoom = "--zoom=" . $config->{global_zoom};
684	my %rrd = (
685		'new' => \&RRDs::graphv,
686		'old' => \&RRDs::graph,
687	);
688	my $version = "new";
689	my $pic;
690	my $picz;
691	my $picz_width;
692	my $picz_height;
693
694	my $u = "";
695	my $width;
696	my $height;
697	my @riglim;
698	my $T = "B";
699	my $vlabel = "bytes/s";
700	my $rate_label = "Messages";
701	my $valform = "%5.0lf";
702	my $gl_valform = "%5.0lf";
703	my @tmp;
704	my @tmpz;
705	my @CDEF;
706	my $n;
707	my $str;
708	my $err;
709
710	$version = "old" if $RRDs::VERSION < 1.3;
711	my $rrd = $config->{base_lib} . $package . ".rrd";
712	my $title = $config->{graph_title}->{$package};
713	my $IMG_DIR = $config->{base_dir} . "/" . $config->{imgs_dir};
714	my $imgfmt_uc = uc($config->{image_format});
715	my $imgfmt_lc = lc($config->{image_format});
716
717	$title = !$silent ? $title : "";
718
719	if(lc($config->{netstats_in_bps}) eq "y") {
720		$T = "b";
721		$vlabel = "bits/s";
722	}
723	if(!$mail->{stats_rate}) {
724		$mail->{stats_rate} = "per_second";
725	}
726	if(lc($mail->{stats_rate}) eq "per_second") {
727		$rate_label = "Messages/s";
728		$valform = "%5.2lf";
729		$gl_valform = "%5.1lf";
730	}
731
732
733	# mode text
734	#
735	if(lc($config->{iface_mode}) eq "text") {
736		if($title) {
737			push(@output, main::graph_header($title, 2));
738			push(@output, "    <tr>\n");
739			push(@output, "    <td bgcolor='$colors->{title_bg_color}'>\n");
740		}
741		my (undef, undef, undef, $data) = RRDs::fetch("$rrd",
742			"--start=-$tf->{nwhen}$tf->{twhen}",
743			"AVERAGE",
744			"-r $tf->{res}");
745		$err = RRDs::error;
746		push(@output, "ERROR: while fetching $rrd: $err\n") if $err;
747		push(@output, "    <pre style='font-size: 12px; color: $colors->{fg_color}';>\n");
748		push(@output, "Time  In.Conn Out.Conn  Receivd   Delivd  Bytes.R  Bytes.D  Rejectd  Bounced  Discard     Held  Forward     Spam    Virus   Queued  Queue.S\n");
749		push(@output, "------------------------------------------------------------------------------------------------------------------------------------------- \n");
750		my $line;
751		my @row;
752		my $time;
753		for($n = 0, $time = $tf->{tb}; $n < ($tf->{tb} * $tf->{ts}); $n++) {
754			$line = @$data[$n];
755			$time = $time - (1 / $tf->{ts});
756			my ($in, $out, $recvd, $delvd, $bytes_recvd, $bytes_delvd, $rejtd, $spam, $virus, $bouncd, $queued, $discrd, $held, $forwrd, $queues) = @$line;
757			@row = ($in, $out, $recvd, $delvd, $bytes_recvd, $bytes_delvd, $rejtd, $bouncd, $discrd, $held, $forwrd, $spam, $virus, $queued, $queues);
758			push(@output, sprintf(" %2d$tf->{tc}  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f\n", $time, @row));
759		}
760		push(@output, "    </pre>\n");
761		if($title) {
762			push(@output, "    </td>\n");
763			push(@output, "    </tr>\n");
764			push(@output, main::graph_footer());
765		}
766		push(@output, "  <br>\n");
767		return @output;
768	}
769
770
771	# graph mode
772	#
773	if($silent eq "yes" || $silent eq "imagetag") {
774		$colors->{fg_color} = "#000000";  # visible color for text mode
775		$u = "_";
776	}
777	if($silent eq "imagetagbig") {
778		$colors->{fg_color} = "#000000";  # visible color for text mode
779		$u = "";
780	}
781
782	my $IMG1 = $u . $package . "1." . $tf->{when} . ".$imgfmt_lc";
783	my $IMG2 = $u . $package . "2." . $tf->{when} . ".$imgfmt_lc";
784	my $IMG3 = $u . $package . "3." . $tf->{when} . ".$imgfmt_lc";
785	my $IMG4 = $u . $package . "4." . $tf->{when} . ".$imgfmt_lc";
786	my $IMG5 = $u . $package . "5." . $tf->{when} . ".$imgfmt_lc";
787	my $IMG6 = $u . $package . "6." . $tf->{when} . ".$imgfmt_lc";
788	my $IMG1z = $u . $package . "1z." . $tf->{when} . ".$imgfmt_lc";
789	my $IMG2z = $u . $package . "2z." . $tf->{when} . ".$imgfmt_lc";
790	my $IMG3z = $u . $package . "3z." . $tf->{when} . ".$imgfmt_lc";
791	my $IMG4z = $u . $package . "4z." . $tf->{when} . ".$imgfmt_lc";
792	my $IMG5z = $u . $package . "5z." . $tf->{when} . ".$imgfmt_lc";
793	my $IMG6z = $u . $package . "6z." . $tf->{when} . ".$imgfmt_lc";
794	unlink ("$IMG_DIR" . "$IMG1",
795		"$IMG_DIR" . "$IMG2",
796		"$IMG_DIR" . "$IMG3",
797		"$IMG_DIR" . "$IMG4",
798		"$IMG_DIR" . "$IMG5",
799		"$IMG_DIR" . "$IMG6");
800	if(lc($config->{enable_zoom}) eq "y") {
801		unlink ("$IMG_DIR" . "$IMG1z",
802			"$IMG_DIR" . "$IMG2z",
803			"$IMG_DIR" . "$IMG3z",
804			"$IMG_DIR" . "$IMG4z",
805			"$IMG_DIR" . "$IMG5z",
806			"$IMG_DIR" . "$IMG6z");
807	}
808
809	if($title) {
810		push(@output, main::graph_header($title, 2));
811	}
812	@riglim = @{setup_riglim($rigid[0], $limit[0])};
813	if(lc($mail->{mta}) eq "sendmail") {
814		push(@tmp, "AREA:in#44EE44:In Connections");
815		push(@tmp, "GPRINT:in:LAST:    Cur\\: $valform");
816		push(@tmp, "GPRINT:in:AVERAGE:    Avg\\: $valform");
817		push(@tmp, "GPRINT:in:MIN:    Min\\: $valform");
818		push(@tmp, "GPRINT:in:MAX:    Max\\: $valform\\n");
819		push(@tmp, "AREA:rejtd#EE4444:Rejected");
820		push(@tmp, "GPRINT:rejtd:LAST:          Cur\\: $valform");
821		push(@tmp, "GPRINT:rejtd:AVERAGE:    Avg\\: $valform");
822		push(@tmp, "GPRINT:rejtd:MIN:    Min\\: $valform");
823		push(@tmp, "GPRINT:rejtd:MAX:    Max\\: $valform\\n");
824		push(@tmp, "AREA:recvd#448844:Received");
825		push(@tmp, "GPRINT:recvd:LAST:          Cur\\: $valform");
826		push(@tmp, "GPRINT:recvd:AVERAGE:    Avg\\: $valform");
827		push(@tmp, "GPRINT:recvd:MIN:    Min\\: $valform");
828		push(@tmp, "GPRINT:recvd:MAX:    Max\\: $valform\\n");
829		push(@tmp, "AREA:spam#EEEE44:Spam");
830		push(@tmp, "GPRINT:spam:LAST:              Cur\\: $valform");
831		push(@tmp, "GPRINT:spam:AVERAGE:    Avg\\: $valform");
832		push(@tmp, "GPRINT:spam:MIN:    Min\\: $valform");
833		push(@tmp, "GPRINT:spam:MAX:    Max\\: $valform\\n");
834		push(@tmp, "AREA:virus#EE44EE:Virus");
835		push(@tmp, "GPRINT:virus:LAST:             Cur\\: $valform");
836		push(@tmp, "GPRINT:virus:AVERAGE:    Avg\\: $valform");
837		push(@tmp, "GPRINT:virus:MIN:    Min\\: $valform");
838		push(@tmp, "GPRINT:virus:MAX:    Max\\: $valform\\n");
839		push(@tmp, "AREA:n_delvd#4444EE:Delivered");
840		push(@tmp, "GPRINT:delvd:LAST:         Cur\\: $valform");
841		push(@tmp, "GPRINT:delvd:AVERAGE:    Avg\\: $valform");
842		push(@tmp, "GPRINT:delvd:MIN:    Min\\: $valform");
843		push(@tmp, "GPRINT:delvd:MAX:    Max\\: $valform\\n");
844		push(@tmp, "AREA:n_out#44EEEE:Out Connections");
845		push(@tmp, "GPRINT:out:LAST:   Cur\\: $valform");
846		push(@tmp, "GPRINT:out:AVERAGE:    Avg\\: $valform");
847		push(@tmp, "GPRINT:out:MIN:    Min\\: $valform");
848		push(@tmp, "GPRINT:out:MAX:    Max\\: $valform\\n");
849		push(@tmp, "LINE1:in#00EE00");
850		push(@tmp, "LINE1:rejtd#EE0000");
851		push(@tmp, "LINE1:recvd#1F881F");
852		push(@tmp, "LINE1:spam#EEEE00");
853		push(@tmp, "LINE1:virus#EE00EE");
854		push(@tmp, "LINE1:n_delvd#0000EE");
855		push(@tmp, "LINE1:n_out#00EEEE");
856		push(@tmp, "COMMENT: \\n");
857		push(@tmp, "COMMENT: \\n");
858		push(@tmp, "COMMENT: \\n");
859
860		push(@tmpz, "AREA:in#44EE44:In Connections");
861		push(@tmpz, "AREA:rejtd#EE4444:Rejected");
862		push(@tmpz, "AREA:recvd#448844:Received");
863		push(@tmpz, "AREA:spam#EEEE44:Spam");
864		push(@tmpz, "AREA:virus#EE44EE:Virus");
865		push(@tmpz, "AREA:n_delvd#4444EE:Delivered");
866		push(@tmpz, "AREA:n_out#44EEEE:Out Connections");
867		push(@tmpz, "LINE1:in#00EE00");
868		push(@tmpz, "LINE1:rejtd#EE0000");
869		push(@tmpz, "LINE1:recvd#1F881F");
870		push(@tmpz, "LINE1:spam#EEEE00");
871		push(@tmpz, "LINE1:virus#EE00EE");
872		push(@tmpz, "LINE1:n_delvd#0000EE");
873		push(@tmpz, "LINE1:n_out#00EEEE");
874	} elsif(lc($mail->{mta}) eq "postfix") {
875		push(@tmp, "AREA:rejtd#EE4444:Rejected");
876		push(@tmp, "GPRINT:rejtd:LAST:          Cur\\: $valform");
877		push(@tmp, "GPRINT:rejtd:AVERAGE:    Avg\\: $valform");
878		push(@tmp, "GPRINT:rejtd:MIN:    Min\\: $valform");
879		push(@tmp, "GPRINT:rejtd:MAX:    Max\\: $valform\\n");
880		push(@tmp, "AREA:rbl#963C74:Rejected (RBL)");
881		push(@tmp, "GPRINT:rbl:LAST:    Cur\\: $valform");
882		push(@tmp, "GPRINT:rbl:AVERAGE:    Avg\\: $valform");
883		push(@tmp, "GPRINT:rbl:MIN:    Min\\: $valform");
884		push(@tmp, "GPRINT:rbl:MAX:    Max\\: $valform\\n");
885		push(@tmp, "AREA:recvd#448844:Received");
886		push(@tmp, "GPRINT:recvd:LAST:          Cur\\: $valform");
887		push(@tmp, "GPRINT:recvd:AVERAGE:    Avg\\: $valform");
888		push(@tmp, "GPRINT:recvd:MIN:    Min\\: $valform");
889		push(@tmp, "GPRINT:recvd:MAX:    Max\\: $valform\\n");
890		push(@tmp, "AREA:spam#EEEE44:Spam");
891		push(@tmp, "GPRINT:spam:LAST:              Cur\\: $valform");
892		push(@tmp, "GPRINT:spam:AVERAGE:    Avg\\: $valform");
893		push(@tmp, "GPRINT:spam:MIN:    Min\\: $valform");
894		push(@tmp, "GPRINT:spam:MAX:    Max\\: $valform\\n");
895		push(@tmp, "AREA:virus#EE44EE:Virus");
896		push(@tmp, "GPRINT:virus:LAST:             Cur\\: $valform");
897		push(@tmp, "GPRINT:virus:AVERAGE:    Avg\\: $valform");
898		push(@tmp, "GPRINT:virus:MIN:    Min\\: $valform");
899		push(@tmp, "GPRINT:virus:MAX:    Max\\: $valform\\n");
900		push(@tmp, "AREA:bouncd#FFA500:Bounced");
901		push(@tmp, "GPRINT:bouncd:LAST:           Cur\\: $valform");
902		push(@tmp, "GPRINT:bouncd:AVERAGE:    Avg\\: $valform");
903		push(@tmp, "GPRINT:bouncd:MIN:    Min\\: $valform");
904		push(@tmp, "GPRINT:bouncd:MAX:    Max\\: $valform\\n");
905		push(@tmp, "AREA:discrd#CCCCCC:Discarded");
906		push(@tmp, "GPRINT:discrd:LAST:         Cur\\: $valform");
907		push(@tmp, "GPRINT:discrd:AVERAGE:    Avg\\: $valform");
908		push(@tmp, "GPRINT:discrd:MIN:    Min\\: $valform");
909		push(@tmp, "GPRINT:discrd:MAX:    Max\\: $valform\\n");
910		push(@tmp, "AREA:held#44EE44:Held");
911		push(@tmp, "GPRINT:held:LAST:              Cur\\: $valform");
912		push(@tmp, "GPRINT:held:AVERAGE:    Avg\\: $valform");
913		push(@tmp, "GPRINT:held:MIN:    Min\\: $valform");
914		push(@tmp, "GPRINT:held:MAX:    Max\\: $valform\\n");
915		push(@tmp, "AREA:n_forwrd#44EEEE:Forwarded");
916		push(@tmp, "GPRINT:forwrd:LAST:         Cur\\: $valform");
917		push(@tmp, "GPRINT:forwrd:AVERAGE:    Avg\\: $valform");
918		push(@tmp, "GPRINT:forwrd:MIN:    Min\\: $valform");
919		push(@tmp, "GPRINT:forwrd:MAX:    Max\\: $valform\\n");
920		push(@tmp, "AREA:n_delvd#4444EE:Delivered");
921		push(@tmp, "GPRINT:delvd:LAST:         Cur\\: $valform");
922		push(@tmp, "GPRINT:delvd:AVERAGE:    Avg\\: $valform");
923		push(@tmp, "GPRINT:delvd:MIN:    Min\\: $valform");
924		push(@tmp, "GPRINT:delvd:MAX:    Max\\: $valform\\n");
925		push(@tmp, "LINE1:rejtd#EE0000");
926		push(@tmp, "LINE1:rbl#963C74");
927		push(@tmp, "LINE1:recvd#1F881F");
928		push(@tmp, "LINE1:spam#EEEE00");
929		push(@tmp, "LINE1:virus#EE00EE");
930		push(@tmp, "LINE1:bouncd#FFA500");
931		push(@tmp, "LINE1:discrd#888888");
932		push(@tmp, "LINE1:held#00EE00");
933		push(@tmp, "LINE1:n_forwrd#00EEEE");
934		push(@tmp, "LINE1:n_delvd#0000EE");
935
936		push(@tmpz, "AREA:rejtd#EE4444:Rejected");
937		push(@tmpz, "AREA:rbl#963C74:Rejected (RBL)");
938		push(@tmpz, "AREA:recvd#448844:Received");
939		push(@tmpz, "AREA:spam#EEEE44:Spam");
940		push(@tmpz, "AREA:virus#EE44EE:Virus");
941		push(@tmpz, "AREA:bouncd#FFA500:Bounced");
942		push(@tmpz, "AREA:discrd#888888:Discarded");
943		push(@tmpz, "AREA:held#44EE44:Held");
944		push(@tmpz, "AREA:n_forwrd#44EEEE:Forwarded");
945		push(@tmpz, "AREA:n_delvd#4444EE:Delivered");
946		push(@tmpz, "LINE1:rejtd#EE0000");
947		push(@tmpz, "LINE1:rbl#963C74");
948		push(@tmpz, "LINE1:recvd#1F881F");
949		push(@tmpz, "LINE1:spam#EEEE00");
950		push(@tmpz, "LINE1:virus#EE00EE");
951		push(@tmpz, "LINE1:bouncd#FFA500");
952		push(@tmpz, "LINE1:discrd#888888");
953		push(@tmpz, "LINE1:held#00EE00");
954		push(@tmpz, "LINE1:n_forwrd#00EEEE");
955		push(@tmpz, "LINE1:n_delvd#0000EE");
956	}
957	if(lc($config->{show_gaps}) eq "y") {
958		push(@tmp, "AREA:wrongdata_p#$colors->{gap}:");
959		push(@tmp, "AREA:wrongdata_m#$colors->{gap}:");
960		push(@tmpz, "AREA:wrongdata_p#$colors->{gap}:");
961		push(@tmpz, "AREA:wrongdata_m#$colors->{gap}:");
962		push(@CDEF, "CDEF:wrongdata_p=allvalues_p,UN,INF,UNKN,IF");
963		push(@CDEF, "CDEF:wrongdata_m=allvalues_m,0,LT,INF,-1,*,UNKN,IF");
964	}
965
966	if($title) {
967		push(@output, "    <tr>\n");
968		push(@output, "    <td bgcolor='$colors->{title_bg_color}'>\n");
969	}
970	($width, $height) = split('x', $config->{graph_size}->{main});
971	if($silent =~ /imagetag/) {
972		($width, $height) = split('x', $config->{graph_size}->{remote}) if $silent eq "imagetag";
973		($width, $height) = split('x', $config->{graph_size}->{main}) if $silent eq "imagetagbig";
974		@tmp = @tmpz;
975		push(@tmp, "COMMENT: \\n");
976		push(@tmp, "COMMENT: \\n");
977	}
978	$pic = $rrd{$version}->("$IMG_DIR" . "$IMG1",
979		"--title=$config->{graphs}->{_mail1}  ($tf->{nwhen}$tf->{twhen})",
980		"--start=-$tf->{nwhen}$tf->{twhen}",
981		"--imgformat=$imgfmt_uc",
982		"--vertical-label=$rate_label",
983		"--width=$width",
984		"--height=$height",
985		@riglim,
986		$zoom,
987		@{$cgi->{version12}},
988		@{$colors->{graph_colors}},
989		"DEF:in=$rrd:mail_in:AVERAGE",
990		"DEF:out=$rrd:mail_out:AVERAGE",
991		"DEF:recvd=$rrd:mail_recvd:AVERAGE",
992		"DEF:delvd=$rrd:mail_delvd:AVERAGE",
993		"DEF:rejtd=$rrd:mail_rejtd:AVERAGE",
994		"DEF:spam=$rrd:mail_spam:AVERAGE",
995		"DEF:virus=$rrd:mail_virus:AVERAGE",
996		"DEF:bouncd=$rrd:mail_bouncd:AVERAGE",
997		"DEF:discrd=$rrd:mail_discrd:AVERAGE",
998		"DEF:held=$rrd:mail_held:AVERAGE",
999		"DEF:forwrd=$rrd:mail_forwrd:AVERAGE",
1000		"DEF:rbl=$rrd:mail_val05:AVERAGE",
1001		"CDEF:allvalues_p=in,out,recvd,delvd,rejtd,spam,virus,bouncd,discrd,held,forwrd,rbl,+,+,+,+,+,+,+,+,+,+,+",
1002		"CDEF:allvalues_m=allvalues_p,UN,-1,UNKN,IF",
1003		@CDEF,
1004		"CDEF:n_forwrd=forwrd,-1,*",
1005		"CDEF:n_delvd=delvd,-1,*",
1006		"CDEF:n_out=out,-1,*",
1007		"COMMENT: \\n",
1008		@tmp);
1009	$err = RRDs::error;
1010	push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG1: $err\n") if $err;
1011	if(lc($config->{enable_zoom}) eq "y") {
1012		($width, $height) = split('x', $config->{graph_size}->{zoom});
1013		$picz = $rrd{$version}->("$IMG_DIR" . "$IMG1z",
1014			"--title=$config->{graphs}->{_mail1}  ($tf->{nwhen}$tf->{twhen})",
1015			"--start=-$tf->{nwhen}$tf->{twhen}",
1016			"--imgformat=$imgfmt_uc",
1017			"--vertical-label=$rate_label",
1018			"--width=$width",
1019			"--height=$height",
1020			@riglim,
1021			$zoom,
1022			@{$cgi->{version12}},
1023			@{$colors->{graph_colors}},
1024			"DEF:in=$rrd:mail_in:AVERAGE",
1025			"DEF:out=$rrd:mail_out:AVERAGE",
1026			"DEF:recvd=$rrd:mail_recvd:AVERAGE",
1027			"DEF:delvd=$rrd:mail_delvd:AVERAGE",
1028			"DEF:rejtd=$rrd:mail_rejtd:AVERAGE",
1029			"DEF:spam=$rrd:mail_spam:AVERAGE",
1030			"DEF:virus=$rrd:mail_virus:AVERAGE",
1031			"DEF:bouncd=$rrd:mail_bouncd:AVERAGE",
1032			"DEF:discrd=$rrd:mail_discrd:AVERAGE",
1033			"DEF:held=$rrd:mail_held:AVERAGE",
1034			"DEF:forwrd=$rrd:mail_forwrd:AVERAGE",
1035			"DEF:rbl=$rrd:mail_val05:AVERAGE",
1036			"CDEF:allvalues_p=in,out,recvd,delvd,rejtd,spam,virus,bouncd,discrd,held,forwrd,rbl,+,+,+,+,+,+,+,+,+,+,+",
1037			"CDEF:allvalues_m=allvalues_p,UN,-1,UNKN,IF",
1038			@CDEF,
1039			"CDEF:n_forwrd=forwrd,-1,*",
1040			"CDEF:n_delvd=delvd,-1,*",
1041			"CDEF:n_out=out,-1,*",
1042			@tmpz);
1043		$err = RRDs::error;
1044		push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG1z: $err\n") if $err;
1045	}
1046	if($title || ($silent =~ /imagetag/ && $graph =~ /mail1/)) {
1047		if(lc($config->{enable_zoom}) eq "y") {
1048			if(lc($config->{disable_javascript_void}) eq "y") {
1049				push(@output, "      <a href=\"" . $config->{url} . "/" . $config->{imgs_dir} . $IMG1z . "\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG1 . "' border='0'></a>\n");
1050			} else {
1051				if($version eq "new") {
1052					$picz_width = $picz->{image_width} * $config->{global_zoom};
1053					$picz_height = $picz->{image_height} * $config->{global_zoom};
1054				} else {
1055					$picz_width = $width + 115;
1056					$picz_height = $height + 100;
1057				}
1058				push(@output, "      <a href=\"javascript:void(window.open('" . $config->{url} . "/" . $config->{imgs_dir} . $IMG1z . "','','width=" . $picz_width . ",height=" . $picz_height . ",scrollbars=0,resizable=0'))\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG1 . "' border='0'></a>\n");
1059			}
1060		} else {
1061			push(@output, "      <img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG1 . "'>\n");
1062		}
1063	}
1064
1065	@riglim = @{setup_riglim($rigid[1], $limit[1])};
1066	undef(@tmp);
1067	undef(@tmpz);
1068	undef(@CDEF);
1069	push(@tmp, "AREA:B_in#44EE44:K$T/s Received");
1070	push(@tmp, "GPRINT:K_in:LAST:      Cur\\: %5.0lf");
1071	push(@tmp, "GPRINT:K_in:AVERAGE:    Avg\\: %5.0lf");
1072	push(@tmp, "GPRINT:K_in:MIN:    Min\\: %5.0lf");
1073	push(@tmp, "GPRINT:K_in:MAX:    Max\\: %5.0lf\\n");
1074	push(@tmp, "AREA:B_out#4444EE:K$T/s Delivered");
1075	push(@tmp, "GPRINT:K_out:LAST:     Cur\\: %5.0lf");
1076	push(@tmp, "GPRINT:K_out:AVERAGE:    Avg\\: %5.0lf");
1077	push(@tmp, "GPRINT:K_out:MIN:    Min\\: %5.0lf");
1078	push(@tmp, "GPRINT:K_out:MAX:    Max\\: %5.0lf\\n");
1079	push(@tmp, "AREA:B_out#4444EE:");
1080	push(@tmp, "AREA:B_in#44EE44:");
1081	push(@tmp, "LINE1:B_out#0000EE");
1082	push(@tmp, "LINE1:B_in#00EE00");
1083	push(@tmpz, "AREA:B_in#44EE44:Received");
1084	push(@tmpz, "AREA:B_out#4444EE:Delivered");
1085	push(@tmpz, "AREA:B_out#4444EE:");
1086	push(@tmpz, "AREA:B_in#44EE44:");
1087	push(@tmpz, "LINE1:B_out#0000EE");
1088	push(@tmpz, "LINE1:B_in#00EE00");
1089	if(lc($config->{netstats_in_bps}) eq "y") {
1090		push(@CDEF, "CDEF:B_in=in,8,*");
1091		push(@CDEF, "CDEF:B_out=out,8,*");
1092	} else {
1093		push(@CDEF, "CDEF:B_in=in");
1094		push(@CDEF, "CDEF:B_out=out");
1095	}
1096	if(lc($config->{show_gaps}) eq "y") {
1097		push(@tmp, "AREA:wrongdata#$colors->{gap}:");
1098		push(@tmpz, "AREA:wrongdata#$colors->{gap}:");
1099		push(@CDEF, "CDEF:wrongdata=allvalues,UN,INF,UNKN,IF");
1100	}
1101	($width, $height) = split('x', $config->{graph_size}->{main});
1102	if($silent =~ /imagetag/) {
1103		($width, $height) = split('x', $config->{graph_size}->{remote}) if $silent eq "imagetag";
1104		($width, $height) = split('x', $config->{graph_size}->{main}) if $silent eq "imagetagbig";
1105		@tmp = @tmpz;
1106		push(@tmp, "COMMENT: \\n");
1107	}
1108
1109	$pic = $rrd{$version}->("$IMG_DIR" . "$IMG2",
1110		"--title=$config->{graphs}->{_mail2}  ($tf->{nwhen}$tf->{twhen})",
1111		"--start=-$tf->{nwhen}$tf->{twhen}",
1112		"--imgformat=$imgfmt_uc",
1113		"--vertical-label=$vlabel",
1114		"--width=$width",
1115		"--height=$height",
1116		@riglim,
1117		$zoom,
1118		@{$cgi->{version12}},
1119		@{$colors->{graph_colors}},
1120		"DEF:in=$rrd:mail_bytes_recvd:AVERAGE",
1121		"DEF:out=$rrd:mail_bytes_delvd:AVERAGE",
1122		"CDEF:allvalues=in,out,+",
1123		@CDEF,
1124		"CDEF:K_in=B_in,1024,/",
1125		"CDEF:K_out=B_out,1024,/",
1126		"COMMENT: \\n",
1127		@tmp,
1128		"COMMENT: \\n");
1129	$err = RRDs::error;
1130	push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG2: $err\n") if $err;
1131	if(lc($config->{enable_zoom}) eq "y") {
1132		($width, $height) = split('x', $config->{graph_size}->{zoom});
1133		$picz = $rrd{$version}->("$IMG_DIR" . "$IMG2z",
1134			"--title=$config->{graphs}->{_mail2}  ($tf->{nwhen}$tf->{twhen})",
1135			"--start=-$tf->{nwhen}$tf->{twhen}",
1136			"--imgformat=$imgfmt_uc",
1137			"--vertical-label=$vlabel",
1138			"--width=$width",
1139			"--height=$height",
1140			@riglim,
1141			$zoom,
1142			@{$cgi->{version12}},
1143			@{$colors->{graph_colors}},
1144			"DEF:in=$rrd:mail_bytes_recvd:AVERAGE",
1145			"DEF:out=$rrd:mail_bytes_delvd:AVERAGE",
1146			"CDEF:allvalues=in,out,+",
1147			@CDEF,
1148			"CDEF:K_in=B_in,1024,/",
1149			"CDEF:K_out=B_out,1024,/",
1150			@tmpz);
1151		$err = RRDs::error;
1152		push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG2z: $err\n") if $err;
1153	}
1154	if($title || ($silent =~ /imagetag/ && $graph =~ /mail2/)) {
1155		if(lc($config->{enable_zoom}) eq "y") {
1156			if(lc($config->{disable_javascript_void}) eq "y") {
1157				push(@output, "      <a href=\"" . $config->{url} . "/" . $config->{imgs_dir} . $IMG2z . "\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG2 . "' border='0'></a>\n");
1158			} else {
1159				if($version eq "new") {
1160					$picz_width = $picz->{image_width} * $config->{global_zoom};
1161					$picz_height = $picz->{image_height} * $config->{global_zoom};
1162				} else {
1163					$picz_width = $width + 115;
1164					$picz_height = $height + 100;
1165				}
1166				push(@output, "      <a href=\"javascript:void(window.open('" . $config->{url} . "/" . $config->{imgs_dir} . $IMG2z . "','','width=" . $picz_width . ",height=" . $picz_height . ",scrollbars=0,resizable=0'))\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG2 . "' border='0'></a>\n");
1167			}
1168		} else {
1169			push(@output, "      <img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG2 . "'>\n");
1170		}
1171	}
1172
1173	if($title) {
1174		push(@output, "    </td>\n");
1175		push(@output, "    <td valign='top' bgcolor='" . $colors->{title_bg_color} . "'>\n");
1176	}
1177	@riglim = @{setup_riglim($rigid[2], $limit[2])};
1178	undef(@tmp);
1179	undef(@tmpz);
1180	undef(@CDEF);
1181	push(@tmp, "AREA:queued#EEEE44:Queued");
1182	push(@tmp, "LINE1:queued#EEEE00");
1183	push(@tmp, "GPRINT:queued:LAST:               Current\\: %5.0lf\\n");
1184	push(@tmpz, "AREA:queued#EEEE44:Queued");
1185	push(@tmpz, "LINE1:queued#EEEE00");
1186	if(lc($config->{show_gaps}) eq "y") {
1187		push(@tmp, "AREA:wrongdata#$colors->{gap}:");
1188		push(@tmpz, "AREA:wrongdata#$colors->{gap}:");
1189		push(@CDEF, "CDEF:wrongdata=allvalues,UN,INF,UNKN,IF");
1190	}
1191	($width, $height) = split('x', $config->{graph_size}->{small});
1192	if($silent =~ /imagetag/) {
1193		($width, $height) = split('x', $config->{graph_size}->{remote}) if $silent eq "imagetag";
1194		($width, $height) = split('x', $config->{graph_size}->{main}) if $silent eq "imagetagbig";
1195		@tmp = @tmpz;
1196		push(@tmp, "COMMENT: \\n");
1197		push(@tmp, "COMMENT: \\n");
1198		push(@tmp, "COMMENT: \\n");
1199	}
1200	$pic = $rrd{$version}->("$IMG_DIR" . "$IMG3",
1201		"--title=$config->{graphs}->{_mail3}  ($tf->{nwhen}$tf->{twhen})",
1202		"--start=-$tf->{nwhen}$tf->{twhen}",
1203		"--imgformat=$imgfmt_uc",
1204		"--vertical-label=Messages",
1205		"--width=$width",
1206		"--height=$height",
1207		@riglim,
1208		$zoom,
1209		@{$cgi->{version12}},
1210		@{$cgi->{version12_small}},
1211		@{$colors->{graph_colors}},
1212		"DEF:queued=$rrd:mail_queued:AVERAGE",
1213		"CDEF:allvalues=queued",
1214		@CDEF,
1215		@tmp);
1216	$err = RRDs::error;
1217	push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG3: $err\n") if $err;
1218	if(lc($config->{enable_zoom}) eq "y") {
1219		($width, $height) = split('x', $config->{graph_size}->{zoom});
1220		$picz = $rrd{$version}->("$IMG_DIR" . "$IMG3z",
1221			"--title=$config->{graphs}->{_mail3}  ($tf->{nwhen}$tf->{twhen})",
1222			"--start=-$tf->{nwhen}$tf->{twhen}",
1223			"--imgformat=$imgfmt_uc",
1224			"--vertical-label=Messages",
1225			"--width=$width",
1226			"--height=$height",
1227			@riglim,
1228			$zoom,
1229			@{$cgi->{version12}},
1230			@{$cgi->{version12_small}},
1231			@{$colors->{graph_colors}},
1232			"DEF:queued=$rrd:mail_queued:AVERAGE",
1233			"CDEF:allvalues=queued",
1234			@CDEF,
1235			@tmpz);
1236		$err = RRDs::error;
1237		push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG3z: $err\n") if $err;
1238	}
1239	if($title || ($silent =~ /imagetag/ && $graph =~ /mail3/)) {
1240		if(lc($config->{enable_zoom}) eq "y") {
1241			if(lc($config->{disable_javascript_void}) eq "y") {
1242				push(@output, "      <a href=\"" . $config->{url} . "/" . $config->{imgs_dir} . $IMG3z . "\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG3 . "' border='0'></a>\n");
1243			} else {
1244				if($version eq "new") {
1245					$picz_width = $picz->{image_width} * $config->{global_zoom};
1246					$picz_height = $picz->{image_height} * $config->{global_zoom};
1247				} else {
1248					$picz_width = $width + 115;
1249					$picz_height = $height + 100;
1250				}
1251				push(@output, "      <a href=\"javascript:void(window.open('" . $config->{url} . "/" . $config->{imgs_dir} . $IMG3z . "','','width=" . $picz_width . ",height=" . $picz_height . ",scrollbars=0,resizable=0'))\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG3 . "' border='0'></a>\n");
1252			}
1253		} else {
1254			push(@output, "      <img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG3 . "'>\n");
1255		}
1256	}
1257
1258	@riglim = @{setup_riglim($rigid[3], $limit[3])};
1259	undef(@tmp);
1260	undef(@tmpz);
1261	undef(@CDEF);
1262	push(@tmp, "AREA:queues#44AAEE:Size in KB");
1263	push(@tmp, "LINE1:queues#00AAEE");
1264	push(@tmp, "GPRINT:K_queues:LAST:           Current\\: %5.1lf\\n");
1265	push(@tmpz, "AREA:queues#44AAEE:Size");
1266	push(@tmpz, "LINE1:queues#00AAEE");
1267	if(lc($config->{show_gaps}) eq "y") {
1268		push(@tmp, "AREA:wrongdata#$colors->{gap}:");
1269		push(@tmpz, "AREA:wrongdata#$colors->{gap}:");
1270		push(@CDEF, "CDEF:wrongdata=allvalues,UN,INF,UNKN,IF");
1271	}
1272	($width, $height) = split('x', $config->{graph_size}->{small});
1273	if($silent =~ /imagetag/) {
1274		($width, $height) = split('x', $config->{graph_size}->{remote}) if $silent eq "imagetag";
1275		($width, $height) = split('x', $config->{graph_size}->{main}) if $silent eq "imagetagbig";
1276		@tmp = @tmpz;
1277		push(@tmp, "COMMENT: \\n");
1278		push(@tmp, "COMMENT: \\n");
1279		push(@tmp, "COMMENT: \\n");
1280	}
1281	$pic = $rrd{$version}->("$IMG_DIR" . "$IMG4",
1282		"--title=$config->{graphs}->{_mail4}  ($tf->{nwhen}$tf->{twhen})",
1283		"--start=-$tf->{nwhen}$tf->{twhen}",
1284		"--imgformat=$imgfmt_uc",
1285		"--vertical-label=bytes",
1286		"--width=$width",
1287		"--height=$height",
1288		@riglim,
1289		$zoom,
1290		@{$cgi->{version12}},
1291		@{$cgi->{version12_small}},
1292		@{$colors->{graph_colors}},
1293		"DEF:queues=$rrd:mail_queues:AVERAGE",
1294		"CDEF:allvalues=queues",
1295		@CDEF,
1296		"CDEF:K_queues=queues,1024,/",
1297		@tmp);
1298	$err = RRDs::error;
1299	push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG4: $err\n") if $err;
1300	if(lc($config->{enable_zoom}) eq "y") {
1301		($width, $height) = split('x', $config->{graph_size}->{zoom});
1302		$picz = $rrd{$version}->("$IMG_DIR" . "$IMG4z",
1303			"--title=$config->{graphs}->{_mail4}  ($tf->{nwhen}$tf->{twhen})",
1304			"--start=-$tf->{nwhen}$tf->{twhen}",
1305			"--imgformat=$imgfmt_uc",
1306			"--vertical-label=bytes",
1307			"--width=$width",
1308			"--height=$height",
1309			@riglim,
1310			$zoom,
1311			@{$cgi->{version12}},
1312			@{$cgi->{version12_small}},
1313			@{$colors->{graph_colors}},
1314			"DEF:queues=$rrd:mail_queues:AVERAGE",
1315			"CDEF:allvalues=queues",
1316			@CDEF,
1317			@tmpz);
1318		$err = RRDs::error;
1319		push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG4z: $err\n") if $err;
1320	}
1321	if($title || ($silent =~ /imagetag/ && $graph =~ /mail4/)) {
1322		if(lc($config->{enable_zoom}) eq "y") {
1323			if(lc($config->{disable_javascript_void}) eq "y") {
1324				push(@output, "      <a href=\"" . $config->{url} . "/" . $config->{imgs_dir} . $IMG4z . "\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG4 . "' border='0'></a>\n");
1325			} else {
1326				if($version eq "new") {
1327					$picz_width = $picz->{image_width} * $config->{global_zoom};
1328					$picz_height = $picz->{image_height} * $config->{global_zoom};
1329				} else {
1330					$picz_width = $width + 115;
1331					$picz_height = $height + 100;
1332				}
1333				push(@output, "      <a href=\"javascript:void(window.open('" . $config->{url} . "/" . $config->{imgs_dir} . $IMG4z . "','','width=" . $picz_width . ",height=" . $picz_height . ",scrollbars=0,resizable=0'))\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG4 . "' border='0'></a>\n");
1334			}
1335		} else {
1336			push(@output, "      <img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG4 . "'>\n");
1337		}
1338	}
1339
1340	@riglim = @{setup_riglim($rigid[4], $limit[4])};
1341	undef(@tmp);
1342	undef(@tmpz);
1343	undef(@CDEF);
1344	push(@tmp, "LINE2:none#4444EE:None");
1345	push(@tmp, "GPRINT:none:LAST:                 Current\\: %5.0lf\\n");
1346	push(@tmp, "LINE2:pass#44EE44:Pass");
1347	push(@tmp, "GPRINT:pass:LAST:                 Current\\: %5.0lf\\n");
1348	push(@tmp, "LINE2:softfail#EEEE44:SoftFail");
1349	push(@tmp, "GPRINT:softfail:LAST:             Current\\: %5.0lf\\n");
1350	push(@tmp, "LINE2:fail#EE4444:Fail");
1351	push(@tmp, "GPRINT:fail:LAST:                 Current\\: %5.0lf\\n");
1352	push(@tmpz, "LINE2:none#4444EE:None");
1353	push(@tmpz, "LINE2:pass#44EE44:Pass");
1354	push(@tmpz, "LINE2:softfail#EEEE44:SoftFail");
1355	push(@tmpz, "LINE2:fail#EE4444:Fail");
1356	if(lc($config->{show_gaps}) eq "y") {
1357		push(@tmp, "AREA:wrongdata#$colors->{gap}:");
1358		push(@tmpz, "AREA:wrongdata#$colors->{gap}:");
1359		push(@CDEF, "CDEF:wrongdata=allvalues,UN,INF,UNKN,IF");
1360	}
1361	($width, $height) = split('x', $config->{graph_size}->{small});
1362	if($silent =~ /imagetag/) {
1363		($width, $height) = split('x', $config->{graph_size}->{remote}) if $silent eq "imagetag";
1364		($width, $height) = split('x', $config->{graph_size}->{main}) if $silent eq "imagetagbig";
1365		@tmp = @tmpz;
1366		push(@tmp, "COMMENT: \\n");
1367		push(@tmp, "COMMENT: \\n");
1368		push(@tmp, "COMMENT: \\n");
1369	}
1370	$pic = $rrd{$version}->("$IMG_DIR" . "$IMG5",
1371		"--title=$config->{graphs}->{_mail5}  ($tf->{nwhen}$tf->{twhen})",
1372		"--start=-$tf->{nwhen}$tf->{twhen}",
1373		"--imgformat=$imgfmt_uc",
1374		"--vertical-label=Messages",
1375		"--width=$width",
1376		"--height=$height",
1377		@riglim,
1378		$zoom,
1379		@{$cgi->{version12}},
1380		@{$cgi->{version12_small}},
1381		@{$colors->{graph_colors}},
1382		"DEF:none=$rrd:mail_val01:AVERAGE",
1383		"DEF:pass=$rrd:mail_val02:AVERAGE",
1384		"DEF:softfail=$rrd:mail_val03:AVERAGE",
1385		"DEF:fail=$rrd:mail_val04:AVERAGE",
1386		"CDEF:allvalues=none,pass,softfail,fail,+,+,+",
1387		@CDEF,
1388		@tmp);
1389	$err = RRDs::error;
1390	push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG5: $err\n") if $err;
1391	if(lc($config->{enable_zoom}) eq "y") {
1392		($width, $height) = split('x', $config->{graph_size}->{zoom});
1393		$picz = $rrd{$version}->("$IMG_DIR" . "$IMG5z",
1394			"--title=$config->{graphs}->{_mail5}  ($tf->{nwhen}$tf->{twhen})",
1395			"--start=-$tf->{nwhen}$tf->{twhen}",
1396			"--imgformat=$imgfmt_uc",
1397			"--vertical-label=Messages",
1398			"--width=$width",
1399			"--height=$height",
1400			@riglim,
1401			$zoom,
1402			@{$cgi->{version12}},
1403			@{$cgi->{version12_small}},
1404			@{$colors->{graph_colors}},
1405			"DEF:none=$rrd:mail_val01:AVERAGE",
1406			"DEF:pass=$rrd:mail_val02:AVERAGE",
1407			"DEF:softfail=$rrd:mail_val03:AVERAGE",
1408			"DEF:fail=$rrd:mail_val04:AVERAGE",
1409			"CDEF:allvalues=none,pass,softfail,fail,+,+,+",
1410			@CDEF,
1411			@tmpz);
1412		$err = RRDs::error;
1413		push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG5z: $err\n") if $err;
1414	}
1415	if($title || ($silent =~ /imagetag/ && $graph =~ /mail5/)) {
1416		if(lc($config->{enable_zoom}) eq "y") {
1417			if(lc($config->{disable_javascript_void}) eq "y") {
1418				push(@output, "      <a href=\"" . $config->{url} . "/" . $config->{imgs_dir} . $IMG5z . "\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG5 . "' border='0'></a>\n");
1419			} else {
1420				if($version eq "new") {
1421					$picz_width = $picz->{image_width} * $config->{global_zoom};
1422					$picz_height = $picz->{image_height} * $config->{global_zoom};
1423				} else {
1424					$picz_width = $width + 115;
1425					$picz_height = $height + 100;
1426				}
1427				push(@output, "      <a href=\"javascript:void(window.open('" . $config->{url} . "/" . $config->{imgs_dir} . $IMG5z . "','','width=" . $picz_width . ",height=" . $picz_height . ",scrollbars=0,resizable=0'))\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG5 . "' border='0'></a>\n");
1428			}
1429		} else {
1430			push(@output, "      <img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG5 . "'>\n");
1431		}
1432	}
1433
1434	@riglim = @{setup_riglim($rigid[5], $limit[5])};
1435	undef(@tmp);
1436	undef(@tmpz);
1437	undef(@CDEF);
1438	if(lc($mail->{greylist}) eq "milter-greylist") {
1439		push(@tmp, "AREA:greylisted#4444EE:Greylisted");
1440		push(@tmp, "GPRINT:greylisted:LAST:           Current\\: %5.0lf\\n");
1441		push(@tmp, "AREA:whitelisted#44EEEE:Whitelisted");
1442		push(@tmp, "GPRINT:whitelisted:LAST:          Current\\: %5.0lf\\n");
1443		push(@tmp, "LINE2:greylisted#0000EE");
1444		push(@tmp, "LINE2:whitelisted#00EEEE");
1445		push(@tmp, "LINE2:records#EE0000:Records");
1446		push(@tmp, "GPRINT:records:LAST:              Current\\: %5.0lf\\n");
1447		push(@tmpz, "AREA:greylisted#4444EE:Greylisted");
1448		push(@tmpz, "AREA:whitelisted#44EEEE:Whitelisted");
1449		push(@tmpz, "LINE2:greylisted#0000EE");
1450		push(@tmpz, "LINE2:whitelisted#00EEEE");
1451		push(@tmpz, "LINE2:records#EE0000:Records");
1452	}
1453	if(lc($mail->{greylist}) eq "postgrey") {
1454		push(@tmp, "LINE2:greylisted#0000EE:Greylisted");
1455		push(@tmp, "GPRINT:greylisted:LAST:           Current\\: $gl_valform\\n");
1456		push(@tmp, "LINE2:delayed#EEEE00:Delayed");
1457		push(@tmp, "GPRINT:delayed:LAST:              Current\\: $gl_valform\\n");
1458		push(@tmp, "LINE2:whitelisted#00EEEE:Whitelisted");
1459		push(@tmp, "GPRINT:whitelisted:LAST:          Current\\: $gl_valform\\n");
1460		push(@tmp, "LINE2:records#EE00EE:Passed");
1461		push(@tmp, "GPRINT:records:LAST:               Current\\: $gl_valform\\n");
1462		push(@tmpz, "LINE2:greylisted#0000EE:Greylisted");
1463		push(@tmpz, "LINE2:delayed#EEEE00:Delayed");
1464		push(@tmpz, "LINE2:whitelisted#00EEEE:Whitelisted");
1465		push(@tmpz, "LINE2:records#EE00EE:Passed");
1466	}
1467	if(lc($config->{show_gaps}) eq "y") {
1468		push(@tmp, "AREA:wrongdata#$colors->{gap}:");
1469		push(@tmpz, "AREA:wrongdata#$colors->{gap}:");
1470		push(@CDEF, "CDEF:wrongdata=allvalues,UN,INF,UNKN,IF");
1471	}
1472	($width, $height) = split('x', $config->{graph_size}->{small});
1473	if($silent =~ /imagetag/) {
1474		($width, $height) = split('x', $config->{graph_size}->{remote}) if $silent eq "imagetag";
1475		($width, $height) = split('x', $config->{graph_size}->{main}) if $silent eq "imagetagbig";
1476		@tmp = @tmpz;
1477		push(@tmp, "COMMENT: \\n");
1478		push(@tmp, "COMMENT: \\n");
1479		push(@tmp, "COMMENT: \\n");
1480	}
1481	$pic = $rrd{$version}->("$IMG_DIR" . "$IMG6",
1482		"--title=$config->{graphs}->{_mail6}  ($tf->{nwhen}$tf->{twhen})",
1483		"--start=-$tf->{nwhen}$tf->{twhen}",
1484		"--imgformat=$imgfmt_uc",
1485		"--vertical-label=$rate_label",
1486		"--width=$width",
1487		"--height=$height",
1488		@riglim,
1489		$zoom,
1490		@{$cgi->{version12}},
1491		@{$cgi->{version12_small}},
1492		@{$colors->{graph_colors}},
1493		"DEF:records=$rrd:mail_val07:AVERAGE",
1494		"DEF:greylisted=$rrd:mail_val08:AVERAGE",
1495		"DEF:whitelisted=$rrd:mail_val09:AVERAGE",
1496		"DEF:delayed=$rrd:mail_val10:AVERAGE",
1497		"CDEF:allvalues=records,greylisted,whitelisted,delayed,+,+,+",
1498		@CDEF,
1499		@tmp);
1500	$err = RRDs::error;
1501	push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG6: $err\n") if $err;
1502	if(lc($config->{enable_zoom}) eq "y") {
1503		($width, $height) = split('x', $config->{graph_size}->{zoom});
1504		$picz = $rrd{$version}->("$IMG_DIR" . "$IMG6z",
1505			"--title=$config->{graphs}->{_mail6}  ($tf->{nwhen}$tf->{twhen})",
1506			"--start=-$tf->{nwhen}$tf->{twhen}",
1507			"--imgformat=$imgfmt_uc",
1508			"--vertical-label=$rate_label",
1509			"--width=$width",
1510			"--height=$height",
1511			@riglim,
1512			$zoom,
1513			@{$cgi->{version12}},
1514			@{$cgi->{version12_small}},
1515			@{$colors->{graph_colors}},
1516			"DEF:records=$rrd:mail_val07:AVERAGE",
1517			"DEF:greylisted=$rrd:mail_val08:AVERAGE",
1518			"DEF:whitelisted=$rrd:mail_val09:AVERAGE",
1519			"DEF:delayed=$rrd:mail_val10:AVERAGE",
1520			"CDEF:allvalues=records,greylisted,whitelisted,delayed,+,+,+",
1521			@CDEF,
1522			@tmpz);
1523		$err = RRDs::error;
1524		push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG6z: $err\n") if $err;
1525	}
1526	if($title || ($silent =~ /imagetag/ && $graph =~ /mail6/)) {
1527		if(lc($config->{enable_zoom}) eq "y") {
1528			if(lc($config->{disable_javascript_void}) eq "y") {
1529				push(@output, "      <a href=\"" . $config->{url} . "/" . $config->{imgs_dir} . $IMG6z . "\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG6 . "' border='0'></a>\n");
1530			} else {
1531				if($version eq "new") {
1532					$picz_width = $picz->{image_width} * $config->{global_zoom};
1533					$picz_height = $picz->{image_height} * $config->{global_zoom};
1534				} else {
1535					$picz_width = $width + 115;
1536					$picz_height = $height + 100;
1537				}
1538				push(@output, "      <a href=\"javascript:void(window.open('" . $config->{url} . "/" . $config->{imgs_dir} . $IMG6z . "','','width=" . $picz_width . ",height=" . $picz_height . ",scrollbars=0,resizable=0'))\"><img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG6 . "' border='0'></a>\n");
1539			}
1540		} else {
1541			push(@output, "      <img src='" . $config->{url} . "/" . $config->{imgs_dir} . $IMG6 . "'>\n");
1542		}
1543	}
1544
1545	if($title) {
1546		push(@output, "    </td>\n");
1547		push(@output, "    </tr>\n");
1548		push(@output, main::graph_footer());
1549	}
1550	push(@output, "  <br>\n");
1551	return @output;
1552}
1553
15541;
1555