{"thread":{"id":"37229","subject":"[PATCH] imap-send: clarify CRAM-MD5 vs LOGIN documentation","startedAt":"2014-07-28T10:38:20Z","lastAt":"2014-08-03T06:38:08Z","messageCount":12,"participants":["Tony Finch","Junio C Hamano","Ramsay Jones"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"246784","messageId":"alpine.LSU.2.00.1407281138100.13901@hermes-1.csi.cam.ac.uk","threadId":"37229","inReplyTo":null,"subject":"[PATCH] imap-send: clarify CRAM-MD5 vs LOGIN documentation","fromName":"Tony Finch","fromEmail":"dot@dotat.at","sentAt":"2014-07-28T10:38:20Z","receivedAt":"2014-07-28T10:38:20Z","isPatch":true,"sender":{"key":"dot@dotat.at","avatar":"https://avatars.githubusercontent.com/u/68429?v=4"},"body":"Explicitly mention that leaving imap.authMethod unset makes\ngit imap-send use the basic IMAP plaintext LOGIN command.\n---\n Documentation/git-imap-send.txt | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt\nindex 875d283..770cbe8 100644\n--- a/Documentation/git-imap-send.txt\n+++ b/Documentation/git-imap-send.txt\n@@ -76,7 +76,8 @@ imap.preformattedHTML::\n\n imap.authMethod::\n \tSpecify authenticate method for authentication with IMAP server.\n-\tCurrent supported method is 'CRAM-MD5' only.\n+\tCurrent supported method is 'CRAM-MD5' only. If this is not set\n+\tthen 'git imap-send' uses the basic IMAP plaintext LOGIN command.\n\n Examples\n ~~~~~~~~\n-- \n2.0.3.dirty\n"},{"id":"246988","messageId":"xmqqzjfqy7br.fsf@gitster.dls.corp.google.com","threadId":"37229","inReplyTo":"alpine.LSU.2.00.1407281138100.13901@hermes-1.csi.cam.ac.uk","subject":"Re: [PATCH] imap-send: clarify CRAM-MD5 vs LOGIN documentation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-07-30T19:28:40Z","receivedAt":"2014-07-30T19:28:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tony Finch <dot@dotat.at> writes:\n\n> Explicitly mention that leaving imap.authMethod unset makes\n> git imap-send use the basic IMAP plaintext LOGIN command.\n> ---\n>  Documentation/git-imap-send.txt | 3 ++-\n>  1 file changed, 2 insertions(+), 1 deletion(-)\n>\n> diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt\n> index 875d283..770cbe8 100644\n> --- a/Documentation/git-imap-send.txt\n> +++ b/Documentation/git-imap-send.txt\n> @@ -76,7 +76,8 @@ imap.preformattedHTML::\n>\n>  imap.authMethod::\n>  \tSpecify authenticate method for authentication with IMAP server.\n> -\tCurrent supported method is 'CRAM-MD5' only.\n> +\tCurrent supported method is 'CRAM-MD5' only. If this is not set\n> +\tthen 'git imap-send' uses the basic IMAP plaintext LOGIN command.\n>\n>  Examples\n>  ~~~~~~~~\n\nBoth patches make sense to me, but can you please sign-off your\npatches?  See Documentation/SubmittingPatches for details.\n\nThanks.\n"},{"id":"247013","messageId":"alpine.LSU.2.00.1407310910230.10413@hermes-1.csi.cam.ac.uk","threadId":"37229","inReplyTo":"xmqqzjfqy7br.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] imap-send: clarify CRAM-MD5 vs LOGIN documentation","fromName":"Tony Finch","fromEmail":"dot@dotat.at","sentAt":"2014-07-31T08:11:12Z","receivedAt":"2014-07-31T08:11:12Z","isPatch":true,"sender":{"key":"dot@dotat.at","avatar":"https://avatars.githubusercontent.com/u/68429?v=4"},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Both patches make sense to me, but can you please sign-off your\n> patches?\n\nOops, sorry about that. Re-roll on its way...\n\nTony.\n-- \nf.anthony.n.finch  <dot@dotat.at>  http://dotat.at/\nThames, Dover: Southwest 4 or 5, increasing 6 at times. Slight or moderate.\nFair. Good.\n"},{"id":"247014","messageId":"alpine.LSU.2.00.1407310914260.13901@hermes-1.csi.cam.ac.uk","threadId":"37229","inReplyTo":"alpine.LSU.2.00.1407310910230.10413@hermes-1.csi.cam.ac.uk","subject":"[PATCH 1/2] imap-send: clarify CRAM-MD5 vs LOGIN documentation","fromName":"Tony Finch","fromEmail":"dot@dotat.at","sentAt":"2014-07-31T08:14:30Z","receivedAt":"2014-07-31T08:14:30Z","isPatch":true,"sender":{"key":"dot@dotat.at","avatar":"https://avatars.githubusercontent.com/u/68429?v=4"},"body":"Explicitly mention that leaving imap.authMethod unset makes\ngit imap-send use the basic IMAP plaintext LOGIN command.\n\nSigned-off-by: Tony Finch <dot@dotat.at>\n---\n Documentation/git-imap-send.txt | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt\nindex 875d283..770cbe8 100644\n--- a/Documentation/git-imap-send.txt\n+++ b/Documentation/git-imap-send.txt\n@@ -76,7 +76,8 @@ imap.preformattedHTML::\n\n imap.authMethod::\n \tSpecify authenticate method for authentication with IMAP server.\n-\tCurrent supported method is 'CRAM-MD5' only.\n+\tCurrent supported method is 'CRAM-MD5' only. If this is not set\n+\tthen 'git imap-send' uses the basic IMAP plaintext LOGIN command.\n\n Examples\n ~~~~~~~~\n-- \n2.1.0.rc0.229.gaee38de\n"},{"id":"247015","messageId":"alpine.LSU.2.00.1407310914320.13901@hermes-1.csi.cam.ac.uk","threadId":"37229","inReplyTo":"alpine.LSU.2.00.1407310910230.10413@hermes-1.csi.cam.ac.uk","subject":"[PATCH 2/2] imap-send: create target mailbox if it is missing","fromName":"Tony Finch","fromEmail":"dot@dotat.at","sentAt":"2014-07-31T08:14:34Z","receivedAt":"2014-07-31T08:14:34Z","isPatch":true,"sender":{"key":"dot@dotat.at","avatar":"https://avatars.githubusercontent.com/u/68429?v=4"},"body":"Some MUAs delete their \"drafts\" folder when it is empty, so\ngit imap-send should be able to create it if necessary.\n\nThis change checks that the folder exists immediately after\nlogin and tries to create it if it is missing.\n\nThere was some vestigial code to handle a [TRYCREATE] response\nfrom the server when an APPEND target is missing. However this\ncode never ran (the create and trycreate flags were never set)\nand when I tried to make it run I found that the code had already\nthrown away the contents of the message it was trying to append.\n\nSigned-off-by: Tony Finch <dot@dotat.at>\n---\n imap-send.c | 56 +++++++++++++++++++++++++-------------------------------\n 1 file changed, 25 insertions(+), 31 deletions(-)\n\ndiff --git a/imap-send.c b/imap-send.c\nindex 524fbab..5e4a24e 100644\n--- a/imap-send.c\n+++ b/imap-send.c\n@@ -128,7 +128,6 @@ struct imap_cmd_cb {\n \tchar *data;\n \tint dlen;\n \tint uid;\n-\tunsigned create:1, trycreate:1;\n };\n\n struct imap_cmd {\n@@ -714,8 +713,8 @@ static int parse_response_code(struct imap_store *ctx, struct imap_cmd_cb *cb,\n static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)\n {\n \tstruct imap *imap = ctx->imap;\n-\tstruct imap_cmd *cmdp, **pcmdp, *ncmdp;\n-\tchar *cmd, *arg, *arg1, *p;\n+\tstruct imap_cmd *cmdp, **pcmdp;\n+\tchar *cmd, *arg, *arg1;\n \tint n, resp, resp2, tag;\n\n \tfor (;;) {\n@@ -801,30 +800,9 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)\n \t\t\tif (!strcmp(\"OK\", arg))\n \t\t\t\tresp = DRV_OK;\n \t\t\telse {\n-\t\t\t\tif (!strcmp(\"NO\", arg)) {\n-\t\t\t\t\tif (cmdp->cb.create && cmd && (cmdp->cb.trycreate || !memcmp(cmd, \"[TRYCREATE]\", 11))) { /* SELECT, APPEND or UID COPY */\n-\t\t\t\t\t\tp = strchr(cmdp->cmd, '\"');\n-\t\t\t\t\t\tif (!issue_imap_cmd(ctx, NULL, \"CREATE \\\"%.*s\\\"\", (int)(strchr(p + 1, '\"') - p + 1), p)) {\n-\t\t\t\t\t\t\tresp = RESP_BAD;\n-\t\t\t\t\t\t\tgoto normal;\n-\t\t\t\t\t\t}\n-\t\t\t\t\t\t/* not waiting here violates the spec, but a server that does not\n-\t\t\t\t\t\t   grok this nonetheless violates it too. */\n-\t\t\t\t\t\tcmdp->cb.create = 0;\n-\t\t\t\t\t\tif (!(ncmdp = issue_imap_cmd(ctx, &cmdp->cb, \"%s\", cmdp->cmd))) {\n-\t\t\t\t\t\t\tresp = RESP_BAD;\n-\t\t\t\t\t\t\tgoto normal;\n-\t\t\t\t\t\t}\n-\t\t\t\t\t\tfree(cmdp->cmd);\n-\t\t\t\t\t\tfree(cmdp);\n-\t\t\t\t\t\tif (!tcmd)\n-\t\t\t\t\t\t\treturn 0;\t/* ignored */\n-\t\t\t\t\t\tif (cmdp == tcmd)\n-\t\t\t\t\t\t\ttcmd = ncmdp;\n-\t\t\t\t\t\tcontinue;\n-\t\t\t\t\t}\n+\t\t\t\tif (!strcmp(\"NO\", arg))\n \t\t\t\t\tresp = RESP_NO;\n-\t\t\t\t} else /*if (!strcmp(\"BAD\", arg))*/\n+\t\t\t\telse /*if (!strcmp(\"BAD\", arg))*/\n \t\t\t\t\tresp = RESP_BAD;\n \t\t\t\tfprintf(stderr, \"IMAP command '%s' returned response (%s) - %s\\n\",\n \t\t\t\t\t memcmp(cmdp->cmd, \"LOGIN\", 5) ?\n@@ -833,7 +811,6 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)\n \t\t\t}\n \t\t\tif ((resp2 = parse_response_code(ctx, &cmdp->cb, cmd)) > resp)\n \t\t\t\tresp = resp2;\n-\t\tnormal:\n \t\t\tif (cmdp->cb.done)\n \t\t\t\tcmdp->cb.done(ctx, cmdp, resp);\n \t\t\tfree(cmdp->cb.data);\n@@ -944,7 +921,7 @@ static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const cha\n \treturn 0;\n }\n\n-static struct imap_store *imap_open_store(struct imap_server_conf *srvc)\n+static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *folder)\n {\n \tstruct credential cred = CREDENTIAL_INIT;\n \tstruct imap_store *ctx;\n@@ -1156,6 +1133,25 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc)\n \t\tcredential_approve(&cred);\n \tcredential_clear(&cred);\n\n+\t/* check the target mailbox exists */\n+\tctx->name = folder;\n+\tswitch (imap_exec(ctx, NULL, \"EXAMINE \\\"%s\\\"\", ctx->name)) {\n+\tcase RESP_OK:\n+\t\t/* ok */\n+\t\tbreak;\n+\tcase RESP_BAD:\n+\t\tfprintf(stderr, \"IMAP error: could not check mailbox\\n\");\n+\t\tgoto bail;\n+\tcase RESP_NO:\n+\t\tif (imap_exec(ctx, NULL, \"CREATE \\\"%s\\\"\", ctx->name) == RESP_OK) {\n+\t\t\timap_info(\"Created missing mailbox\\n\");\n+\t\t} else {\n+\t\t\tfprintf(stderr, \"IMAP error: could not create missing mailbox\\n\");\n+\t\t\tgoto bail;\n+\t\t}\n+\t\tbreak;\n+\t}\n+\n \tctx->prefix = \"\";\n \treturn ctx;\n\n@@ -1219,7 +1215,6 @@ static int imap_store_msg(struct imap_store *ctx, struct strbuf *msg)\n\n \tbox = ctx->name;\n \tprefix = !strcmp(box, \"INBOX\") ? \"\" : ctx->prefix;\n-\tcb.create = 0;\n \tret = imap_exec_m(ctx, &cb, \"APPEND \\\"%s%s\\\" \", prefix, box);\n \timap->caps = imap->rcaps;\n \tif (ret != DRV_OK)\n@@ -1418,14 +1413,13 @@ int main(int argc, char **argv)\n \t}\n\n \t/* write it to the imap server */\n-\tctx = imap_open_store(&server);\n+\tctx = imap_open_store(&server, imap_folder);\n \tif (!ctx) {\n \t\tfprintf(stderr, \"failed to open store\\n\");\n \t\treturn 1;\n \t}\n\n \tfprintf(stderr, \"sending %d message%s\\n\", total, (total != 1) ? \"s\" : \"\");\n-\tctx->name = imap_folder;\n \twhile (1) {\n \t\tunsigned percent = n * 100 / total;\n\n-- \n2.1.0.rc0.229.gaee38de\n"},{"id":"247073","messageId":"xmqqy4v9we3k.fsf@gitster.dls.corp.google.com","threadId":"37229","inReplyTo":"alpine.LSU.2.00.1407310914320.13901@hermes-1.csi.cam.ac.uk","subject":"Re: [PATCH 2/2] imap-send: create target mailbox if it is missing","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-07-31T18:57:35Z","receivedAt":"2014-07-31T18:57:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tony Finch <dot@dotat.at> writes:\n\n> Some MUAs delete their \"drafts\" folder when it is empty, so\n> git imap-send should be able to create it if necessary.\n>\n> This change checks that the folder exists immediately after\n> login and tries to create it if it is missing.\n>\n> There was some vestigial code to handle a [TRYCREATE] response\n> from the server when an APPEND target is missing. However this\n> code never ran (the create and trycreate flags were never set)\n> and when I tried to make it run I found that the code had already\n> thrown away the contents of the message it was trying to append.\n>\n> Signed-off-by: Tony Finch <dot@dotat.at>\n> ---\n\nThe basic idea looks good, but I have doubts on one point.\n\n> diff --git a/imap-send.c b/imap-send.c\n> index 524fbab..5e4a24e 100644\n> --- a/imap-send.c\n> +++ b/imap-send.c\n> @@ -1156,6 +1133,25 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc)\n>  \t\tcredential_approve(&cred);\n>  \tcredential_clear(&cred);\n>\n> +\t/* check the target mailbox exists */\n> +\tctx->name = folder;\n> +\tswitch (imap_exec(ctx, NULL, \"EXAMINE \\\"%s\\\"\", ctx->name)) {\n> +\tcase RESP_OK:\n> +\t\t/* ok */\n> +\t\tbreak;\n> +\tcase RESP_BAD:\n> +\t\tfprintf(stderr, \"IMAP error: could not check mailbox\\n\");\n> +\t\tgoto bail;\n> +\tcase RESP_NO:\n> +\t\tif (imap_exec(ctx, NULL, \"CREATE \\\"%s\\\"\", ctx->name) == RESP_OK) {\n> +\t\t\timap_info(\"Created missing mailbox\\n\");\n> +\t\t} else {\n> +\t\t\tfprintf(stderr, \"IMAP error: could not create missing mailbox\\n\");\n> +\t\t\tgoto bail;\n> +\t\t}\n> +\t\tbreak;\n> +\t}\n\nAt any and all the existing places that \"goto bail\" in the function,\nwe know we failed to authenticate.  I think they are all sensible\nplaces to call credential_reject().\n\nOn the other hand, at this point before you try to \"check the target\nmailbox exists\", we have authenticated sucessfully, we know the\ncredential used was good, and called credential_approve() to mark it\nas such.  I do agree that you would want to signal an error to the\ncaller upon these two failures, but I do not think you want to \"goto\nbail\" and reject the credential.  The error you observed in the new\ncodepath is caused by something else, not authentication failure,\nand in such a case you do not want to cause the credential helper to\nevict the user/pass pair from the keyring, no?\n\nThanks.\n"},{"id":"247074","messageId":"alpine.LSU.2.00.1407312034410.25674@hermes-1.csi.cam.ac.uk","threadId":"37229","inReplyTo":"xmqqy4v9we3k.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 2/2] imap-send: create target mailbox if it is missing","fromName":"Tony Finch","fromEmail":"dot@dotat.at","sentAt":"2014-07-31T19:35:31Z","receivedAt":"2014-07-31T19:35:31Z","isPatch":true,"sender":{"key":"dot@dotat.at","avatar":"https://avatars.githubusercontent.com/u/68429?v=4"},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n>\n> The basic idea looks good, but I have doubts on one point.\n\nThanks for spotting the mistake in the error handling. I'll send an update\nwith a fix.\n\nTony.\n-- \nf.anthony.n.finch  <dot@dotat.at>  http://dotat.at/\nSouth Utsire: Southwesterly 4 or 5, occasionally 6 at first in south, backing\nsoutheasterly later. Moderate. Thundery showers. Good.\n"},{"id":"247095","messageId":"alpine.LSU.2.00.1408010915470.23775@hermes-1.csi.cam.ac.uk","threadId":"37229","inReplyTo":"alpine.LSU.2.00.1407312034410.25674@hermes-1.csi.cam.ac.uk","subject":"[PATCH v3 1/2] imap-send: clarify CRAM-MD5 vs LOGIN documentation","fromName":"Tony Finch","fromEmail":"dot@dotat.at","sentAt":"2014-08-01T08:15:48Z","receivedAt":"2014-08-01T08:15:48Z","isPatch":true,"sender":{"key":"dot@dotat.at","avatar":"https://avatars.githubusercontent.com/u/68429?v=4"},"body":"Explicitly mention that leaving imap.authMethod unset makes\ngit imap-send use the basic IMAP plaintext LOGIN command.\n\nSigned-off-by: Tony Finch <dot@dotat.at>\n---\n Documentation/git-imap-send.txt | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt\nindex 875d283..770cbe8 100644\n--- a/Documentation/git-imap-send.txt\n+++ b/Documentation/git-imap-send.txt\n@@ -76,7 +76,8 @@ imap.preformattedHTML::\n\n imap.authMethod::\n \tSpecify authenticate method for authentication with IMAP server.\n-\tCurrent supported method is 'CRAM-MD5' only.\n+\tCurrent supported method is 'CRAM-MD5' only. If this is not set\n+\tthen 'git imap-send' uses the basic IMAP plaintext LOGIN command.\n\n Examples\n ~~~~~~~~\n-- \n2.1.0.rc0.60.gb5b18e5\n"},{"id":"247096","messageId":"alpine.LSU.2.00.1408010915500.23775@hermes-1.csi.cam.ac.uk","threadId":"37229","inReplyTo":"alpine.LSU.2.00.1407312034410.25674@hermes-1.csi.cam.ac.uk","subject":"[PATCH v3 2/2] imap-send: create target mailbox if it is missing","fromName":"Tony Finch","fromEmail":"dot@dotat.at","sentAt":"2014-08-01T08:15:52Z","receivedAt":"2014-08-01T08:15:52Z","isPatch":true,"sender":{"key":"dot@dotat.at","avatar":"https://avatars.githubusercontent.com/u/68429?v=4"},"body":"Some MUAs delete their \"drafts\" folder when it is empty, so\ngit imap-send should be able to create it if necessary.\n\nThis change checks that the folder exists immediately after\nlogin and tries to create it if it is missing.\n\nThere was some vestigial code to handle a [TRYCREATE] response\nfrom the server when an APPEND target is missing. However this\ncode never ran (the create and trycreate flags were never set)\nand when I tried to make it run I found that the code had already\nthrown away the contents of the message it was trying to append.\n\nSigned-off-by: Tony Finch <dot@dotat.at>\n---\n imap-send.c | 57 ++++++++++++++++++++++++++-------------------------------\n 1 file changed, 26 insertions(+), 31 deletions(-)\n\ndiff --git a/imap-send.c b/imap-send.c\nindex 524fbab..a29d03e 100644\n--- a/imap-send.c\n+++ b/imap-send.c\n@@ -128,7 +128,6 @@ struct imap_cmd_cb {\n \tchar *data;\n \tint dlen;\n \tint uid;\n-\tunsigned create:1, trycreate:1;\n };\n\n struct imap_cmd {\n@@ -714,8 +713,8 @@ static int parse_response_code(struct imap_store *ctx, struct imap_cmd_cb *cb,\n static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)\n {\n \tstruct imap *imap = ctx->imap;\n-\tstruct imap_cmd *cmdp, **pcmdp, *ncmdp;\n-\tchar *cmd, *arg, *arg1, *p;\n+\tstruct imap_cmd *cmdp, **pcmdp;\n+\tchar *cmd, *arg, *arg1;\n \tint n, resp, resp2, tag;\n\n \tfor (;;) {\n@@ -801,30 +800,9 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)\n \t\t\tif (!strcmp(\"OK\", arg))\n \t\t\t\tresp = DRV_OK;\n \t\t\telse {\n-\t\t\t\tif (!strcmp(\"NO\", arg)) {\n-\t\t\t\t\tif (cmdp->cb.create && cmd && (cmdp->cb.trycreate || !memcmp(cmd, \"[TRYCREATE]\", 11))) { /* SELECT, APPEND or UID COPY */\n-\t\t\t\t\t\tp = strchr(cmdp->cmd, '\"');\n-\t\t\t\t\t\tif (!issue_imap_cmd(ctx, NULL, \"CREATE \\\"%.*s\\\"\", (int)(strchr(p + 1, '\"') - p + 1), p)) {\n-\t\t\t\t\t\t\tresp = RESP_BAD;\n-\t\t\t\t\t\t\tgoto normal;\n-\t\t\t\t\t\t}\n-\t\t\t\t\t\t/* not waiting here violates the spec, but a server that does not\n-\t\t\t\t\t\t   grok this nonetheless violates it too. */\n-\t\t\t\t\t\tcmdp->cb.create = 0;\n-\t\t\t\t\t\tif (!(ncmdp = issue_imap_cmd(ctx, &cmdp->cb, \"%s\", cmdp->cmd))) {\n-\t\t\t\t\t\t\tresp = RESP_BAD;\n-\t\t\t\t\t\t\tgoto normal;\n-\t\t\t\t\t\t}\n-\t\t\t\t\t\tfree(cmdp->cmd);\n-\t\t\t\t\t\tfree(cmdp);\n-\t\t\t\t\t\tif (!tcmd)\n-\t\t\t\t\t\t\treturn 0;\t/* ignored */\n-\t\t\t\t\t\tif (cmdp == tcmd)\n-\t\t\t\t\t\t\ttcmd = ncmdp;\n-\t\t\t\t\t\tcontinue;\n-\t\t\t\t\t}\n+\t\t\t\tif (!strcmp(\"NO\", arg))\n \t\t\t\t\tresp = RESP_NO;\n-\t\t\t\t} else /*if (!strcmp(\"BAD\", arg))*/\n+\t\t\t\telse /*if (!strcmp(\"BAD\", arg))*/\n \t\t\t\t\tresp = RESP_BAD;\n \t\t\t\tfprintf(stderr, \"IMAP command '%s' returned response (%s) - %s\\n\",\n \t\t\t\t\t memcmp(cmdp->cmd, \"LOGIN\", 5) ?\n@@ -833,7 +811,6 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)\n \t\t\t}\n \t\t\tif ((resp2 = parse_response_code(ctx, &cmdp->cb, cmd)) > resp)\n \t\t\t\tresp = resp2;\n-\t\tnormal:\n \t\t\tif (cmdp->cb.done)\n \t\t\t\tcmdp->cb.done(ctx, cmdp, resp);\n \t\t\tfree(cmdp->cb.data);\n@@ -944,7 +921,7 @@ static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const cha\n \treturn 0;\n }\n\n-static struct imap_store *imap_open_store(struct imap_server_conf *srvc)\n+static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *folder)\n {\n \tstruct credential cred = CREDENTIAL_INIT;\n \tstruct imap_store *ctx;\n@@ -1156,6 +1133,25 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc)\n \t\tcredential_approve(&cred);\n \tcredential_clear(&cred);\n\n+\t/* check the target mailbox exists */\n+\tctx->name = folder;\n+\tswitch (imap_exec(ctx, NULL, \"EXAMINE \\\"%s\\\"\", ctx->name)) {\n+\tcase RESP_OK:\n+\t\t/* ok */\n+\t\tbreak;\n+\tcase RESP_BAD:\n+\t\tfprintf(stderr, \"IMAP error: could not check mailbox\\n\");\n+\t\tgoto out;\n+\tcase RESP_NO:\n+\t\tif (imap_exec(ctx, NULL, \"CREATE \\\"%s\\\"\", ctx->name) == RESP_OK) {\n+\t\t\timap_info(\"Created missing mailbox\\n\");\n+\t\t} else {\n+\t\t\tfprintf(stderr, \"IMAP error: could not create missing mailbox\\n\");\n+\t\t\tgoto out;\n+\t\t}\n+\t\tbreak;\n+\t}\n+\n \tctx->prefix = \"\";\n \treturn ctx;\n\n@@ -1164,6 +1160,7 @@ bail:\n \t\tcredential_reject(&cred);\n \tcredential_clear(&cred);\n\n+ out:\n \timap_close_store(ctx);\n \treturn NULL;\n }\n@@ -1219,7 +1216,6 @@ static int imap_store_msg(struct imap_store *ctx, struct strbuf *msg)\n\n \tbox = ctx->name;\n \tprefix = !strcmp(box, \"INBOX\") ? \"\" : ctx->prefix;\n-\tcb.create = 0;\n \tret = imap_exec_m(ctx, &cb, \"APPEND \\\"%s%s\\\" \", prefix, box);\n \timap->caps = imap->rcaps;\n \tif (ret != DRV_OK)\n@@ -1418,14 +1414,13 @@ int main(int argc, char **argv)\n \t}\n\n \t/* write it to the imap server */\n-\tctx = imap_open_store(&server);\n+\tctx = imap_open_store(&server, imap_folder);\n \tif (!ctx) {\n \t\tfprintf(stderr, \"failed to open store\\n\");\n \t\treturn 1;\n \t}\n\n \tfprintf(stderr, \"sending %d message%s\\n\", total, (total != 1) ? \"s\" : \"\");\n-\tctx->name = imap_folder;\n \twhile (1) {\n \t\tunsigned percent = n * 100 / total;\n\n-- \n2.1.0.rc0.60.gb5b18e5\n"},{"id":"247150","messageId":"xmqqppgju9kj.fsf@gitster.dls.corp.google.com","threadId":"37229","inReplyTo":"alpine.LSU.2.00.1408010915500.23775@hermes-1.csi.cam.ac.uk","subject":"Re: [PATCH v3 2/2] imap-send: create target mailbox if it is missing","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-08-01T22:30:36Z","receivedAt":"2014-08-01T22:30:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tony Finch <dot@dotat.at> writes:\n\n> Some MUAs delete their \"drafts\" folder when it is empty, so\n> git imap-send should be able to create it if necessary.\n\nThanks for an update; queued.\n"},{"id":"247170","messageId":"53DCEB4A.1030009@ramsay1.demon.co.uk","threadId":"37229","inReplyTo":"xmqqppgju9kj.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v3 2/2] imap-send: create target mailbox if it is missing","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsay1.demon.co.uk","sentAt":"2014-08-02T13:44:42Z","receivedAt":"2014-08-02T13:44:42Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"On 01/08/14 23:30, Junio C Hamano wrote:\n> Tony Finch <dot@dotat.at> writes:\n> \n>> Some MUAs delete their \"drafts\" folder when it is empty, so\n>> git imap-send should be able to create it if necessary.\n> \n> Thanks for an update; queued.\n\nBTW, this provokes a warning from gcc (v4.8.2) for me:\n\n        CC imap-send.o\n    imap-send.c:561:25: warning: ‘issue_imap_cmd’ defined but not used [-Wunused-function]\n     static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,\n                             ^\nIt seems the change to get_cmd_result(), in commit 7ebac713, removes\nthe only remaining (two) calls to issue_imap_cmd().\n\nHTH\n\nATB,\nRamsay Jones\n"},{"id":"247190","messageId":"CAPc5daWPiCj7Uap4J+AOfebYYVewhnQX-pbT=ByuzOE-K2tA_A@mail.gmail.com","threadId":"37229","inReplyTo":"53DCEB4A.1030009@ramsay1.demon.co.uk","subject":"Re: [PATCH v3 2/2] imap-send: create target mailbox if it is missing","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-08-03T06:38:08Z","receivedAt":"2014-08-03T06:38:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Yup. I think I also queued a fix-up on top.\nThanks for reporting.\n\nOn Sat, Aug 2, 2014 at 6:44 AM, Ramsay Jones <ramsay@ramsay1.demon.co.uk> wrote:\n> On 01/08/14 23:30, Junio C Hamano wrote:\n>> Tony Finch <dot@dotat.at> writes:\n>>\n>>> Some MUAs delete their \"drafts\" folder when it is empty, so\n>>> git imap-send should be able to create it if necessary.\n>>\n>> Thanks for an update; queued.\n>\n> BTW, this provokes a warning from gcc (v4.8.2) for me:\n>\n>         CC imap-send.o\n>     imap-send.c:561:25: warning: ‘issue_imap_cmd’ defined but not used [-Wunused-function]\n>      static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,\n>                              ^\n> It seems the change to get_cmd_result(), in commit 7ebac713, removes\n> the only remaining (two) calls to issue_imap_cmd().\n>\n> HTH\n>\n> ATB,\n> Ramsay Jones\n>\n>\n>\n"}]}