ExtMail服务器社区's Archiver

hmfjacky 发表于 2009-7-29 09:47

分享小弟針對emos 1.3備份mail perl 程式!

分享小弟針對 emos1.3 系統備份mail perl 程式!
小弟接觸perl 才二星期,寫得很粗糙,可能不適合各位大大,但因為小弟受到各位大大照顧,才能建置emos mail server ,所以想為論壇儘點棉薄之力,謝謝各位大大!!!

#!/usr/bin/perl
use File::Copy;
use File::stat;
use Date::Format;
use Mail::Internet;
use Encode qw/encode decode/;
use Encode;
use Encode::Guess qw/big5-eten utf8/;

#使用 postfix rcpt_bcc_list、send_bcc_list設定,將要備份mail 轉寄至 lin 目錄
sys_copy('/home/domains/mail.xxxx.com.tw/lin/Maildir/cur/','/backup/mail/');
sys_copy('/home/domains/mail.xxxx.com.tw/lin/Maildir/new/','/backup/mail/');
#要篩選使用者
@user=("jliu","young7","elaine","pacila","woodyg","doreen","gisele","jessice","liky","chris","enerce","sunny","jenny");

if (! -e "/mailbackup/anyone/") { mkdir("/mailbackup/anyone/", 0755);}
my $mail_size = sprintf("%.2f",dir_size('/mailbackup/')/1024);

#燒錄容量大小(MB)
my $burn_szie = 4200;
#檢測要燒錄檔案是否超過容量
if ($mail_size >= $burn_szie) {
    $iname = makeISO();
    burniso($iname);
    print "燒錄mail成功!!\n";
    #正式刪除mail檔案,只保留ISO檔
    !system "rm -rf /mailbackup/*" or die "can't delete:$!--/mailbackup/*\n";
    die mail("jacky\@mail.xxxx.com.tw","已燒錄mail備份成功 !!","" );
}

print "mail目錄現有容量共有:$mail_size MB\n";

my $total_size;

#針對 目錄 /backup/mail/ 下所備份mail 作處理
for  $file (</backup/mail/*>) {
    $i = 'Y';
    $x = 'N';   # =Y時,此信件有要備份使用者
    $y =  0 ;   
    #獲得檔案建立日期
    my $date_string = time2str("%Y-%m-%d %H-%M",stat($file)->mtime);
    #獲得檔案容量大小,sprintf 四拾五入
    my $filesize = sprintf("%.2f", (-s $file)/(1024*1024));
    print "filesize=$filesize MB\n";
    my $subj;
    open FH, $file;
    @all=<FH>;
    close(FH);
    while ($y <= $#user){  #  $#user 帶出 @userb陣列總共有幾個元素
        for $num(@all){
            #針對 @user 使用者作篩選
           if (($num =~ /^To: .*$user[$y]\@mail.xxxx.com.tw/)||
                ($num =~ /^Return-Path: <$user[$y]\@mail.xxxx.com.tw>/)||
                ($num =~ /^Cc:.*$user[$y]\@mail.xxxx.com.tw/)||
                ($num =~ /for.*$user[$y]\@mail.xxxx.com.tw/)){
                print "name=$user[$y]\n";
                #print $_ while (<FH>);
                #print "$file\n";
                $x = 'Y';
           } elsif (($num =~ /^Subject:/i) && ($i eq 'Y')){
                chomp($num); #去除變數值的最後換行符號(\n)
            
                #將主旨(subject)含有中文字轉換為可視中文
                if (($num =~ /\?utf-8\?/i)||($num =~ /\?big5\?/i)){
                    if ($num=~/\?B\?/){
                        use MIME::Base64;
                        $num =~/\?B\?.*\?/;
                        $num1 = substr($&,3,length($&)-4);
                        #print "num=$num\n";
                        $subj = decode_base64($num1);
                    } elsif ($num=~/\?Q\?/) {
                        use MIME::QuotedPrint;
                        $num =~/\?Q\?.*\?/;
                        $num1 = substr($&,3,length($&)-4);
                        $subj = decode_qp($num1);
                   }
                   #針對utf8 -> big5
                   if ($num =~ /\?utf-8\?/i){
                        $subj= encode("big5",decode("utf8",$subj));
                        #print "num=$num\n";
                        #print "長度=length($num)\n";
                   }
                } else {
                   #print "原文英文信:$num\n";
                   $num1 = substr($num,9);
                   my $enc = guess_encoding($num1) ;
                   if ((length($num1) > 0) && (($enc -> name) eq "big5-eten")) {
                        #print "中文信:$num1\t",$enc->name,"\n";
                        $subj=$num1;
                   } else {
                        $subj = substr($num1,0,42);#針對超過64字元長字串進行裁減
                        #printf "裁減英文信:$subj ,長度:%s\n",length($num1);
                   }
                }
                #print"----$file---\n";
                $i = 'N';
           } else { next;}
        }
        if ($x eq 'Y'){
           $dir = "/mailbackup/$user[$y]/";
           #print "dir=$dir\n";
           if (! -e $dir) { mkdir($dir, 0755);} #辨別是否有此使用者目錄,如沒有此使用者就新增此目錄
           print "$date_string $subj.eml\n";
           copy("$file", "$dir$date_string $subj.eml");
           unlink $file if -e $file;
           if (! -e $file) { print "$file 已備份匯出!\n"; }
           last;  # 此信件已尋找到符合帳號,所以跳出 while迴圈:
        }
        $y++;
    }
    #針對無法辨識信件歸類至 anyone目錄
    if (-e $file) {
        $dir = "/mailbackup/anyone/";
        copy("$file", "$dir$date_string $subj.eml");
        print "name=anyone\n";
        print "$date_string $subj.eml\n";
        unlink $file if -e $file;
        print "$file 已備份匯出!\n";
    }
    $total_size = $total_size + $filesize;
    print "匯出mail容量累計:$total_size MB\n";

    $mail_tol = $mail_size+$total_size;
    print "總容量:$mail_tol MB\n";

    if ($mail_tol >= $burn_szie){
        print "mail匯出已超過 $burn_szie MB容量,請放入DVD 片!!\n";
        $iname = makeISO();
        burniso($iname);
        #正式刪除mail檔案,只保留ISO檔
        !system "rm -rf /mailbackup/*" or die "can't delete:$!--/mailbackup/*\n";
        mail("jacky\@mail.xxxx.com.tw","已燒錄mail備份成功 !!","" );
    }

    last if ($mail_tol >= $burn_szie);
    print "換檔案\n";
}


# 複製完刪除
sub copy_dir{
  my $source = $_[0];
  my $target = $_[1];
  use File::Copy;
  opendir(DIR,$source);
  while(my $filename = readdir(DIR)){
    if(-f "$source/$filename"){
      copy("$source/$filename","$target/$filename") or die "can't copy: $!--$source/$filename\n";
      unlink "$source/$filename" if -e "$source/$filename";
    }
  }
  close(DIR);
}

#呼叫系統 shell cp
sub sys_copy{
  my $source = $_[0];
  my $target = $_[1];
  #use File::Copy;
  opendir(DIR,$source);
  while(my $filename = readdir(DIR)){
    if(-f "$source/$filename"){
      !system "cp -rfp $source/$filename $target/$filename" or die "can't copy: $!--$source/$filename\n";
      unlink "$source/$filename" if -e "$source/$filename";
    }
  }
  close(DIR);
}

#回傳指定目錄大小(KB)
sub dir_size{
  $dir = `du -sk $_[0]` ;
  $dir =~ s/$_[0]//;    #去除多餘文字
  $dir =~ s/\s+//;      #去除空白地方
  return $dir;
}


sub round {
    my $val = shift;
    my $col = shift;
    my $r = 10 ** $col;
    my $a = ($val > 0) ? 0.5 : -0.5;
    return int($val * $r + $a) / $r;
}

#製作影像檔
sub makeISO {
    ($sec,$min,$hour,$day,$mon,$year)=localtime(time);
    $year+=1900 ;
    $mon++ ;
    $isoname = "mailbackup$year-$mon-$day.iso";
    #$iso = Filesys::MakeISO->new;
    #$iso->image('mailbackup.iso');
    #$iso->dir('/mailbackup');
    #$iso->make_iso;
    #if(!$iso) {mail("jacky\@mail.xxxx.com.tw","無法制作ISO檔!!","$!" );}
    !system "mkisofs -o /backup/mail-iso/$isoname -r -J -graft-point /mailbackup/=/mailbackup/"
      or  die mail("jacky\@mail.xxxx.com.tw",'無法製作ISO檔!!',"$!" );
    return $isoname;
}

sub burniso {
    $isoname = $_[0];
    !system "cdrecord -v dev=2,0,0  fs=8m speed=4 -data -sao driveropts=burnfree /backup/mail-iso/$isoname" or die unlink "/backup/mail-iso/$isoname" if -e "/backup/mail-iso/$isoname" and mail("jacky\@mail.xxxx.com.tw","無法燒錄ISO檔:$isoname!!","$!" );
}


#sub del_file {
#   ;
#}

sub mail {
    #收件者
    $to = $_[0];
    # sendmail 程式路徑位址
    my $mailprg = "/usr/sbin/sendmail -t";
    # 寄件者 l
    my $from = "root\@mail.xxxx.com.tw";
    #主旨
    my $subj = $_[1];
    #內容
    my $messg = $_[2];

    open (MAIL,"|$mailprg") || die "$!\n";
    print MAIL "Return-Path: $from\n";
    print MAIL "From: $from\n";
    print MAIL "To: $to\n";
    print MAIL "Subject:$subj\n";
    print MAIL "\n";
    print MAIL "$messg\n";
    print MAIL "--- mail message for xxxx (c) 2009 written by mailbackup\n";
    close(MAIL);
    print "OK!\n\n";
}

[[i] 本帖最后由 hmfjacky 于 2009-7-29 15:28 编辑 [/i]]

hzqbbc 发表于 2009-7-29 10:58

狂顶!!!兄弟的脚本很详细哦!!很感谢,希望以后有更多好的作品问世!!

mouse 发表于 2009-7-29 11:17

1楼的台湾老大太强悍了,学2周就能写那么复杂的程式,太崇拜了:funk: :funk: 顶礼膜拜中...:lol

fengyong 发表于 2009-7-29 13:59

:lol 支持顶顶,写得太复杂了。

liushaobo 发表于 2009-7-29 21:36

偶像呀, :handshake

happyqq 发表于 2009-7-30 10:19

感谢分享!

phelp 发表于 2009-10-21 15:21

我不懂,但上面几份老大都说好,肯定非常不错,:handshake

hmfjacky 发表于 2009-11-12 16:23

小弟最近想將 mail backup ISO 檔案名稱,加上mail 備份時間的期間,好讓以後要尋找mail 不用那麼辛苦,小弟已做到可以搜尋最大、最小日期,所以先將程式 post 出來,如果和主程式測試成功,另外找時間將主程式一齊post 出來,謝謝。

#! /usr/bin/perl

use File::Find;

# 路徑設定,命令列輸入路徑
my $dir=shift;
#print "dir=$dir\n";

my @array;   #儲存 sub do_search 所搜尋到檔案日期

find(\&do_search, $dir);
#print "array=@array\n";
diff(@array);

#搜尋檔案名稱日期格式
sub do_search {
    $name = $File::Find::name;
    if (-f $name){
        if ($name =~ /(\d+)\-(\d+)\-(\d+)/){ #搜尋檔案名稱含有日期(2009-11-02)
            $content = $&;   #搜尋完畢,將搜尋到字串帶入變數
            #print "$content,$name\n" if ($content =~ s/\-//g);
            #去掉日期多餘符號(-),並塞給陣列(@array)
            push @array,$content if ($content =~ s/\-//g);
        }
    }
}

#將搜尋到日期帶入,求最大、最小日期
sub diff {
    my @param = @_;
    my ($max, $min) = ($param[0], $param[0]);
    for (@param) {
      $max = $_ if $_ > $max;           # 求最大值
      $min = $_ if $_ < $min;           # 求最小值
    }
    print "max=$max\n";
    print "min=$min\n";
}

[[i] 本帖最后由 hmfjacky 于 2009-11-12 16:36 编辑 [/i]]

mouse 发表于 2009-11-12 20:13

实在太猛了,希望enjoylinux老大可以集成到emos里啊!

jojo 发表于 2009-11-13 08:54

好东西,看来就可以用上了

pandayy 发表于 2009-12-24 10:30

好东西啊。支持支持。正在学习中

hmfjacky 发表于 2011-2-11 13:52

[i=s] 本帖最后由 hmfjacky 于 2011-2-11 13:55 编辑 [/i]

各位大大,好久不見,去年工作太忙了,一直沒有時間上來,真的很抱歉。小弟應該只針對下面二隻子程式作稍微修改,先將備份日期期間當作目錄名稱,並針對/mailbackup目錄,各別user製作各別壓縮檔(因以前小弟在製作影像檔並燒錄成光碟片時,發現mail 檔名是繁體中文時會打不開,所以先壓縮再來燒錄就不會出現奇怪問題),再燒錄成光碟片。
因小弟比較沒時間上來論壇,如果有問題要互相切磋可以 mail 小弟信箱:[email]jacky@yfang.idv.tw[/email],謝謝。



#製作影像檔
sub makeISO {
    ($sec,$min,$hour,$day,$mon,$year)=localtime(time);
    $year+=1900 ;
    $mon++ ;
   
    #搜尋 /mailbackup 內檔案日期最大及最小值,把備份日期當作目錄名稱
    find(\&do_search,"/mailbackup");
    #print "array=@array\n";
    $name = diff(@array);
    if (! -e "/backup/mail-iso/$name") { mkdir("/backup/mail-iso/$name", 0755);}

    #針對各user製作各別壓縮檔
    my @catalog = </mailbackup/*>;
    #print "file=@files\n";
    for $catalog(@catalog){
        $catalog =~ /\/mailbackup\//i;  #$'代表字串中比對成功之後的部分
        !system "zip -r /backup/mail-iso/$name/$'.zip /mailbackup/$'" or die mail("jacky\@mail.xxx.com.tw","無法製作壓縮檔$'!!","$!" );
    }

   
    #製作影像檔
    !system "mkisofs -o /backup/mail-iso/$name.iso -r -l -J -graft-point /$name/=/backup/mail-iso/$name"  or  die   
                      mail("jacky\@mail.xxx.com.tw",'無法製作ISO檔!!',"$!" );
   
    #刪除 tar 檔
    #unlink "/backup/mail-iso/$name.tar.gz" if -e "/backup/mail-iso/$name.tar.gz";

    return "$name.iso";
    #print "iso檔名:$name.iso\n";
}

#將搜尋到日期帶入,求最大、最小日期
sub diff {
    my @param = @_;
    my ($max, $min) = ($param[0], $param[0]);
    for (@param) {
      $max = $_ if $_ > $max;           # 求最大值
      $min = $_ if $_ < $min;           # 求最小值
    }
    print "max=$max\n";
    print "min=$min\n";
    #回傳檔名
    $year = substr $max,0,4;
    $mon = substr $max,4,2;
    $day = substr $max,6,2;
    $max = "$year-$mon-$day";
    $year = substr $min,0,4;
    $mon = substr $min,4,2;
    $day = substr $min,6,2;
    $min = "$year-$mon-$day";
   
    return "mailbackup$min~$max";
}

hzqbbc 发表于 2011-2-13 21:11

非常感谢台湾的兄弟贡献那么好的东西!!!再次感谢,感谢一万次。哈哈~~

hmfjacky 发表于 2011-2-14 17:00

[i=s] 本帖最后由 hmfjacky 于 2011-2-14 17:03 编辑 [/i]

小弟今天發現mail 備份燒錄出來時,只要mail 檔名含有分號[:]就無法在windows系統下打開,小弟在linux是可以打開,所以先前沒有注意到,真的是太對不起各位大大。所以今天重看程式,想要加入剔掉分號,但有點不能理解先前的寫法,所以二、三天改完程式再post 到網站上,謝謝!

hmfjacky 发表于 2011-2-16 09:39

[i=s] 本帖最后由 hmfjacky 于 2011-2-16 09:41 编辑 [/i]

針mail 檔名在windows 系統不能有特殊符號[\/:*?"<>|],小弟增加一段程式來更換為(_)字元:

#100/02/15 因windows系統檔名不能含有特別符號(\/:*?"<>|),所以更換為(_)字元
#但有二個字元(/"),沒辦法替換,還要繼續研究
$_ = $subj;
if ((tr/\\\/:\*\?\"\<\>\|/_/)>0){
    $subj = $_;
    #print"is change character subj--- $subj\n";
}

hmfjacky 发表于 2011-2-16 16:13

小弟上傳一個程式,可修改先前已作完備份,含有特殊符號的mail檔名。

#!/usr/bin/perl

for $file (</backup/mail-iso/mailbackup2010-11-26~2011-01-07/mailbackup/*>) {
    if (!-f $file){
        print " $file as floder\n";
        #搜尋目錄下檔案:
        opendir(DIR, $file);
        @array = readdir(DIR);
        foreach $filename(@array){
           print "file--$filename\n";
           $_ = $filename;
           if ((tr/\\\/:\*\?\"\<\>\|/_/)>0){
              #更改檔名
              rename("$file/$filename","$file/$_");
              print"is change character subj--- $_\n";
           }
        }
    }
}

hzqbbc 发表于 2011-3-1 10:15

顶一下兄弟的帖子,难得的技术原创精华牛贴!!

261767353 发表于 2011-5-13 17:26

2周。太强悍了

lovemay 发表于 2011-12-22 17:23

楼主挺厉害的

页: [1]

Powered by Discuz! Archiver 7.0.0  © 2001-2009 Comsenz Inc.