📄 imap4r1.c
字号:
/* * Program: Interactive Message Access Protocol 4rev1 (IMAP4R1) routines * * Author: Mark Crispin * Networks and Distributed Computing * Computing & Communications * University of Washington * Administration Building, AG-44 * Seattle, WA 98195 * Internet: MRC@CAC.Washington.EDU * * Date: 15 June 1988 * Last Edited: 13 October 2000 * * Sponsorship: The original version of this work was developed in the * Symbolic Systems Resources Group of the Knowledge Systems * Laboratory at Stanford University in 1987-88, and was funded * by the Biomedical Research Technology Program of the National * Institutes of Health under grant number RR-00785. * * Original version Copyright 1988 by The Leland Stanford Junior University * Copyright 2000 by the University of Washington * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notices appear in all copies and that both the * above copyright notices and this permission notice appear in supporting * documentation, and that the name of the University of Washington or The * Leland Stanford Junior University not be used in advertising or publicity * pertaining to distribution of the software without specific, written prior * permission. This software is made available "as is", and * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE, * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */#include <ctype.h>#include <stdio.h>#include <time.h>#include "mail.h"#include "osdep.h"#include "imap4r1.h"#include "rfc822.h"#include "misc.h"/* Driver dispatch used by MAIL */DRIVER imapdriver = { "imap", /* driver name */ /* driver flags */ DR_MAIL|DR_NEWS|DR_NAMESPACE|DR_CRLF|DR_RECYCLE, (DRIVER *) NIL, /* next driver */ imap_valid, /* mailbox is valid for us */ imap_parameters, /* manipulate parameters */ imap_scan, /* scan mailboxes */ imap_list, /* find mailboxes */ imap_lsub, /* find subscribed mailboxes */ imap_subscribe, /* subscribe to mailbox */ imap_unsubscribe, /* unsubscribe from mailbox */ imap_create, /* create mailbox */ imap_delete, /* delete mailbox */ imap_rename, /* rename mailbox */ imap_status, /* status of mailbox */ imap_open, /* open mailbox */ imap_close, /* close mailbox */ imap_fast, /* fetch message "fast" attributes */ imap_flags, /* fetch message flags */ imap_overview, /* fetch overview */ imap_structure, /* fetch message envelopes */ NIL, /* fetch message header */ NIL, /* fetch message body */ imap_msgdata, /* fetch partial message */ imap_uid, /* unique identifier */ imap_msgno, /* message number */ imap_flag, /* modify flags */ NIL, /* per-message modify flags */ imap_search, /* search for message based on criteria */ imap_sort, /* sort messages */ imap_thread, /* thread messages */ imap_ping, /* ping mailbox to see if still alive */ imap_check, /* check for new messages */ imap_expunge, /* expunge deleted messages */ imap_copy, /* copy messages to another mailbox */ imap_append, /* append string message to mailbox */ imap_gc /* garbage collect stream */}; /* prototype stream */MAILSTREAM imapproto = {&imapdriver}; /* driver parameters */static unsigned long imap_maxlogintrials = MAXLOGINTRIALS;static long imap_lookahead = IMAPLOOKAHEAD;static long imap_uidlookahead = IMAPUIDLOOKAHEAD;static long imap_defaultport = 0;static long imap_altport = 0;static char *imap_altname = NIL;static long imap_prefetch = IMAPLOOKAHEAD;static long imap_closeonerror = NIL;static imapenvelope_t imap_envelope = NIL;static imapreferral_t imap_referral = NIL;static char *imap_extrahdrs = NIL; /* constants */static char *hdrheader = "BODY.PEEK[HEADER.FIELDS (Path Message-ID";static char *hdrtrailer ="Newsgroups Followup-To References)]";static char *allheader = "(UID ENVELOPE";static char *fasttrailer = "INTERNALDATE RFC822.SIZE FLAGS)";/* Append data */typedef struct append_data { append_t af; void *data;} APPENDDATA;/* IMAP validate mailbox * Accepts: mailbox name * Returns: our driver if name is valid, NIL otherwise */DRIVER *imap_valid (char *name){ return mail_valid_net (name,&imapdriver,NIL,NIL);}/* IMAP manipulate driver parameters * Accepts: function code * function-dependent value * Returns: function-dependent return value */void *imap_parameters (long function,void *value){ switch ((int) function) { case SET_NAMESPACE: fatal ("SET_NAMESPACE not permitted"); case GET_NAMESPACE: if (((IMAPLOCAL *) ((MAILSTREAM *) value)->local)->use.namespace && !((IMAPLOCAL *) ((MAILSTREAM *) value)->local)->namespace) imap_send (((MAILSTREAM *) value),"NAMESPACE",NIL); value = (void *) &((IMAPLOCAL *) ((MAILSTREAM *) value)->local)->namespace; break; case GET_THREADERS: value = (void *) ((IMAPLOCAL *) ((MAILSTREAM *) value)->local)->threader; break; case SET_MAXLOGINTRIALS: imap_maxlogintrials = (long) value; break; case GET_MAXLOGINTRIALS: value = (void *) imap_maxlogintrials; break; case SET_LOOKAHEAD: imap_lookahead = (long) value; break; case GET_LOOKAHEAD: value = (void *) imap_lookahead; break; case SET_UIDLOOKAHEAD: imap_uidlookahead = (long) value; break; case GET_UIDLOOKAHEAD: value = (void *) imap_uidlookahead; break; case SET_IMAPPORT: imap_defaultport = (long) value; break; case GET_IMAPPORT: value = (void *) imap_defaultport; break; case SET_ALTIMAPPORT: imap_altport = (long) value; break; case GET_ALTIMAPPORT: value = (void *) imap_altport; break; case SET_ALTIMAPNAME: imap_altname = (char *) value; break; case GET_ALTIMAPNAME: value = (void *) imap_altname; break; case SET_PREFETCH: imap_prefetch = (long) value; break; case GET_PREFETCH: value = (void *) imap_prefetch; break; case SET_CLOSEONERROR: imap_closeonerror = (long) value; break; case GET_CLOSEONERROR: value = (void *) imap_closeonerror; break; case SET_IMAPENVELOPE: imap_envelope = (imapenvelope_t) value; break; case GET_IMAPENVELOPE: value = (void *) imap_envelope; break; case SET_IMAPREFERRAL: imap_referral = (imapreferral_t) value; break; case GET_IMAPREFERRAL: value = (void *) imap_referral; break; case SET_IMAPEXTRAHEADERS: imap_extrahdrs = (char *) value; break; case GET_IMAPEXTRAHEADERS: value = (void *) imap_extrahdrs; break; default: value = NIL; /* error case */ break; } return value;}/* IMAP scan mailboxes * Accepts: mail stream * reference * pattern to search * string to scan */void imap_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents){ imap_list_work (stream,"SCAN",ref,pat,contents);}/* IMAP list mailboxes * Accepts: mail stream * reference * pattern to search */void imap_list (MAILSTREAM *stream,char *ref,char *pat){ imap_list_work (stream,"LIST",ref,pat,NIL);}/* IMAP list subscribed mailboxes * Accepts: mail stream * reference * pattern to search */void imap_lsub (MAILSTREAM *stream,char *ref,char *pat){ void *sdb = NIL; char *s,mbx[MAILTMPLEN]; /* do it on the server */ imap_list_work (stream,"LSUB",ref,pat,NIL); if (*pat == '{') { /* if remote pattern, must be IMAP */ if (!imap_valid (pat)) return; ref = NIL; /* good IMAP pattern, punt reference */ } /* if remote reference, must be valid IMAP */ if (ref && (*ref == '{') && !imap_valid (ref)) return; /* kludgy application of reference */ if (ref && *ref) sprintf (mbx,"%s%s",ref,pat); else strcpy (mbx,pat); if (s = sm_read (&sdb)) do if (imap_valid (s) && pmatch (s,mbx)) mm_lsub (stream,NIL,s,NIL); while (s = sm_read (&sdb)); /* until no more subscriptions */}/* IMAP find list of mailboxes * Accepts: mail stream * list command * reference * pattern to search * string to scan */void imap_list_work (MAILSTREAM *stream,char *cmd,char *ref,char *pat, char *contents){ MAILSTREAM *st = stream; int pl; char *s,prefix[MAILTMPLEN],mbx[MAILTMPLEN]; IMAPARG *args[4],aref,apat,acont; if (ref && *ref) { /* have a reference? */ if (!(imap_valid (ref) && /* make sure valid IMAP name and open stream */ ((stream && LOCAL && LOCAL->netstream) || (stream = mail_open (NIL,ref,OP_HALFOPEN|OP_SILENT))))) return; /* calculate prefix length */ pl = strchr (ref,'}') + 1 - ref; strncpy (prefix,ref,pl); /* build prefix */ prefix[pl] = '\0'; /* tie off prefix */ ref += pl; /* update reference */ } else { if (!(imap_valid (pat) && /* make sure valid IMAP name and open stream */ ((stream && LOCAL && LOCAL->netstream) || (stream = mail_open (NIL,pat,OP_HALFOPEN|OP_SILENT))))) return; /* calculate prefix length */ pl = strchr (pat,'}') + 1 - pat; strncpy (prefix,pat,pl); /* build prefix */ prefix[pl] = '\0'; /* tie off prefix */ pat += pl; /* update reference */ } LOCAL->prefix = prefix; /* note prefix */ if (contents) { /* want to do a scan? */ if (LEVELSCAN (stream)) { /* make sure permitted */ args[0] = &aref; args[1] = &apat; args[2] = &acont; args[3] = NIL; aref.type = ASTRING; aref.text = (void *) (ref ? ref : ""); apat.type = LISTMAILBOX; apat.text = (void *) pat; acont.type = ASTRING; acont.text = (void *) contents; imap_send (stream,cmd,args); } else mm_log ("Scan not valid on this IMAP server",ERROR); } else if (LEVELIMAP4 (stream)){/* easy if IMAP4 */ args[0] = &aref; args[1] = &apat; args[2] = NIL; aref.type = ASTRING; aref.text = (void *) (ref ? ref : ""); apat.type = LISTMAILBOX; apat.text = (void *) pat; /* referrals armed? */ if (LOCAL->use.mbx_ref && mail_parameters (stream,GET_IMAPREFERRAL,NIL) && ((cmd[0] == 'L') || (cmd[0] == 'l')) && !cmd[4]) { /* yes, convert LIST -> RLIST */ if (((cmd[1] == 'I') || (cmd[1] == 'i')) && ((cmd[2] == 'S') || (cmd[1] == 's')) && ((cmd[3] == 'T') || (cmd[3] == 't'))) cmd = "RLIST"; /* and convert LSUB -> RLSUB */ else if (((cmd[1] == 'S') || (cmd[1] == 's')) && ((cmd[2] == 'U') || (cmd[1] == 'u')) && ((cmd[3] == 'B') || (cmd[3] == 'b'))) cmd = "RLSUB"; } imap_send (stream,cmd,args); } else if (LEVEL1176 (stream)) {/* convert to IMAP2 format wildcard */ /* kludgy application of reference */ if (ref && *ref) sprintf (mbx,"%s%s",ref,pat); else strcpy (mbx,pat); for (s = mbx; *s; s++) if (*s == '%') *s = '*'; args[0] = &apat; args[1] = NIL; apat.type = LISTMAILBOX; apat.text = (void *) mbx; if (!(strstr (cmd,"LIST") &&/* if list, try IMAP2bis, then RFC-1176 */ strcmp (imap_send (stream,"FIND ALL.MAILBOXES",args)->key,"BAD")) && !strcmp (imap_send (stream,"FIND MAILBOXES",args)->key,"BAD")) LOCAL->rfc1176 = NIL; /* must be RFC-1064 */ } LOCAL->prefix = NIL; /* no more prefix */ /* close temporary stream if we made one */ if (stream != st) mail_close (stream);}/* IMAP subscribe to mailbox * Accepts: mail stream * mailbox to add to subscription list * Returns: T on success, NIL on failure */long imap_subscribe (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) ? "Subscribe" : "Subscribe Mailbox",NIL) : NIL; /* toss out temporary stream */ if (st != stream) mail_close (stream); return ret;}/* IMAP unsubscribe to mailbox
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -