From: Junio C Hamano Date: Tue, 9 Sep 2014 19:54:08 +0000 (-0700) Subject: Merge branch 'tf/imap-send-create' X-Git-Tag: v2.2.0-rc0~151 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/c0ad561a468f7f95c3697b73b7cffc2851988a8b?ds=inline;hp=-c Merge branch 'tf/imap-send-create' * tf/imap-send-create: imap-send: create target mailbox if it is missing imap-send: clarify CRAM-MD5 vs LOGIN documentation --- c0ad561a468f7f95c3697b73b7cffc2851988a8b diff --combined Documentation/git-imap-send.txt index eabcaf0388,770cbe80a3..7d991d919c --- a/Documentation/git-imap-send.txt +++ b/Documentation/git-imap-send.txt @@@ -38,17 -38,18 +38,17 @@@ Variable imap.folder:: The folder to drop the mails into, which is typically the Drafts folder. For example: "INBOX.Drafts", "INBOX/Drafts" or - "[Gmail]/Drafts". Required to use imap-send. + "[Gmail]/Drafts". Required. imap.tunnel:: Command used to setup a tunnel to the IMAP server through which commands will be piped instead of using a direct network connection - to the server. Required when imap.host is not set to use imap-send. + to the server. Required when imap.host is not set. imap.host:: A URL identifying the server. Use a `imap://` prefix for non-secure connections and a `imaps://` prefix for secure connections. - Ignored when imap.tunnel is set, but required to use imap-send - otherwise. + Ignored when imap.tunnel is set, but required otherwise. imap.user:: The username to use when logging in to the server. @@@ -75,7 -76,8 +75,8 @@@ imap.preformattedHTML: imap.authMethod:: Specify authenticate method for authentication with IMAP server. - Current supported method is 'CRAM-MD5' only. + Current supported method is 'CRAM-MD5' only. If this is not set + then 'git imap-send' uses the basic IMAP plaintext LOGIN command. Examples ~~~~~~~~ diff --combined imap-send.c index 524fbabc96,48733ccc45..87f9bb18f6 --- a/imap-send.c +++ b/imap-send.c @@@ -128,7 -128,6 +128,6 @@@ struct imap_cmd_cb char *data; int dlen; int uid; - unsigned create:1, trycreate:1; }; struct imap_cmd { @@@ -493,9 -492,9 +492,9 @@@ static int nfsnprintf(char *buf, int bl return ret; } - static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx, - struct imap_cmd_cb *cb, - const char *fmt, va_list ap) + static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx, + struct imap_cmd_cb *cb, + const char *fmt, va_list ap) { struct imap *imap = ctx->imap; struct imap_cmd *cmd; @@@ -558,20 -557,6 +557,6 @@@ return cmd; } - __attribute__((format (printf, 3, 4))) - static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx, - struct imap_cmd_cb *cb, - const char *fmt, ...) - { - struct imap_cmd *ret; - va_list ap; - - va_start(ap, fmt); - ret = v_issue_imap_cmd(ctx, cb, fmt, ap); - va_end(ap); - return ret; - } - __attribute__((format (printf, 3, 4))) static int imap_exec(struct imap_store *ctx, struct imap_cmd_cb *cb, const char *fmt, ...) @@@ -580,7 -565,7 +565,7 @@@ struct imap_cmd *cmdp; va_start(ap, fmt); - cmdp = v_issue_imap_cmd(ctx, cb, fmt, ap); + cmdp = issue_imap_cmd(ctx, cb, fmt, ap); va_end(ap); if (!cmdp) return RESP_BAD; @@@ -596,7 -581,7 +581,7 @@@ static int imap_exec_m(struct imap_stor struct imap_cmd *cmdp; va_start(ap, fmt); - cmdp = v_issue_imap_cmd(ctx, cb, fmt, ap); + cmdp = issue_imap_cmd(ctx, cb, fmt, ap); va_end(ap); if (!cmdp) return DRV_STORE_BAD; @@@ -714,8 -699,8 +699,8 @@@ static int parse_response_code(struct i static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd) { struct imap *imap = ctx->imap; - struct imap_cmd *cmdp, **pcmdp, *ncmdp; - char *cmd, *arg, *arg1, *p; + struct imap_cmd *cmdp, **pcmdp; + char *cmd, *arg, *arg1; int n, resp, resp2, tag; for (;;) { @@@ -801,30 -786,9 +786,9 @@@ if (!strcmp("OK", arg)) resp = DRV_OK; else { - if (!strcmp("NO", arg)) { - if (cmdp->cb.create && cmd && (cmdp->cb.trycreate || !memcmp(cmd, "[TRYCREATE]", 11))) { /* SELECT, APPEND or UID COPY */ - p = strchr(cmdp->cmd, '"'); - if (!issue_imap_cmd(ctx, NULL, "CREATE \"%.*s\"", (int)(strchr(p + 1, '"') - p + 1), p)) { - resp = RESP_BAD; - goto normal; - } - /* not waiting here violates the spec, but a server that does not - grok this nonetheless violates it too. */ - cmdp->cb.create = 0; - if (!(ncmdp = issue_imap_cmd(ctx, &cmdp->cb, "%s", cmdp->cmd))) { - resp = RESP_BAD; - goto normal; - } - free(cmdp->cmd); - free(cmdp); - if (!tcmd) - return 0; /* ignored */ - if (cmdp == tcmd) - tcmd = ncmdp; - continue; - } + if (!strcmp("NO", arg)) resp = RESP_NO; - } else /*if (!strcmp("BAD", arg))*/ + else /*if (!strcmp("BAD", arg))*/ resp = RESP_BAD; fprintf(stderr, "IMAP command '%s' returned response (%s) - %s\n", memcmp(cmdp->cmd, "LOGIN", 5) ? @@@ -833,7 -797,6 +797,6 @@@ } if ((resp2 = parse_response_code(ctx, &cmdp->cb, cmd)) > resp) resp = resp2; - normal: if (cmdp->cb.done) cmdp->cb.done(ctx, cmdp, resp); free(cmdp->cb.data); @@@ -944,7 -907,7 +907,7 @@@ static int auth_cram_md5(struct imap_st return 0; } - static struct imap_store *imap_open_store(struct imap_server_conf *srvc) + static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *folder) { struct credential cred = CREDENTIAL_INIT; struct imap_store *ctx; @@@ -952,7 -915,7 +915,7 @@@ char *arg, *rsp; int s = -1, preauth; - ctx = xcalloc(sizeof(*ctx), 1); + ctx = xcalloc(1, sizeof(*ctx)); ctx->imap = imap = xcalloc(sizeof(*imap), 1); imap->buf.sock.fd[0] = imap->buf.sock.fd[1] = -1; @@@ -1156,6 -1119,25 +1119,25 @@@ credential_approve(&cred); credential_clear(&cred); + /* check the target mailbox exists */ + ctx->name = folder; + switch (imap_exec(ctx, NULL, "EXAMINE \"%s\"", ctx->name)) { + case RESP_OK: + /* ok */ + break; + case RESP_BAD: + fprintf(stderr, "IMAP error: could not check mailbox\n"); + goto out; + case RESP_NO: + if (imap_exec(ctx, NULL, "CREATE \"%s\"", ctx->name) == RESP_OK) { + imap_info("Created missing mailbox\n"); + } else { + fprintf(stderr, "IMAP error: could not create missing mailbox\n"); + goto out; + } + break; + } + ctx->prefix = ""; return ctx; @@@ -1164,6 -1146,7 +1146,7 @@@ bail credential_reject(&cred); credential_clear(&cred); + out: imap_close_store(ctx); return NULL; } @@@ -1219,7 -1202,6 +1202,6 @@@ static int imap_store_msg(struct imap_s box = ctx->name; prefix = !strcmp(box, "INBOX") ? "" : ctx->prefix; - cb.create = 0; ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" ", prefix, box); imap->caps = imap->rcaps; if (ret != DRV_OK) @@@ -1328,9 -1310,13 +1310,9 @@@ static char *imap_folder static int git_imap_config(const char *key, const char *val, void *cb) { - char imap_key[] = "imap."; - - if (strncmp(key, imap_key, sizeof imap_key - 1)) + if (!skip_prefix(key, "imap.", &key)) return 0; - key += sizeof imap_key - 1; - /* check booleans first, and barf on others */ if (!strcmp("sslverify", key)) server.ssl_verify = git_config_bool(key, val); @@@ -1418,14 -1404,13 +1400,13 @@@ int main(int argc, char **argv } /* write it to the imap server */ - ctx = imap_open_store(&server); + ctx = imap_open_store(&server, imap_folder); if (!ctx) { fprintf(stderr, "failed to open store\n"); return 1; } fprintf(stderr, "sending %d message%s\n", total, (total != 1) ? "s" : ""); - ctx->name = imap_folder; while (1) { unsigned percent = n * 100 / total;