📄 pop3.c
字号:
if (t) { /* flush end of text indicator */ if (stream->debug) mm_dlog (t); fs_give ((void **) &t); } } if (auths) { /* got any authenticators? */ for (t = NIL; LOCAL->netstream && auths && (at = mail_lookup_auth (find_rightmost_bit (&auths)+1)); ) { if (t) { /* previous authenticator failed? */ sprintf (tmp,"Retrying using %.80s authentication after %.80s", at->name,t); mm_log (tmp,NIL); fs_give ((void **) &t); } trial = 0; /* initial trial count */ tmp[0] = '\0'; /* empty buffer */ if (LOCAL->netstream) do { if (tmp[0]) mm_log (tmp,WARN); if (pop3_send (stream,"AUTH",at->name) && (*at->client) (pop3_challenge,pop3_response,mb,stream,&trial,usr)&& LOCAL->response) { if (*LOCAL->response == '+') return LONGT; if (!trial) { /* if main program requested cancellation */ mm_log ("POP3 Authentication cancelled",ERROR); return NIL; } } t = cpystr (LOCAL->reply); sprintf (tmp,"Retrying %s authentication after %s",at->name,t); } while (LOCAL->netstream && trial && (trial < pop3_maxlogintrials)); } if (t) { /* previous authenticator failed? */ sprintf (tmp,"Can not authenticate to POP3 server: %.80s",t); mm_log (tmp,ERROR); fs_give ((void **) &t); } } else if (stream->secure) mm_log ("Can't do secure authentication with this server",ERROR); else if (mb->authuser[0]) mm_log ("Can't do /authuser with this server",ERROR); else { /* traditional login */ for (i = 0; LOCAL->netstream && (i < pop3_maxlogintrials); ++i) { tmp[0] = '\0'; /* prompt user for password */ mm_login (mb,usr,tmp,i); if (tmp[0]) { /* send login sequence */ if (pop3_send (stream,"USER",usr) && pop3_send (stream,"PASS",tmp)) return LONGT; /* success */ mm_log (LOCAL->reply,WARN); } else { /* user refused to give a password */ mm_log ("Login aborted",ERROR); return NIL; } } mm_log ("Too many login failures",ERROR); } return NIL; /* ran out of authenticators */}/* Get challenge to authenticator in binary * Accepts: stream * pointer to returned size * Returns: challenge or NIL if not challenge */void *pop3_challenge (void *s,unsigned long *len){ MAILSTREAM *stream = (MAILSTREAM *) s; return ((*LOCAL->response == '+') && (LOCAL->response[1] == ' ')) ? rfc822_base64 ((unsigned char *) LOCAL->reply,strlen (LOCAL->reply),len) : NIL;}/* Send authenticator response in BASE64 * Accepts: MAIL stream * string to send * length of string * Returns: T if successful, else NIL */long pop3_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'; *u = '\0'; ret = net_sout (LOCAL->netstream,t,u - t); fs_give ((void **) &t); } else ret = net_sout (LOCAL->netstream,"\015\012",2); } /* abort requested */ else ret = net_sout (LOCAL->netstream,"*\015\012",3); /* get response */ if (!pop3_reply (stream)) ret = NIL; return ret;}/* POP3 mail close * Accepts: MAIL stream * option flags */void pop3_close (MAILSTREAM *stream,long options){ int silent = stream->silent; if (LOCAL) { /* only if a file is open */ if (LOCAL->netstream) { /* close POP3 connection */ stream->silent = T; if (options & CL_EXPUNGE) pop3_expunge (stream); stream->silent = silent; pop3_send (stream,"QUIT",NIL); mm_notify (stream,LOCAL->reply,BYE); } /* close POP3 connection */ if (LOCAL->netstream) net_close (LOCAL->netstream); if (LOCAL->txt) fclose (LOCAL->txt); LOCAL->txt = NIL; if (LOCAL->response) fs_give ((void **) &LOCAL->response); /* nuke the local data */ fs_give ((void **) &stream->local); stream->dtb = NIL; /* log out the DTB */ }}/* POP3 mail fetch fast information * Accepts: MAIL stream * sequence * option flags * This is ugly and slow */void pop3_fetchfast (MAILSTREAM *stream,char *sequence,long flags){ unsigned long i; MESSAGECACHE *elt; /* get sequence */ if (stream && LOCAL && ((flags & FT_UID) ? mail_uid_sequence (stream,sequence) : mail_sequence (stream,sequence))) for (i = 1; i <= stream->nmsgs; i++) if ((elt = mail_elt (stream,i))->sequence && !(elt->day && !elt->rfc822_size)) { ENVELOPE **env = NIL; ENVELOPE *e = NIL; if (!stream->scache) env = &elt->private.msg.env; else if (stream->msgno == i) env = &stream->env; else env = &e; if (!*env || !elt->rfc822_size) { STRING bs; unsigned long hs; char *ht = (*stream->dtb->header) (stream,i,&hs,NIL); /* need to make an envelope? */ if (!*env) rfc822_parse_msg (env,NIL,ht,hs,NIL,BADHOST, stream->dtb->flags); /* need message size too, ugh */ if (!elt->rfc822_size) { (*stream->dtb->text) (stream,i,&bs,FT_PEEK); elt->rfc822_size = hs + SIZE (&bs) - GETPOS (&bs); } } /* if need date, have date in envelope? */ if (!elt->day && *env && (*env)->date) mail_parse_date (elt,(*env)->date); /* sigh, fill in bogus default */ if (!elt->day) mail_parse_date (elt,"01-JAN-1969 00:00:00 +0000"); mail_free_envelope (&e); }}/* POP3 fetch header as text * Accepts: mail stream * message number * pointer to return size * flags * Returns: header text */char *pop3_header (MAILSTREAM *stream,unsigned long msgno,unsigned long *size, long flags){ MESSAGECACHE *elt; if ((flags & FT_UID) && !(msgno = mail_msgno (stream,msgno))) return NIL; /* have header text? */ if (!(elt = mail_elt (stream,msgno))->private.msg.header.text.data) { elt->private.msg.header.text.size = pop3_cache (stream,elt); /* read the header */ fread (elt->private.msg.header.text.data = (unsigned char *) fs_get ((size_t) elt->private.msg.header.text.size + 1), (size_t) 1,(size_t) elt->private.msg.header.text.size,LOCAL->txt); elt->private.msg.header.text.data[elt->private.msg.header.text.size] ='\0'; } /* return size of text */ if (size) *size = elt->private.msg.header.text.size; return (char *) elt->private.msg.header.text.data;}/* POP3 fetch body * Accepts: mail stream * message number * pointer to stringstruct to initialize * flags * Returns: T if successful, else NIL */long pop3_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags){ MESSAGECACHE *elt; INIT (bs,mail_string,(void *) "",0); if ((flags & FT_UID) && !(msgno = mail_msgno (stream,msgno))) return NIL; elt = mail_elt (stream,msgno); pop3_cache (stream,elt); /* make sure cache loaded */ if (!LOCAL->txt) return NIL; /* error if don't have a file */ if (!(flags & FT_PEEK)) { /* mark seen if needed */ elt->seen = T; mm_flags (stream,elt->msgno); } INIT (bs,file_string,(void *) LOCAL->txt,elt->rfc822_size); SETPOS (bs,LOCAL->hdrsize); /* skip past header */ return T;}/* POP3 cache message * Accepts: mail stream * message number * Returns: header size */unsigned long pop3_cache (MAILSTREAM *stream,MESSAGECACHE *elt){ /* already cached? */ if (LOCAL->msgno != elt->msgno) { /* no, close current file */ if (LOCAL->txt) fclose (LOCAL->txt); LOCAL->txt = NIL; LOCAL->msgno = LOCAL->hdrsize = 0; if (pop3_send_num (stream,"RETR",elt->msgno)) { LOCAL->msgno = elt->msgno;/* set as current message number */ /* load the cache */ LOCAL->txt = netmsg_slurp (LOCAL->netstream,&elt->rfc822_size, &LOCAL->hdrsize); } else elt->deleted = T; } return LOCAL->hdrsize;}/* POP3 mail ping mailbox * Accepts: MAIL stream * Returns: T if stream alive, else NIL */long pop3_ping (MAILSTREAM *stream){ return pop3_send (stream,"NOOP",NIL);}/* POP3 mail check mailbox * Accepts: MAIL stream */void pop3_check (MAILSTREAM *stream){ if (pop3_ping (stream)) mm_log ("Check completed",NIL);}/* POP3 mail expunge mailbox * Accepts: MAIL stream */void pop3_expunge (MAILSTREAM *stream){ char tmp[MAILTMPLEN]; unsigned long i = 1,n = 0; while (i <= stream->nmsgs) { if (mail_elt (stream,i)->deleted && pop3_send_num (stream,"DELE",i)) { mail_expunged (stream,i); n++; } else i++; /* try next message */ } if (!stream->silent) { /* only if not silent */ if (n) { /* did we expunge anything? */ sprintf (tmp,"Expunged %lu messages",n); mm_log (tmp,(long) NIL); } else mm_log ("No messages deleted, so no update needed",(long) NIL); }}/* POP3 mail copy message(s) * Accepts: MAIL stream * sequence * destination mailbox * option flags * Returns: T if copy successful, else NIL */long pop3_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options){ mailproxycopy_t pc = (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL); if (pc) return (*pc) (stream,sequence,mailbox,options); mm_log ("Copy not valid for POP3",ERROR); return NIL;}/* POP3 mail append message from stringstruct * Accepts: MAIL stream * destination mailbox * append callback * data for callback * Returns: T if append successful, else NIL */long pop3_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){ mm_log ("Append not valid for POP3",ERROR); return NIL;}/* Internal routines *//* Post Office Protocol 3 send command with number argument * Accepts: MAIL stream * command * number * Returns: T if successful, NIL if failure */long pop3_send_num (MAILSTREAM *stream,char *command,unsigned long n){ char tmp[MAILTMPLEN]; sprintf (tmp,"%lu",mail_uid (stream,n)); return pop3_send (stream,command,tmp);}/* Post Office Protocol 3 send command * Accepts: MAIL stream * command * command argument * Returns: T if successful, NIL if failure */long pop3_send (MAILSTREAM *stream,char *command,char *args){ long ret; char *s = (char *) fs_get (strlen (command) + (args ? strlen (args) + 1: 0) + 3); mail_lock (stream); /* lock up the stream */ if (!LOCAL->netstream) ret = pop3_fake (stream,"No-op dead stream"); else { /* build the complete command */ if (args) sprintf (s,"%s %s",command,args); else strcpy (s,command); if (stream->debug) mm_dlog (s); strcat (s,"\015\012"); /* send the command */ ret = net_soutr (LOCAL->netstream,s) ? pop3_reply (stream) : pop3_fake (stream,"POP3 connection broken in command"); } fs_give ((void **) &s); mail_unlock (stream); /* unlock stream */ return ret;}/* Post Office Protocol 3 get reply * Accepts: MAIL stream * Returns: T if success reply, NIL if error reply */long pop3_reply (MAILSTREAM *stream){ char *s; /* flush old reply */ if (LOCAL->response) fs_give ((void **) &LOCAL->response); /* get reply */ if (!(LOCAL->response = net_getline (LOCAL->netstream))) return pop3_fake (stream,"POP3 connection broken in response"); if (stream->debug) mm_dlog (LOCAL->response); LOCAL->reply = (s = strchr (LOCAL->response,' ')) ? s + 1 : LOCAL->response; /* return success or failure */ return (*LOCAL->response =='+') ? T : NIL;}/* Post Office Protocol 3 set fake error * Accepts: MAIL stream * error text * Returns: NIL, always */long pop3_fake (MAILSTREAM *stream,char *text){ mm_notify (stream,text,BYE); /* send bye alert */ if (LOCAL->netstream) net_close (LOCAL->netstream); LOCAL->netstream = NIL; /* farewell, dear TCP stream */ /* flush any old reply */ if (LOCAL->response) fs_give ((void **) &LOCAL->response); LOCAL->reply = text; /* set up pseudo-reply string */ return NIL; /* return error code */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -