📄 imap4r1.c
字号:
imap_parse_unsolicited (stream,reply); /* make sure it looked like good stuff */ if (imap_OK (stream,reply)) { LOCAL->netstream = tstream; return reply; /* return success */ } } } net_close (tstream); /* failed, punt the temporary netstream */ } return NIL;}/* IMAP log in as anonymous * Accepts: stream to authenticate * scratch buffer * Returns: T on success, NIL on failure */long imap_anon (MAILSTREAM *stream,char *tmp){ IMAPPARSEDREPLY *reply; char *s = net_localhost (LOCAL->netstream); if (LOCAL->use.authanon) { char tag[16]; unsigned long i; char *broken = "IMAP connection broken (anonymous auth)"; sprintf (tag,"%08lx",stream->gensym++); /* build command */ sprintf (tmp,"%s AUTHENTICATE ANONYMOUS",tag); if (!imap_soutr (stream,tmp)) { mm_log (broken,ERROR); return NIL; } if (imap_challenge (stream,&i)) imap_response (stream,s,strlen (s)); /* get response */ if (!(reply = &LOCAL->reply)->tag) reply = imap_fake (stream,tag,broken); /* what we wanted? */ if (strcmp (reply->tag,tag)) { /* abort if don't have tagged response */ while (strcmp ((reply = imap_reply (stream,tag))->tag,tag)) imap_soutr (stream,"*"); } } else { IMAPARG *args[2]; IMAPARG ausr; ausr.type = ASTRING; ausr.text = (void *) s; args[0] = &ausr; args[1] = NIL; /* send "LOGIN anonymous <host>" */ reply = imap_send (stream,"LOGIN ANONYMOUS",args); } /* success if reply OK */ if (imap_OK (stream,reply)) return T; mm_log (reply->text,ERROR); return NIL;}/* IMAP authenticate * Accepts: stream to authenticate * parsed network mailbox structure * scratch buffer * place to return user name * Returns: T on success, NIL on failure */long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr){ unsigned long trial,ua; int ok; char tag[16]; char *lsterr = NIL; AUTHENTICATOR *at; IMAPPARSEDREPLY *reply; for (ua = LOCAL->use.auth; LOCAL->netstream && ua && (at = mail_lookup_auth (find_rightmost_bit (&ua) + 1));) { if (lsterr) { /* previous authenticator failed? */ sprintf(tmp,"Retrying using %s authentication after %s",at->name,lsterr); mm_log (tmp,NIL); fs_give ((void **) &lsterr); } trial = 0; /* initial trial count */ tmp[0] = '\0'; /* no error */ do { /* gensym a new tag */ if (tmp[0]) mm_log (tmp,WARN); sprintf (tag,"%08lx",stream->gensym++); /* build command */ sprintf (tmp,"%s AUTHENTICATE %s",tag,at->name); if (imap_soutr (stream,tmp)) { ok = (*at->client) (imap_challenge,imap_response,mb,stream,&trial,usr); /* get response */ if (!(reply = &LOCAL->reply)->tag) reply=imap_fake (stream,tag,"IMAP connection broken (authenticate)"); /* what we wanted? */ if (strcmp (reply->tag,tag)) { /* abort if don't have tagged response */ while (strcmp ((reply = imap_reply (stream,tag))->tag,tag)) imap_soutr (stream,"*"); } /* cancel any last error */ if (lsterr) fs_give ((void **) &lsterr); if (ok) { /* done if got success response */ if (imap_OK (stream,reply)) return T; if (!trial) { /* if main program requested cancellation */ mm_log ("IMAP Authentication cancelled",ERROR); return NIL; } } lsterr = cpystr (reply->text); sprintf (tmp,"Retrying %s authentication after %s",at->name,lsterr); } } while (LOCAL->netstream && !LOCAL->byeseen && trial && (trial < imap_maxlogintrials)); } if (lsterr) { /* previous authenticator failed? */ sprintf (tmp,"Can not authenticate to IMAP server: %s",lsterr); mm_log (tmp,ERROR); fs_give ((void **) &lsterr); } return NIL; /* ran out of authenticators */}/* IMAP login * Accepts: stream to login * parsed network mailbox structure * scratch buffer * place to return user name * Returns: T on success, NIL on failure */long imap_login (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr){ unsigned long trial = 0; IMAPPARSEDREPLY *reply; IMAPARG *args[3]; IMAPARG ausr,apwd; if (stream->secure) { /* never do LOGIN if want security */ mm_log ("Can't do secure authentication with this server",ERROR); return NIL; } if (LOCAL->logindisabled) { /* never do LOGIN if server disabled it */ mm_log ("Server disables LOGIN, no recognized SASL authenticator",ERROR); return NIL; } if (mb->authuser[0]) { /* never do LOGIN with /authuser */ mm_log ("Can't do /authuser with this server",ERROR); return NIL; } ausr.type = apwd.type = ASTRING; ausr.text = (void *) usr; apwd.text = (void *) tmp; args[0] = &ausr; args[1] = &apwd; args[2] = NIL; while (LOCAL->netstream && !LOCAL->byeseen && !LOCAL->referral && (trial < imap_maxlogintrials)) { tmp[0] = 0; /* prompt user for password */ mm_login (mb,usr,tmp,trial++); if (!tmp[0]) { /* user refused to give a password */ mm_log ("Login aborted",ERROR); return NIL; } /* send "LOGIN usr tmp" */ if (imap_OK (stream,reply = imap_send (stream,"LOGIN",args))) return T; mm_log (reply->text,WARN); } if (!LOCAL->referral) mm_log ("Too many login failures",ERROR); return NIL;}/* Get challenge to authenticator in binary * Accepts: stream * pointer to returned size * Returns: challenge or NIL if not challenge */void *imap_challenge (void *s,unsigned long *len){ MAILSTREAM *stream = (MAILSTREAM *) s; IMAPPARSEDREPLY *reply; while (LOCAL->netstream) { /* parse reply from server */ if (reply = imap_parse_reply (stream,net_getline (LOCAL->netstream))) { /* received challenge? */ if (!strcmp (reply->tag,"+")) return rfc822_base64 ((unsigned char *) reply->text, strlen (reply->text),len); /* untagged data? */ else if (!strcmp (reply->tag,"*")) imap_parse_unsolicited (stream,reply); else break; /* tagged response */ } } return NIL; /* tagged response, bogon, or lost stream */}/* Send authenticator response in BASE64 * Accepts: MAIL stream * string to send * length of string * Returns: T if successful, else NIL */long imap_response (void *s,char *response,unsigned long size){ MAILSTREAM *stream = (MAILSTREAM *) s; unsigned long i,j,ret; char *t,*u; if (response) { /* make CRLFless BASE64 string */ if (size) { for (t = (char *) rfc822_binary ((void *) response,size,&i),u = t,j = 0; j < i; j++) if (t[j] > ' ') *u++ = t[j]; *u = '\0'; /* tie off string for mm_dlog() */ if (stream->debug) mm_dlog (t); /* append CRLF */ *u++ = '\015'; *u++ = '\012'; ret = net_sout (LOCAL->netstream,t,u - t); fs_give ((void **) &t); } else ret = imap_soutr (stream,""); } /* abort requested */ else ret = imap_soutr (stream,"*"); return ret;}/* IMAP close * Accepts: MAIL stream * option flags */void imap_close (MAILSTREAM *stream,long options){ THREADER *thr,*t; IMAPPARSEDREPLY *reply; if (stream && LOCAL) { /* send "LOGOUT" */ if (!LOCAL->byeseen) { /* don't even think of doing it if saw a BYE */ /* expunge silently if requested */ if (options & CL_EXPUNGE) imap_send (stream,"EXPUNGE",NIL); if (LOCAL->netstream && !imap_OK (stream,reply = imap_send (stream,"LOGOUT",NIL))) mm_log (reply->text,WARN); } /* close NET connection if still open */ if (LOCAL->netstream) net_close (LOCAL->netstream); LOCAL->netstream = NIL; /* free up memory */ if (LOCAL->sortdata) fs_give ((void **) &LOCAL->sortdata); if (LOCAL->namespace) { mail_free_namespace (&LOCAL->namespace[0]); mail_free_namespace (&LOCAL->namespace[1]); mail_free_namespace (&LOCAL->namespace[2]); fs_give ((void **) &LOCAL->namespace); } if (LOCAL->threaddata) mail_free_threadnode (&LOCAL->threaddata); if (thr = LOCAL->threader) {/* flush threaders */ while (t = thr) { fs_give ((void **) &t->name); thr = t->next; fs_give ((void **) &t); } } if (LOCAL->referral) fs_give ((void **) &LOCAL->referral); if (LOCAL->user) fs_give ((void **) &LOCAL->user); if (LOCAL->reply.line) fs_give ((void **) &LOCAL->reply.line); /* nuke the local data */ fs_give ((void **) &stream->local); }}/* IMAP fetch fast information * Accepts: MAIL stream * sequence * option flags * * Generally, imap_fetchstructure is preferred */void imap_fast (MAILSTREAM *stream,char *sequence,long flags){ /* send "FETCH sequence FAST" */ char *cmd = (LEVELIMAP4 (stream) && (flags & FT_UID)) ? "UID FETCH":"FETCH"; IMAPPARSEDREPLY *reply; IMAPARG *args[4],aseq,aatt[2]; aseq.type = SEQUENCE; aseq.text = (void *) sequence; args[0] = &aseq; args[1] = &aatt[0]; if (LEVELIMAP4 (stream)) { /* send the hairier form if IMAP4 */ aatt[0].type = aatt[1].type = ATOM; aatt[0].text = (void *) "(UID"; aatt[1].text = (void *) fasttrailer; args[2] = &aatt[1]; args[3] = NIL; } else { /* just do FETCH FAST */ aatt[0].type = ATOM; aatt[0].text = (void *) "FAST"; args[2] = NIL; } if (!imap_OK (stream,reply = imap_send (stream,cmd,args))) mm_log (reply->text,ERROR);}/* IMAP fetch flags * Accepts: MAIL stream * sequence * option flags */void imap_flags (MAILSTREAM *stream,char *sequence,long flags){ /* send "FETCH sequence FLAGS" */ char *cmd = (LEVELIMAP4 (stream) && (flags & FT_UID)) ? "UID FETCH":"FETCH"; IMAPPARSEDREPLY *reply; IMAPARG *args[3],aseq,aatt; aseq.type = SEQUENCE; aseq.text = (void *) sequence; aatt.type = ATOM; aatt.text = (void *) "FLAGS"; args[0] = &aseq; args[1] = &aatt; args[2] = NIL; if (!imap_OK (stream,reply = imap_send (stream,cmd,args))) mm_log (reply->text,ERROR);}/* IMAP fetch message overview * Accepts: mail stream * UID sequence to fetch * pointer to overview return function * Returns: T if successful, NIL otherwise */long imap_overview (MAILSTREAM *stream,char *sequence,overview_t ofn){ MESSAGECACHE *elt; ENVELOPE *env; OVERVIEW ov; char *s,*t; unsigned long i,j,start,last,len; if (!mail_uid_sequence (stream,sequence) || !LOCAL->netstream) return NIL; /* build overview sequence */ for (i = 1,len = start = last = 0,s = t = NIL; i <= stream->nmsgs; ++i) if ((elt = mail_elt (stream,i))->sequence) { if (!elt->private.msg.env) { if (s) { /* continuing a sequence */ if (i == last + 1) last = i; else { /* end of range */ if (last != start) sprintf (t,":%lu,%lu",last,i); else sprintf (t,",%lu",i); start = last = i; /* begin a new range */ if ((j = ((t += strlen (t)) - s)) > (MAILTMPLEN - 20)) { fs_resize ((void **) s,len += MAILTMPLEN); t = s + j; /* relocate current pointer */ } } } else { /* first time, start new buffer */ s = (char *) fs_get (len = MAILTMPLEN); sprintf (s,"%lu",start = last = i); t = s + strlen (s); /* end of buffer */ } } } /* last sequence */ if (last != start) sprintf (t,":%lu",last); if (s) { /* prefetch as needed */ IMAPARG *args[7],aseq,aatt[5]; args[0] = &aseq; args[1] = &aatt[0]; aseq.type = SEQUENCE; aseq.text = (void *) s; /* send the hairier form if IMAP4rev1 */ if (LEVELIMAP4rev1 (stream)) { aatt[0].type = aatt[1].type = aatt[2].type = aatt[3].type = aatt[4].type = ATOM; aatt[0].text = (void *) allheader; aatt[1].text = (void *) hdrheader; aatt[3].text = (void *) hdrtrailer; aatt[4].text = (void *) fasttrailer; args[i = 2] = &aatt[1]; if (aatt[2].text = (void *) imap_extrahdrs) args[++i] = &aatt[2]; args[++i] = &aatt[3]; args[++i] = &aatt[4]; args[++i] = NIL; } else { /* just do FETCH ALL */ aatt[0].type = ATOM; aatt[0].text = (void *) "ALL"; args[2] = NIL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -