Handle hostnames with upper-case letters
[webmin.git] / status / mailserver-monitor.pl
1 # mailserver-monitor.pl
2 # Check a remote mail server by sending email at period intervals and waiting
3 # for a response. This depends on the remote address being an autoreponder that
4 # replies to the sending address with the same or derived subject line.
5 # XXX other monitors (like net) should be able to do the same thing ..
6
7 $alias_name = "webmin-status-mailserver";
8 $replies_file = "$module_config_directory/mailserver-replies";
9
10 sub get_mailserver_status
11 {
12 local %oldstatus;
13 &read_file($oldstatus_file, \%oldstatus);
14 local $rv = { 'up' => defined($oldstatus{$_[0]->{'id'}}) ?
15                         $oldstatus{$_[0]->{'id'}} : 1 };
16 local %replies;
17 &read_file($replies_file, \%replies);
18 local ($when, $got, $id) = split(/\s+/, $replies{$_[0]->{'id'}});
19 local $now = time();
20 local $timeout = $_[0]->{'timeout'}*($_[0]->{'units'} == 0 ? 1 :
21                                      $_[0]->{'units'} == 1 ? 60 :
22                                      $_[0]->{'units'} == 2 ? 60*60 : 24*60*60);
23 if ($got && $got <= $when + $timeout) {
24         # Reply received .. status should be OK
25         $rv = { 'up' => 1 };
26         }
27 if ($when + $timeout < $now) {
28         # Time has elapsed .. check if we got a response in time
29         if ($when && (!$got || $got > $when + $timeout)) {
30                 # We didn't!
31                 $rv = { 'up' => 0 };
32                 }
33
34         # Send a new message, just as the status monitor does
35         $id = time().".".$$;
36         local $from = "$alias_name\@".&get_system_hostname();
37         local $subject = "TEST-$_[0]->{'id'}-$id";
38         local $body = "Mail server test";
39         if ($config{'sched_smtp'}) {
40                 # Connect to SMTP server
41                 &open_socket($config{'sched_smtp'}, 25, MAIL);
42                 &smtp_command(MAIL);
43                 &smtp_command(MAIL, "helo ".&get_system_hostname()."\r\n");
44                 &smtp_command(MAIL, "mail from: <$from>\r\n");
45                 &smtp_command(MAIL, "rcpt to: <$_[0]->{'to'}>\r\n");
46                 &smtp_command(MAIL, "data\r\n");
47                 print MAIL "From: $from\r\n";
48                 print MAIL "To: $_[0]->{'to'}\r\n";
49                 print MAIL "Subject: $subject\r\n";
50                 print MAIL "\r\n";
51                 print MAIL "$body\r\n";
52                 &smtp_command(MAIL, ".\r\n");
53                 &smtp_command(MAIL, "quit\r\n");
54                 close(MAIL);
55                 }
56         else {
57                 # Run sendmail executable
58                 local %sconfig = &foreign_config("sendmail");
59                 open(MAIL, "|$sconfig{'sendmail_path'} -t -f$from >/dev/null 2>&1");
60                 print MAIL "From: $from\n";
61                 print MAIL "To: $_[0]->{'to'}\n";
62                 print MAIL "Subject: $subject\n";
63                 print MAIL "\n";
64                 print MAIL "$body\n";
65                 print MAIL "\n";
66                 close(MAIL);
67
68                 # Record in file
69                 $replies{$_[0]->{'id'}} = "$now 0 $id";
70                 &write_file($replies_file, \%replies);
71                 }
72         }
73 return $rv;
74 }
75
76 sub show_mailserver_dialog
77 {
78 print "<tr> <td colspan=4>$text{'mailserver_desc'}</td> </tr>\n";
79
80 print "<tr> <td><b>$text{'mailserver_to'}</b></td>\n";
81 print "<td><input name=to size=25 value='$_[0]->{'to'}'></td>\n";
82
83 print "<td><b>$text{'mailserver_timeout'}</b></td>\n";
84 print "<td><input name=timeout size=5 value='$_[0]->{'timeout'}'>\n";
85 print "<select name=units>\n";
86 for($i=0; defined($text{"mailserver_units_$i"}); $i++) {
87         printf "<option value=%s %s>%s\n",
88                 $i, $_[0]->{'units'} == $i ? "selected" : "",
89                 $text{"mailserver_units_$i"};
90         }
91 print "</select></td> </tr>\n";
92 }
93
94 sub parse_mailserver_dialog
95 {
96 # Parse and save inputs
97 $in{'to'} =~ /^\S+$/ || &error($text{'mailserver_eto'});
98 $in{'timeout'} =~ /^\d+$/ || &error($text{'mailserver_etimeout'});
99 $_[0]->{'to'} = $in{'to'};
100 $_[0]->{'timeout'} = $in{'timeout'};
101 $_[0]->{'units'} = $in{'units'};
102 &depends_check($_[0], "sendmail");
103
104 # Set up the alias if needed
105 &foreign_require("sendmail", "sendmail-lib.pl");
106 &foreign_require("sendmail", "aliases-lib.pl");
107 local $conf = &sendmail::get_sendmailcf();
108 local $afile = &sendmail::aliases_file($conf);
109 local @aliases = &sendmail::list_aliases($afile);
110 local ($reply) = grep { $_->{'name'} eq $alias_name } @aliases;
111
112         # We do need to set up a wrapper to call the real mailserver.pl
113         local $alias_cmd = "$module_config_directory/mailserver.pl";
114         local $perl_path = &get_perl_path();
115         &lock_file($alias_cmd);
116         open(CMD, ">$alias_cmd");
117         print CMD <<EOF;
118 #!$perl_path
119 open(CONF, "$config_directory/miniserv.conf") ||
120         die "Failed to open miniserv.conf : \$!";
121 while(<CONF>) {
122         \$root = \$1 if (/^root=(.*)/);
123         }
124 close(CONF);
125 \$ENV{'WEBMIN_CONFIG'} = "$ENV{'WEBMIN_CONFIG'}";
126 \$ENV{'WEBMIN_VAR'} = "$ENV{'WEBMIN_VAR'}";
127 chdir("\$root/$module_name");
128 exec("\$root/$module_name/mailserver.pl", \$ARGV[0]);
129 EOF
130         close(CMD);
131         chmod(06755, $alias_cmd);
132         &unlock_file($alias_cmd);
133
134 if (!$reply) {
135         # Create the alias
136         local $alias = { 'name' => $alias_name,
137                          'values' => [ "|".$alias_cmd ],
138                          'enabled' => 1 };
139         &sendmail::create_alias($alias, $afile);
140         }
141
142 local %sconfig = &foreign_config("sendmail");
143 if (-d $sconfig{'smrsh_dir'}) {
144         &system_logged("ln -s $alias_cmd $sconfig{'smrsh_dir'}/mailserver.pl >/dev/null 2>&1");
145         }
146
147 # Create the file to which replies are written
148 open(TOUCH, ">>$replies_file");
149 close(TOUCH);
150 #chmod(0777, $replies_file);
151 }
152