📄 imap4r1.c
字号:
* Accepts: mail stream * mailbox to delete from manage list * Returns: T on success, NIL on failure */long imap_unsubscribe (MAILSTREAM *stream,char *mailbox){ MAILSTREAM *st = stream; long ret = ((stream && LOCAL && LOCAL->netstream) || (stream = mail_open (NIL,mailbox,OP_HALFOPEN|OP_SILENT))) ? imap_manage (stream,mailbox,LEVELIMAP4 (stream) ? "Unsubscribe" : "Unsubscribe Mailbox",NIL) : NIL; /* toss out temporary stream */ if (st != stream) mail_close (stream); return ret;}/* IMAP create mailbox * Accepts: mail stream * mailbox name to create * Returns: T on success, NIL on failure */long imap_create (MAILSTREAM *stream,char *mailbox){ return imap_manage (stream,mailbox,"Create",NIL);}/* IMAP delete mailbox * Accepts: mail stream * mailbox name to delete * Returns: T on success, NIL on failure */long imap_delete (MAILSTREAM *stream,char *mailbox){ return imap_manage (stream,mailbox,"Delete",NIL);}/* IMAP rename mailbox * Accepts: mail stream * old mailbox name * new mailbox name * Returns: T on success, NIL on failure */long imap_rename (MAILSTREAM *stream,char *old,char *newname){ return imap_manage (stream,old,"Rename",newname);}/* IMAP manage a mailbox * Accepts: mail stream * mailbox to manipulate * command to execute * optional second argument * Returns: T on success, NIL on failure */long imap_manage (MAILSTREAM *stream,char *mailbox,char *command,char *arg2){ MAILSTREAM *st = stream; IMAPPARSEDREPLY *reply; long ret = NIL; char mbx[MAILTMPLEN],mbx2[MAILTMPLEN]; IMAPARG *args[3],ambx,amb2; imapreferral_t ir = (imapreferral_t) mail_parameters (stream,GET_IMAPREFERRAL,NIL); ambx.type = amb2.type = ASTRING; ambx.text = (void *) mbx; amb2.text = (void *) mbx2; args[0] = &ambx; args[1] = args[2] = NIL; /* require valid names and open stream */ if (mail_valid_net (mailbox,&imapdriver,NIL,mbx) && (arg2 ? mail_valid_net (arg2,&imapdriver,NIL,mbx2) : &imapdriver) && ((stream && LOCAL && LOCAL->netstream) || (stream = mail_open (NIL,mailbox,OP_HALFOPEN|OP_SILENT)))) { if (arg2) args[1] = &amb2; /* second arg present? */ if (!(ret = (imap_OK (stream,reply = imap_send (stream,command,args)))) && ir && LOCAL->referral) { long code = -1; switch (*command) { /* which command was it? */ case 'S': code = REFSUBSCRIBE; break; case 'U': code = REFUNSUBSCRIBE; break; case 'C': code = REFCREATE; break; case 'D': code = REFDELETE; break; case 'R': code = REFRENAME; break; default: fatal ("impossible referral command"); } if ((code >= 0) && (mailbox = (*ir) (stream,LOCAL->referral,code))) ret = imap_manage (NIL,mailbox,command,(*command == 'R') ? (mailbox + strlen (mailbox) + 1) : NIL); } mm_log (reply->text,ret ? NIL : ERROR); /* toss out temporary stream */ if (st != stream) mail_close (stream); } return ret;}/* IMAP status * Accepts: mail stream * mailbox name * status flags * Returns: T on success, NIL on failure */long imap_status (MAILSTREAM *stream,char *mbx,long flags){ IMAPARG *args[3],ambx,aflg; char tmp[MAILTMPLEN]; NETMBX mb; unsigned long i; long ret = NIL; MAILSTREAM *tstream = stream; imapreferral_t ir = (imapreferral_t) mail_parameters (stream,GET_IMAPREFERRAL,NIL); mail_valid_net_parse (mbx,&mb); /* can't use stream if not IMAP4rev1, STATUS, or halfopen and right host */ if (stream && (!(LEVELSTATUS (stream) || stream->halfopen) || strcmp (ucase (strcpy (tmp,imap_host (stream))), ucase (mb.host)))) return imap_status (NIL,mbx,flags); /* make stream if don't have one */ if (!(stream || (stream = mail_open (NIL,mbx,OP_HALFOPEN|OP_SILENT)))) return NIL; args[0] = &ambx;args[1] = NIL;/* set up first argument as mailbox */ ambx.type = ASTRING; ambx.text = (void *) mb.mailbox; if (LEVELSTATUS (stream)) { /* have STATUS command? */ aflg.type = FLAGS; aflg.text = (void *) tmp; args[1] = &aflg; args[2] = NIL; tmp[0] = tmp[1] = '\0'; /* build flag list */ if (flags & SA_MESSAGES) strcat (tmp," MESSAGES"); if (flags & SA_RECENT) strcat (tmp," RECENT"); if (flags & SA_UNSEEN) strcat (tmp," UNSEEN"); if (flags & SA_UIDNEXT) strcat (tmp,LEVELIMAP4rev1 (stream) ? " UIDNEXT" : " UID-NEXT"); if (flags & SA_UIDVALIDITY) strcat (tmp,LEVELIMAP4rev1 (stream) ? " UIDVALIDITY" : " UID-VALIDITY"); tmp[0] = '('; strcat (tmp,")"); /* send "STATUS mailbox flag" */ if (imap_OK (stream,imap_send (stream,"STATUS",args))) ret = T; else if (ir && LOCAL->referral && (mbx = (*ir) (stream,LOCAL->referral,REFSTATUS))) ret = imap_status (NIL,mbx,flags); } /* IMAP2 way */ else if (imap_OK (stream,imap_send (stream,"EXAMINE",args))) { MAILSTATUS status; status.flags = flags & ~ (SA_UIDNEXT | SA_UIDVALIDITY); status.messages = stream->nmsgs; status.recent = stream->recent; status.unseen = 0; if (flags & SA_UNSEEN) { /* must search to get unseen messages */ /* clear search vector */ for (i = 1; i <= stream->nmsgs; ++i) mail_elt (stream,i)->searched = NIL; if (imap_OK (stream,imap_send (stream,"SEARCH UNSEEN",NIL))) for (i = 1,status.unseen = 0; i <= stream->nmsgs; i++) if (mail_elt (stream,i)->searched) status.unseen++; } strcpy (strchr (strcpy (tmp,stream->mailbox),'}') + 1,mb.mailbox); /* pass status to main program */ mm_status (stream,tmp,&status); ret = T; /* note success */ } if (stream != tstream) mail_close (stream); return ret; /* success */}/* IMAP open * Accepts: stream to open * Returns: stream to use on success, NIL on failure */MAILSTREAM *imap_open (MAILSTREAM *stream){ unsigned long i,j; char *s,tmp[MAILTMPLEN],usr[MAILTMPLEN]; NETMBX mb; IMAPPARSEDREPLY *reply = NIL; imapreferral_t ir = (imapreferral_t) mail_parameters (stream,GET_IMAPREFERRAL,NIL); /* return prototype for OP_PROTOTYPE call */ if (!stream) return &imapproto; mail_valid_net_parse (stream->mailbox,&mb); usr[0] = '\0'; /* initially no user name */ if (LOCAL) { /* if stream opened earlier by us */ if (LOCAL->netstream) { /* recycle if still alive */ i = stream->silent; /* temporarily mark silent */ stream->silent = T; /* don't give mm_exists() events */ j = imap_ping (stream); /* learn if stream still alive */ stream->silent = i; /* restore prior state */ if (j) { /* was stream still alive? */ sprintf (tmp,"Reusing connection to %s",imap_host (stream)); if (LOCAL->user) sprintf (tmp + strlen (tmp),"/user=\"%s\"", LOCAL->user); if (!stream->silent) mm_log (tmp,(long) NIL); } else imap_close (stream,NIL); } else imap_close (stream,NIL); } /* copy flags from name */ if (mb.dbgflag) stream->debug = T; if (mb.anoflag) stream->anonymous = T; if (mb.secflag) stream->secure = T; mb.tryaltflag = stream->tryalt; if (!LOCAL) { /* open new connection if no recycle */ NETDRIVER *altd = (NETDRIVER *) mail_parameters (NIL,GET_ALTDRIVER,NIL); char * alts = (char *) mail_parameters(NIL,GET_ALTIMAPNAME,NIL); unsigned long altp = (unsigned long) mail_parameters (NIL,GET_ALTIMAPPORT,NIL); unsigned long defprt = imap_defaultport ? imap_defaultport : IMAPTCPPORT; stream->local = /* instantiate localdata */ (void *) memset (fs_get (sizeof (IMAPLOCAL)),0,sizeof (IMAPLOCAL)); /* assume IMAP2bis server */ LOCAL->imap2bis = LOCAL->rfc1176 = T; /* IMAP connection open logic is more complex than net_open() normally * deals with, because of the simap and rimap hacks. * If the session is anonymous, a specific port is given, or if alt is * set, do net_open() since those conditions override everything else. */ if (stream->anonymous || mb.port || mb.altflag) reply = (LOCAL->netstream = net_open (&mb,NIL,defprt,altd,alts,altp)) ? imap_reply (stream,NIL) : NIL; /* * No overriding conditions, so get the best connection that we can. In * order, attempt to open via simap, tryalt, rimap, and finally TCP. */ /* try simap */ else if (reply = imap_rimap (stream,"*imap",&mb,usr,tmp)); else if (altd && /* try tryalt if enabled */ (mb.tryaltflag || mail_parameters (NIL,GET_TRYALTFIRST,NIL)) && (LOCAL->netstream = net_open_work (altd,mb.host,alts,altp,mb.port, NET_SILENT | (mb.altopt ? NET_ALTOPT : 0))) && (reply = imap_reply (stream,NIL))) mb.altflag = T; /* no alt, try rimap first, then TCP */ else if (!(reply = imap_rimap (stream,"imap",&mb,usr,tmp)) && (LOCAL->netstream = net_open (&mb,NIL,defprt,NIL,NIL,NIL))) reply = imap_reply (stream,NIL); /* if have a connection */ if (LOCAL->netstream && reply && imap_OK (stream,reply)) { /* if not preauthenticated */ if (strcmp (reply->key,"PREAUTH")) { LOCAL->authflags = (stream->secure ? AU_SECURE : NIL) | (mb.authuser[0] ? AU_AUTHUSER : NIL); /* get server capabilities */ if (!LOCAL->gotcapability) imap_send (stream,"CAPABILITY",NIL); /* remote name for authentication */ strncpy (mb.host,net_remotehost (LOCAL->netstream),NETMAXHOST-1); mb.host[NETMAXHOST-1] = '\0'; /* need new capabilities after login */ LOCAL->gotcapability = NIL; if (!(stream->anonymous ? imap_anon (stream,tmp) : (LOCAL->use.auth ? imap_auth (stream,&mb,tmp,usr) : imap_login (stream,&mb,tmp,usr)))) { /* failed, is there a referral? */ if (ir && LOCAL->referral && (s = (*ir) (stream,LOCAL->referral,REFAUTHFAILED))) { imap_close (stream,NIL); fs_give ((void **) &stream->mailbox); stream->mailbox = s;/* set as new mailbox name to open */ return imap_open (stream); } return NIL; /* authentication failed */ } } } else { /* log error if there was one */ if (reply) mm_log (reply->text,ERROR); return NIL; /* lost during greeting */ } /* get server capabilities again */ if (!LOCAL->gotcapability) imap_send (stream,"CAPABILITY",NIL); } if (LOCAL->netstream) { /* still have a connection? */ if (ir && LOCAL->referral && (s = (*ir) (stream,LOCAL->referral,REFAUTH))) { imap_close (stream,NIL); fs_give ((void **) &stream->mailbox); stream->mailbox = s; /* set as new mailbox name to open */ return imap_open (stream);/* recurse to log in on real site */ } stream->perm_seen = stream->perm_deleted = stream->perm_answered = stream->perm_draft = LEVELIMAP4 (stream) ? NIL : T; stream->perm_user_flags = LEVELIMAP4 (stream) ? NIL : 0xffffffff; stream->sequence++; /* bump sequence number */ sprintf (tmp,"{%s",net_host (LOCAL->netstream)); if (!((i = net_port (LOCAL->netstream)) & 0xffff0000)) sprintf (tmp + strlen (tmp),":%lu",i); strcat (tmp,"/imap"); if (mb.altflag) sprintf (tmp + strlen (tmp),"/%s",(char *) mail_parameters (NIL,GET_ALTDRIVERNAME,NIL)); if (mb.altopt) sprintf (tmp + strlen (tmp),"/%s",(char *) mail_parameters (NIL,GET_ALTOPTIONNAME,NIL)); if (mb.secflag) strcat (tmp,"/secure"); if (stream->anonymous) strcat (tmp,"/anonymous}"); else { /* record user name */ if (!LOCAL->user && usr[0]) LOCAL->user = cpystr (usr); if (LOCAL->user) sprintf (tmp + strlen (tmp),"/user=\"%s\"", LOCAL->user); else strcat (tmp,"}"); } if (!stream->halfopen) { /* wants to open a mailbox? */ IMAPARG *args[2]; IMAPARG ambx; ambx.type = ASTRING; ambx.text = (void *) mb.mailbox; args[0] = &ambx; args[1] = NIL; if (imap_OK (stream,reply = imap_send (stream,stream->rdonly ? "EXAMINE": "SELECT",args))) { /* mailbox name */ sprintf (tmp + strlen (tmp),"}%s",mb.mailbox); if (!stream->nmsgs && !stream->silent) mm_log ("Mailbox is empty",(long) NIL); /* note if an INBOX or not */ stream->inbox = !strcmp (ucase (mb.mailbox),"INBOX"); } else if (ir && LOCAL->referral && (s = (*ir) (stream,LOCAL->referral,REFSELECT))) { imap_close (stream,NIL); fs_give ((void **) &stream->mailbox); stream->mailbox = s; /* set as new mailbox name to open */ return imap_open (stream); } else { mm_log (reply->text,ERROR); if (imap_closeonerror) return NIL; stream->halfopen = T; /* let him keep it half-open */ } } if (stream->halfopen) { /* half-open connection? */ strcat (tmp,"}<no_mailbox>"); /* make sure dummy message counts */ mail_exists (stream,(long) 0); mail_recent (stream,(long) 0); } fs_give ((void **) &stream->mailbox); stream->mailbox = cpystr (tmp); } /* success if stream open */ return LOCAL->netstream ? stream : NIL;}/* IMAP rimap connect * Accepts: MAIL stream * NETMBX specification * service to use * user name * scratch buffer * Returns: parsed reply if success, else NIL */IMAPPARSEDREPLY *imap_rimap (MAILSTREAM *stream,char *service,NETMBX *mb, char *usr,char *tmp){ unsigned long i; char c[2]; NETSTREAM *tstream; IMAPPARSEDREPLY *reply = NIL; /* try rimap open */ if (tstream = net_aopen (NIL,mb,service,usr)) { /* if success, see if reasonable banner */ if (net_getbuffer (tstream,(long) 1,c) && (*c == '*')) { i = 0; /* copy to buffer */ do tmp[i++] = *c; while (net_getbuffer (tstream,(long) 1,c) && (*c != '\015') && (*c != '\012') && (i < (MAILTMPLEN-1))); tmp[i] = '\0'; /* tie off */ /* snarfed a valid greeting? */ if ((*c == '\015') && net_getbuffer (tstream,(long) 1,c) && (*c == '\012') && !strcmp ((reply = imap_parse_reply (stream,cpystr (tmp)))->tag,"*")){ /* parse line as IMAP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -