#!/usr/bin/perl # Drakwizard # Copyright (C) 2002, 2005 Mandrakesoft # # Authors: Antoine Ginies # Arnaud Desmons # Florent Villard # # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. package MDK::Wizard::Postfix; use strict; use lib qw(/usr/lib/libDrakX); # required for service package use common; use MDK::Wizard::Wizcommon; use MDK::Wizard::Varspaceval; use Libconf qw(:functions); use Libconf::Glueconf::Postfix::Main_cf; my $default_conf = "/etc/postfix/main.cf.dist"; # provide a default postfix configuration file !-d mkdir("/etc/postfix/") and mkdir("/etc/postfix/"); !-f $default_conf and cp_af("/usr/share/wizards/postfix_wizard/scripts/main.cf.dist.default", $default_conf); if (!-f "/etc/postfix/main.cf") { cp_af($default_conf, "/etc/postfix/main.cf") } my $postfix = new Libconf::Glueconf::Postfix::Main_cf({ filename => '/etc/postfix/main.cf', }); use Data::Dumper; print Dumper($postfix); my $wiz = new MDK::Wizard::Wizcommon; my $wiz_domain_name = $wiz->{net}->network_get("DOMAINNAME"); my $wiz_host_name = $wiz->{net}->network_get("HOSTNAME"); my $wiz_postfix_etc = "/etc/sysconfig/wizard_postfix"; my ($IPSERVER_MASQ) = `/sbin/ip addr show dev eth1` =~ /^\s*inet\s+(\d+\.\d+\.\d+)\.\d+/m; my $o = { name => N("Postfix wizard"), var => { wiz_myhostname => '', wiz_mydomain => '', wiz_myorigin => '', wiz_inet_interfaces => '', wiz_mydestination => '', wiz_mynetworks => '', wiz_smtpd_helo_required => '', wiz_disable_vrfy_command => '', wiz_maximal_queue_lifetime => '', wiz_message_size_limit => '', wiz_smtpd_banner => '', wiz_debug_peer_level => '', wiz_debugger_command => '', wiz_delay_warning_time => '', wiz_sendmail_path => '', wiz_newaliases_path => '', wiz_mailq_path => '', wiz_setgid_group => '', wiz_manpage_directory => '', wiz_sample_directory => '', wiz_readme_directory => '', wiz_html_directory => '', wiz_masquerade_domains => '', wiz_mail_masquerade => '', wiz_relayhost => '', wiz_relay_domains => '', }, init => sub { check_sendmail(); my $t = any { /$wiz_host_name/ } cat_("/etc/hosts"); if ($t == 0) { return 0, N("Error, can't find your hostname in /etc/hosts. Exiting. Please launch drakconnect and choose static IP address."); } 1; }, needed_rpm => [ 'postfix' ], defaultimage => "$ENV{__WIZ_HOME__}postfix_wizard/images/courrier.png" }; $::Wizard_pix_up = "/usr/share/mcc/themes/default/postfix-mdk.png"; my %type = ( 1 => N("Main mail server"), 2 => N("Relay mail server"), ); my %understanding = ( 1 => N("Newbie - classical options"), 2 => N("Expert - advanced options"), ); my @yesorno = qw(yes no); push @yesorno, ""; $o->{pages} = { welcome => { name => N("Internet mail configuration wizard") . "\n\n" . N("This wizard will help you configure a Postfix mail server or a Postfix mail relay."), no_back => 1, pre => sub { $postfix->{relayhost} and $o->{var}{wiz_type} = 2; if (-f $wiz_postfix_etc) { $::in->ask_warn(N("Information"), N("It seems you previously setup a Postfix configuration. This wizard will re-read your old configuration, and show you the Postfix server type you choose")); my $data = cat_($wiz_postfix_etc); # detect old Postfix type my ($old_type) = $data =~ /type=(\d)/; $o->{var}{wiz_type} = chomp_($old_type); } else { $o->{var}{wiz_type} = 1 } }, data => [ { label => N("What do you want to do:"), val => \$o->{var}{wiz_type}, list => [ keys %type ], format => sub { $type{$_[0]} } }, ], next => 'global_config', }, understanding => { name => N('Now I need to know your understanding in Postfix server configuration'), data => [ { label => N("What kind of user are you:"), val => \$o->{var}{wiz_understanding}, list => [ keys %understanding ], format => sub { $understanding{$_[0]} } }, ], no_back => 1, next => 'global_config', }, global_config => { name => N('Global postfix configuration'), pre => sub { $o->{var}{wiz_smtpd_banner} ||= $postfix->{smtpd_banner}; $o->{var}{wiz_myhostname} ||= $postfix->{myhostname} or $o->{var}{wiz_myhostname} = $wiz_host_name; $o->{var}{wiz_mydomain} ||= $postfix->{mydomain} or $o->{var}{wiz_mydomain} = $wiz_domain_name; $o->{var}{wiz_myorigin} ||= $postfix->{myorigin}; }, post => sub { if ($o->{var}{wiz_type} == 1) { return 'main_server' ; } else { return 'relay_server'; } }, data => [ { label => N('Smtpd banner:'), val => \$o->{var}{wiz_smtpd_banner}, help => 'You MUST specify $myhostname at the start of the text. That is an RFC requirement. ie: $myhostname ESMTP $mail_name ($mail_version) (Mandriva Linux)' }, { label => N('Hostname:'), val => \$o->{var}{wiz_myhostname}, help => N('The myhostname parameter specifies the internet hostname of this mail system. ie: myhostname = myhostname') }, { label => N('Domain:'), val => \$o->{var}{wiz_mydomain}, help => N('The mydomain parameter specifies the local internet domain name. ie: mydomain = mydomain') }, { label => N('Origin:'), val => \$o->{var}{wiz_myorigin}, help => N('The myorigin parameter specifies the domain that locally-posted mail appears to come from. ie: myorigin = $myhostname') }, ], complete => sub { if (!$o->{var}{wiz_smtpd_banner}) { $::in->ask_warn(N('Error'), N('Please provide an Smtpd banner.')); return 1; } if (!$o->{var}{wiz_myhostname}) { $::in->ask_warn(N('Error'), N('You must provide an internet hostname of this mail system.')); return 1; } if (!$o->{var}{wiz_mydomain}) { $::in->ask_warn(N('Error'), N('You must specify the local internet domain name.')); return 1; } }, }, main_server => { name => N('Main Postfix server') . "\n\n" . N('helo_required: require that a remote SMTP client introduces itself at the beginning of an SMTP session with the HELO or EHLO command.') . "\n" . N('Verify command: this stops some techniques used to harvest email addresses.'), pre => sub { $o->{var}{wiz_smtpd_helo_required} ||= $postfix->{smtpd_helo_required}; $o->{var}{wiz_disable_vrfy_command} ||= $postfix->{disable_vrfy_command}; $o->{var}{wiz_masquerade_domains} ||=$postfix->{masquerade_domains}; }, data => [ { label => N('helo required:'), val => \$o->{var}{wiz_smtpd_helo_required}, fixed_list => \@yesorno }, { label => N('Disable verify command:'), val => \$o->{var}{wiz_disable_vrfy_command}, fixed_list => \@yesorno }, { label => N('Masquerade domains'), val => \$o->{var}{wiz_masquerade_domains}, help => N('This should be chosen consistently with the address you use for incoming mail. Address masquerading is a method to hide all hosts inside a domain behind their mail gateway, and to make it appear as if the mail comes from the gateway itself, instead of from individual machines.') }, ], complete => sub { if ($o->{var}{wiz_masquerade_domains} !~ /\w+\.\w+\s\w+\.\w+$/ and $o->{var}{wiz_masquerade_domains}) { $::in->ask_warn(N("Error"), N("Masquerade should be a valid domain name such as \"domain_to_masquerade.com with_this_domain.com\"!")); return 1; } else { return 0; }; }, next => 'message_config', }, relay_server => { name => N('Relay server') . N('Relay domains: what destination domains (and subdomains thereof) this system will relay mail to.') . "\n" , pre => sub { $o->{var}{wiz_relayhost} ||= $postfix->{relayhost}; $postfix->{relay_domains} and $o->{var}{wiz_relay_domains} = $postfix->{relay_domains} or $o->{var}{wiz_relay_domains} = $wiz_domain_name; }, data => [ { label => N('Relay host:'), val => \$o->{var}{wiz_relayhost}, help => 'The default host to send non-local mail to when no entry is matched in the optional transport(5) table. ie: relayhost = [gateway.my.domain], relayhost = uucphost, relayhost = [an.ip.add.ress].' }, { label => N('Relay domains:'), val => \$o->{var}{wiz_relay_domains}, help => N('What destination domains (and subdomains thereof) this system will relay mail to. ie: mydomain.com') }, ], complete => sub { if (!$o->{var}{wiz_relayhost}) { $::in->ask_warn(N('Error'), N('Need a relayhost.')); return 1; } else { return 0; }; }, next => 'message_config', }, network_config => { name => N('Network config'), pre => sub { $postfix->{inet_interfaces} and $o->{var}{wiz_inet_interfaces} = $postfix->{inet_interfaces} or $o->{var}{wiz_inet_interfaces} = 'all'; $postfix->{mydestination} and $o->{var}{wiz_mydestination} = $postfix->{mydestination} or $o->{var}{wiz_mydestination} = "\$myhostname, localhost.\$mydomain"; my $mynetworks; $IPSERVER_MASQ and $mynetworks = "127.0.0.0/32, " . $IPSERVER_MASQ . ".0/24" or $mynetworks = "127.0.0.0/32"; $postfix->{mynetworks} and $o->{var}{wiz_mynetworks} = $postfix->{mynetworks} or $o->{var}{wiz_mynetworks} = $mynetworks; $o->{var}{wiz_mynetworks_style} ||= $postfix->{mynetworks_style}; }, data => [ { label => N('inet interfaces:'), val => \$o->{var}{wiz_inet_interfaces}, help => N('The network interface addresses that this mail system receives mail on. By default, the software claims all active interfaces on the machine. ie: all') }, { label => N('my destination:'), val => \$o->{var}{wiz_mydestination}, help => N('The list of domains that are delivered via the $local_transport mail delivery transport. ie: $myhostname, localhost.$mydomain, /etc/postfix/destinations') }, { label => N('my networks:'), val => \$o->{var}{wiz_mynetworks}, help => N('The list of trusted SMTP clients. ie: 127.0.0.0/32, 192.168.1.0/24') }, ], complete => sub { if (!$o->{var}{wiz_mynetworks}) { $::in->ask_warn(N('Error'), N('This is the list of trusted SMTP clients. For security reason, please provide one. ie: 127.0.0.0/32, 192.168.1.0/24')); return 1; } else { return 0; }; }, post => sub { if ($o->{var}{wiz_type} == 1) { return 'summary_main' ; } else { return 'summary_relay'; } } }, message_config => { name => N('Message options') . N('Various options to configure your message queue, delay, size...'), pre => sub { $postfix->{maximal_queue_lifetime} and $o->{var}{wiz_maximal_queue_lifetime} = $postfix->{maximal_queue_lifetime} or $o->{var}{wiz_maximal_queue_lifetime} = "5d"; $postfix->{message_size_limit} and $o->{var}{wiz_message_size_limit} = $postfix->{message_size_limit} or $o->{var}{wiz_message_size_limit} = "10240000"; $o->{var}{wiz_delay_warning_time} ||= $postfix->{delay_warning_time} or $postfix->{delay_warning_time} = "2h"; }, data => [ { label => N('Maximal queue life:'), val => \$o->{var}{wiz_maximal_queue_lifetime}, help => N('Determines how long a message should stay in the queue before it is deemed undeliverable. The default is five days (5d)') }, { label => N('Message size limit:'), val => \$o->{var}{wiz_message_size_limit}, help => N('Maximum size of a message in Kb') }, { label => N('Delay warning time:'), val => \$o->{var}{wiz_delay_warning_time}, help => N('The delay_warning_time specifies after how many hours a warning is sent that mail has not yet been delivered.') }, ], next => 'network_config', }, error_sendmail => { name => N("Error, sendmail is installed. Please remove it before installing or configuring Postfix"), no_back => 1, next => 0, end => 1, }, summary_relay => { name => N("Configuring your relay mail server") . "\n\n" . N("The wizard collected the following parameters needed to configure your relay mail server:") . "\n\n" . N("To accept these values, and configure your server, click the next button or use the back button to correct them."), data => [ { label => N('Relay host:'), fixed_val => \$o->{var}{wiz_relayhost} }, { label => N('Relay domains:'), fixed_val => \$o->{var}{wiz_relay_domains} }, ], post => \&do_it_relay_server, next => 'end' }, summary_main => { name => N("The wizard will now configure your Postfix mail server."), data => [ { label => N('inet interfaces:'), fixed_val => \$o->{var}{wiz_inet_interfaces} }, { label => N('my destination:'), fixed_val => \$o->{var}{wiz_mydestination} }, { label => N('my networks:'), fixed_val => \$o->{var}{wiz_mynetworks} }, ], post => \&do_it_main_server, next => 'end' }, end => { name => N("Congratulations") . "\n\n" . N("The wizard successfully configured your Postfix Mail server."), post => sub { store_postfix_type($o->{var}{wiz_type}); }, no_back => 1, end => 1, next => 0 }, error_end => { name => N("Failed"), data => [ { label => N("Please relaunch drakwizard, and try to change some parameters.") } ], no_back => 1, end => 1, next => 0, }, }; sub new { my ($class) = @_; bless $o, $class; } sub check_sendmail { my $in = 'interactive'->vnew('su', 'Check sendmail'); my $w = $in->wait_message(N("Postfix Server"), N("removing Sendmail to avoid conflict....")); my $test = any { /sendmail/ } system("rpm -q sendmail"); !$test or return 'error_sendmail'; undef $w; } sub postfix_options { # global $o->{var}{wiz_myhostname} and $postfix->{myhostname} = $o->{var}{wiz_myhostname}; $o->{var}{wiz_mydomain} and $postfix->{mydomain} = $o->{var}{wiz_mydomain}; $o->{var}{wiz_myorigin} and $postfix->{myorigin} = $o->{var}{wiz_myorigin}; $o->{var}{wiz_inet_interfaces} and $postfix->{inet_interfaces} = $o->{var}{wiz_inet_interfaces}; $o->{var}{wiz_mydestination} and $postfix->{mydestination} = $o->{var}{wiz_mydestination}; $o->{var}{wiz_mynetworks} and $postfix->{mynetworks} = $o->{var}{wiz_mynetworks}; $o->{var}{wiz_smtpd_banner} and $postfix->{smtpd_banner} = $o->{var}{wiz_smtpd_banner}; # not defined but wanted $postfix->{debug_peer_level} or $postfix->{debug_peer_level} = "1"; #$postfix->{debugger_command} or $postfix->{debugger_command} = "PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin xxgdb $daemon_directory/$process_name $process_id & sleep 5"; $postfix->{sendmail_path} or $postfix->{sendmail_path} = "/usr/sbin/sendmail.postfix"; $postfix->{newaliases_path} or $postfix->{newaliases_path} = "/usr/bin/newaliases.postfix"; $postfix->{mailq_path} or $postfix->{mailq_path} = "/usr/bin/mailq.postfix"; $postfix->{setgid_group} or $postfix->{setgid_group} = "postdrop"; $postfix->{alias_maps} or $postfix->{alias_maps} = "hash:/etc/postfix/aliases"; $postfix->{mail_spool_directory} or $postfix->{mail_spool_directory} = "/var/spool/mail"; $postfix->{alias_database} or $postfix->{alias_database} = "hash:/etc/postfix/aliases"; $postfix->{command_directory} or $postfix->{command_directory} = "/usr/sbin"; $postfix->{queue_directory} or $postfix->{queue_directory} = "/var/spool/postfix"; $postfix->{daemon_directory} or $postfix->{daemon_directory} = "/usr/lib/postfix"; $postfix->{mail_owner} or $postfix->{mail_owner} = "postfix"; } sub store_postfix_type { # write config file to store Postfix type my ($type) = @_; output($wiz_postfix_etc, <write_conf("/etc/postfix/main.cf"); require services; if (services::is_service_running('postfix')) { services::restart('postfix'); } else { services::start('postfix'); } } sub do_it_relay_server { $::testing and return; my $in = 'interactive'->vnew('su', 'postfix configuration'); my $w = $in->wait_message(N("Postfix Server"), N("Configuring your Postfix server.....")); save_config(); postfix_options(); $o->{var}{wiz_relayhost} and $postfix->{relayhost} = $o->{var}{wiz_relayhost}; $o->{var}{wiz_relay_domains} and $postfix->{relay_domains} = $o->{var}{wiz_relay_domains}; # remove server unwanted options $postfix->{smtpd_helo_required} and delete $postfix->{smtpd_helo_required}; $postfix->{disable_vrfy_command} and delete $postfix->{disable_vrfy_command}; $postfix->{masquerade_domains} and delete $postfix->{masquerade_domains}; cmd_needed(); undef $w; check_started('master'); } sub do_it_main_server { $::testing and return; my $in = 'interactive'->vnew('su', 'postfix configuration'); my $w = $in->wait_message(N("Postfix Server"), N("Configuring your Postfix server.....")); save_config(); postfix_options(); $o->{var}{wiz_smtpd_helo_required} and $postfix->{smtpd_helo_required} = $o->{vawiz_smtpd_helo_required}; $o->{var}{wiz_disable_vrfy_command} and $postfix->{disable_vrfy_command} = $o->{var}{wiz_disable_vrfy_command}; $o->{var}{wiz_maximal_queue_lifetime} and $postfix->{maximal_queue_lifetime} = $o->{var}{wiz_maximal_queue_lifetime}; $o->{var}{wiz_message_size_limit} and $postfix->{message_size_limit} = $o->{var}{wiz_message_size_limit}; $o->{var}{wiz_masquerade_domains} and $postfix->{masquerade_domains} = $o->{var}{wiz_masquerade_domains}; $o->{var}{wiz_delay_warning_time} and $postfix->{delay_warning_time} = $o->{var}{wiz_delay_warning_time}; # remove relay options $postfix->{relayhost} and delete $postfix->{relayhost}; $postfix->{relay_domains} and delete $postfix->{relay_domains}; cmd_needed(); undef $w; check_started('master'); } 1;