{"thread":{"id":"66248","subject":"[PATCH] imap-send: add --draft to set IMAP \\Draft flag","startedAt":"2026-09-02T00:14:38Z","lastAt":"2026-09-03T14:37:41Z","messageCount":7,"participants":["Wolfgang Faust","Junio C Hamano","Aditya Garg"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"551715","messageId":"761c3f1b-e280-48b1-a2ad-770b68be3434@slotpi01m90","threadId":"66248","inReplyTo":null,"subject":"[PATCH] imap-send: add --draft to set IMAP \\Draft flag","fromName":"Wolfgang Faust","fromEmail":"contrib-git@wolfgangfaust.com","sentAt":"2026-09-02T00:13:21Z","receivedAt":"2026-09-02T00:14:38Z","isPatch":true,"body":"The documented purpose of imap-send is to upload draft emails for sending\nlater, but it did not have any way to mark the messages as \\Draft, so some\nemail clients presented the result as an un-editable, un-sendable email\neven if it happened to be in a \"Drafts\" folder.\n\nSigned-off-by: Wolfgang Faust <contrib-git@wolfgangfaust.com>\n---\n Documentation/git-imap-send.adoc |  9 ++++++++-\n git-curl-compat.h                |  8 ++++++++\n imap-send.c                      | 15 +++++++++++++--\n 3 files changed, 29 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-imap-send.adoc b/Documentation/git-imap-send.adoc\nindex 1814d94491..cf415df45a 100644\n--- a/Documentation/git-imap-send.adoc\n+++ b/Documentation/git-imap-send.adoc\n@@ -9,7 +9,7 @@ git-imap-send - Send a collection of patches from stdin to an IMAP folder\n SYNOPSIS\n --------\n [synopsis]\n-git imap-send [-v] [-q] [--[no-]curl] [(--folder|-f) <folder>]\n+git imap-send [-v] [-q] [--[no-]curl] [--[no-]draft] [(--folder|-f) <folder>]\n git imap-send --list\n \n \n@@ -55,6 +55,13 @@ OPTIONS\n \tusing libcurl.  Ignored if Git was built with the NO_OPENSSL option\n \tset.\n \n+`--draft`::\n+`--no-draft`::\n+\tMark uploaded messages with the IMAP `\\Draft` flag. The default is `--no-draft`.\n++\n+With libcurl, `--draft` requires version 8.13.0 or later.\n+Older libcurl still uploads the message but cannot set the flag.\n+\n `--list`::\n \tRun the IMAP LIST command to output a list of all the folders present.\n \ndiff --git a/git-curl-compat.h b/git-curl-compat.h\nindex dccdd4d6e5..032aaf7126 100644\n--- a/git-curl-compat.h\n+++ b/git-curl-compat.h\n@@ -67,4 +67,12 @@\n #define GIT_CURL_HAVE_CURLOPT_TCP_KEEPCNT\n #endif\n \n+/**\n+ * CURLOPT_UPLOAD_FLAGS and CURLULFLAG_* were added in 8.13.0,\n+ * released in April 2025.\n+ */\n+#if LIBCURL_VERSION_NUM >= 0x080D00\n+#define GIT_CURL_HAVE_CURLOPT_UPLOAD_FLAGS\n+#endif\n+\n #endif\ndiff --git a/imap-send.c b/imap-send.c\nindex 0d16d02029..bf1d2cf74d 100644\n--- a/imap-send.c\n+++ b/imap-send.c\n@@ -35,6 +35,7 @@\n #include \"setup.h\"\n #include \"strbuf.h\"\n #ifdef USE_CURL_FOR_IMAP_SEND\n+#include \"git-curl-compat.h\"\n #include \"http.h\"\n #endif\n \n@@ -49,10 +50,11 @@\n static int verbosity;\n static int list_folders;\n static int use_curl = USE_CURL_DEFAULT;\n+static int opt_draft;\n static char *opt_folder;\n \n static char const * const imap_send_usage[] = {\n-\tN_(\"git imap-send [-v] [-q] [--[no-]curl] [(--folder|-f) <folder>] < <mbox>\"),\n+\tN_(\"git imap-send [-v] [-q] [--[no-]curl] [--[no-]draft] [(--folder|-f) <folder>] < <mbox>\"),\n \t\"git imap-send --list\",\n \tNULL\n };\n@@ -60,6 +62,7 @@ static char const * const imap_send_usage[] = {\n static struct option imap_send_options[] = {\n \tOPT__VERBOSITY(&verbosity),\n \tOPT_BOOL(0, \"curl\", &use_curl, \"use libcurl to communicate with the IMAP server\"),\n+\tOPT_BOOL(0, \"draft\", &opt_draft, \"mark uploaded messages with the IMAP \\\\Draft flag\"),\n \tOPT_STRING('f', \"folder\", &opt_folder, \"folder\", \"specify the IMAP folder\"),\n \tOPT_BOOL(0, \"list\", &list_folders, \"list all folders on the IMAP server\"),\n \tOPT_END()\n@@ -1416,7 +1419,8 @@ 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-\tret = imap_exec_m(ctx, &cb, \"APPEND \\\"%s%s\\\" \", prefix, box);\n+\tret = imap_exec_m(ctx, &cb, \"APPEND \\\"%s%s\\\" %s\", prefix, box,\n+\t\t\t  opt_draft ? \"(\\\\Draft) \" : \"\");\n \timap->caps = imap->rcaps;\n \tif (ret != DRV_OK)\n \t\treturn ret;\n@@ -1718,6 +1722,13 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server,\n \n \tcurl_easy_setopt(curl, CURLOPT_READDATA, &msgbuf);\n \n+\tif (opt_draft) {\n+#ifdef GIT_CURL_HAVE_CURLOPT_UPLOAD_FLAGS\n+\t\tcurl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, CURLULFLAG_DRAFT);\n+#else\n+\t\twarning(\"--draft requires libcurl 8.13.0 or later\");\n+#endif\n+\t}\n \tfprintf(stderr, \"Sending %d message%s to %s folder...\\n\",\n \t\ttotal, (total != 1) ? \"s\" : \"\", server->folder);\n \twhile (1) {\n-- \n2.52.0\n\n"},{"id":"551718","messageId":"xmqq8q5kl4gq.fsf@gitster.g","threadId":"66248","inReplyTo":"761c3f1b-e280-48b1-a2ad-770b68be3434@slotpi01m90","subject":"Re: [PATCH] imap-send: add --draft to set IMAP \\Draft flag","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-09-02T03:25:25Z","receivedAt":"2026-09-02T03:25:29Z","isPatch":true,"body":"\"Wolfgang Faust\" <contrib-git@wolfgangfaust.com> writes:\n\n> The documented purpose of imap-send is to upload draft emails for sending\n> later, but it did not have any way to mark the messages as \\Draft, so some\n> email clients presented the result as an un-editable, un-sendable email\n> even if it happened to be in a \"Drafts\" folder.\n\nI agree that defaulting to '--no-draft' is a sensible design choice\nto avoid breaking clients that have been working fine.\n\nIt would be helpful to know if e-mail clients that send messages\nfrom the Drafts folder without the '\\Draft' flag would misbehave if\nthey encounter messages marked as such.  Knowing this would help us\ndecide whether to flip the default to '--draft', while keeping\n'--no-draft' as an escape hatch nobody is expected to use.\n\n> +`--draft`::\n> +`--no-draft`::\n> +\tMark uploaded messages with the IMAP `\\Draft` flag. The default is `--no-draft`.\n> ++\n> +With libcurl, `--draft` requires version 8.13.0 or later.\n> +Older libcurl still uploads the message but cannot set the flag.\n\nWhen compiled with older libcurl, would the command error out when\nrun with '--draft', or would it silently ignore the option?  I have\na mild preference for the former over the latter.  Issuing a warning\nwithout erroring out is better than nothing, but people tend to\noverlook warning messages.\n\nAlso you might want to consider adding a configuration variable,\nperhaps?  I dunno.\n\nThanks.\n"},{"id":"551719","messageId":"31d24dc3-3ef6-41cb-acbd-4cb4fb0d2338@app.fastmail.com","threadId":"66248","inReplyTo":"xmqq8q5kl4gq.fsf@gitster.g","subject":"Re: [PATCH] imap-send: add --draft to set IMAP \\Draft flag","fromName":"Wolfgang Faust","fromEmail":"contrib-git@wolfgangfaust.com","sentAt":"2026-09-02T04:28:55Z","receivedAt":"2026-09-02T04:29:25Z","isPatch":true,"body":"On Tue, Sep 1, 2026, at 8:25 PM, Junio C Hamano wrote:\n> \"Wolfgang Faust\" <contrib-git@wolfgangfaust.com> writes:\n>\n>> The documented purpose of imap-send is to upload draft emails for sending\n>> later, but it did not have any way to mark the messages as \\Draft, so some\n>> email clients presented the result as an un-editable, un-sendable email\n>> even if it happened to be in a \"Drafts\" folder.\n>\n> I agree that defaulting to '--no-draft' is a sensible design choice\n> to avoid breaking clients that have been working fine.\n\nDefinite agree; I elaborate further below.\n\n> It would be helpful to know if e-mail clients that send messages\n> from the Drafts folder without the '\\Draft' flag would misbehave if\n> they encounter messages marked as such.\n\nNot sure how to find this out without doing a complete survey of every\npossible email client, but I think it's unlikely to be a major issue:\nany such client would already be incompatible with other standards-\ncompliant clients using the same IMAP account. However:\n\n> Knowing this would help us\n> decide whether to flip the default to '--draft', while keeping\n> '--no-draft' as an escape hatch nobody is expected to use.\n\nI think the default should probably be --no-draft anyway.\n\nFirst, imap-send is also used for cases like `git send-email\n--imap-sent-folder`, which would need to be taught *not* to mark the\nemail as a draft, as in this case it has already been sent and should\nnot be editable. We can change `send-email` to set that flag but this\ndoes not help any external tooling that might be relying on this\nbehavior.\n \nSecond, as `--draft` requires a relatively recent version of curl, or a\n(non-default) `--no-curl` flag, trying to turn it on would cause most\ncurrent systems to continue *not* updating the flag, so in practice\nthe behavior would change depending on the user's system libraries,\nwhich seems very unusual. (Or, if we changed the curl version check\nfrom warning to error, the command would default to being broken unless\nyou pass `--no-draft`.)\n\n\n>> +`--draft`::\n>> +`--no-draft`::\n>> +\tMark uploaded messages with the IMAP `\\Draft` flag. The default is `--no-draft`.\n>> ++\n>> +With libcurl, `--draft` requires version 8.13.0 or later.\n>> +Older libcurl still uploads the message but cannot set the flag.\n>\n> When compiled with older libcurl, would the command error out when\n> run with '--draft', or would it silently ignore the option?  I have\n> a mild preference for the former over the latter.  Issuing a warning\n> without erroring out is better than nothing, but people tend to\n> overlook warning messages.\n\nRight now it issues a warning. I don't think I had any particular\nreason for that decision and changing to an error seems fine.\n\n\n> Also you might want to consider adding a configuration variable,\n> perhaps?  I dunno.\n\nI assume you mean something like `git config imap.draft true`? This has\nall the same problems as changing the default (in particular the\n`--imap-sent-folder` case), though I guess at least it would be opt-in.\n\nI also read in some past thread (I forget which) that we generally want\nto start by adding a flag, and only introduce a configuration if there\nis demand for it after the flag has proven itself.\n\n> Thanks.\n"},{"id":"551771","messageId":"xmqqtso7k9cn.fsf@gitster.g","threadId":"66248","inReplyTo":"31d24dc3-3ef6-41cb-acbd-4cb4fb0d2338@app.fastmail.com","subject":"Re: [PATCH] imap-send: add --draft to set IMAP \\Draft flag","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-09-02T14:37:28Z","receivedAt":"2026-09-02T14:37:31Z","isPatch":true,"body":"\"Wolfgang Faust\" <contrib-git@wolfgangfaust.com> writes:\n\n> I also read in some past thread (I forget which) that we generally want\n> to start by adding a flag, and only introduce a configuration if there\n> is demand for it after the flag has proven itself.\n\nThat indeed is a strong personal prefference of mine.  Sadly, nobody\nseems to have followed it in their topics---you are the first ;-).\n\n"},{"id":"551830","messageId":"MAUPR01MB1154649CE9D154B98459B09CEB8B62@MAUPR01MB11546.INDPRD01.PROD.OUTLOOK.COM","threadId":"66248","inReplyTo":"761c3f1b-e280-48b1-a2ad-770b68be3434@slotpi01m90","subject":"Re: [PATCH] imap-send: add --draft to set IMAP \\Draft flag","fromName":"Aditya Garg","fromEmail":"gargaditya08@live.com","sentAt":"2026-09-03T05:42:50Z","receivedAt":"2026-09-03T05:43:05Z","isPatch":true,"body":"I'm not sure if its acceptable to use newer versions of curl.\n\nThis patch was rejected because of this reason: https://lore.kernel.org/git/7108764f437a25079c95a25c227eb79f9f4aee6a.1753273554.git.gargaditya08@live.com/\n\nOn 02/09/26 5:43 am, Wolfgang Faust wrote:\n> The documented purpose of imap-send is to upload draft emails for sending\n> later, but it did not have any way to mark the messages as \\Draft, so some\n> email clients presented the result as an un-editable, un-sendable email\n> even if it happened to be in a \"Drafts\" folder.\n> \n> Signed-off-by: Wolfgang Faust <contrib-git@wolfgangfaust.com>\n> ---\n>  Documentation/git-imap-send.adoc |  9 ++++++++-\n>  git-curl-compat.h                |  8 ++++++++\n>  imap-send.c                      | 15 +++++++++++++--\n>  3 files changed, 29 insertions(+), 3 deletions(-)\n> \n> diff --git a/Documentation/git-imap-send.adoc b/Documentation/git-imap-send.adoc\n> index 1814d94491..cf415df45a 100644\n> --- a/Documentation/git-imap-send.adoc\n> +++ b/Documentation/git-imap-send.adoc\n> @@ -9,7 +9,7 @@ git-imap-send - Send a collection of patches from stdin to an IMAP folder\n>  SYNOPSIS\n>  --------\n>  [synopsis]\n> -git imap-send [-v] [-q] [--[no-]curl] [(--folder|-f) <folder>]\n> +git imap-send [-v] [-q] [--[no-]curl] [--[no-]draft] [(--folder|-f) <folder>]\n>  git imap-send --list\n>  \n>  \n> @@ -55,6 +55,13 @@ OPTIONS\n>  \tusing libcurl.  Ignored if Git was built with the NO_OPENSSL option\n>  \tset.\n>  \n> +`--draft`::\n> +`--no-draft`::\n> +\tMark uploaded messages with the IMAP `\\Draft` flag. The default is `--no-draft`.\n> ++\n> +With libcurl, `--draft` requires version 8.13.0 or later.\n> +Older libcurl still uploads the message but cannot set the flag.\n> +\n>  `--list`::\n>  \tRun the IMAP LIST command to output a list of all the folders present.\n>  \n> diff --git a/git-curl-compat.h b/git-curl-compat.h\n> index dccdd4d6e5..032aaf7126 100644\n> --- a/git-curl-compat.h\n> +++ b/git-curl-compat.h\n> @@ -67,4 +67,12 @@\n>  #define GIT_CURL_HAVE_CURLOPT_TCP_KEEPCNT\n>  #endif\n>  \n> +/**\n> + * CURLOPT_UPLOAD_FLAGS and CURLULFLAG_* were added in 8.13.0,\n> + * released in April 2025.\n> + */\n> +#if LIBCURL_VERSION_NUM >= 0x080D00\n> +#define GIT_CURL_HAVE_CURLOPT_UPLOAD_FLAGS\n> +#endif\n> +\n>  #endif\n> diff --git a/imap-send.c b/imap-send.c\n> index 0d16d02029..bf1d2cf74d 100644\n> --- a/imap-send.c\n> +++ b/imap-send.c\n> @@ -35,6 +35,7 @@\n>  #include \"setup.h\"\n>  #include \"strbuf.h\"\n>  #ifdef USE_CURL_FOR_IMAP_SEND\n> +#include \"git-curl-compat.h\"\n>  #include \"http.h\"\n>  #endif\n>  \n> @@ -49,10 +50,11 @@\n>  static int verbosity;\n>  static int list_folders;\n>  static int use_curl = USE_CURL_DEFAULT;\n> +static int opt_draft;\n>  static char *opt_folder;\n>  \n>  static char const * const imap_send_usage[] = {\n> -\tN_(\"git imap-send [-v] [-q] [--[no-]curl] [(--folder|-f) <folder>] < <mbox>\"),\n> +\tN_(\"git imap-send [-v] [-q] [--[no-]curl] [--[no-]draft] [(--folder|-f) <folder>] < <mbox>\"),\n>  \t\"git imap-send --list\",\n>  \tNULL\n>  };\n> @@ -60,6 +62,7 @@ static char const * const imap_send_usage[] = {\n>  static struct option imap_send_options[] = {\n>  \tOPT__VERBOSITY(&verbosity),\n>  \tOPT_BOOL(0, \"curl\", &use_curl, \"use libcurl to communicate with the IMAP server\"),\n> +\tOPT_BOOL(0, \"draft\", &opt_draft, \"mark uploaded messages with the IMAP \\\\Draft flag\"),\n>  \tOPT_STRING('f', \"folder\", &opt_folder, \"folder\", \"specify the IMAP folder\"),\n>  \tOPT_BOOL(0, \"list\", &list_folders, \"list all folders on the IMAP server\"),\n>  \tOPT_END()\n> @@ -1416,7 +1419,8 @@ 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> -\tret = imap_exec_m(ctx, &cb, \"APPEND \\\"%s%s\\\" \", prefix, box);\n> +\tret = imap_exec_m(ctx, &cb, \"APPEND \\\"%s%s\\\" %s\", prefix, box,\n> +\t\t\t  opt_draft ? \"(\\\\Draft) \" : \"\");\n>  \timap->caps = imap->rcaps;\n>  \tif (ret != DRV_OK)\n>  \t\treturn ret;\n> @@ -1718,6 +1722,13 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server,\n>  \n>  \tcurl_easy_setopt(curl, CURLOPT_READDATA, &msgbuf);\n>  \n> +\tif (opt_draft) {\n> +#ifdef GIT_CURL_HAVE_CURLOPT_UPLOAD_FLAGS\n> +\t\tcurl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, CURLULFLAG_DRAFT);\n> +#else\n> +\t\twarning(\"--draft requires libcurl 8.13.0 or later\");\n> +#endif\n> +\t}\n>  \tfprintf(stderr, \"Sending %d message%s to %s folder...\\n\",\n>  \t\ttotal, (total != 1) ? \"s\" : \"\", server->folder);\n>  \twhile (1) {\n\n"},{"id":"551865","messageId":"xmqqfqzqfo3a.fsf@gitster.g","threadId":"66248","inReplyTo":"MAUPR01MB1154649CE9D154B98459B09CEB8B62@MAUPR01MB11546.INDPRD01.PROD.OUTLOOK.COM","subject":"Re: [PATCH] imap-send: add --draft to set IMAP \\Draft flag","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-09-03T13:42:33Z","receivedAt":"2026-09-03T13:42:37Z","isPatch":true,"body":"Aditya Garg <gargaditya08@live.com> writes:\n\n> I'm not sure if its acceptable to use newer versions of curl.\n>\n> This patch was rejected because of this reason: https://lore.kernel.org/git/7108764f437a25079c95a25c227eb79f9f4aee6a.1753273554.git.gargaditya08@live.com/\n\nA huge difference is that the patch in the thread you pointed at did\nnot come any way to build with older versions.  The patch in this\nthread is different, isn't it?\n"},{"id":"551872","messageId":"MAUPR01MB11546486A8DD9C23224D52607B8B62@MAUPR01MB11546.INDPRD01.PROD.OUTLOOK.COM","threadId":"66248","inReplyTo":"xmqqfqzqfo3a.fsf@gitster.g","subject":"Re: [PATCH] imap-send: add --draft to set IMAP \\Draft flag","fromName":"Aditya Garg","fromEmail":"gargaditya08@live.com","sentAt":"2026-09-03T14:37:33Z","receivedAt":"2026-09-03T14:37:41Z","isPatch":true,"body":"So we can still consider that patch if I add version checks right?\n\n> On 3 Sep 2026, at 7:12 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> \n> ﻿Aditya Garg <gargaditya08@live.com> writes:\n> \n>> I'm not sure if its acceptable to use newer versions of curl.\n>> \n>> This patch was rejected because of this reason: https://lore.kernel.org/git/7108764f437a25079c95a25c227eb79f9f4aee6a.1753273554.git.gargaditya08@live.com/\n> \n> A huge difference is that the patch in the thread you pointed at did\n> not come any way to build with older versions.  The patch in this\n> thread is different, isn't it?\n"}]}