#! /usr/bin/perl
#
# grmail.cgi
#
# 1.005 : 11/22/06 : 送信後のリターンページオプションのバグを修正
# 1.004 : 1/21/06 : Added an option to not display name on To: and From:
# 1.003 : 1/15/06 : Added recipient, sender non-display mode
# 1.002 : 1/6/06 : Fixed MIME encode
# 1.001 : 10/18/05 : Deleted unnecessary spaces in title
# 1.0 : 10/17/05 : Initial revision
#
# Group mail
# グループメール
#
# グループモードとユーザーモードとあります。
# - グループモード
# グループモードでは管理人のみメールアドレスを登録することができます。
# 登録されているユーザーはグループパスワードを使ってのみメールを
# 送信することができます。
# 登録削除は管理人のみ可能です。
# - ユーザーモード
# ユーザーモードではユーザーが自分のメールアドレスを登録することができます。
# 登録の際にはグループパスワードが必要になります。その際個人パスワードを
# 設定します。
# メールを送信するときには個人のパスワードが必要になります。
# 登録削除はユーザーが個人のパスワードを使ってすることができます。
#
# いずれのモードもメール送信にはパスワードが必要になります。
#
# http://www.hidekik.com/
#
# Copyright(c) 2005-2006, Hideki Kanayama All rights reserved
use strict;
use CGI qw(:cgi-lib);
use CGI::Carp qw(fatalsToBrowser);
use File::Basename;
use Jcode;
my $lastupdatedyear = 2006;
my $version = "1.005";
my $script = basename($0);
my $setupfile = "grmail_setup.pl";
my $admindat = "adminpwd.dat";
my $groupdat = "grouppwd.dat";
my $charset = "Shift_JIS";
my $lang = 0;
###########################################
our $datafile = "member.dat";
# Title
our $title = ('グループメール','Group mail')[$lang];
# Background
our $bgimage_en = 0;
our $bgimage_file = '';
our $bgcolor = "#ffffff";
# Back link
our $backlink_en = 1;
our $backlink = '..';
our $backlink_name = '戻る';
# Body width
our $body_width = '100';
# col mux of address list
our $colmax = 5;
# Display admin link
our $setup_en = 1;
our $setup_name = '管理用';
# Group mode 0:user mode, 1:group mode
our $group_mode = 0;
# Bcc copoy 0:off, 1:on
our $bcc_en = 1;
# body_head
our $body_head = "
グループメール
";
# body_tail
our $body_tail = '
';
# return page after sending a mail
# 0: group mail, 1: done page, 2: top page
our $return_page = 0;
# mail command
our $mail_cmd = '/usr/sbin/sendmail -t';
# Recipent, sender non-display mode
our $recip_nondisp = 0;
our $sender_nondisp = 0;
our $sender_dummy = 'dummy@dummy.dum';
# Name on To:, From:, Bcc:
# 1: display, 0:no display
our $mail_name = 1;
# Style Sheet
our $style_sheet_en = 0;
our $style_sheet = '
';
# Head insert
our $head_insert_en = 0;
our $head_insert = '
';
our $offset = 9;
#######################################
require "$setupfile" if (-e "$setupfile");
my $q = CGI->new;
my $cgierror = $q->cgi_error;
&error($cgierror) if ($cgierror);
my %in = $q->Vars;
if (! -e "$admindat"){
if ($in{mode} eq 'wradminpwd'){
&wradminpwd($in{pwd},$admindat);
} else {
&setadminpwd($admindat);
}
}
if (! -e "$groupdat"){
if ($in{mode} eq 'grwradminpwd'){
&wradminpwd($in{pwd},$groupdat);
} else {
&setadminpwd($groupdat);
}
}
if ($in{mode} eq 'setmember'){
&setmember;
} elsif ($in{mode} eq 'wrmember'){
&wrmember;
} elsif ($in{mode} eq 'register_list'){
®ister_list;
} elsif ($in{mode} eq 'register'){
®ister;
} elsif ($in{mode} eq 'delete_list'){
&delete_list;
} elsif ($in{mode} eq 'delete_mail'){
&delete_mail;
} elsif ($in{mode} eq 'setup'){
&setup;
} elsif ($in{mode} eq 'setupwrite'){
&setupwrite;
} elsif ($in{mode} eq 'send'){
&send;
} else {
&mainpage;
}
sub mainpage {
&nomember if (! -e $datafile);
my ($maillist,$finnum,$items) = &get_maillist;
&htmlhead($title);
print $body_head;
print "$backlink_name
" if ($backlink_en);
print qq(
END
print qq($titleへ);
&htmltail;
}
sub register {
if ($group_mode) {
&error('グループモードなので管理人のみ登録できます。') if (!&checkadmin($in{grouppwd}));
} else {
&error('グループパスワードが違います。') if (!&checkadmin($in{grouppwd},$groupdat));
}
my ($data, $finnum) = &get_maillist;
$finnum++ if (-e $datafile);
my $pwd;
if ($group_mode == 0){
$pwd = &makecrypt($in{persopwd});
}
open(FILE, ">> $datafile") or &error('$datafileが開けません。');
print FILE "$finnum,$in{name},$in{address},$pwd\n";
close(FILE);
print "Location: $script\n\n";
}
sub get_maillist {
my @data;
if (open(FILE, "< $datafile")) {
my @detail;
my $i=0;
my $items;
while (){
chomp;
@detail = split /,/;
$data[$i] = [@detail];
$i++;
$items++ if ($detail[2] ne 'deleted');
}
close(FILE);
my $finnum = $detail[0];
return (\@data,$finnum,$items);
} else {
return (\@data,0); # return null and final number 0
}
}
sub send {
my $subject = $in{subject};
my $contents = $in{main};
my ($data, $finnum) = &get_maillist;
&error("送信者の名前を選択してください。") if ($in{sender} eq 'none');
my $sender_name = $data->[$in{sender}][1];
my $sender_mail = $data->[$in{sender}][2];
my $sender_pwd = $data->[$in{sender}][3];
if ($group_mode){
&error('メンバー用パスワードが違います。') unless (&checkadmin($in{pwd},$groupdat) or &checkadmin($in{pwd},$admindat));
} else {
&error('個人用パスワードが違います。') unless (&checkcrypt($in{pwd},$sender_pwd));
}
my $i;
my @to_mail;
foreach $i (0 .. $finnum){
my $item = "m" . "$i";
if ("$in{$item}" eq 'on') {
&error('選択されたメールアドレス'."$data->[$i][1]".'が削除されています。') if ($data->[$i][2] eq 'deleted');
my $toaddr = $mail_name ? "$data->[$i][1] <$data->[$i][2]>" :
"$data->[$i][2]";
push(@to_mail,"$toaddr");
}
}
&error('宛先を選択してください。') if ($#to_mail < 0);
&error('タイトルと本文は必ず書いてください。') if ($subject eq '' or $contents eq '');
my $to_mail = join ",", @to_mail;
$contents = jcode($contents)->jis;
my $from_mail;
if ($sender_nondisp){
if ($sender_dummy ne '') {
$from_mail = $mail_name ? "$sender_name <$sender_dummy>" :
"$sender_dummy";
} else {
$from_mail = $mail_name ? "$sender_name " :
"dummy\@dummy.dum";
}
} else {
$from_mail = $mail_name ? "$sender_name <$sender_mail>" :
"$sender_mail";
}
my $header;
$header = "To: " . jcode($to_mail)->mime_encode . "\n" if (!$recip_nondisp);
$header .= "From: " . jcode("$from_mail")->mime_encode . "\n";
$header .= "Bcc: " if ($bcc_en or $recip_nondisp);
$header .= jcode($from_mail)->mime_encode if ($bcc_en);
$header .= "," if ($bcc_en and $recip_nondisp);
$header .= jcode($to_mail)->mime_encode if ($recip_nondisp);
$header .= "\n" if ($bcc_en or $recip_nondisp);
$header .= "Subject: " . jcode($subject)->mime_encode . "\n";
$header .= "MIME-Version: 1.0\n";
$header .= "Content-type: text/plain; charset=ISO-2022-JP\n";
$header .= "Content-Transfer-Encoding: 7bit\n\n";
if (open(SMAIL, "| $mail_cmd")){
print SMAIL $header;
print SMAIL $contents;
close(SMAIL);
} else {
&error("メールコマンドが実行できません。");
}
if ($return_page == 0) {
print "Location: $script\n\n";
} elsif ($return_page == 1) {
&error("送信しました。$title $backlink_name");
} else {
print "Location: $backlink\n\n";
}
}
sub delete_list {
&htmlhead('メールアドレス削除');
my ($maillist,$finnum) = &get_maillist;
print qq(
\n);
print qq($titleへ);
&htmltail;
}
sub delete_mail {
my ($data, $finnum) = &get_maillist;
my $inpwd;
if ($group_mode) {
&error('グループモードなので管理人のみ削除できます。') unless (&checkadmin($in{pwd}));
} else {
$inpwd = $data->[$in{delnumber}][3];
&error('個人用パスワードが違います。') unless (&checkcrypt($in{pwd},$inpwd));
}
&error("削除する名前を選択してください。") if ($in{delnumber} eq 'none');
open(FILE, "< $datafile") or &error("$datafileが開けません。");
open(TMP, "> tmp.$$");
while (){
my ($i,$name,$email,$pwd) = split /,/;
if ($in{delnumber} == $i){
print TMP "$i,$name,deleted\n";
} else {
print TMP "$_";
}
}
close(FILE);
close(TMP);
rename ("tmp.$$","$datafile");
print "Location: $script\n\n";
}
sub checkcrypt {
my ($pwd,$encpwd)=@_;
return(crypt($pwd,$encpwd) eq "$encpwd" or &checkadmin($pwd));
}
sub htmlhead {
my $title = shift;
my $bgimage;
if ($bgimage_en == 1){
$bgimage = "background=\"$bgimage_file\"";
} else {
$bgimage = "bgcolor=\"$bgcolor\"";
}
print $q->header(-charset=>$charset);
print "\n";
print "\n";
print "\n";
print "$title\n";
if ($head_insert_en == 1){
print "$head_insert\n";
}
if ($style_sheet_en == 1){
print "\n";
}
if ($in{mode} eq ''){
my ($data, $finnum) = &get_maillist;
print qq(\n";
}
print "\n";
print "\n";
print "\n";
}
sub copyright {
my $mysite = ('http://www.hidekik.com/','http://www.hidekik.com/en/')[$lang];
print "grmail.cgi Ver. $version\n";
print " Copyright(C) 2005-$lastupdatedyear, hidekik.com \n";
}
sub htmltail {
©right;
print " |
\n";
exit;
}
sub error {
my ($msg) = shift;
&htmlhead($msg);
print "
$msg\n";
print "
";
print "
";
&htmltail;
exit;
}
sub makecrypt {
my $plain = shift;
my $salt = join "", ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64];
my $result = crypt($plain,$salt) or crypt($plain,'$1$'.$salt.'$');
return $result;
}
sub setadminpwd {
my $file = shift;
&htmlhead('パスワードを入力してください');
print "