#include #include #include #include #include "tlmpmail.h" #include "tlmpmail.m" #include "keys.h" /* Return true if one string in shortlist is found in longlist. false otherwise */ static bool classify_onematch ( const SSTRINGS &longlist, const SSTRINGS &shortlist) { bool ret = false; int n = shortlist.getnb(); for (int i=0; iget(); if (longlist.ilookup(s)!=-1){ ret = true; break; } } return ret; } static bool classify_checktmpfriends (const SSTRINGS &tmp, const char *addr) { bool ret = false; int n = tmp.getnb(); for (int i=0; iget()); if (t.icmp(addr)==0){ ret = true; break; } } return ret; } /* Set the classN features of all messages in the folder view */ PUBLIC void FOLDER_VIEW::classify() { MAIL_MESSAGES tbs; int rev = -1; loadindex (tbs,rev); SSTRINGS friends,rejected,mlist,myaddrs,tmpfriends,subjects; linuxconf_getall (K_FRIENDS,K_INDEX,friends,false); linuxconf_getall (K_TMPFRIENDS,K_INDEX,tmpfriends,false); linuxconf_getall (K_REJECTED,K_INDEX,rejected,false); linuxconf_getall (K_MLIST,K_INDEX,mlist,false); linuxconf_getall (K_SUBJECTS,K_INDEX,subjects,false); prefs_getmyaddrs(myaddrs); NICKS nicks; // Everyone in the address book is a friend glocal int i; for (glocal.i=0; glocal.ireply.getfirstaddr(); if (from[0] == '\0') from = m->from.getfirstaddr(); const char *fromdomain = strchr(from,'@'); if (fromdomain == NULL){ fromdomain = ""; } if (from[0] == '\0'){ classes[0].setfrom (MSG_U(I_BOGUS,"Bogus")); }else if (classify_onematch (mlist,m->to.addrs) || classify_onematch (mlist,m->cc.addrs)){ classes[0].setfrom (MSG_U(I_MLIST,"Mailing-list")); }else if (friends.ilookup(from)!=-1 || friends.ilookup(fromdomain)!=-1 || nicks.locateaddr(from)!=NULL){ classes[0].setfrom (MSG_U(I_FRIENDS,"Friend")); }else if (classify_checktmpfriends(tmpfriends,from)){ classes[0].setfrom (MSG_U(I_CONTACT,"Contact")); }else if (rejected.ilookup(from)!=-1 || rejected.ilookup(fromdomain)!=-1){ classes[0].setfrom (MSG_U(I_REJECTED,"Bugger")); }else{ // Can't find my name or any known mailing list // classes[0].setfrom (MSG_R(I_BOGUS)); } if (classify_onematch (myaddrs,m->to.addrs) || classify_onematch (myaddrs,m->cc.addrs)){ classes[1].setfrom (MSG_U(I_ME,"Personal")); } if (0){ // Check attachement MAIL_MESSAGE_FULL full; if (m->loadmsg(full) != -1){ (full,true,false); fprintf (stderr,"%d,%d :%s: :%s:\n",glocal.i,no,info.name.get(),info.description.get()); } } const char *subject = m->subject.get(); for (int j=0; jget()); rest = str_skip(rest); if (stristr(subject,rest)!=NULL){ classes[2].setfrom (MSG_U(I_KNOWNSUB,"related")); break; } } for (int j=0; jflags.set_str (tbclass[j],classes[j].get()); } m->setmodified(); } } /* Add the addresses of a message into a given list. The user picks the addresses he wants to add. */ PRIVATE void MAIL_MESSAGE::set_in_list( const char *key, const char *title, const char *intro) { SSTRINGS tb; linuxconf_getall (key,K_INDEX,tb,true); SSTRING addr(from.getfirstaddr()); if (addr.is_empty()){ xconf_error (MSG_U(E_NOFROM,"No address in message")); }else{ if (tb.lookup(addr)!=-1){ xconf_error (MSG_R(E_INLIST)); }else{ DIALOG dia; dia.settype (DIATYPE_POPUP); SSTRING comment; dia.newf_str (MSG_R(F_EMAILADDR),addr); dia.last_noempty(); dia.newf_str (MSG_R(F_COMMENT),comment); int nof = 0; while (1){ MENU_STATUS code = dia.edit (title,intro,help_nil,nof); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else{ if (comment.is_filled()){ linuxconf_replace (key,addr.get(),comment); }else{ linuxconf_removeall (key,addr.get()); } tb.add (new SSTRING(addr)); linuxconf_replace (key,K_INDEX,tb); linuxconf_save(); break; } } } } } /* Add an email correspondant to the list of friends */ PUBLIC void MAIL_MESSAGE::set_friends() { set_in_list (K_FRIENDS,MSG_U(T_NEWFRIEND,"New friend") ,MSG_U(I_NEWFRIEND,"This address will be added to the friend list")); } /* Add an email correspondant to the black list (rejected) */ PUBLIC void MAIL_MESSAGE::set_rejected() { set_in_list (K_REJECTED,MSG_U(T_NEWBUGGER,"New bugger") ,MSG_U(I_NEWBUGGER,"This address will be added to the black list")); } static void classify_edit (const char *key, const char *title) { glocal SSTRINGS tb; glocal const char *key = key; linuxconf_getall (key,K_INDEX,glocal.tb,true); (title,"",help_nil); newf_head (MSG_U(H_ADDRS,"Address\tComment")); sortable(); sortpolicy("aa"); addwhat (MSG_U(I_ADDADDR,"an email address")); for (int i=0; iget(); const char *comment = linuxconf_getval (glocal.key,addr); if (comment == NULL) comment = ""; new_menuitem (addr,comment); } DIALOG dia; dia.settype (DIATYPE_POPUP); SSTRING addr(glocal.tb.getitem(no)->get()); SSTRING oldaddr(addr); SSTRING comment(linuxconf_getval(glocal.key,addr.get())); dia.newf_str (MSG_R(F_EMAILADDR),addr); dia.last_noempty(); dia.newf_str (MSG_R(F_COMMENT),comment); int nof = 0; while (1){ MENU_STATUS code = dia.edit ("","",help_nil,nof ,MENUBUT_ACCEPT|MENUBUT_CANCEL|MENUBUT_DEL); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else if (code == MENU_DEL){ if (xconf_delok()){ glocal.tb.remove_del(no); linuxconf_replace (glocal.key,K_INDEX,glocal.tb); linuxconf_removeall (glocal.key,addr.get()); linuxconf_save(); break; } }else if (addr.icmp(oldaddr)!=0 && glocal.tb.ilookup(addr.get())!=-1){ xconf_error (MSG_U(E_INLIST,"Already in list")); }else{ // We clean up the old address glocal.tb.remove_del(no); linuxconf_removeall (glocal.key,oldaddr.get()); // Put the new one in place glocal.tb.add (new SSTRING(addr)); linuxconf_replace (glocal.key,K_INDEX,glocal.tb); if (comment.is_filled()){ linuxconf_replace (glocal.key,addr.get(),comment); }else{ linuxconf_removeall (glocal.key,addr.get()); } linuxconf_save(); break; } } DIALOG dia; dia.settype (DIATYPE_POPUP); SSTRING addr,comment; dia.newf_str (MSG_R(F_EMAILADDR),addr); dia.last_noempty(); dia.newf_str (MSG_R(F_COMMENT),comment); int nof = 0; while (1){ MENU_STATUS code = dia.edit ("","",help_nil,nof); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else if (glocal.tb.lookup(addr.get())!=-1){ xconf_error (MSG_R(E_INLIST)); }else{ glocal.tb.add (new SSTRING(addr)); linuxconf_replace (glocal.key,K_INDEX,glocal.tb); if (comment.is_filled()){ linuxconf_replace (glocal.key,addr.get(),comment); }else{ linuxconf_removeall (glocal.key,addr.get()); } linuxconf_save(); break; } } } /* Edit the list of known people */ void classify_editfriends() { classify_edit (K_FRIENDS,MSG_U(T_FRIENDS,"Known corespondants")); } /* Edit the black list (rejected) */ void classify_editrejected() { classify_edit (K_REJECTED,MSG_U(T_REJECTED,"Black list")); } /* Edit the list of mailing lists */ void classify_editmlist() { classify_edit (K_MLIST,MSG_U(T_MAILINGLISTS,"Mailing lists")); } /* Record an address in a temporary friend list. This list usually contains addresses of people we contacted (or replied to). In this case, we probably expect to exchange with them for a while. Since these people may be somewhat unrelated to us, we expect to clean this list once in a while. Also since this list is built on the fly (not under direct user control), it is a good thing to use a different list. addresses already in friends,rejected, mailing lists and address book are not added there. */ void classify_addtmpfriend (const char *addr) { SSTRINGS friends,mlist,rejected; NICKS nicks; linuxconf_getall (K_FRIENDS,K_INDEX,friends,false); linuxconf_getall (K_REJECTED,K_INDEX,rejected,false); linuxconf_getall (K_MLIST,K_INDEX,mlist,false); if (friends.ilookup(addr)==-1 && mlist.ilookup(addr)==-1 && rejected.ilookup(addr)==-1 && nicks.locateaddr(addr)==NULL){ // Ok, not a friend, we must add it in tmpfriends SSTRINGS tmpfriends; linuxconf_getall (K_TMPFRIENDS,K_INDEX,tmpfriends,true); // tmp friends contains not only email address but a date. // So we must parse the line bool found = false; time_t now = time(NULL); for (int i=0; iget()); if (a.icmp(addr)==0){ // Ok, we have a match, we replace the date s->setfromf ("%s %lu",addr,now); found = true; break; } } if (!found){ SSTRING *s = new SSTRING; s->setfromf ("%s %lu",addr,now); tmpfriends.add (s); } linuxconf_replace (K_TMPFRIENDS,K_INDEX,tmpfriends); linuxconf_save(); } } /* Records some addresses as contact (temporary friends). These are people from which we expect some mails, so must be managed like friends. */ void classify_addtmpfriends (const SSTRINGS &addrs) { // This is highly inneficient if we are sending emails to // several people since the other classify_addtmpfriend is loading/saving // all the time. Later... for (int i=0; iget()); } } /* Record a string (the subject of a message). Incoming messages partially matching this string will be filtered differently. This is useful when we send a message to a friend or a mailing list and then somebody completly unknown to us reply on it. */ void classify_addsubject (const char *subject) { SSTRINGS subs; linuxconf_getall (K_SUBJECTS,K_INDEX,subs,true); // Each line contains a date followed by the subject // So we must parse the line bool found = false; time_t now = time(NULL); for (int i=0; iget()); rest = str_skip(rest); if (strcmp(rest,subject)==0){ // Ok, we have a match, we replace the date s->setfromf ("%lu %s",now,rest); found = true; break; } } if (!found){ SSTRING *s = new SSTRING; s->setfromf ("%lu %s",now,subject); subs.add (s); } linuxconf_replace (K_SUBJECTS,K_INDEX,subs); linuxconf_save(); } static int classify_editsubject (SSTRING &line) { int ret = -1; DIALOG dia; SSTRING sub,date; const char *s = date.copyword(line.get()); sub = str_skip(s); dia.settype (DIATYPE_POPUP); dia.newf_str (MSG_U(F_KEYWORD,"Keyword or subject"),sub); dia.newf_str (MSG_U(F_DATESUB,"Entry last used"),date); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_KEYWORD,"New keyword entry") ,"",help_nil,nof ,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_DEL); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else if (code == MENU_DEL){ ret = 1; break; }else if (code == MENU_ACCEPT){ time_t ti = time(NULL); line.setfromf ("%lu %s",ti,sub.get()); ret = 0; break; } } return ret; } void classify_editsubjects () { glocal SSTRINGS tb; (MSG_U(T_INTEREST,"Keyword in subjects") ,"",help_nil); newf_head (MSG_U(H_INTEREST,"Subject\tLast used")); sortable(); sortpolicy ("aa"); addwhat (MSG_U(I_NEWKEYWORD,"a new keyword")); glocal.tb.remove_all(); linuxconf_getall (K_SUBJECTS,K_INDEX,glocal.tb,true); for (int i=0; iget(); SSTRING tmp; const char *rest = tmp.copyword (s); rest = str_skip(rest); time_t ti = tmp.getval(); struct tm *t = localtime (&ti); new_menuitemf(rest,"%04d/%02d/%02d",t->tm_year+1900,t->tm_mon+1,t->tm_mday); } SSTRING *s = glocal.tb.getitem(no); int ret = classify_editsubject(*s); if (ret != -1){ if (ret == 1){ glocal.tb.remove_del (no); } linuxconf_replace (K_SUBJECTS,K_INDEX,glocal.tb); linuxconf_save(); } SSTRING tmp; int ret = classify_editsubject(tmp); if (ret == 0){ linuxconf_add (K_SUBJECTS,K_INDEX,tmp); linuxconf_save(); } }