#!/usr/bin/env pike

/*
 * pinmn - Pike IMAP New Mail Notifyer 
 *
 * Coypright (C) 1999 Mikael Brandstrm. <mikael@unix.pp.se>
 *
 * May be freely distributed and/or modified as long as the copyright notice
 * is not removed. (You may add the word "Portions" in front of the copyright
 * notice.
 */

/* Usage: Change the lines below to values according to your needs and
 * just start the program.
 * This program REQUIERS my IMAP.pmod, which should have come along with
 * the program. It should be located in the same direktory as the program is
 * run from. (Otherwise change the inherit line below.)
 */

#define IMAPHOST "localhost"
#define IMAPLOGIN "loginimap"
#define IMAPPWD "thepasswordimap"
#define MAILBOX "INBOX"
#define TIME 300

/* END configuration lines */

inherit .CAMAS.IMAPclient2;

object con;
int recent;
int exists;
mixed co;

/* Called whenever a status response arrives */

void status_handler(string what, mixed data){
  switch(what){
  case "exists": 
    if(data-exists>0){
      for(int i=1; i<=(data-exists); i++){ 
	// Fetch header and size for new messages.
	con->fetch(exists+i,({"flags","envelope","rfc822.size"}));
      }
    }
    exists=data;
    break;
  case "fetch":
    // Result from con->fetch()
    //    write(sprintf("%O\n",data));
    if(data->flags->recent){
      write("\nNew mail from \"" + myconv(data->envelope->from[0][0]) + 
	    "\" (" + (string) data->size + " bytes)\nSubject: " + 
	    myconv(data->envelope->subject) + "\n\n");
    }
      break;
  }
}

void my_co(){
  con->noop(); // NOOP is used for polling mailbox status
  co=call_out(my_co,TIME);
}

// select_handler is called when SELECT succeeds/fails
void select_handler(string tag, mapping data){
  if(!data){
    write("Select failed\n");
    con->logout();
  }
  co=call_out(my_co,TIME);
}


// The ready callback is called when the initial connection negotiation is
// done. The first argument is true if the connection succeeded.

void ready_handler(int s, string msg){
  if(s){
    write("Server ready. " + (msg? "Message of the day is:\n\t" + msg : "") 
	  + "\n");
    con->select(MAILBOX,select_handler);
  }else{
    write("Connection failed: " + (msg?msg:"") + "\n");
    con->logout();
  }
}

// Handle closed connection
void close_handler(){
  write("Connection closed\n");
  if(co)
    remove_call_out(co);
  con=0;
  exit(0);
}

// Handle "BYE" response
void bye_handler(string msg){
  write("IMAP server is disconnecting: " + msg + "\n");
}

// Main is really simple
int main(){
  con=Client(IMAPHOST,143,IMAPLOGIN,IMAPPWD,
	     status_handler,close_handler,bye_handler,ready_handler);
  exists=0;
  recent=0;
  co=0;
  signal(signum("SIGKILL"),lambda(){if(con)con->logout();else exit(0);});
  signal(signum("SIGHUP"),lambda(){if(con)con->logout();else exit(0);});
  signal(signum("SIGINT"),lambda(){if(con)con->logout();else exit(0);});
  return -1;

}
	     
string myconv(string str){
  array(string) spl,splny=({ });
  if(str==0)
    return "";
  spl = (string)str / " ";
  int i;
  mixed tmp;
  for(i=0;i<sizeof(spl);i++){
    splny+=({MIME.decode_word(spl[i])[0]});
  }
  string ret = splny * " ";
  return ret;
}

