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
This commit is contained in:
commit
c0ad561a46
@ -75,7 +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
|
||||
~~~~~~~~
|
||||
|
81
imap-send.c
81
imap-send.c
@ -128,7 +128,6 @@ struct imap_cmd_cb {
|
||||
char *data;
|
||||
int dlen;
|
||||
int uid;
|
||||
unsigned create:1, trycreate:1;
|
||||
};
|
||||
|
||||
struct imap_cmd {
|
||||
@ -493,9 +492,9 @@ static int nfsnprintf(char *buf, int blen, const char *fmt, ...)
|
||||
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 @@ static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
|
||||
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 @@ static int imap_exec(struct imap_store *ctx, struct imap_cmd_cb *cb,
|
||||
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 @@ static int imap_exec_m(struct imap_store *ctx, struct imap_cmd_cb *cb,
|
||||
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 @@ static int parse_response_code(struct imap_store *ctx, struct imap_cmd_cb *cb,
|
||||
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 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
|
||||
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 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
|
||||
}
|
||||
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 @@ static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const cha
|
||||
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;
|
||||
@ -1156,6 +1119,25 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc)
|
||||
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 @@ bail:
|
||||
credential_reject(&cred);
|
||||
credential_clear(&cred);
|
||||
|
||||
out:
|
||||
imap_close_store(ctx);
|
||||
return NULL;
|
||||
}
|
||||
@ -1219,7 +1202,6 @@ static int imap_store_msg(struct imap_store *ctx, struct strbuf *msg)
|
||||
|
||||
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)
|
||||
@ -1418,14 +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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user