示例#1
0
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;
}
示例#2
0
文件: ext_imap.cpp 项目: 2bj/hhvm
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;
}
示例#3
0
/*
 * 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;
}
示例#4
0
文件: ext_imap.cpp 项目: 2bj/hhvm
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);
}
示例#5
0
文件: imap-common.c 项目: upwhere/fdm
/* 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);
}
示例#6
0
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);
}
示例#7
0
文件: dmail.c 项目: alpinemail/alpine
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);
}
示例#8
0
/* 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 */
}
示例#11
0
文件: fetch-mbox.c 项目: mbeck-/fdm
/* 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);
}