Category: Miscellaneus
Author/Contact Info /msg sulfericacid
Description: UPDATE: added database flocking thanks to merlyn

Basic mailing list system. Two scripts: subscribe/unsubscribe and the actual mailing.

Mailing section has a basic password check so other's who find the file cannot use your mailing list.

Special commands like [name] and [time] (instructions inside).

Basic function is to store a database of user names and user email addresses and send each recipient an email.

Emailing Form
#!/usr/bin/perl -w

# Signature sending is optional and will only be used if you click "us
+e sig".
# You can change and save your present copy of Signature by clicking "
+save sig" otherwise
# it will use the last saved version of it


use strict;
use warnings;
use POSIX;
use CGI qw/:standard/;
require SDBM_File;

my (%sig, %emails);
my $sigsave   = "";   # location of sigsave db
my $lock      = "";   # password
my $list      = "";   # location of list db

my $adminmail = "admin\@test.com";
my $sendmail  = "/usr/lib/sendmail";
my $unsub     = "";  # unsub link

tie %emails, 'SDBM_File', $list, O_CREAT | O_RDWR, 0644;
flock($list, 2) || die "Cannot flock file $!";

if ( !tied %emails ) {
    print "database unsuccessful $!.\n";
}

tie %sig, 'SDBM_File', $sigsave, O_CREAT | O_RDWR, 0644;
flock($sigsave, 2) || die "Cannot flock file $!";
if ( !tied %sig ) {
    print "database unsuccessful $!.\n";
}

print header, start_html('Email Management');

print start_form(), table(
    Tr(
        td("Subject: "),
        td(
            textfield(
                -name => 'subject',
                -size => 40
            )
        )
    ),
    Tr(
        td("Message: "),
        td(
            textarea(
                -name    => 'message',
                -columns => 40,
                -rows    => 5
            )
        )
    ),
    Tr(
        td("Signature: "),
        td(
            textarea(
                -name    => 'signature',
                -default => $sig{'default'},
                -columns => 40,
                -rows    => 5
            )
        )
    ),
    Tr(
        td("Password: "),
        td(
            password_field(
                -name    => 'password',
                -size    => 10
            )
        )
    ),
    Tr(
        td(
checkbox(-name=>'use',
               -value=>'yes',
               -label=>'Use signature'),
        )
    ),       
    Tr(
        td(           
checkbox(-name=>'save',
               -value=>'yes',
               -label=>'Save signature'),
        )

    ),
        td(submit('button','submit'))
    ),
  end_form(), 
  hr();
print "Usefull commands:<br>\n";
print "[name]  = user's name<br>\n";
print "[time]  = mailing time<br>\n";
print "[unsub] = unsub url<br><br><br>\n";

if ( param() ) {

# rid ourselves from those nasty params
my $message   = param('message');
my $password  = param('password');
my $subject   = param('subject');
my $signature = param('signature');
my $save      = param('save');
my $use       = param('use');
my $time      = localtime;

if ($password ne $lock) {
print "Wrong password.  Email rejected from server.\n";
}
else {
    if ( $message eq "" || $subject eq "" ) {
        print "Your subject or email content was missing.\n";
        exit;
    }
    else {
    
        if ( $save eq "yes" ) {
        print "<br>";
        print "Saving to database...<br>\n";
                $sig{'default'} = $signature;
                $sig{'stored'} = $sig{'default'};
        print "Your Signature has been saved.<br><br>\n";
    }
        print "<br>\n";

        while ( my ( $key, $value ) = each(%emails) ) {
                    # Email Subs, special commands
                    
            my $editmes = $message;             # let's not edit $mess
+age
            $editmes =~ s/\[name\]/$value/g;    #[name] = user name
            $editmes =~ s/\[time\]/$time/g;     #[time] = time sent 
            $editmes =~ s/\[unsub\]/$unsub/g;   #[unsub] = unsubscribe
+ email  

            my $editsig = $signature;           # let's not edit $sign
+ature
            $editsig =~ s/\[name\]/$value/g;    #[name] = user name
            $editsig =~ s/\[time\]/$time/g;     #[time] = time sent 
            $editsig =~ s/\[unsub\]/$unsub/g;   #[unsub] = unsubscribe
+ email   
            
            my $editsub = $subject;             # let's not edit $subj
+ect
            $editsub =~ s/\[name\]/$value/g;    # [name] = user name  
+     
       
            open( MAIL, "| $sendmail -t" );
            print MAIL "To: $key\n";
            print MAIL "From: $adminmail\n";
            print MAIL "Subject: $editsub\n\n";
            print MAIL "$editmes\n";
             if ( $use eq "yes" && $signature ne "" ) {          
                print MAIL "$editsig\n";
            }
            print MAIL ".\n";
            close(MAIL);         
        }
my $time      = localtime;
print "<b>Email successfully sent on $time</b>";
    }

}
}
untie %emails;
untie %sig;

Subsribe/Unsubscribe form

#!/usr/bin/perl -w

use strict;
use warnings;
use POSIX;
use CGI qw/:standard/;

require SDBM_File;

my %emails;
my $list      = ""; #change to location of database
my $adminmail = 'admin@test.com';
my $sendmail  = "/usr/lib/sendmail";

tie %emails, 'SDBM_File', $list, O_CREAT | O_RDWR, 0644;
flock($list, 2) || die "flocking failed $!";

if ( !tied %emails ) {
    print "database unsuccessful $!.\n";
    }


print header, start_html('Email Management');

print start_form(), table(
    Tr(
        td("Name: "),
        td(
            textfield(
                -name => 'name',
                -size => 40
            )
        )
    ),
    Tr(
        td("Email: "),
        td(
            textfield(
                -name => 'email',
                -size => 40
            )
        )
    ),
    Tr(
        td(
            radio_group(
                -name   => 'update',
                -values => [ 'add', 'rem' ]
            )
        ),
    ),

    Tr( td(), td(submit) ),
  ),
  end_form(), hr();

if(param()){
    my $email  = param('email');
    my $name   = param('name');
    my $update = param('update');
    
    if($name){
        if($email){
            if($update eq "add"){
                if(exists $emails{$email}){
                    print "Email already exists in database.\n";
                    }
                else{
                    $emails{$email} = $name;
                    print "Email address added to our system!<p>\n";
                    print "Database contains:\n";
                            foreach ( sort keys(%emails) ) {
                            print "$_ => $emails{$_}<br>";
        }

                }
            }
            elsif($update eq "rem"){
                if(exists $emails{$email}){
                    del $emails{$email};
                    print "Email address was removed from the system.\
+n";
                    }
                else{
                    print "Oops, it doesn't appear that address is in 
+our database.\n";
                }
            }
        }
        else{
            print "For this to work please add your email address.\n";
        }
    }else{
        print "Unless your name is null, please go back and fill it in
+.\n";
    }
}

            print end_html();
Replies are listed 'Best First'.
•Re: Mailing List v1.0
by merlyn (Sage) on Apr 12, 2003 at 20:46 UTC
    You've got no locking on your DBM, so you could get multiple writers on your update form (bad) or a writer at the same time as a reader for the mailing form (bad).

    You will get corruption sooner or later. Ick. Learn to flock. {grin}

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.