Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

msgmail.pl

by zdog (Priest)
on Feb 20, 2002 at 03:33 UTC ( #146483=sourcecode: print w/replies, xml ) Need Help??
Category: PerlMonks Related Scripts
Author/Contact Info Zenon Zabinski | zdog | zdog@perlmonk.org
Description: This script checks to see if you have received any /msg's, emails them to you, and then provides an interface to handle replies (at least it's supposed to). When you get such an email, all you do is hit reply (making sure that the info within the brackets is still in the subject), type in your msg, and hit send. In order to set it up, you need a Un*x system running an SMTP server (at least I think you do). You run this script as a daemon using root and whoever wants to take advantage of the service just creates a configuration file in their home directory in the following form:

pm_username|pm_passwd|email_addy

It's that simple (at least I hope it is).

use strict;
use warnings;

use Unix::PasswdFile;
use HTTP::Cookies;
use XML::Simple;
use MIME::Lite;
use Mail::Box::Mbox;
use URI::Escape;
require LWP::UserAgent;
require HTTP::Request;

use vars qw ($username $host $maildir $msgsleep $usersleep 
  $configfile $cookiefile $pmurl %users);

### BEGINNING OF USER SETTINGS #######################################
+#########

$username = 'msgmail';            # Username of the daemon.
$host     = 'localhost';          # Host of the msgmail daemon.
$maildir  = '/var/spool/mail';    # Location of mbox mail "folders".
$msgsleep = 5;                    # Time (in minutes) between /msg che
+cks.
$usersleep  = 60;            # Time (in minutes) between checks for ne
+w users.
$configfile = '.msgmail';    # Name of config file in each user's home
+dir.
$cookiefile = '.msgmail_cookie';   # Name of cookie file in each user'
+s homedir.
$pmurl = 'http://www.perlmonks.org/';    # Url of PerlMonks.

### END OF USER SETTINGS #############################################
+#########

{
    init();

    my $i = 0;

    for ( ; ; ) {
        if ( $i == $usersleep ) {
            getUsers();
            $i = 0;
        }

        for my $user ( keys %users ) {
            my $msgreq = HTTP::Request->new( GET => "$pmurl?node_id=15
+848" );
            $users{$user}{ua}->cookie_jar->add_cookie_header($msgreq);
            ( my $xml =
              XMLin( $users{$user}{ua}->simple_request($msgreq)->{_con
+tent},
              forcearray => 1 ) ) || next();

            for my $msg ( @{ $$xml{message} } ) {
                if ( $$msg{content} =~ m/\[(.*?)\] announcement -- / )
+ {
                    my $temp_auth = $1;
                    $$msg{content} =~ s/--/-- [$$msg{author}] says:/;
                    $$msg{author} = $temp_auth;
                }

                my $mail = MIME::Lite->new(
                  From    => "$username\@$host",
                  To      => $users{$user}{email},
                  Subject => "/msgmail from $$msg{author} "
                  . "[$$msg{author}:$user:"
                  . crypt( $users{$user}{passwd}, $user ) . "]",
                  Data => $$msg{content}
                );

                if ( $mail->send ) {
                    my $delreq =
                      HTTP::Request->new( HEAD =>
                      "$pmurl?op=message&deletemsg_$$msg{message_id}=y
+up" );
                    $users{$user}{ua}->cookie_jar->add_cookie_header($
+delreq);
                    $users{$user}{ua}->simple_request($delreq);
                }
            }
        }

        my $folder =
          Mail::Box::Mbox->new( folder => "=$username", folderdir => $
+maildir,
          access => 'rw' );

        for (@$folder) {
            ( my ( $to, $from, $passwd ) =
              $_->subject() =~ m/\[(.*?):(.*?):(.*?)\]/ )
              || $_->delete() && next();

            if ( $passwd ne crypt( $users{$from}{passwd}, $from ) ) {
                $_->delete() && next();
            }

            my $text = $_->body();
            $text =~ s/\n/ /g;
            $text = uri_escape($text);

            my $sendreq =
              HTTP::Request->new( HEAD =>
              "$pmurl?op=message&message=/msg\%20$to\%20$text" );
            $users{$from}{ua}->cookie_jar->add_cookie_header($sendreq)
+;
            $users{$from}{ua}->simple_request($sendreq) && $_->delete(
+);
        }

        $folder->close();

        $i++;
        sleep($msgsleep);
    }
}

sub getUsers {
    my $pw = Unix::PasswdFile->new("/etc/passwd");

    foreach ( $pw->users() ) {
        open( FILE, "<" . $pw->home($_) . "/$configfile" ) || next();
        chomp( my $line = <FILE> );
        close(FILE);
        my ( $user, $passwd, $email ) = split ( /\|/, $line );

        my $ua = LWP::UserAgent->new();
        $ua->cookie_jar(
          HTTP::Cookies->new(
          File           => $pw->home($_) . "/$cookiefile",
          AutoSave       => 1,
          ignore_discard => 1 )
        );
        $ua->cookie_jar->load( $pw->home($_) . "/$cookiefile" );
        $ua->simple_request( HTTP::Request->new( GET =>
          "$pmurl?user=$user&passwd=$passwd&op=login" ) ) || next();
        $ua->cookie_jar->save() || next();

        $users{$_} = { ua => $ua, email => $email, passwd => $passwd }
+;
    }
}

sub init {  # Initializes stuff for the program to use.
    getUsers();

    $usersleep = int( $usersleep / $msgsleep );
    $msgsleep *= 60;

    MIME::Lite->send( 'smtp', 'localhost', Timeout => 60 );
}
Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: sourcecode [id://146483]
help
Chatterbox?
Corion watches from the sidelines. Or rather, from behind, as my system only gets output from that process and my programs adhere strictly to the GIGO design principle.
[erix]: ah, that's nice to hear Corion :)
[Corion]: erix: Yeah, the sad thing is that all I can do is document things, so I can point fingers when the auditors come :-/
[Corion]: "I'm here to open tickets and point fingers. And I'm all out of tickets."
[erix]: didn't Sybase have pretty good auditing? :) (this is a vague memory)
[erix]: (culprits often are upstream of db of course)
[Corion]: Ah, how I missed it. After some years, I revisit slashdot on a click-bait link, and it provides the usual humor instantly: "I didn't know Drupal had rules for sex. It must be a plug-in"
[Corion]: erix: This is not for sybase, but for the input data files, resp. their contents.

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (8)
As of 2017-03-28 08:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Should Pluto Get Its Planethood Back?



    Results (328 votes). Check out past polls.