long dummy_ping (MAILSTREAM *stream) { MAILSTREAM *test; /* time to do another test? */ if (time (0) >= ((time_t) (stream->gensym + 30))) { /* has mailbox format changed? */ if ((test = mail_open (NIL,stream->mailbox,OP_PROTOTYPE)) && (test->dtb != stream->dtb) && (test = mail_open (NIL,stream->mailbox,NIL))) { /* preserve some resources */ test->original_mailbox = stream->original_mailbox; stream->original_mailbox = NIL; test->sparep = stream->sparep; stream->sparep = NIL; test->sequence = stream->sequence; mail_close ((MAILSTREAM *) /* flush resources used by dummy stream */ memcpy (fs_get (sizeof (MAILSTREAM)),stream, sizeof (MAILSTREAM))); /* swap the streams */ memcpy (stream,test,sizeof (MAILSTREAM)); fs_give ((void **) &test);/* flush test now that copied */ /* make sure application knows */ mail_exists (stream,stream->recent = stream->nmsgs); } /* still hasn't changed */ else stream->gensym = time (0); } return T; }
bool f_imap_reopen(const Resource& imap_stream, const String& mailbox, int64_t options /* = 0 */, int64_t retries /* = 0 */) { ImapStream *obj = imap_stream.getTyped<ImapStream>(); long flags = NIL; long cl_flags = NIL; if (options) { flags = options; if (flags & PHP_EXPUNGE) { cl_flags = CL_EXPUNGE; flags ^= PHP_EXPUNGE; } obj->m_flag = cl_flags; } if (retries) { mail_parameters(NIL, SET_MAXLOGINTRIALS, (void *) retries); } MAILSTREAM *stream = mail_open(obj->m_stream, (char*)mailbox.data(), flags); if (stream == NIL) { raise_warning("Couldn't re-open stream"); return false; } obj->m_stream = stream; return true; }
/* * Create header for bounced mail */ int bounce_header(char *to) /* To: */ { /* * Open new mail */ if(mail_open('m') == ERROR) return ERROR; /* * Create RFC header */ fprintf(mail_file('m'), "From Mailer-Daemon %s\n", date(DATE_FROM, NULL) ); fprintf(mail_file('m'), "Date: %s\n", date(NULL, NULL) ); fprintf(mail_file('m'), "From: Mailer-Daemon@%s (Mail Delivery Subsystem)\n", cf_fqdn() ); fprintf(mail_file('m'), "To: %s\n", to); if(bounce_ccmail) fprintf(mail_file('m'), "Cc: %s\n", bounce_ccmail); /* Additional header may follow in message file */ return OK; }
Variant f_imap_open(const String& mailbox, const String& username, const String& password, int64_t options /* = 0 */, int64_t retries /* = 0 */) { String filename = mailbox; if (filename[0] != '{') { filename = File::TranslatePath(filename); if (filename.empty()) { return false; } } if (retries < 0) { Logger::Warning("Retries must be greater or equal to 0"); } else { mail_parameters(NIL, SET_MAXLOGINTRIALS, (void *) retries); } IMAPG(user) = std::string(username.data(), username.size()); IMAPG(password) = std::string(password.data(), password.size()); MAILSTREAM *stream = mail_open(NIL, (char*)filename.data(), options); if (stream == NIL) { Logger::Warning("Couldn't open stream %s", filename.data()); IMAPG(user).clear(); IMAPG(password).clear(); return false; } return NEWOBJ(ImapStream)(stream, (options & PHP_EXPUNGE) ? CL_EXPUNGE : NIL); }
/* Body state. */ int imap_state_body(struct account *a, struct fetch_ctx *fctx) { struct fetch_imap_data *data = a->data; struct mail *m = fctx->mail; struct fetch_imap_mail *aux; char *line, *ptr; u_int n; if (imap_getln(a, fctx, IMAP_UNTAGGED, &line) != 0) return (FETCH_ERROR); if (line == NULL) return (FETCH_BLOCK); if (sscanf(line, "* %u FETCH (", &n) != 1) return (imap_invalid(a, line)); if ((ptr = strstr(line, "BODY[] {")) == NULL) return (imap_invalid(a, line)); if (sscanf(ptr, "BODY[] {%zu}", &data->size) != 1) return (imap_invalid(a, line)); data->lines = 0; /* Fill in local data. */ aux = xcalloc(1, sizeof *aux); aux->uid = ARRAY_FIRST(&data->wanted); m->auxdata = aux; m->auxfree = imap_free; ARRAY_REMOVE(&data->wanted, 0); /* Open the mail. */ if (mail_open(m, data->size) != 0) { log_warnx("%s: failed to create mail", a->name); return (FETCH_ERROR); } m->size = 0; /* Tag mail. */ default_tags(&m->tags, data->src); if (data->server.host != NULL) { add_tag(&m->tags, "server", "%s", data->server.host); add_tag(&m->tags, "port", "%s", data->server.port); } add_tag(&m->tags, "server_uid", "%u", aux->uid); add_tag(&m->tags, "folder", "%s", ARRAY_ITEM(data->folders, data->folder)); /* If we already know the mail is oversize, start off flushing it. */ data->flushing = data->size > conf.max_size; fctx->state = imap_state_line; return (FETCH_AGAIN); }
void parent_fetch_action(struct child *child, struct children *children, struct deliver_ctx *dctx, struct msg *msg) { struct actitem *ti = msg->data.actitem; struct mail *m = dctx->mail; struct mail *md = &dctx->wr_mail; struct child_deliver_data *data; uid_t uid = msg->data.uid; gid_t gid = msg->data.gid; memset(md, 0, sizeof *md); /* * If writing back, open a new mail now and set its ownership so it * can be accessed by the child. */ if (ti->deliver->type == DELIVER_WRBACK) { if (mail_open(md, IO_BLOCKSIZE) != 0) { log_warn("parent: failed to create mail"); parent_fetch_error(child, msg); return; } if (geteuid() == 0 && shm_owner(&md->shm, conf.child_uid, conf.child_gid) != 0) { mail_destroy(md); log_warn("parent: failed to set mail ownership"); parent_fetch_error(child, msg); return; } md->decision = m->decision; } data = xmalloc(sizeof *data); data->child = child; data->msgid = msg->id; data->account = dctx->account; data->hook = child_deliver_action_hook; data->actitem = ti; data->dctx = dctx; data->mail = m; data->name = "deliver"; data->uid = uid; data->gid = gid; child = child_start( children, uid, gid, child_deliver, parent_deliver, data, child); log_debug3("parent: deliver " "child %ld started (uid %lu)", (long) child->pid, (u_long) uid); }
int deliver (FILE *f,unsigned long msglen,char *user) { MAILSTREAM *ds = NIL; char *s,*mailbox,tmp[MAILTMPLEN],path[MAILTMPLEN]; STRING st; struct stat sbuf; /* have a mailbox specifier? */ if ((mailbox = strchr (user,'+')) != NULL) { *mailbox++ = '\0'; /* yes, tie off user name */ if (!*mailbox || !compare_cstring ((unsigned char *) mailbox,"INBOX")) mailbox = NIL; /* user+ and user+INBOX same as user */ } if (!*user) user = myusername (); else if (strcmp (user,myusername ())) return fail ("can't deliver to other user",EX_CANTCREAT); sprintf (tmp,"delivering to %.80s+%.80s",user,mailbox ? mailbox : "INBOX"); mm_dlog (tmp); /* prepare stringstruct */ INIT (&st,file_string,(void *) f,msglen); if (mailbox) { /* non-INBOX name */ switch (mailbox[0]) { /* make sure a valid name */ default: /* other names, try to deliver if not INBOX */ if ((strlen (mailbox) <= NETMAXMBX) && !strstr (mailbox,"..") && !strstr (mailbox,"//") && !strstr (mailbox,"/~") && mailboxfile (path,mailbox) && path[0] && !deliver_safely (NIL,&st,mailbox,path,tmp)) return NIL; case '%': case '*': /* wildcards not valid */ case '/': /* absolute path names not valid */ case '~': /* user names not valid */ sprintf (tmp,"invalid mailbox name %.80s+%.80s",user,mailbox); mm_log (tmp,WARN); break; } mm_dlog ("retrying delivery to INBOX"); SETPOS (&st,0); /* rewind stringstruct just in case */ } /* no -I, resolve "INBOX" into path */ if (mailboxfile (path,mailbox = "INBOX") && !path[0]) { /* clear box, get generic INBOX prototype */ if (!(ds = mail_open (NIL,"INBOX",OP_PROTOTYPE))) fatal ("no INBOX prototype"); /* standard system driver? */ if (!strcmp (ds->dtb->name,"unix") || !strcmp (ds->dtb->name,"mmdf")) { strcpy (path,sysinbox ());/* use system INBOX */ if (!lstat (path,&sbuf)) /* deliver to existing system INBOX */ return deliver_safely (ds,&st,mailbox,path,tmp); } else { /* other driver, try ~/INBOX */ if ((mailboxfile (path,"&&&&&") == path) && (s = strstr (path,"&&&&&")) && strcpy (s,"INBOX") && !lstat (path,&sbuf)){ /* deliver to existing ~/INBOX */ sprintf (tmp,"#driver.%s/INBOX",ds->dtb->name); return deliver_safely (ds,&st,cpystr (tmp),path,tmp); } } /* not dummy, deliver to driver imputed path */ if (strcmp (ds->dtb->name,"dummy")) return (ibxpath (ds,&mailbox,path) && !lstat (path,&sbuf)) ? deliver_safely (ds,&st,mailbox,path,tmp) : fail ("unable to resolve INBOX path",EX_CANTCREAT); /* dummy, empty imputed append path exist? */ if (ibxpath (ds = default_proto (T),&mailbox,path) && !lstat (path,&sbuf) && !sbuf.st_size) return deliver_safely (ds,&st,mailbox,path,tmp); /* impute path that we will create */ if (!ibxpath (ds = default_proto (NIL),&mailbox,path)) return fail ("unable to resolve INBOX",EX_CANTCREAT); } /* black box, must create, get create proto */ else if (lstat (path,&sbuf)) ds = default_proto (NIL); else { /* black box, existing file */ /* empty file, get append prototype */ if (!sbuf.st_size) ds = default_proto (T); /* non-empty, get prototype from its data */ else if (!(ds = mail_open (NIL,"INBOX",OP_PROTOTYPE))) fatal ("no INBOX prototype"); /* error if unknown format */ if (!strcmp (ds->dtb->name,"phile")) return fail ("unknown format INBOX",EX_UNAVAILABLE); /* otherwise can deliver to it */ return deliver_safely (ds,&st,mailbox,path,tmp); } sprintf (tmp,"attempting to create mailbox %.80s path %.80s",mailbox,path); mm_dlog (tmp); /* supplicate to the Evil One */ if (!path_create (ds,path)) return fail ("can't create INBOX",EX_CANTCREAT); sprintf (tmp,"created %.80s",path); mm_dlog (tmp); /* deliver the message */ return deliver_safely (ds,&st,mailbox,path,tmp); }
/* Fetch mail from stdin. */ int fetch_stdin_state_mail(struct account *a, struct fetch_ctx *fctx) { struct mail *m = fctx->mail; struct io *io; char *line, *cause; /* Open io for stdin. */ io = io_create(STDIN_FILENO, NULL, IO_LF); if (conf.debug > 3 && !conf.syslog) io->dup_fd = STDOUT_FILENO; /* Initialise the mail. */ if (mail_open(m, IO_BLOCKSIZE) != 0) { log_warn("%s: failed to create mail", a->name); goto error; } m->size = 0; /* Add default tags. */ default_tags(&m->tags, NULL); /* Loop reading the mail. */ for (;;) { /* * There can only be one mail on stdin so reentrancy is * irrelevent. This is a good thing since we want to check for * close which means end of mail. */ switch (io_pollline2(io, &line, &fctx->lbuf, &fctx->llen, conf.timeout, &cause)) { case 0: /* Normal close is fine. */ goto out; case -1: if (errno == EAGAIN) continue; log_warnx("%s: %s", a->name, cause); xfree(cause); goto error; } if (append_line(m, line, strlen(line)) != 0) { log_warn("%s: failed to resize mail", a->name); goto error; } if (m->size > conf.max_size) break; } out: if (io != NULL) io_free(io); fctx->state = fetch_stdin_state_exit; return (FETCH_MAIL); error: if (io != NULL) io_free(io); return (FETCH_ERROR); }
int mbxcopy (MAILSTREAM *source,MAILSTREAM *dest,char *dst,int create,int del, int mode) { char *s,tmp[MAILTMPLEN]; APPENDPACKAGE ap; STRING st; char *ndst = NIL; int ret = NIL; trycreate = NIL; /* no TRYCREATE yet */ if (create) while (!mail_create (dest,dst) && (mode != mAPPEND)) { switch (mode) { case mPROMPT: /* prompt user for new name */ tmp[0] = '\0'; while (!tmp[0]) { /* read name */ fputs ("alternative name: ",stdout); fflush (stdout); fgets (tmp,MAILTMPLEN-1,stdin); if (s = strchr (tmp,'\n')) *s = '\0'; } if (ndst) fs_give ((void **) &ndst); ndst = cpystr (tmp); break; case mSUFFIX: /* try again with new suffix */ if (ndst) fs_give ((void **) &ndst); sprintf (ndst = (char *) fs_get (strlen (dst) + strlen (suffix) + 1), "%s%s",dst,suffix); printf ("retry to create %s\n",ndst); mode = mPROMPT; /* switch to prompt mode if name fails */ break; case NIL: /* not merging */ return NIL; } if (ndst) dst = ndst; /* if alternative name given, use it */ } if (kwcopyp) { int i; size_t len; char *dummymsg = "Date: Thu, 18 May 2006 00:00 -0700\r\nFrom: [email protected]\r\nSubject: dummy\r\n\r\ndummy\r\n"; for (i = 0,len = 0; i < NUSERFLAGS; ++i) if (source->user_flags[i]) len += strlen (source->user_flags[i]) + 1; if (len) { /* easy if no user flags to copy... */ char *t; char *tail = "\\Deleted)"; char *flags = (char *) fs_get (1 + len + strlen (tail) + 1); s = flags; *s++ = '('; for (i = 0; i < NUSERFLAGS; ++i) if (t = source->user_flags[i]) { while (*t) *s++ = *t++; *s++ = ' '; } strcpy (s,tail); /* terminate flags list */ if ((dst[0] == '#') && ((dst[1] == 'D') || (dst[1] == 'd')) && ((dst[2] == 'R') || (dst[2] == 'r')) && ((dst[3] == 'I') || (dst[3] == 'i')) && ((dst[4] == 'V') || (dst[4] == 'v')) && ((dst[5] == 'E') || (dst[5] == 'e')) && ((dst[6] == 'R') || (dst[6] == 'r')) && (dst[7] == '.') && (t = strchr (dst+8,'/'))) ++t; else t = dst; INIT (&st,mail_string,dummymsg,strlen (dummymsg)); if (!(mail_append (dest,dst,&st) && (dest = mail_open (dest,t,debugp ? OP_DEBUG : NIL)))) { fs_give ((void **) &flags); return NIL; } mail_setflag (dest,"*",flags); mail_expunge (dest); fs_give ((void **) &flags); } } if (source->nmsgs) { /* non-empty source */ if (verbosep) printf ("%s [%lu message(s)] => %s\n", source->mailbox,source->nmsgs,dst); ap.stream = source; /* prepare append package */ ap.msgno = 0; ap.msgmax = source->nmsgs; ap.flags = ap.date = NIL; ap.message = &st; /* make sure we have all messages */ sprintf (tmp,"1:%lu",ap.msgmax); mail_fetchfast (source,tmp); if (mail_append_multiple (dest,dst,mm_append,(void *) &ap)) { --ap.msgno; /* make sure user knows it won */ if (verbosep) printf ("[Ok %lu messages(s)]\n",ap.msgno); if (del && ap.msgno) { /* delete source messages */ sprintf (tmp,"1:%lu",ap.msgno); mail_flag (source,tmp,"\\Deleted",ST_SET); /* flush moved messages */ mail_expunge (source); } ret = T; } else if ((mode == mAPPEND) && trycreate) ret = mbxcopy (source,dest,dst,create,del,mPROMPT); else if (verbosep) puts ("[Failed]"); } else { /* empty source */ if (verbosep) printf ("%s [empty] => %s\n",source->mailbox,dst); ret = T; } if (ndst) fs_give ((void **) &ndst); return ret; }
int main (int argc,char *argv[]) { MAILSTREAM *source = NIL; MAILSTREAM *dest = NIL; SEARCHPGM *criteria; char c,*s,*dp,*t,*t1,tmp[MAILTMPLEN],mbx[MAILTMPLEN]; unsigned long m,len,curlen,start,last; int i; int merge = NIL; int retcode = 1; int moreswitchp = T; char *cmd = NIL; char *src = NIL; char *dst = NIL; char *pgm = argc ? argv[0] : "mailutil"; #include "linkage.c" for (i = 1; i < argc; i++) { s = argv[i]; /* pick up argument */ /* parse switches */ if (moreswitchp && (*s == '-')) { if (!strcmp (s,"-debug") || !strcmp (s,"-d")) debugp = T; else if (!strcmp (s,"-verbose") || !strcmp (s,"-v")) verbosep = T; else if (!strcmp (s,"-rwcopy") || !strcmp (s,"-rw")) rwcopyp = T; else if (!strcmp (s,"-kwcopy") || !strcmp (s,"-kw")) kwcopyp = T; else if (!strcmp (s,"-ignore") || !strcmp (s,"-ig")) ignorep = T; else if ((!strcmp (s,"-merge") || !strcmp (s,"-m")) && (++i < argc)) { if (!strcmp (s = argv[i],"prompt")) merge = mPROMPT; else if (!strcmp (s,"append")) merge = mAPPEND; else if (!strncmp (s,"suffix=",7) && s[7]) { merge = mSUFFIX; suffix = cpystr (s+7); } else { printf ("unknown merge option: %s\n",s); exit (retcode); } } #ifdef SYSCONFIG else if ((!strcmp (s,"-user") || !strcmp (s,"-u")) && (++i < argc)) { struct passwd *pw = getpwnam (s = argv[i]); if (!pw) { printf ("unknown user id: %s\n",argv[i]); exit (retcode); } else if (setuid (pw->pw_uid)) { perror ("unable to change user id"); exit (retcode); } } #endif /* -- means no more switches, so mailbox name can start with "-" */ else if ((s[1] == '-') && !s[2]) moreswitchp = NIL; else { printf ("unknown switch: %s\n",s); exit (retcode); } } else if (!cmd) cmd = s; /* first non-switch is command */ else if (!src) src = s; /* second non-switch is source */ else if (!dst) dst = s; /* third non-switch is destination */ else { printf ("unknown argument: %s\n",s); exit (retcode); } } if (kwcopyp && ignorep) { puts ("-kwcopy and -ignore are mutually exclusive"); exit (retcode); } if (!cmd) cmd = ""; /* prevent SEGV */ if (!strcmp (cmd,"check")) { /* check for new messages */ if (!src) src = "INBOX"; if (dst || merge || rwcopyp || kwcopyp || ignorep) printf (usage2,pgm,usgchk,stdsw); else if (mail_status (source = (*src == '{') ? mail_open (NIL,src,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)) : NIL, src,SA_MESSAGES | SA_RECENT | SA_UNSEEN)) retcode = 0; } else if (!strcmp (cmd,"create")) { if (!src || dst || merge || rwcopyp || kwcopyp || ignorep) printf (usage2,pgm,usgcre,stdsw); else if (mail_create (source = (*src == '{') ? mail_open (NIL,src,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)) : NIL,src)) retcode = 0; } else if (!strcmp (cmd,"delete")) { if (!src || dst || merge || rwcopyp || kwcopyp || ignorep) printf (usage2,pgm,usgdel,stdsw); else if (mail_delete (source = (*src == '{') ? mail_open (NIL,src,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)) : NIL,src)) retcode = 0; } else if (!strcmp (cmd,"rename")) { if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep) printf (usage2,pgm,usgren,stdsw); else if (mail_rename (source = (*src == '{') ? mail_open (NIL,src,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)) : NIL,src,dst)) retcode = 0; } else if ((i = !strcmp (cmd,"move")) || !strcmp (cmd,"copy")) { if (!src || !dst || merge) printf (usage3,pgm,cmd,usgcpymov,stdsw); else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) | (debugp ? OP_DEBUG : NIL))) { dest = NIL; /* open destination stream if network */ if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)))) { if (mbxcopy (source,dest,dst,T,i,merge)) retcode = 0; } } } else if ((i = !strcmp (cmd,"appenddelete")) || !strcmp (cmd,"append")) { if (!src || !dst || merge) printf (usage3,pgm,cmd,usgappdel,stdsw); else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) | (debugp ? OP_DEBUG : NIL))) { dest = NIL; /* open destination stream if network */ if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)))) { if (mbxcopy (source,dest,dst,NIL,i,merge)) retcode = 0; } } } else if (!strcmp (cmd,"prune")) { if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep || !(criteria = prune_criteria (dst))) printf (usage2,pgm,usgprn,stdsw); else if ((source = mail_open (NIL,src,(debugp ? OP_DEBUG : NIL))) && mail_search_full (source,NIL,criteria,SE_FREE)) { for (m = 1, s = t = NIL, len = start = last = 0; m <= source->nmsgs; m++) if (mail_elt (source,m)->searched) { if (s) { /* continuing a range? */ if (m == last + 1) last = m; else { /* no, end of previous range? */ if (last != start) sprintf (t,":%lu,%lu",last,m); /* no, just this message */ else sprintf (t,",%lu",m); start = last = m; /* either way, start new range */ /* running out of space? */ if ((len - (curlen = (t += strlen (t)) - s)) < 20) { fs_resize ((void **) &s,len += MAILTMPLEN); t = s + curlen; /* relocate current pointer */ } } } else { /* first time, start new buffer */ s = (char *) fs_get (len = MAILTMPLEN); sprintf (s,"%lu",start = last = m); t = s + strlen (s); /* end of buffer */ } } /* finish last range if necessary */ if (last != start) sprintf (t,":%lu",last); if (s) { /* delete/expunge any matching messages */ mail_flag (source,s,"\\Deleted",ST_SET); m = source->nmsgs; /* get number of messages before purge */ mail_expunge (source); printf ("%lu message(s) purged\n",m - source->nmsgs); fs_give ((void **) &s); /* flush buffer */ } else puts ("No matching messages, so nothing purged"); source = mail_close (source); } } else if (!strcmp (cmd,"transfer")) { if (!src || !dst) printf (usage2,pgm,usgxfr,stdsw); else if ((*src == '{') && /* open source mailbox */ !(source = mail_open (NIL,src,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)))); else if ((*dst == '{') && /* open destination server */ !(dest = mail_open (NIL,dst,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)))); else if (!(f = tmpfile ())) puts ("can't open temporary file"); else { if (verbosep) puts ("Listing mailboxes..."); if (dest) strcpy (strchr (strcpy (tmp,dest->mailbox),'}') + 1, dp = strchr (dst,'}') + 1); else { dp = dst; tmp[0] = '\0'; } mail_list (dest,tmp,""); rewind (f); /* list all mailboxes matching prefix */ if (ddelim < 0) { /* if server failed to give delimiter */ puts ("warning: unable to get destination hierarchy delimiter!"); ddelim = 0; /* default to none */ } if (source) strcpy (strchr (strcpy (tmp,source->mailbox),'}') + 1, strchr (src,'}') + 1); else strcpy (tmp,src); mail_list (source,tmp,"*"); rewind (f); /* read back mailbox names */ for (retcode = 0; !retcode && (fgets (tmp,MAILTMPLEN-1,f)); ) { if (t = strchr (tmp+1,'\n')) *t = '\0'; for (t = mbx,t1 = dest ? dest->mailbox : "",c = NIL; (c != '}') && *t1; *t++ = c= *t1++); for (t1 = dp; *t1; *t++ = *t1++); /* point to name without delim or netspec */ t1 = source ? (strchr (tmp+1,'}') + 1) : tmp + 1; /* src and mbx have different delimiters? */ if (ddelim && (ddelim != tmp[0])) while (c = *t1++) { /* swap delimiters then */ if (c == ddelim) c = tmp[0] ? tmp[0] : 'x'; else if (c == tmp[0]) c = ddelim; *t++ = c; } /* easy case */ else while (*t1) *t++ = *t1++; *t++ = '\0'; if (verbosep) { printf ("Copying %s\n => %s\n",tmp+1,mbx); fflush (stdout); } if (source = mail_open (source,tmp+1,(debugp ? OP_DEBUG : NIL) | (rwcopyp ? NIL : OP_READONLY))) { if (!mbxcopy (source,dest,mbx,T,NIL,merge)) retcode = 1; if (source->dtb->flags & DR_LOCAL) source = mail_close (source); } else printf ("can't open source mailbox %s\n",tmp+1); } } } else { printf ("%s version %s.%s\n\n",pgm,CCLIENTVERSION,version); printf (usage2,pgm,"command [switches] arguments",stdsw); printf ("\nCommands:\n %s\n",usgchk); puts (" ;; report number of messages and new messages"); printf (" %s\n",usgcre); puts (" ;; create new mailbox"); printf (" %s\n",usgdel); puts (" ;; delete existing mailbox"); printf (" %s\n",usgren); puts (" ;; rename mailbox to a new name"); printf (" copy %s\n",usgcpymov); printf (" move %s\n",usgcpymov); puts (" ;; create new mailbox and copy/move messages"); printf (" append %s\n",usgappdel); printf (" appenddelete %s\n",usgappdel); puts (" ;; copy/move messages to existing mailbox"); printf (" %s\n",usgprn); puts (" ;; prune mailbox of messages matching criteria"); printf (" %s\n",usgxfr); puts (" ;; copy source hierarchy to destination"); puts (" ;; -merge modes are prompt, append, or suffix=xxxx"); } /* close streams */ if (source) mail_close (source); if (dest) mail_close (dest); exit (retcode); return retcode; /* stupid compilers */ }
/* Mail state. Find and read mail file. */ int fetch_mbox_state_mail(struct account *a, struct fetch_ctx *fctx) { struct fetch_mbox_data *data = a->data; struct mail *m = fctx->mail; struct fetch_mbox_mbox *fmbox; struct fetch_mbox_mail *aux; char *line, *ptr, *lptr; size_t llen; int flushing; /* Find current mbox and check for EOF. */ fmbox = ARRAY_ITEM(&data->fmboxes, data->index); if (data->off == fmbox->size) { fctx->state = fetch_mbox_state_next; return (FETCH_AGAIN); } /* Open the mail. */ if (mail_open(m, IO_BLOCKSIZE) != 0) { log_warn("%s: failed to create mail", a->name); mail_destroy(m); return (FETCH_ERROR); } /* Create aux data. */ aux = xmalloc(sizeof *aux); aux->off = data->off; aux->size = 0; aux->fmbox = fmbox; if (++fmbox->reference == 0) fatalx("reference count overflow"); m->auxdata = aux; m->auxfree = fetch_mbox_free; /* Tag mail. */ default_tags(&m->tags, NULL); add_tag(&m->tags, "mbox", "%s", xbasename(fmbox->path)); add_tag(&m->tags, "mbox_path", "%s", xdirname(fmbox->path)); add_tag(&m->tags, "mbox_file", "%s", fmbox->path); /* * We start at a "From " line and include it in the mail (it can be * trimmed later with minimal penalty). */ flushing = 0; for (;;) { /* Check for EOF. */ if (data->off == fmbox->size) { aux->size = data->off - aux->off; break; } /* Locate the EOL. */ line = fmbox->base + data->off; ptr = memchr(line, '\n', fmbox->size - data->off); if (ptr == NULL) { ptr = fmbox->base + fmbox->size; data->off = fmbox->size; } else data->off += ptr - line + 1; /* Check if the line is "From ". */ if (line > fmbox->base && ptr - line >= 5 && strncmp(line, "From ", 5) == 0) { /* End of mail. */ aux->size = (line - fmbox->base) - aux->off; break; } /* Trim >s from From. */ if (*line == '>') { lptr = line; llen = ptr - line; while (*lptr == '>' && llen > 0) { lptr++; llen--; } if (llen >= 5 && strncmp(lptr, "From ", 5) == 0) line++; } if (flushing) continue; if (append_line(m, line, ptr - line) != 0) { log_warn("%s: failed to resize mail", a->name); mail_destroy(m); return (FETCH_ERROR); } if (m->size > conf.max_size) flushing = 1; } fmbox->total++; /* * Check if there was a blank line between the mails and remove it if * so. */ if (aux->size >= 2 && fmbox->base[aux->off + aux->size - 1] == '\n' && fmbox->base[aux->off + aux->size - 2] == '\n') { aux->size -= 2; m->size -= 2; } return (FETCH_MAIL); }