#!/usr/bin/perl -w ### # Perl modules that need to be installed ### use MIME::Parser; use MIME::Entity; use MIME::Base64; #use Net::POP3; use Mail::POP3Client; use XMLRPC::Lite; use LWP::UserAgent; use HTTP::Request::Common qw(POST); ### # User Configurable Variables ### #THREE DIFFERENT POP MAILBOX EXAMPLES # GMAIL SETTINGS #my $username = "denspop"; ## CHANGE THIS LINE #my $password = "password"; ## CHANGE THIS LINE #my $mailserver = "pop.gmail.com"; ## CHANGE THIS LINE # DREAMHOST SETTINGS my $username = ""; ## CHANGE THIS LINE my $password = ""; ## CHANGE THIS LINE my $mailserver = ""; ## CHANGE THIS LINE # HOTPOP SETTINGS #my $username = "dpstyles97"; ## CHANGE THIS LINE #my $password = "password"; ## CHANGE THIS LINE #my $mailserver = "pop.hotpop.com"; ## CHANGE THIS LINE # TWO DIFFERENT HOSTING EXAMPLES (NYU vs. DREAMHOST) # MY DREAMHOST SETTINGS my $temp_folder = ""; my $attachment_output_folder = ""; my $attachment_output_folder_relative = ""; # this is the URL to the hack.php folder. This passes all the needed information to hack.php. my $logic_url = ""; # MY NYU SETTINGS #my $temp_folder = "/home/dc788/public_html/ubicompmobile/tmp/"; ## CHANGE #THIS LINE #my $attachment_output_folder = #"/home/dc788/public_html/ubicompmobile/img/"; ## CHANGE THIS LINE #my $attachment_output_folder_relative = "img/"; ## CHANGE THIS LINE #my $logic_url = "http://itp.nyu.edu/ubicompmobile/quick/logic.php"; # QUICK DEBUGGING SETTINGS my $delete_messages = 1; # Should we delete messages when we pop them? my $print_output = 1; # Print output (for error checking / debugging) my $hit_url = 1; # Forward our parsed values (to + from + subject + body) to our PHP script ### # Other Variables that *may be* changed ### #my $pop = Net::POP3($mailserver, Timeout => 15, USESSL => 1); my $pop = new Mail::POP3Client( USER => $username, PASSWORD => $password, HOST => $mailserver, USESSL => 1); my $max_chars = 70; # Number of chars to allow in a line of text from an incoming message my $delete_temp_files = 1; # Delete temporary files that are created my $post_to_blog = 0; # Post to your blog? my $use_gif = 0; # 1 to allow GIF's as attachments, 0 to not allow them (T-Mobile issues) my @bad_attachments = ("masthead.jpg"); # A list of attachment filename regular expressions that you don't w$ my $umask = '0002'; # File creation to 775, 0022 would be 755 # THINGS WE'RE NOT USING (for posting to blogs) my $blog_xmlrpc_url = ""; ## CHANGE THIS LINE my $blog_id = 2; ## CHANGE THIS LINE my $blog_username = ""; ## CHANGE THIS LINE my $blog_password = ""; ## CHANGE THIS LINE my %mime_types = ("image\/jpeg", "jpg", "image\/jpg", "jpg", "image\/gif", "gif", "video\/3gpp", "3gp", "audio\/x-wav", "wav", "video\/mp4", "mp4", "video\/3gpp2", "3g2", "video\/mpeg", "mpg", "video\/quicktime", "mov", "video\/x-quicktime", "mov", "video/x-msvideo", "avi" ); # A list of the attachment mime types to extract ### # Parsing Subroutine ### sub parseMessageParts { my @messageParts = @_; my $partnum = 0; my $is_mime_message = 0; while(my $part = shift(@messageParts)) { $is_mime_message = 1; # Yes we have a mime message my $known_type = 0; # Did we find the type yet? # Get the Mime type of the part my $type=$part->head->mime_type || $part->head->effective_type; ## Loop through the types we understand foreach $valid_type (keys %mime_types) { if ($type =~ $valid_type) { $known_type = 1; for (my $i = 0; $i <= $#bad_attachments; $i++) { if ($part->head->recommended_filename =~ $bad_attachments[$i]) { $skip = 1; } } if (!$skip) { my $attachment = $part->bodyhandle->as_string; my $file_name = "eastDown_" . time() . "_" . int(rand(1000)) . "\." . $mime_types{$valid_type}; my $image_file = $attachment_output_folder . $file_name; my $fh = new FileHandle "> $image_file"; if (defined $fh) { print $fh $attachment; $fh->close; } $attachments[++$#attachments] = $file_name; $attachments_type[++$#attachments_type] = $mime_types{$valid_type}; $attachments_relative[++$#attachments_relative] = $attachment_output_folder_relative . $file_name; } } } ## Not in our list, let's check for text or multipart messages if ($known_type == 0) { if ($type =~ /text\/plain/i) { my $message_bodyhandle = $part->bodyhandle; $mime_message_body = $message_bodyhandle->as_string; @mime_message_array = split('\n',$mime_message_body); foreach $message_line (@mime_message_array) { if ($message_line =~ /^\n/ || $message_line =~ /^\s*\n/ || $message_line !~ /\w/) { # Ignore blank lines } else { $body .= $message_line . "\n"; } } } elsif ($type =~ /text\/html/i) { # Plain Text portions or attachments my $message_bodyhandle = $part->bodyhandle; $mime_message_body = $message_bodyhandle->as_string; @mime_message_array = split('\n',$mime_message_body); foreach $message_line (@mime_message_array) { $message_line =~ s/<.*>//gi; # Strip out any HTML tags if ($message_line =~ /^\n/ || $message_line =~ /^\s*\n/ || $message_line !~ /\w/) { # Ignore blank lines } else { $body .= $message_line . "\n"; } } } elsif ($type =~ /multipart\/.*/i || $type =~ /message\/.*/i) { # Multipart Message, Parse This Again # Thanks again T-Mobile my @otherparts=$part->parts; &parseMessageParts(@otherparts); } else { if ($print_output) { print "Other Type: " . $type . "\n\n"; # OUTPUT } } } $partnum++; } return $is_mime_message; } ### # Main Program Execution ### if ($print_output) { print("Running at: " . localtime() . "\n"); } #if ($pop->login($username, $password)) if ($pop->login()) { $umask = oct($umask) if $umask =~ /^0/; umask $umask; if ($print_output) { print("Logged into mailserver\n"); } # Create the parser object my $parser = MIME::Parser->new(); $parser->output_dir($temp_folder); #my $msgnums = $pop->list; # hashref of msgnum => size #foreach my $msgnum (keys %$msgnums) #{ my $messageCount = $pop->Count; if ($print_output) { print $messageCount . " messages\n"; print "--------------------------\n"; } my $msgnum = 1; while ($msgnum <= $messageCount) { #my $msg = $pop->get($msgnum); my $msg = $pop->Retrieve($msgnum); #print $msg; my $entity = $parser->parse_data($msg); ### # GET MESSAGE HEADER ### my $msg_head = $entity->head; my $subject = ""; my $to = ""; my $from = ""; my $attachment = ""; ### # MESSAGE Related Vars ### $body = ""; @attachments = (); @attachments_type = (); @attachments_relative = (); ## # GET MESSAGE SUBJECT ## if ($msg_head->count('Subject') > 0) { $subject = $msg_head->get('Subject'); } ## # GET MESSAGE FROM ## if ($msg_head->count('From') > 0) { $from = $msg_head->get('From'); if ($from =~ /<(.*)>/) { $from = $1; } } ## # GET MESSAGE TO ## if ($msg_head->count('To') > 0) { $to = $msg_head->get('To'); if ($to =~ /<(.*)>/) { $to = $1; } } ### # GET MESSAGE PARTS (BODY AND ATTACHMENTS) ### my @parts=$entity->parts; my $is_mime = &parseMessageParts(@parts); ## Calling our parse subroutine ## # IF IT ISN'T A MIME MESSAGE (NO ATTACHMENTS) ## if (!$is_mime) { ### # GET MESSAGE BODY LINES ### $msg_body = $entity->body; foreach $message_line (@$msg_body) { if ($message_line =~ /^\n/) { } else { $body .= $message_line; } } } chomp($to); # REMOVE TRAILING LINE BREAKS chomp($from); chomp($subject); chomp($body); if ($post_to_blog) { my $attachment_html = ""; for (my $i = 0; $i <= $#attachments; $i++) { my $attachment = $attachments[$i]; my $attachment_type = $attachments_type[$i]; my $attachment_relative = $attachments_relative[$i]; if ($attachment_type eq "jpg" || $attachment_type eq "gif") { $attachment_html .= "\n"; } elsif ( $attachment_type eq "3gp" || $attachment_type eq "wav" || $attachment_type eq "mp4" || $attachment_type eq "3g2" || $attachment_type eq "mpg" || $attachment_type eq "mov" || $attachment_type eq "avi" ) { $attachment_html .= " \n \n \n \n \n \n "; } } my $postresult=XMLRPC::Lite ->proxy($blog_xmlrpc_url) ->call('metaWeblog.newPost',$blog_id,$blog_username,$blog_password, { 'title'=>$subject, 'description'=>$body . $attachment_html, 'mt_allow_comments'=>1, 'mt_allow_pings'=>1 }, 1 ) ->result; #### NEED TO POST ENCLOSURE TO XML-RPC and ADD FUNCTION TO XMLRPC.PHP if ($print_output) { print "Message To: $to\n"; print "Message From $from\n"; print "Message Subject $subject\n"; print "Message Body $body\n"; for (my $i = 0; $i <= $#attachments; $i++) { print "Message Attachment $attachments[$i] . " - " . $attachments_type[$i] . " - " . $attachments_relative[$i]\n"; } print "Post to Blog Result: " . $postresult . "\n"; print "--------------------------\n"; } } elsif ($print_output) { # FOR HITTING URL, WE EDIT THIS PART #strip out anythign after the first line break $body =~ s/\n.*$//gis; print "MESSAGE #" . $msgnum . "\n"; print "To: " . $to . "\n"; print "From: " . $from ."\n"; print "Subject: " . $subject ."\n"; print "Body: " . $body ."\n"; for (my $i = 0; $i <= $#attachments; $i++) { $attachment = $attachments[$i]; print "Attachment: " . $attachments[$i] . " - " . $attachments_type[$i] . " - " . $attachments_relative[$i] ."\n"; } # $url = $logic_url . "?task=sms"; $url = $logic_url . "?task=sms&to=" . $to . "&from=" . $from . "&subject=" . $subject . "&file=" . $attachment . "&body=" . $body . ""; print "URL:" . $url . "\n"; if ($hit_url) { print "Data fwd'ed to URL!\n"; } print "--------------------------\n"; $attachment = ""; } if ($hit_url) { # added 2/9/06 for (my $i = 0; $i <= $#attachments; $i++) { $attachment = $attachments[$i]; } # $url = $logic_url . "?task=sms"; $url = $logic_url . "?task=sms&to=" . $to . "&from=" . $from . "&subject=" . $subject . "&file=" . $attachment . "&body=" . $body . ""; my $ua = LWP::UserAgent->new(); my $req = POST $url; $ua->request($req)->as_string; } if ($delete_messages) { $pop->delete_message($msgnum); # seems to work for all emails (include @gmail) } $msgnum++; } if ($delete_temp_files) { $parser->filer->purge; } } else { print("Error: Can't log into mailbox. Make sure to check:\n"); print("(a) username + password + mailserver are correct\n"); print("(b) if using a gmail address, make sure POP is enabled in your gmail settings\n"); } #$pop->quit;