#======================================================================# # sendmail.pl for ActivePerl 5.6.1.628 #======================================================================# # 書式 : perl sendmail.pl [-itfr] [address] # 配布元: http://wan.magical.gr.jp #======================================================================# # 設定 #◇SMTPサーバ $smtp = "***.ddo.jp"; #◇標準 FORM アドレス $from = '***@***.ddo.jp'; #◇ エラーログの作成(sendmail.log) $logs = 1 ; #◇ タイムアウト秒数 (デフォルト推奨) $timeout = 20; #◇ アラームファイル (デフォルト推奨) $alarm =".alarmpid"; #======================================================================# #◇POP before SMTPを使用する yes=1 no=0 $pop_before_smtp = 1; #◇ POP3サーバアドレス $pop3 = "***.ddo.jp"; #◇POP3接続用 USER-ID/PASSWORD $user = '***'; $pass = '***'; #◇設定ここまで #======================================================================# # fork式alarm開始 $fileid ="$$-"; if($pid = fork){ open(NEW,"> $fileid$pid$alarm") && close(NEW); for(my $time = $timeout;$time > 0 ; $time--){ last if ! -e "$fileid$pid$alarm"; sleep(1); } if(-e "$fileid$pid$alarm"){ print "Kill"; kill(1,$pid); unlink("$fileid$pid$alarm"); } $time = time - $timeout - 10; while(<*$alarm>){ if($time > (stat($_))[9]){ unlink($_); } } }else{ #======================================================================# # コマンドライン引数解析処理 $p="rf"; while($_ = shift @ARGV){ if(s/^-(.)(.*)/$2 ne "" && "-$2"/e){ if(index($p,$1) >= 0){ $P{$1} = $2 ne "" ? $2 : shift @ARGV; }else{ $P{$1} = 1; redo; } }else{ push(@tos,$_) if /^.+\@.+\..+$/; } } #======================================================================# # メール本文の受信 binmode(STDIN); while(<>){ last if !$P{i} && /^\.\x0D?\x0A/; s/^\./../; $mail .= $_; @head = split(/\x0D?\x0A/,$mail) if ! @head && /^\x0D?\x0A/; } #======================================================================# # ヘッダの解析 // -t 送信先の抽出/BCC削除 foreach $i (0..$#head){ if($head[$i] =~ /^([A-Z].*?)\s*:/){ $HEAD{($n = $1)} = $head[$i]; $HEAD{$n} .= $head[++$i] if $head[$i + 1] =~ /^\s/; } } $from = $P{'f'} if $P{'f'}; if($P{"t"}){ $to = $HEAD{"To"}; $cc = $HEAD{"Cc"}; $bcc = $HEAD{"Bcc"}; } $from =~ /^.+\@.+\..+$/ || &error("#Error#fromメールアドレスが不正です。$from"); for($from,$to,$cc,$bcc){ s/^(?:To|Bcc|Cc|From)\s*:\s*//; s/"(?:[^"]|\")*"//g; 1 while s/\([^()]*\)//g; } if($P{"t"}){ @to = split(/,/,$to); @cc = split(/,/,$cc); @bcc = split(/,/,$bcc); } for($from,@to,@cc,@bcc,@tos){ $_ = $1 if /<([^>]*)>/; s/^[\s\x0D\x0A]+|[\s\x0D\x0A]+$//g; undef $_ unless /^.+\@.+\..+$/; $tos++; } $mail =~ s/Bcc\s*:(?:\s+[^\x0D\x0A]*\x0D?\x0A)+//; #$mail =~ s/From\s*:(?:\s+[^\x0D\x0A]*\x0D?\x0A)+/From: $from\x0D\x0A/; if($mail !~ /\r\n/){ $mail =~ s/\n/\r\n/g; } #======================================================================# # 最終チェック $ENV{'SERVER_NAME'} = $smtp unless $ENV{'SERVER_NAME'}; &error('#Error#送信元アドレスがありません') unless $from; &error('#Error#送信先アドレスがありません') unless $tos; if($smtp !~ /^\d+(?:\.\d+){3}$/){ $smtp = gethostbyname($smtp); }else{ $smtp = pack('C4',split(/\./, $smtp)); } #======================================================================# # POP サーバに接続 &pop3 if $pop_before_smtp =~ /^(?:1|y(?:es)?)$/i; #======================================================================# # メール送信 / 終了 $sock_addr = pack('S n a4 x8',2,25,$smtp); socket(SOCK, 2, 1, 6) || &error('#Error#socket関数でエラーが発生しました。'); binmode(SOCK); binmode(O); connect(SOCK, $sock_addr) || &error('#Error#connect関数でエラーが発生しました。'); select(SOCK);$|=1;select(STDOUT); &check(220,"SMTP"); for("HELO $ENV{'SERVER_NAME'}","MAIL FROM:<$from>"){ print SOCK $_ , "\r\n"; &check(250,"SMTP($_)"); } foreach $head (@to,@cc,@bcc,@tos){ next unless $head; print SOCK "RCPT TO:<$head>\r\n"; &check(25,"SMTP(RCPT TO: <$head>)"); } print SOCK "DATA\r\n"; &check(354,"SMTP"); print SOCK "$mail\r\n.\r\n"; &check(250,"SMTP"); print SOCK "QUIT\r\n"; close (SOCK); #======================================================================# # fork式alarm終了 unlink("${fileid}${$}${alarm}") if -e "${fileid}${$}${alarm}"; exit; } exit; #======================================================================# # エラー処理 (sendmail.logファイルに書き出し) sub error{ @a=@_; print SOCK "QUIT\r\n"; close(SOCK); if($logs && open(OUT,">> sendmail.log")){ $a[0] =~ s/\r?\n//g; ($sec,$min,$hour,$day,$mon)=localtime(time);$mon++; @d=("00".."59"); print OUT "[$d[$mon]/$d[$day] $d[$hour]:$d[$min]:$d[$sec]] $a[0]\n"; close(OUT); } unlink("${fileid}${$}${alarm}") if -e "${fileid}${$}${alarm}"; exit; } #======================================================================# # 応答チェック sub check{ @a = @_; $res = ; $res =~ /^\Q$a[0]/ || &error("#Error#$a[1]サーバーからのお返事がへんです。\n\t予想:$a[0]\n\t実際:$res"); } #======================================================================# # POP3処理 sub pop3{ if($pop3 !~ /^\d+(?:\.\d+){3}$/){ $pop3 = gethostbyname($pop3); }else{ $pop3 = pack('C4',split(/\./, $pop3)); } $sock_addr = pack('S n a4 x8',2,110,$pop3); socket(SOCK, 2, 1, 6) || &error('#Error#socket関数でエラーが発生しました。'); connect(SOCK, $sock_addr) || &error('#Error#connect関数でエラーが発生しました。'); select(SOCK);$|=1;select(STDOUT); print SOCK "USER $user\r\n"; &check("+OK","POP3"); print SOCK "PASS $pass\r\n"; &check("+OK","POP3"); print SOCK "QUIT\r\n"; &check("+OK","POP3"); close(SOCK); } #======================================================================# #履歴: 2000/11/20 Ver 0.00 送信確認 # 2000/11/21 Ver 0.01 sendmail.log # 2001/07/16 Ver 0.02 Windows98/2000 + ActivePerl 5.6.1.628 用に編集