Git development
 help / color / mirror / Atom feed
* [PATCH] imap-send: add --draft to set IMAP \Draft flag
@ 2026-09-02  0:13 Wolfgang Faust
  2026-09-02  3:25 ` Junio C Hamano
  2026-09-03  5:42 ` Aditya Garg
  0 siblings, 2 replies; 7+ messages in thread
From: Wolfgang Faust @ 2026-09-02  0:13 UTC (permalink / raw)
  To: git; +Cc: Aditya Garg

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


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
  2026-09-02  0:13 [PATCH] imap-send: add --draft to set IMAP \Draft flag Wolfgang Faust
@ 2026-09-02  3:25 ` Junio C Hamano
  2026-09-02  4:28   ` Wolfgang Faust
  2026-09-03  5:42 ` Aditya Garg
  1 sibling, 1 reply; 7+ messages in thread
From: Junio C Hamano @ 2026-09-02  3:25 UTC (permalink / raw)
  To: Wolfgang Faust; +Cc: git, Aditya Garg

"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.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
  2026-09-02  3:25 ` Junio C Hamano
@ 2026-09-02  4:28   ` Wolfgang Faust
  2026-09-02 14:37     ` Junio C Hamano
  0 siblings, 1 reply; 7+ messages in thread
From: Wolfgang Faust @ 2026-09-02  4:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Aditya Garg

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.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
  2026-09-02  4:28   ` Wolfgang Faust
@ 2026-09-02 14:37     ` Junio C Hamano
  0 siblings, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2026-09-02 14:37 UTC (permalink / raw)
  To: Wolfgang Faust; +Cc: git, Aditya Garg

"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 ;-).


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
  2026-09-02  0:13 [PATCH] imap-send: add --draft to set IMAP \Draft flag Wolfgang Faust
  2026-09-02  3:25 ` Junio C Hamano
@ 2026-09-03  5:42 ` Aditya Garg
  2026-09-03 13:42   ` Junio C Hamano
  1 sibling, 1 reply; 7+ messages in thread
From: Aditya Garg @ 2026-09-03  5:42 UTC (permalink / raw)
  To: Wolfgang Faust, git

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) {


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
  2026-09-03  5:42 ` Aditya Garg
@ 2026-09-03 13:42   ` Junio C Hamano
  2026-09-03 14:37     ` Aditya Garg
  0 siblings, 1 reply; 7+ messages in thread
From: Junio C Hamano @ 2026-09-03 13:42 UTC (permalink / raw)
  To: Aditya Garg; +Cc: Wolfgang Faust, git

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?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] imap-send: add --draft to set IMAP \Draft flag
  2026-09-03 13:42   ` Junio C Hamano
@ 2026-09-03 14:37     ` Aditya Garg
  0 siblings, 0 replies; 7+ messages in thread
From: Aditya Garg @ 2026-09-03 14:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Wolfgang Faust, git@vger.kernel.org

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?

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-09-03 14:37 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-02  0:13 [PATCH] imap-send: add --draft to set IMAP \Draft flag Wolfgang Faust
2026-09-02  3:25 ` Junio C Hamano
2026-09-02  4:28   ` Wolfgang Faust
2026-09-02 14:37     ` Junio C Hamano
2026-09-03  5:42 ` Aditya Garg
2026-09-03 13:42   ` Junio C Hamano
2026-09-03 14:37     ` Aditya Garg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox