Blueonyx 5.x 安装 OpenWebmail

By | 2018-11-26
其实安装方法很简单,但确实花了小弟不少时间,以下是详细过程:

平台:  Blueonyx 5.6 + OpenWebmail 2.5.1

下载最新版本的 BlueOnyx , 这套系统还是免费的,前身就是大名鼎鼎的 Sun Cobalt ,当时开发出来是给 ICP 作为 Web host用,系统包括Email Server(SMTP/POP3/IMAP)、FTP Server 、DNS Server、Web Server 全部包括,最适用于ICP主机出租业务了; 介绍就到这里,继续安装。

  • 安装OpenWebmail

Blueonyx 的安装就不再说明了,因为就是光盘安装的很简单,只要稍懂英文真的没有什么难度了! 系统是“定制”版本的 CentOS5 ,所以安装软件与CentOS安装没有什么区别,简单点就是取得“软件源库” repo 文件,然后 yum install xxxxxx 即可,跟”大便“的 apt-get 一样很给力的
其实系统自带有 webmail 了,就是SquirrelMail , 但小弟用了Openwebmail快10年了,感觉很顺手,界面也很友好,功能也全部好用,所以先入为主吧,还是需要在这个系统上使用,所以才post该文!

下文内容参考自: http://coding.infoconex.com/page/Installing-OpenWebmail-on-BlueOnyx-server.aspx

1) Grab the latest install of openwebmail from: http://openwebmail.acatysmoof.com/

2) 下载 openwebmail文件包到 /var/www

3) 解压文件包

  • tar -xvzf openwebmail-2.53.tar.gz
  • This will extract files to 2 different directories
    • /var/www/cgi-bin/openwebmail
    • /var/www/data/openwebmail

4) 更改目录权限为 root:mail

  • chown root:mail /var/www/cgi-bin/openwebmail
  • chown root:mail /var/www/data/openwebmail

5) 安装Text::Iconv perl模块

  • yum install perl-Text-Iconv

    或者直接下载rpm包安装

  • http://openwebmail.org/openwebmail/download/redhat/rpm/packages/centos5/
    下载 perl-Text-Iconv/ 的rpm包到 Blueonyx 中,然后执行
    # rpm -i perl-Text-Iconv.xx.xxx.rpm

6) 新建apache配置文件

  • 新建 /etc/httpd/conf.d/httpd_openwebmail.conf
  • 贴上以下内容或者直接下载该文件: http_openwebmail.conf

 

### Begin – Added for openwebmail ###

ScriptAlias /webmail “/var/www/cgi-bin/openwebmail/openwebmail.pl”
ScriptAlias /openwebmail “/var/www/cgi-bin/openwebmail/”
Alias /data “/var/www/data”

<Directory /var/www/cgi-bin/openwebmail>
AllowOverride None
Options +ExecCGI
Order allow,deny
Allow from all
AddHandler cgi-script .cgi .pl
</Directory>

<Directory “/var/www/data/openwebmail”>
ExpiresActive On
ExpiresByType image/gif A86400
ExpiresByType image/png A86400
ExpiresByType image/jpg A86400
ExpiresByType application/x-javascript A86400
</Directory>

###  End  ###

7) 修改两个openwebmail.conf文件的参数

  • vi /var/www/cgi-bin/openwebmail/etc/openwebmail.conf
    再者就是
    vi /var/www/cgi-bin/openwebmail/etc/default/openwebmail.conf
    两个文件里的对应参数都必须按以下修改
    • auth_module                   auth_pam_cobalt.pl
    • ow_cgidir                         /var/www/cgi-bin/openwebmail
    • ow_cgiurl                         /openwebmail
    • ow_htmldir                       /var/www/data/openwebmail
    • ow_htmlurl                       /data/openwebmail

      这里的 auth_pam_cobalt.pl 里 Sun Cobalt 公司专用的验证程序
      程序代码来自: http://cobaltfaqs.com/index.php?title=Auth_pam_cobalt.pl&redirect=no

      以上内容请在 /var/www/cgi-bin/openwebmail/auth 目录下创建

      #***************************  auth_pam_cobalt.pl  ********************************

      package ow::auth_pam_cobalt;
      use strict;
      #
      # auth_pam.pl - authenticate user with PAM
      #
      # 2002/08/01 webmaster.AT.pkgmaster.com
      #            add check for nologin, validshell, cobaltuser
      #            based on work from Trevor.Paquette.AT.TeraGo.ca
      # 2001/10/05 tung.AT.turtle.ee.ncku.edu.tw
      #
      # The code of check_userpassword and change_userpassword is from
      # the example code of Authen::PAM by Nikolay Pelov <nikip.AT.iname.com>
      # Webpage is available at http://www.cs.kuleuven.ac.be/~pelov/pam
      #
      
      ########## No configuration required from here ###################
      
      use Authen::PAM;
      use Fcntl qw(:DEFAULT :flock);
      require "modules/filelock.pl";
      require "modules/tool.pl";
      
      my %conf;
      if (($_=ow::tool::find_configfile('etc/auth_pam.conf', 'etc/defaults/auth_pam.conf')) ne '') {
         my ($ret, $err)=ow::tool::load_configfile($_, \%conf);
         die $err if ($ret<0);
      }
      
      my $servicename = $conf{'servicename'} || "login";
      my $passwdfile_plaintext = $conf{'passwdfile_plaintext'} || "/etc/passwd";
      
      my $check_nologin = $conf{'check_nologin'} || 'no';
      my $check_shell = $conf{'check_shell'} || 'no';
      my $check_cobaltuser = $conf{'check_cobaltuser'} || 'no';
      
      ########## end init ##############################################
      
      # routines get_userinfo() and get_userlist still get data from a passwdfile
      # instead of PAM, you may have to rewrite if it does notfit your requirement
      
      #  0 : ok
      # -2 : parameter format error
      # -3 : authentication system/internal error
      # -4 : user doesn't exist
      sub get_userinfo {
         my ($r_config, $user)=@_;
         return(-2, 'User is null') if ($user eq '');
      
         my ($uid, $gid, $realname, $homedir);
         if ($passwdfile_plaintext eq "/etc/passwd") {
            ($uid, $gid, $realname, $homedir)= (getpwnam($user))[2,3,6,7];
         } else {
            if ($passwdfile_plaintext=~/\|/) { # maybe NIS, try getpwnam first
               ($uid, $gid, $realname, $homedir)= (getpwnam($user))[2,3,6,7];
            }
            if ($uid eq "") { # else, open file directly
               ($uid, $gid, $realname, $homedir)= (getpwnam_file($user, $passwdfile_plaintext))[2,3,6,7];
            }
         }
         return(-4, "User $user doesn't exist") if ($uid eq "");
      
         # get other gid for this user in /etc/group
         while (my @gr=getgrent()) {
            $gid.=' '.$gr[2] if ($gr[3]=~/\b$user\b/ && $gid!~/\b$gr[2]\b/);
         }
         # use first field only
         $realname=(split(/,/, $realname))[0];
         # guess real homedir under sun's automounter
         $homedir="/export$homedir" if (-d "/export$homedir");
      
         return(0, "", $realname, $uid, $gid, $homedir);
      }
      
      
      #  0 : ok
      # -1 : function not supported
      # -3 : authentication system/internal error
      sub get_userlist {      # only used by openwebmail-tool.pl -a
         my $r_config=$_[0];
      
         my @userlist=();
         my $line;
      
         # a file should be locked only if it is local accessable
         if ( -f $passwdfile_plaintext) {
            ow::filelock::lock($passwdfile_plaintext, LOCK_SH) or
               return (-3, "Couldn't get read lock on $passwdfile_plaintext", @userlist);
         }
         open(PASSWD, $passwdfile_plaintext);
         while (defined($line=<PASSWD>)) {
            next if ($line=~/^#/);
            chomp($line);
            push(@userlist, (split(/:/, $line))[0]);
         }
         close(PASSWD);
         ow::filelock::lock($passwdfile_plaintext, LOCK_UN) if ( -f $passwdfile_plaintext);
         return(0, "", @userlist);
      }
      
      # globals passed to inner function to avoid closure effect
      use vars qw($pam_user $pam_password $pam_newpassword $pam_convstate);
      
      #  0 : ok
      # -2 : parameter format error
      # -3 : authentication system/internal error
      # -4 : password incorrect
      sub check_userpassword {
         my $r_config;
         local ($pam_user, $pam_password);    # localized global to make reentry safe
         ($r_config, $pam_user, $pam_password)=@_;
         return (-2, "User or password is null") if ($pam_user eq '' || $pam_password eq '');
      
         sub checkpwd_conv_func {
            my @res;
            while ( @_ ) {
               my $code = shift;
               my $msg = shift;
               my $ans = "";
      
               if ($code == PAM_PROMPT_ECHO_ON() ) {
                  $ans = $pam_user;
               } elsif ($code == PAM_PROMPT_ECHO_OFF() ) {
                  $ans = $pam_password;
               }
               push @res, (PAM_SUCCESS(),$ans);
      #ow::tool::log_time("code:$code, msg:$msg, ans:$ans\n");        # debug
            }
            push @res, PAM_SUCCESS();
            return @res;
         }
      
         # disable SIG CHLD since authsys in PAM may fork process
         local $SIG{CHLD}; undef $SIG{CHLD};
      
         my ($pamh, $ret, $errmsg);
         if ( ref($pamh = new Authen::PAM($servicename, $pam_user, \&checkpwd_conv_func)) ) {
            my $tty_name = "";
            my $error=$pamh->pam_set_item(PAM_TTY(), $tty_name);
            $error=$pamh->pam_authenticate();
            if ($error==0) {
               ($ret, $errmsg)= (0, "");
            } else {
               ($ret, $errmsg)= (-4, "pam_authticate() err $error, ".pam_strerror($pamh, $error));
            }
         } else {
            ($ret, $errmsg)= (-3, "PAM init error $pamh");
         }
         $pamh = 0;  # force Destructor (per docs) (invokes pam_close())
      
         return($ret, $errmsg) if ($ret<0);
      
         # emulate pam_nologin.so
         if ($check_nologin=~/yes/i && -e "/etc/nologin") {
            return (-4, "/etc/nologin found, all logins are suspended");
         }
         # emulate pam_shells.so
         if ($check_shell=~/yes/i && !has_valid_shell($pam_user)) {
            return (-4, "user $pam_user doesn't have valid shell");
         }
         # valid user on cobalt ?
         if ($check_cobaltuser=~/yes/i) {
            my $cbhttphost=$ENV{'HTTP_HOST'}; $cbhttphost=~s/:\d+$//; # remove port number
            my $cbhomedir="/home/sites/$cbhttphost/users/$pam_user";
            if (!-d $cbhomedir) {
               return (-4, "This cobalt user $pam_user doesn't has homedir $cbhomedir");
            }
         }
      
         return (0, "");
      }
      
      
      #  0 : ok
      # -1 : function not supported
      # -2 : parameter format error
      # -3 : authentication system/internal error
      # -4 : password incorrect
      sub change_userpassword {
         local ($pam_user, $pam_password, $pam_newpassword); # localized global to make reentry safe
         my $r_config;
         ($r_config, $pam_user, $pam_password, $pam_newpassword)=@_;
         return (-2, "User or password is null") if ($pam_user eq '' || $pam_password eq '' || $pam_newpassword eq '');
      
         local $pam_convstate=0;      # localized global to make reentry safe
         sub changepwd_conv_func {
            my @res;
      
            while ( @_ ) {
               my $code = shift;
               my $msg = shift;
               my $ans = "";
      
               if ($code == PAM_PROMPT_ECHO_ON() ) {
                  $ans = $pam_user;
               } elsif ($code == PAM_PROMPT_ECHO_OFF() ) {
                  if ($pam_convstate>1 || $msg =~ /new/i ) {
                     $ans = $pam_newpassword;
                  } else {
                     $ans = $pam_password;
                  }
                  $pam_convstate++;
               }
               push @res, (PAM_SUCCESS(),$ans);
      #ow::tool::log_time("code:$code, msg:$msg, ans:$ans\n");        # debug
            }
            push @res, PAM_SUCCESS();
            return @res;
         }
      
         # disable SIG CHLD since authsys in PAM may fork process
         local $SIG{CHLD}; undef $SIG{CHLD};
      
         my ($pamh, $ret, $errmsg);
         if (ref($pamh = new Authen::PAM($servicename, $pam_user, \&changepwd_conv_func)) ) {
            my $error=$pamh->pam_chauthtok();
            if ( $error==0 ) {
               ($ret, $errmsg)= (0, "");
            } else {
               ($ret, $errmsg)= (-4, "pam_authtok() err $error, ".pam_strerror($pamh, $error));
            }
         } else {
            ($ret, $errmsg)= (-3, "PAM init error $pamh");
         }
         $pamh = 0;  # force Destructor (per docs) (invokes pam_close())
         return($ret, $errmsg);
      }
      
      
      ########## misc support routine ##################################
      
      # this routine is slower than system getpwnam() but can work with file
      # other than /etc/passwd. ps: it always return '*' for passwd field.
      sub getpwnam_file {
         my ($user, $passwdfile_plaintext)=@_;
         my ($name, $passwd, $uid, $gid, $gcos, $dir, $shell);
      
         return("", "", "", "", "", "", "", "", "") if ($user eq "");
      
         open(PASSWD, "$passwdfile_plaintext");
         while(<PASSWD>) {
            next if (/^#/);
            chomp;
            ($name, $passwd, $uid, $gid, $gcos, $dir, $shell)=split(/:/);
            last if ($name eq $user);
         }
         close(PASSWD);
      
         if ($name eq $user) {
            return($name, "*", $uid, $gid, 0, "", $gcos, $dir, $shell);
         } else {
            return("", "", "", "", "", "", "", "", "");
         }
      }
      
      sub has_valid_shell {
         my $user=$_[0];
      
         my ($name, $shell);
         if ($passwdfile_plaintext eq "/etc/passwd") {
            $shell = (getpwnam($user))[8];
         } else {
            if ($passwdfile_plaintext=~/\|/) { # maybe NIS, try getpwnam first
               ($name, $shell)= (getpwnam($user))[0,8];
            }
            if ($name eq "") { # else, open file directly
               ($name, $shell) = (getpwnam_file($user, $passwdfile_plaintext))[0,8];
            }
         }
         return 0 if ($shell eq '');
      
         my $validshell = 0;
         if (open(ES, "/etc/shells")) {
            while(<ES>) {
               chomp;
               if( $shell eq $_ ) {
                  $validshell = 1; last;
               }
            }
            close(ES);
         }
         return 0 if (!$validshell);
      
         return 1;
      }
      
      1;

      #***************************  auth_pam_cobalt.pl  ********************************

  • Here is a complete example file that is from my system that reflects not only the above changes but other changes I make from the default to support our current user preferences.
  • openwebmail.conf
    • Note if you enable spell check like my above example configuration make sure you install the aspell library
    • yum install aspell
  • You should open /var/www/cgi-bin/openwebmail/etc/openwebmail.conf.help if you want to understand all the possible settings that can be made
    以上是openwebmail.conf的配置说明,大家可以从网上找到很多关于openwebmail默认配置实例,这里就不再重申了!

8) 修改 db.conf

  • nano -w /var/www/cgi-bin/openwebmail/etc/defaults/dbm.conf
  • 修改为以下内容
    dbm_ext                       .db
    dbmopen_ext               .db
    dbmopen_haslock        no

9) 重启 httpd 服务

  • /etc/init.d/httpd restart

10) 执行以下命令

  • /var/www/cgi-bin/openwebmail/openwebmail-tool.pl –init

      11) 完成全部安装及配置过程

  • http://server_ip_address/webmail

多域名時用戶跟隨域名:
openwebmail.conf 裡增加參數,寄件人地址會跟隨訪問OPENWEBMAIL使用的域名

domainoverride     yes
——————-

增加用户邮箱 quota 功能

# vi /var/www/cgi-bin/openwebmail/etc/openwebmail.conf

在文件最后加入以下代码,即限制用户邮箱空间为60M
############################################
# Quota System (limit in KB and threshold in %)
1 MB =     1,024 KB
10 MB =    10,240 KB
100 MB =   102,400 KB
1 GB = 1,024 MB = 1,048,576 KB
# uncomment following lines if you wish to enable Quota System for 10 Mb

quota_module            quota_du.pl    <– 如果使用 quota_unixfs.pl 將會跟隨系統對每個用戶的限額
spool_limit             61440
quota_limit             61440
quota_threshold         0
delmail_ifquotahit      yes
delfile_ifquotahit      yes

如果使用CentOS 平台 openwebmail 使用 auth_unix.pl 的验证模式,需要修改openwebmail.conf

# vi /var/www/cgi-bin/openwebmail/etc/defaults/auth_unix.conf

a. set passwdfile_encrypted to ‘/etc/shadow’

b. set passwdmkdb           to ‘none’

不然用户使用openwebmail无法登录

發佈留言