Skip to content

Commit c0ad561

Browse files
committed
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
2 parents 6401489 + e0d8e30 commit c0ad561

File tree

2 files changed

+33
-51
lines changed

2 files changed

+33
-51
lines changed

Documentation/git-imap-send.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ imap.preformattedHTML::
7575

7676
imap.authMethod::
7777
Specify authenticate method for authentication with IMAP server.
78-
Current supported method is 'CRAM-MD5' only.
78+
Current supported method is 'CRAM-MD5' only. If this is not set
79+
then 'git imap-send' uses the basic IMAP plaintext LOGIN command.
7980

8081
Examples
8182
~~~~~~~~

imap-send.c

Lines changed: 31 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ struct imap_cmd_cb {
128128
char *data;
129129
int dlen;
130130
int uid;
131-
unsigned create:1, trycreate:1;
132131
};
133132

134133
struct imap_cmd {
@@ -493,9 +492,9 @@ static int nfsnprintf(char *buf, int blen, const char *fmt, ...)
493492
return ret;
494493
}
495494

496-
static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
497-
struct imap_cmd_cb *cb,
498-
const char *fmt, va_list ap)
495+
static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,
496+
struct imap_cmd_cb *cb,
497+
const char *fmt, va_list ap)
499498
{
500499
struct imap *imap = ctx->imap;
501500
struct imap_cmd *cmd;
@@ -558,20 +557,6 @@ static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
558557
return cmd;
559558
}
560559

561-
__attribute__((format (printf, 3, 4)))
562-
static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,
563-
struct imap_cmd_cb *cb,
564-
const char *fmt, ...)
565-
{
566-
struct imap_cmd *ret;
567-
va_list ap;
568-
569-
va_start(ap, fmt);
570-
ret = v_issue_imap_cmd(ctx, cb, fmt, ap);
571-
va_end(ap);
572-
return ret;
573-
}
574-
575560
__attribute__((format (printf, 3, 4)))
576561
static int imap_exec(struct imap_store *ctx, struct imap_cmd_cb *cb,
577562
const char *fmt, ...)
@@ -580,7 +565,7 @@ static int imap_exec(struct imap_store *ctx, struct imap_cmd_cb *cb,
580565
struct imap_cmd *cmdp;
581566

582567
va_start(ap, fmt);
583-
cmdp = v_issue_imap_cmd(ctx, cb, fmt, ap);
568+
cmdp = issue_imap_cmd(ctx, cb, fmt, ap);
584569
va_end(ap);
585570
if (!cmdp)
586571
return RESP_BAD;
@@ -596,7 +581,7 @@ static int imap_exec_m(struct imap_store *ctx, struct imap_cmd_cb *cb,
596581
struct imap_cmd *cmdp;
597582

598583
va_start(ap, fmt);
599-
cmdp = v_issue_imap_cmd(ctx, cb, fmt, ap);
584+
cmdp = issue_imap_cmd(ctx, cb, fmt, ap);
600585
va_end(ap);
601586
if (!cmdp)
602587
return DRV_STORE_BAD;
@@ -714,8 +699,8 @@ static int parse_response_code(struct imap_store *ctx, struct imap_cmd_cb *cb,
714699
static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
715700
{
716701
struct imap *imap = ctx->imap;
717-
struct imap_cmd *cmdp, **pcmdp, *ncmdp;
718-
char *cmd, *arg, *arg1, *p;
702+
struct imap_cmd *cmdp, **pcmdp;
703+
char *cmd, *arg, *arg1;
719704
int n, resp, resp2, tag;
720705

721706
for (;;) {
@@ -801,30 +786,9 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
801786
if (!strcmp("OK", arg))
802787
resp = DRV_OK;
803788
else {
804-
if (!strcmp("NO", arg)) {
805-
if (cmdp->cb.create && cmd && (cmdp->cb.trycreate || !memcmp(cmd, "[TRYCREATE]", 11))) { /* SELECT, APPEND or UID COPY */
806-
p = strchr(cmdp->cmd, '"');
807-
if (!issue_imap_cmd(ctx, NULL, "CREATE \"%.*s\"", (int)(strchr(p + 1, '"') - p + 1), p)) {
808-
resp = RESP_BAD;
809-
goto normal;
810-
}
811-
/* not waiting here violates the spec, but a server that does not
812-
grok this nonetheless violates it too. */
813-
cmdp->cb.create = 0;
814-
if (!(ncmdp = issue_imap_cmd(ctx, &cmdp->cb, "%s", cmdp->cmd))) {
815-
resp = RESP_BAD;
816-
goto normal;
817-
}
818-
free(cmdp->cmd);
819-
free(cmdp);
820-
if (!tcmd)
821-
return 0; /* ignored */
822-
if (cmdp == tcmd)
823-
tcmd = ncmdp;
824-
continue;
825-
}
789+
if (!strcmp("NO", arg))
826790
resp = RESP_NO;
827-
} else /*if (!strcmp("BAD", arg))*/
791+
else /*if (!strcmp("BAD", arg))*/
828792
resp = RESP_BAD;
829793
fprintf(stderr, "IMAP command '%s' returned response (%s) - %s\n",
830794
memcmp(cmdp->cmd, "LOGIN", 5) ?
@@ -833,7 +797,6 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
833797
}
834798
if ((resp2 = parse_response_code(ctx, &cmdp->cb, cmd)) > resp)
835799
resp = resp2;
836-
normal:
837800
if (cmdp->cb.done)
838801
cmdp->cb.done(ctx, cmdp, resp);
839802
free(cmdp->cb.data);
@@ -944,7 +907,7 @@ static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const cha
944907
return 0;
945908
}
946909

947-
static struct imap_store *imap_open_store(struct imap_server_conf *srvc)
910+
static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *folder)
948911
{
949912
struct credential cred = CREDENTIAL_INIT;
950913
struct imap_store *ctx;
@@ -1156,6 +1119,25 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc)
11561119
credential_approve(&cred);
11571120
credential_clear(&cred);
11581121

1122+
/* check the target mailbox exists */
1123+
ctx->name = folder;
1124+
switch (imap_exec(ctx, NULL, "EXAMINE \"%s\"", ctx->name)) {
1125+
case RESP_OK:
1126+
/* ok */
1127+
break;
1128+
case RESP_BAD:
1129+
fprintf(stderr, "IMAP error: could not check mailbox\n");
1130+
goto out;
1131+
case RESP_NO:
1132+
if (imap_exec(ctx, NULL, "CREATE \"%s\"", ctx->name) == RESP_OK) {
1133+
imap_info("Created missing mailbox\n");
1134+
} else {
1135+
fprintf(stderr, "IMAP error: could not create missing mailbox\n");
1136+
goto out;
1137+
}
1138+
break;
1139+
}
1140+
11591141
ctx->prefix = "";
11601142
return ctx;
11611143

@@ -1164,6 +1146,7 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc)
11641146
credential_reject(&cred);
11651147
credential_clear(&cred);
11661148

1149+
out:
11671150
imap_close_store(ctx);
11681151
return NULL;
11691152
}
@@ -1219,7 +1202,6 @@ static int imap_store_msg(struct imap_store *ctx, struct strbuf *msg)
12191202

12201203
box = ctx->name;
12211204
prefix = !strcmp(box, "INBOX") ? "" : ctx->prefix;
1222-
cb.create = 0;
12231205
ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" ", prefix, box);
12241206
imap->caps = imap->rcaps;
12251207
if (ret != DRV_OK)
@@ -1418,14 +1400,13 @@ int main(int argc, char **argv)
14181400
}
14191401

14201402
/* write it to the imap server */
1421-
ctx = imap_open_store(&server);
1403+
ctx = imap_open_store(&server, imap_folder);
14221404
if (!ctx) {
14231405
fprintf(stderr, "failed to open store\n");
14241406
return 1;
14251407
}
14261408

14271409
fprintf(stderr, "sending %d message%s\n", total, (total != 1) ? "s" : "");
1428-
ctx->name = imap_folder;
14291410
while (1) {
14301411
unsigned percent = n * 100 / total;
14311412

0 commit comments

Comments
 (0)