Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
Hello community!

Here you have my recent project using Mail::IMAPClient intended to manage some of my incoming emails. It is able to speak too, but the current speaking ability is provided by Win32::SAPI5 so if you want to use on other platforms, just modify the small voice sub at the end of the program (and lines 8 and 22).

The core of this simple client is the infinite while (1) loop at line 135: an incoming message will be passed to process_message (line 164).

Here in the process_message sub I put some simple example of managing emails: extract the sender (both address and display name), subject and body and some IMAP operation: mark as read, move the message.. modify to your needs.

On windows and using the SAPI voice this program will use the system default voice: you can modify it under control panel -> Speech recognition -> properties (or somthing like that.. you can figure it).

The program handles two signals: BREAK to show the current status of the program and, more important, INT to premit the IMAP logout and so a clean exit.

Here a small example of session:

shell>perl imap-monitorV5PM.pl -u user@example.com -s email.example.co +m -p 993 -ssl 1 -i 5 Enter password for user@example.com on email.example.com VOICE: user@example.com succesfully authenticated on email.example.com + port 993. Checking INBOX for incoming messages every 5 seconds. CTRL-C to exit the program permitting the IMAP logout CTRL-BREAK to review the current status of the program Tabella codici attiva: 1252 + # I press CTRL-BREAK ====================================================================== imap-monitorV5PM.pl PID 5052 Mon Jan 30 12:33:45 2023 - email.example.com connected checked messages: 3 ====================================================================== + # a new message triggering default rule ====================================================================== Mon Jan 30 12:47:29 2023 ====================================================================== VOICE: Default rule. New message from: Johann Sebastian Bach. Subject: + Listen to my new album! ====================================================================== + # I press CTRL-C Logging out.. VOICE: IMAP logout.. Exiting..

..and obviously the code:

use strict; use warnings; use Mail::IMAPClient; use Term::ReadKey; use Getopt::Long; use Encode qw(decode encode); use Win32::SAPI5; use utf8; my $VERSION = 5; my $user; my $server; my $port; my $ssl = 0; my $imap_folder = "INBOX"; my $sleep = 60; my $debug = 0; my $substr = 500; # used to cut body_string my %seen; # take count of already seen messages my $voice = Win32::SAPI5::SpVoice->new(); $|++; GetOptions ( "u|user=s" => \$user, "s|server=s" => \$server, "p|porta=i" => \$port, "ssl=i" => \$ssl, "f|folder=s" => \$imap_folder, "i|interval=i" => \$sleep, "debug" => \$debug, "substring=i" => \$substr, ) or show_help(); sub show_help{ print <<EOH; $0 usage: $0 -user LOGIN -server SERVER -port N [ -ssl 0|1 -folder FOLDER +-interval SECONDI --substring --debug] -u -user username to authenticate on the given server (REQU +IRED) -s -server IMAP server to connect to (REQUIRED) -p -port port used by the server for IMAP connections (REQU +IRED) -ssl use or not SSL to connect (0 or 1 - default 1) -f -folder IMAP folder to check (default: "INBOX") -i -interval seconds between checks (default 60) -substring how many bytes of mail body to print on screen (de +fault 500) -d -debug extra debug output EOH exit; } # check of required arguments my %check = (user=>$user,server=>$server,port=>$port); foreach my $need ( keys %check ){ unless ( defined $check{$need} ){ warn "\nPlease provide the parameter: $need"; show_help(); } } # gently ask for password print "Enter password for $user on $server\n"; my $password; ReadMode('noecho'); $password = ReadLine(0); chomp $password; ReadMode 'normal'; # the IMAP client init my $imap = Mail::IMAPClient->new( Server => $server, User => $user, password => $password, Port => $port, Ssl=> $ssl, Uid=> 1, ) or die "IMAP Failure: $@"; $imap->Peek(1);# do NOT mark as read when handling messages $imap->select( $imap_folder ) or die "IMAP Select Error for imap folde +r [$imap_folder]: $@"; # check the connection if ( $imap->IsConnected() ){ print "FOLDERS\n\t",join( "\n\t", $imap->folders ), "\n" if $debug +; voice("$user succesfully authenticated on $server port $port. ". "Checking $imap_folder for incoming messages every $sleep seco +nds."); } else{ print $imap->LastError(); die; } # useful to print something in cmd.exe defaulting on codepage 850 print "changing codepage..\n"; system (1, 'chcp 1252'); print "\n\nCTRL-C to exit the program permitting the IMAP logout\n"; print "CTRL-BREAK to review the current status of the program\n"; # Handle Ctrl-C $SIG{INT} = sub{ print "\n\nLogging out..\n"; voice("IMAP logout..\n"); $imap->logout(); print "Exiting..\n"; exit; }; # Handle Ctrl-Break $SIG{BREAK} = sub{ print '=' x 70, "\n"; print "$0 PID $$\n"; print scalar localtime(time)," - $server ",($imap->IsConnected() ? + 'connected' : 'NOT connected'),"\n"; print "checked messages: ", scalar keys %seen,"\n"; print '=' x 70, "\n"; }; ################################################################### # checking for new messages infinite loop ################################################################### my $now = time; %seen = map { $_ => 1} $imap->sentsince($now); while (1){ my $attempts = 1; my $max_attempts = 12; while ( !$imap->noop ){ print "Reconection retry $attempts..\n"; $imap->reconnect; if( $imap->IsConnected() ){ print "Reconnected succesfully!\n"; last; } else{ sleep 10; die "Impossible to reconnect: $@" if $attempts == $max_att +empts; $attempts++; } } my @msgs = $imap->sentsince($now); foreach my $msg (@msgs){ next if $seen{$msg}; $seen{ $msg }++; process_message( $msg ); } sleep 1 for 1..$sleep; $now = time; } ################################################################### # handling messages ################################################################### sub process_message{ my $msg = shift; # extract some mail details $imap->get_header( $msg, "From" ) =~ /^(.*)\s<(.*)>$/; my $from_name = $1; my $from_addr = $2; my $subj = decode('MIME-Header', $imap->get_header( $msg, "Subjec +t" )); # some decoration print '=' x 70, "\n"; print scalar localtime(time),"\n"; print '=' x 70, "\n"; ##################################### # RULES ##################################### # Flag the message and print subj and part of the body if( $from_addr eq 'larry.wall@example.com' or $subj =~ /^from larry/i ){ # say something fun voice("Larry wrote you!"); # set the Flagged (=important, yellow star in thunderbird) + $imap->set_flag("Flagged",$msg); print "SUBJECT: $subj\nBODY:\n". # cut the body as per --substring paramenter substr(decode('MIME-Header', $imap->body_string( $msg +) ),0, $substr),"\n"; } # mark as read and move it SOMEWHERE # NOTE: this moves the message into INBOX/SOMEWHERE and if the fol +der does not exists # it creates it for you (you might need to 'subscribe' it in order + to see the message) elsif( $from_addr =~ /perl.org$/ ){ voice("New mail from perl.org"); # mark as read $imap->set_flag("Seen",$msg); # move it my $newmsgID = $imap->move( 'INBOX/SOMEWHERE', $msg )or die "C +ould not move: $@\n"; # expunge make effective the move $imap->expunge; # $newmsgID must be valid print "DEBUG: message moved\n" if $debug and $newmsgID; } # DEFAULT RULE else{ voice( "Default rule. New message from: $from_name. Subject: $ +subj" ); } # With the IMAP protocol you can manage five flags : # # \Seen: Message has been read # \Answered: Message has been answered # \Flagged: Message is marked as “flagged” for urgent/special atte +ntion # \Deleted: Message is marked as “to be deleted”. # Note that the actual removal takes effect when the expunge() +function is called, # when you switch the mailbox, or close the connection. # This flag is already added by the delete() function # \Draft: Message has not completed composition (marked as a draft +). # # use them as in (leading slash is optional) # $imap->set_flag("Seen",$msg); # # BE AWARE: if you omit $msg like in $imap->set_flag("Seen") it wi +ll be interpreted as $imap->set_flag("Seen", 'ALL') # THE ABOVE IS TRUE ALSO FOR THESE METHODS: # # bodypart_string # message_uid # body_string # get_bodystructure # get_envelope # fetch_hash (and so also the migrate methods) # flags # parse_headers # size # # https://github.com/plobbes/mail-imapclient/issues/4 print '=' x 70, "\n"; } sub voice{ my $txt = join ' ',@_; $voice->Speak($txt); print "VOICE: $txt\n"; }
L*

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

In reply to Read and manage IMAP mails for me by Discipulus

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (3)
As of 2024-04-20 05:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found