# [PATCH] imap-send: add --draft to set IMAP \Draft flag

7 messages from 2026-09-02 to 2026-09-03. Participants: Wolfgang Faust, Junio C Hamano, Aditya Garg.
Thread: https://gitlist.dev/t/66248

## Wolfgang Faust, 2026-09-02 00:13

Subject: [PATCH] imap-send: add --draft to set IMAP \Draft flag
Message-ID: <761c3f1b-e280-48b1-a2ad-770b68be3434@slotpi01m90>

```
The documented purpose of imap-send is to upload draft emails for sending
later, but it did not have any way to mark the messages as \Draft, so some
email clients presented the result as an un-editable, un-sendable email
even if it happened to be in a "Drafts" folder.

Signed-off-by: Wolfgang Faust <contrib-git@wolfgangfaust.com>
---
 Documentation/git-imap-send.adoc |  9 ++++++++-
 git-curl-compat.h                |  8 ++++++++
 imap-send.c                      | 15 +++++++++++++--
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-imap-send.adoc b/Documentation/git-imap-send.adoc
index 1814d94491..cf415df45a 100644
--- a/Documentation/git-imap-send.adoc
+++ b/Documentation/git-imap-send.adoc
@@ -9,7 +9,7 @@ git-imap-send - Send a collection of patches from stdin to an IMAP folder
 SYNOPSIS
 --------
 [synopsis]
-git imap-send [-v] [-q] [--[no-]curl] [(--folder|-f) <folder>]
+git imap-send [-v] [-q] [--[no-]curl] [--[no-]draft] [(--folder|-f) <folder>]
 git imap-send --list
 
 
@@ -55,6 +55,13 @@ OPTIONS
 	using libcurl.  Ignored if Git was built with the NO_OPENSSL option
 	set.
 
+`--draft`::
+`--no-draft`::
+	Mark uploaded messages with the IMAP `\Draft` flag. The default is `--no-draft`.
++
+With libcurl, `--draft` requires version 8.13.0 or later.
+Older libcurl still uploads the message but cannot set the flag.
+
 `--list`::
 	Run the IMAP LIST command to output a list of all the folders present.
 
diff --git a/git-curl-compat.h b/git-curl-compat.h
index dccdd4d6e5..032aaf7126 100644
--- a/git-curl-compat.h
+++ b/git-curl-compat.h
@@ -67,4 +67,12 @@
 #define GIT_CURL_HAVE_CURLOPT_TCP_KEEPCNT
 #endif
 
+/**
+ * CURLOPT_UPLOAD_FLAGS and CURLULFLAG_* were added in 8.13.0,
+ * released in April 2025.
+ */
+#if LIBCURL_VERSION_NUM >= 0x080D00
+#define GIT_CURL_HAVE_CURLOPT_UPLOAD_FLAGS
+#endif
+
 #endif
diff --git a/imap-send.c b/imap-send.c
index 0d16d02029..bf1d2cf74d 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -35,6 +35,7 @@
 #include "setup.h"
 #include "strbuf.h"
 #ifdef USE_CURL_FOR_IMAP_SEND
+#include "git-curl-compat.h"
 #include "http.h"
 #endif
 
@@ -49,10 +50,11 @@
 static int verbosity;
 static int list_folders;
 static int use_curl = USE_CURL_DEFAULT;
+static int opt_draft;
 static char *opt_folder;
 
 static char const * const imap_send_usage[] = {
-	N_("git imap-send [-v] [-q] [--[no-]curl] [(--folder|-f) <folder>] < <mbox>"),
+	N_("git imap-send [-v] [-q] [--[no-]curl] [--[no-]draft] [(--folder|-f) <folder>] < <mbox>"),
 	"git imap-send --list",
 	NULL
 };
@@ -60,6 +62,7 @@ static char const * const imap_send_usage[] = {
 static struct option imap_send_options[] = {
 	OPT__VERBOSITY(&verbosity),
 	OPT_BOOL(0, "curl", &use_curl, "use libcurl to communicate with the IMAP server"),
+	OPT_BOOL(0, "draft", &opt_draft, "mark uploaded messages with the IMAP \\Draft flag"),
 	OPT_STRING('f', "folder", &opt_folder, "folder", "specify the IMAP folder"),
 	OPT_BOOL(0, "list", &list_folders, "list all folders on the IMAP server"),
 	OPT_END()
@@ -1416,7 +1419,8 @@ static int imap_store_msg(struct imap_store *ctx, struct strbuf *msg)
 
 	box = ctx->name;
 	prefix = !strcmp(box, "INBOX") ? "" : ctx->prefix;
-	ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" ", prefix, box);
+	ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" %s", prefix, box,
+			  opt_draft ? "(\\Draft) " : "");
 	imap->caps = imap->rcaps;
 	if (ret != DRV_OK)
 		return ret;
@@ -1718,6 +1722,13 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server,
 
 	curl_easy_setopt(curl, CURLOPT_READDATA, &msgbuf);
 
+	if (opt_draft) {
+#ifdef GIT_CURL_HAVE_CURLOPT_UPLOAD_FLAGS
+		curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, CURLULFLAG_DRAFT);
+#else
+		warning("--draft requires libcurl 8.13.0 or later");
+#endif
+	}
 	fprintf(stderr, "Sending %d message%s to %s folder...\n",
 		total, (total != 1) ? "s" : "", server->folder);
 	while (1) {
-- 
2.52.0


```

## Junio C Hamano, 2026-09-02 03:25

Subject: Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
Message-ID: <xmqq8q5kl4gq.fsf@gitster.g>
In-Reply-To: <761c3f1b-e280-48b1-a2ad-770b68be3434@slotpi01m90>

```
"Wolfgang Faust" <contrib-git@wolfgangfaust.com> writes:

> The documented purpose of imap-send is to upload draft emails for sending
> later, but it did not have any way to mark the messages as \Draft, so some
> email clients presented the result as an un-editable, un-sendable email
> even if it happened to be in a "Drafts" folder.

I agree that defaulting to '--no-draft' is a sensible design choice
to avoid breaking clients that have been working fine.

It would be helpful to know if e-mail clients that send messages
from the Drafts folder without the '\Draft' flag would misbehave if
they encounter messages marked as such.  Knowing this would help us
decide whether to flip the default to '--draft', while keeping
'--no-draft' as an escape hatch nobody is expected to use.

> +`--draft`::
> +`--no-draft`::
> +	Mark uploaded messages with the IMAP `\Draft` flag. The default is `--no-draft`.
> ++
> +With libcurl, `--draft` requires version 8.13.0 or later.
> +Older libcurl still uploads the message but cannot set the flag.

When compiled with older libcurl, would the command error out when
run with '--draft', or would it silently ignore the option?  I have
a mild preference for the former over the latter.  Issuing a warning
without erroring out is better than nothing, but people tend to
overlook warning messages.

Also you might want to consider adding a configuration variable,
perhaps?  I dunno.

Thanks.

```

## Wolfgang Faust, 2026-09-02 04:28

Subject: Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
Message-ID: <31d24dc3-3ef6-41cb-acbd-4cb4fb0d2338@app.fastmail.com>
In-Reply-To: <xmqq8q5kl4gq.fsf@gitster.g>

```
On Tue, Sep 1, 2026, at 8:25 PM, Junio C Hamano wrote:
> "Wolfgang Faust" <contrib-git@wolfgangfaust.com> writes:
>
>> The documented purpose of imap-send is to upload draft emails for sending
>> later, but it did not have any way to mark the messages as \Draft, so some
>> email clients presented the result as an un-editable, un-sendable email
>> even if it happened to be in a "Drafts" folder.
>
> I agree that defaulting to '--no-draft' is a sensible design choice
> to avoid breaking clients that have been working fine.

Definite agree; I elaborate further below.

> It would be helpful to know if e-mail clients that send messages
> from the Drafts folder without the '\Draft' flag would misbehave if
> they encounter messages marked as such.

Not sure how to find this out without doing a complete survey of every
possible email client, but I think it's unlikely to be a major issue:
any such client would already be incompatible with other standards-
compliant clients using the same IMAP account. However:

> Knowing this would help us
> decide whether to flip the default to '--draft', while keeping
> '--no-draft' as an escape hatch nobody is expected to use.

I think the default should probably be --no-draft anyway.

First, imap-send is also used for cases like `git send-email
--imap-sent-folder`, which would need to be taught *not* to mark the
email as a draft, as in this case it has already been sent and should
not be editable. We can change `send-email` to set that flag but this
does not help any external tooling that might be relying on this
behavior.
 
Second, as `--draft` requires a relatively recent version of curl, or a
(non-default) `--no-curl` flag, trying to turn it on would cause most
current systems to continue *not* updating the flag, so in practice
the behavior would change depending on the user's system libraries,
which seems very unusual. (Or, if we changed the curl version check
from warning to error, the command would default to being broken unless
you pass `--no-draft`.)


>> +`--draft`::
>> +`--no-draft`::
>> +	Mark uploaded messages with the IMAP `\Draft` flag. The default is `--no-draft`.
>> ++
>> +With libcurl, `--draft` requires version 8.13.0 or later.
>> +Older libcurl still uploads the message but cannot set the flag.
>
> When compiled with older libcurl, would the command error out when
> run with '--draft', or would it silently ignore the option?  I have
> a mild preference for the former over the latter.  Issuing a warning
> without erroring out is better than nothing, but people tend to
> overlook warning messages.

Right now it issues a warning. I don't think I had any particular
reason for that decision and changing to an error seems fine.


> Also you might want to consider adding a configuration variable,
> perhaps?  I dunno.

I assume you mean something like `git config imap.draft true`? This has
all the same problems as changing the default (in particular the
`--imap-sent-folder` case), though I guess at least it would be opt-in.

I also read in some past thread (I forget which) that we generally want
to start by adding a flag, and only introduce a configuration if there
is demand for it after the flag has proven itself.

> Thanks.

```

## Junio C Hamano, 2026-09-02 14:37

Subject: Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
Message-ID: <xmqqtso7k9cn.fsf@gitster.g>
In-Reply-To: <31d24dc3-3ef6-41cb-acbd-4cb4fb0d2338@app.fastmail.com>

```
"Wolfgang Faust" <contrib-git@wolfgangfaust.com> writes:

> I also read in some past thread (I forget which) that we generally want
> to start by adding a flag, and only introduce a configuration if there
> is demand for it after the flag has proven itself.

That indeed is a strong personal prefference of mine.  Sadly, nobody
seems to have followed it in their topics---you are the first ;-).


```

## Aditya Garg, 2026-09-03 05:42

Subject: Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
Message-ID: <MAUPR01MB1154649CE9D154B98459B09CEB8B62@MAUPR01MB11546.INDPRD01.PROD.OUTLOOK.COM>
In-Reply-To: <761c3f1b-e280-48b1-a2ad-770b68be3434@slotpi01m90>

```
I'm not sure if its acceptable to use newer versions of curl.

This patch was rejected because of this reason: https://lore.kernel.org/git/7108764f437a25079c95a25c227eb79f9f4aee6a.1753273554.git.gargaditya08@live.com/

On 02/09/26 5:43 am, Wolfgang Faust wrote:
> The documented purpose of imap-send is to upload draft emails for sending
> later, but it did not have any way to mark the messages as \Draft, so some
> email clients presented the result as an un-editable, un-sendable email
> even if it happened to be in a "Drafts" folder.
> 
> Signed-off-by: Wolfgang Faust <contrib-git@wolfgangfaust.com>
> ---
>  Documentation/git-imap-send.adoc |  9 ++++++++-
>  git-curl-compat.h                |  8 ++++++++
>  imap-send.c                      | 15 +++++++++++++--
>  3 files changed, 29 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/git-imap-send.adoc b/Documentation/git-imap-send.adoc
> index 1814d94491..cf415df45a 100644
> --- a/Documentation/git-imap-send.adoc
> +++ b/Documentation/git-imap-send.adoc
> @@ -9,7 +9,7 @@ git-imap-send - Send a collection of patches from stdin to an IMAP folder
>  SYNOPSIS
>  --------
>  [synopsis]
> -git imap-send [-v] [-q] [--[no-]curl] [(--folder|-f) <folder>]
> +git imap-send [-v] [-q] [--[no-]curl] [--[no-]draft] [(--folder|-f) <folder>]
>  git imap-send --list
>  
>  
> @@ -55,6 +55,13 @@ OPTIONS
>  	using libcurl.  Ignored if Git was built with the NO_OPENSSL option
>  	set.
>  
> +`--draft`::
> +`--no-draft`::
> +	Mark uploaded messages with the IMAP `\Draft` flag. The default is `--no-draft`.
> ++
> +With libcurl, `--draft` requires version 8.13.0 or later.
> +Older libcurl still uploads the message but cannot set the flag.
> +
>  `--list`::
>  	Run the IMAP LIST command to output a list of all the folders present.
>  
> diff --git a/git-curl-compat.h b/git-curl-compat.h
> index dccdd4d6e5..032aaf7126 100644
> --- a/git-curl-compat.h
> +++ b/git-curl-compat.h
> @@ -67,4 +67,12 @@
>  #define GIT_CURL_HAVE_CURLOPT_TCP_KEEPCNT
>  #endif
>  
> +/**
> + * CURLOPT_UPLOAD_FLAGS and CURLULFLAG_* were added in 8.13.0,
> + * released in April 2025.
> + */
> +#if LIBCURL_VERSION_NUM >= 0x080D00
> +#define GIT_CURL_HAVE_CURLOPT_UPLOAD_FLAGS
> +#endif
> +
>  #endif
> diff --git a/imap-send.c b/imap-send.c
> index 0d16d02029..bf1d2cf74d 100644
> --- a/imap-send.c
> +++ b/imap-send.c
> @@ -35,6 +35,7 @@
>  #include "setup.h"
>  #include "strbuf.h"
>  #ifdef USE_CURL_FOR_IMAP_SEND
> +#include "git-curl-compat.h"
>  #include "http.h"
>  #endif
>  
> @@ -49,10 +50,11 @@
>  static int verbosity;
>  static int list_folders;
>  static int use_curl = USE_CURL_DEFAULT;
> +static int opt_draft;
>  static char *opt_folder;
>  
>  static char const * const imap_send_usage[] = {
> -	N_("git imap-send [-v] [-q] [--[no-]curl] [(--folder|-f) <folder>] < <mbox>"),
> +	N_("git imap-send [-v] [-q] [--[no-]curl] [--[no-]draft] [(--folder|-f) <folder>] < <mbox>"),
>  	"git imap-send --list",
>  	NULL
>  };
> @@ -60,6 +62,7 @@ static char const * const imap_send_usage[] = {
>  static struct option imap_send_options[] = {
>  	OPT__VERBOSITY(&verbosity),
>  	OPT_BOOL(0, "curl", &use_curl, "use libcurl to communicate with the IMAP server"),
> +	OPT_BOOL(0, "draft", &opt_draft, "mark uploaded messages with the IMAP \\Draft flag"),
>  	OPT_STRING('f', "folder", &opt_folder, "folder", "specify the IMAP folder"),
>  	OPT_BOOL(0, "list", &list_folders, "list all folders on the IMAP server"),
>  	OPT_END()
> @@ -1416,7 +1419,8 @@ static int imap_store_msg(struct imap_store *ctx, struct strbuf *msg)
>  
>  	box = ctx->name;
>  	prefix = !strcmp(box, "INBOX") ? "" : ctx->prefix;
> -	ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" ", prefix, box);
> +	ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" %s", prefix, box,
> +			  opt_draft ? "(\\Draft) " : "");
>  	imap->caps = imap->rcaps;
>  	if (ret != DRV_OK)
>  		return ret;
> @@ -1718,6 +1722,13 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server,
>  
>  	curl_easy_setopt(curl, CURLOPT_READDATA, &msgbuf);
>  
> +	if (opt_draft) {
> +#ifdef GIT_CURL_HAVE_CURLOPT_UPLOAD_FLAGS
> +		curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, CURLULFLAG_DRAFT);
> +#else
> +		warning("--draft requires libcurl 8.13.0 or later");
> +#endif
> +	}
>  	fprintf(stderr, "Sending %d message%s to %s folder...\n",
>  		total, (total != 1) ? "s" : "", server->folder);
>  	while (1) {


```

## Junio C Hamano, 2026-09-03 13:42

Subject: Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
Message-ID: <xmqqfqzqfo3a.fsf@gitster.g>
In-Reply-To: <MAUPR01MB1154649CE9D154B98459B09CEB8B62@MAUPR01MB11546.INDPRD01.PROD.OUTLOOK.COM>

```
Aditya Garg <gargaditya08@live.com> writes:

> I'm not sure if its acceptable to use newer versions of curl.
>
> This patch was rejected because of this reason: https://lore.kernel.org/git/7108764f437a25079c95a25c227eb79f9f4aee6a.1753273554.git.gargaditya08@live.com/

A huge difference is that the patch in the thread you pointed at did
not come any way to build with older versions.  The patch in this
thread is different, isn't it?

```

## Aditya Garg, 2026-09-03 14:37

Subject: Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
Message-ID: <MAUPR01MB11546486A8DD9C23224D52607B8B62@MAUPR01MB11546.INDPRD01.PROD.OUTLOOK.COM>
In-Reply-To: <xmqqfqzqfo3a.fsf@gitster.g>

```
So we can still consider that patch if I add version checks right?

> On 3 Sep 2026, at 7:12 PM, Junio C Hamano <gitster@pobox.com> wrote:
> 
> ﻿Aditya Garg <gargaditya08@live.com> writes:
> 
>> I'm not sure if its acceptable to use newer versions of curl.
>> 
>> This patch was rejected because of this reason: https://lore.kernel.org/git/7108764f437a25079c95a25c227eb79f9f4aee6a.1753273554.git.gargaditya08@live.com/
> 
> A huge difference is that the patch in the thread you pointed at did
> not come any way to build with older versions.  The patch in this
> thread is different, isn't it?

```
