Esempio n. 1
0
/* Commit state. */
int
imap_state_commit(struct account *a, struct fetch_ctx *fctx)
{
	struct fetch_imap_data	*data = a->data;
	char			*line;

	if (imap_getln(a, fctx, IMAP_TAGGED, &line) != 0)
		return (FETCH_ERROR);
	if (line == NULL)
		return (FETCH_BLOCK);
	if (!imap_okay(line))
		return (imap_bad(a, line));

	data->committed++;

	fctx->state = imap_state_next;
	return (FETCH_AGAIN);
}
Esempio n. 2
0
/* Mail state. */
int
imap_state_mail(struct account *a, struct fetch_ctx *fctx)
{
	struct fetch_imap_data	*data = a->data;
	char	*line;

	if (imap_getln(a, fctx, IMAP_TAGGED, &line) != 0)
		return (FETCH_ERROR);
	if (line == NULL)
		return (FETCH_BLOCK);
	if (!imap_okay(line))
		return (imap_bad(a, line));

	if (data->capa & IMAP_CAPA_GMEXT) {
		fctx->state = imap_state_gmext_start;
		return (FETCH_AGAIN);
	}

	fctx->state = imap_state_next;
	return (FETCH_MAIL);
}
Esempio n. 3
0
/* STARTTLS state. */
int
imap_state_starttls(struct account *a, struct fetch_ctx *fctx)
{
	struct fetch_imap_data	*data = a->data;
	char			*line, *cause;

	if (imap_getln(a, fctx, IMAP_TAGGED, &line) != 0)
		return (FETCH_ERROR);
	if (line == NULL)
		return (FETCH_BLOCK);
	if (!imap_okay(line))
		return (imap_bad(a, line));

	data->io->ssl = makessl(&data->server, data->io->fd,
	    conf.verify_certs && data->server.verify, conf.timeout, &cause);
	if (data->io->ssl == NULL) {
		log_warnx("%s: STARTTLS failed: %s", a->name, cause);
		xfree(cause);
		return (FETCH_ERROR);
	}

	return (imap_pick_auth(a, fctx));
}
Esempio n. 4
0
/* Close state. */
int
imap_state_close(struct account *a, struct fetch_ctx *fctx)
{
	struct fetch_imap_data	*data = a->data;
	char			*line;

	if (imap_getln(a, fctx, IMAP_TAGGED, &line) != 0)
		return (FETCH_ERROR);
	if (line == NULL)
		return (FETCH_BLOCK);
	if (!imap_okay(line))
		return (imap_bad(a, line));

	data->folder++;
	if (data->folder != ARRAY_LENGTH(data->folders)) {
		fctx->state = imap_state_select1;
		return (FETCH_AGAIN);
	}

	if (imap_putln(a, "%u LOGOUT", ++data->tag) != 0)
		return (FETCH_ERROR);
	fctx->state = imap_state_quit;
	return (FETCH_BLOCK);
}
Esempio n. 5
0
/* Select state 4. Hold until select completes. */
int
imap_state_select4(struct account *a, struct fetch_ctx *fctx)
{
	struct fetch_imap_data	*data = a->data;
	char			*line;

	if (imap_getln(a, fctx, IMAP_TAGGED, &line) != 0)
		return (FETCH_ERROR);
	if (line == NULL)
		return (FETCH_BLOCK);
	if (!imap_okay(line))
		return (imap_bad(a, line));

	/* If no mails, stop early. */
	if (data->total == 0) {
		if (imap_putln(a, "%u CLOSE", ++data->tag) != 0)
			return (FETCH_ERROR);
		fctx->state = imap_state_close;
		return (FETCH_BLOCK);
	}

	fctx->state = imap_state_search1;
	return (FETCH_AGAIN);
}
Esempio n. 6
0
int
deliver_imap_deliver(struct deliver_ctx *dctx, struct actitem *ti)
{
	struct account			*a = dctx->account;
	struct mail			*m = dctx->mail;
	struct deliver_imap_data	*data = ti->data;
	struct io			*io;
	struct fetch_ctx		 fctx;
	struct fetch_imap_data		 fdata;
	char				*cause, *folder, *ptr, *line;
	size_t				 len, maillen;
	u_int				 total, body;

	/* Connect to the IMAP server. */
	io = connectproxy(&data->server,
	    conf.verify_certs, conf.proxy, IO_CRLF, conf.timeout, &cause);
	if (io == NULL) {
		log_warnx("%s: %s", a->name, cause);
		xfree(cause);
		return (DELIVER_FAILURE);
	}
	if (conf.debug > 3 && !conf.syslog)
		io->dup_fd = STDOUT_FILENO;

	/* Work out the folder name. */
	folder = replacestr(&data->folder, m->tags, m, &m->rml);
	if (folder == NULL || *folder == '\0') {
		log_warnx("%s: empty folder", a->name);
		goto error;
	}

	/* Fake up the fetch context for the fetch code. */
	memset(&fdata, 0, sizeof fdata);
	fdata.user = data->user;
	fdata.pass = data->pass;
	fdata.nocrammd5 = data->nocrammd5;
	fdata.nologin = data->nologin;
	memcpy(&fdata.server, &data->server, sizeof fdata.server);
	fdata.io = io;
	fdata.only = FETCH_ONLY_ALL;
	a->data = &fdata;
	fetch_imap_state_init(a, &fctx);
	fctx.state = imap_state_connected;
	fctx.llen = IO_LINESIZE;
	fctx.lbuf = xmalloc(fctx.llen);

	/* Use the fetch code until the select1 state is reached. */
	if (deliver_imap_pollto(imap_state_select1, a, io, &fctx) != 0)
		goto error;

retry:
	/* Send an append command. */
	if (imap_putln(a, "%u APPEND {%zu}", ++fdata.tag, strlen(folder)) != 0)
		goto error;
	switch (deliver_imap_waitappend(a, &fctx, io, &line)) {
	case IMAP_TAG_ERROR:
		if (line != NULL)
			imap_invalid(a, line);
		goto error;
	case IMAP_TAG_CONTINUE:
		break;
	default:
		if (imap_no(line) && strstr(line, "[TRYCREATE]") != NULL)
			goto try_create;
		imap_invalid(a, line);
		goto error;
	}

	/*
	 * Send the mail size, not forgetting lines are CRLF terminated. The
	 * Google IMAP server is written strangely, so send the size as if
	 * every CRLF was a CR if the server has XYZZY.
	 */
	count_lines(m, &total, &body);
	maillen = m->size + total - 1;
	if (fdata.capa & IMAP_CAPA_XYZZY) {
		log_debug2("%s: adjusting size: actual %zu", a->name, maillen);
		maillen = m->size;
	}
	if (fdata.capa & IMAP_CAPA_NOSPACE) {
		if (imap_putln(a, "%s{%zu}", folder, maillen) != 0)
			goto error;
	} else {
		if (imap_putln(a, "%s {%zu}", folder, maillen) != 0)
			goto error;
	}
	switch (deliver_imap_waitappend(a, &fctx, io, &line)) {
	case IMAP_TAG_ERROR:
		if (line != NULL)
			imap_invalid(a, line);
		goto error;
	case IMAP_TAG_CONTINUE:
		break;
	default:
		if (imap_no(line) && strstr(line, "[TRYCREATE]") != NULL)
			goto try_create;
		imap_invalid(a, line);
		goto error;
	}

	/* Send the mail data. */
	line_init(m, &ptr, &len);
	while (ptr != NULL) {
		if (len > 1)
			io_write(io, ptr, len - 1);
		io_writeline(io, NULL);

		/* Update if necessary. */
		if (io_update(io, conf.timeout, &cause) != 1) {
			log_warnx("%s: %s", a->name, cause);
			xfree(cause);
			goto error;
		}

		line_next(m, &ptr, &len);
	}

	/* Wait for an okay from the server. */
	switch (deliver_imap_waitappend(a, &fctx, io, &line)) {
	case IMAP_TAG_ERROR:
	case IMAP_TAG_CONTINUE:
		if (line != NULL)
			imap_invalid(a, line);
		goto error;
	default:
		if (imap_okay(line))
			break;
		if (strstr(line, "[TRYCREATE]") != NULL)
			goto try_create;
		imap_invalid(a, line);
		goto error;
	}

	xfree(fctx.lbuf);
	xfree(folder);

	if (imap_putln(a, "%u LOGOUT", ++fdata.tag) != 0)
		goto error;
	if (deliver_imap_waitokay(a, &fctx, io, &line) != 0)
		goto error;

	fdata.disconnect(a);
	return (DELIVER_SUCCESS);

try_create:	/* XXX function? */
	/* Try to create the folder. */
	if (imap_putln(a, "%u CREATE {%zu}", ++fdata.tag, strlen(folder)) != 0)
		goto error;
	if (deliver_imap_waitcontinue(a, &fctx, io, &line) != 0)
		goto error;
	if (imap_putln(a, "%s", folder) != 0)
		goto error;
	if (deliver_imap_waitokay(a, &fctx, io, &line) != 0)
		goto error;
	goto retry;

error:
	io_writeline(io, "QUIT");
	io_flush(io, conf.timeout, NULL);

	xfree(fctx.lbuf);
	if (folder != NULL)
		xfree(folder);

	fdata.disconnect(a);
	return (DELIVER_FAILURE);
}