threads / patch / 63831

patchimap-send: add option to mark sent messages as read or unread

Subject: [PATCH] imap-send: add option to mark sent messages as read or unread

## tl;dr

8 messages between Jul 23, 2025 and Jul 23, 2025. Diffs are folded; open one to read it.

replies: 7people: 2as markdown or json

Aditya Garg· Jul 23, 2025, 12:29 UTC · lore

The current behaviour of `git imap-send` is to mark sent messages as read if curl is used, and unread if OpenSSL is used.

Fix this inconsistency by marking the message as read by default in both cases. Also introduce `--[no-]mark-as-read` and `imap.markAsRead` option to allow users to change this behaviour.

While at it, also clarify that `imap.folder` will be used if --folder is not specified.

Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
 Documentation/config/imap.adoc   |  4 ++++
 Documentation/git-imap-send.adoc | 10 +++++++++-
 imap-send.c                      | 18 ++++++++++++++++--
 3 files changed, 29 insertions(+), 3 deletions(-)
Show changes to 3 files +29 −3

Documentation/config/imap.adoc, Documentation/git-imap-send.adoc, imap-send.c

diff --git a/Documentation/config/imap.adoc b/Documentation/config/imap.adoc
index 4682a6bd03..afae49391c 100644
--- a/Documentation/config/imap.adoc
+++ b/Documentation/config/imap.adoc
@@ -45,3 +45,7 @@ imap.authMethod::
 	option, the only supported methods are `PLAIN`, `CRAM-MD5`, `OAUTHBEARER`
 	and `XOAUTH2`. If this is not set then `git imap-send` uses the basic IMAP
 	plaintext `LOGIN` command.
+
+imap.markAsRead::
+	Choose whether to mark the sent message as read or not.
+	Default is `true`.
diff --git a/Documentation/git-imap-send.adoc b/Documentation/git-imap-send.adoc
index 17147f93c3..3976c128c7 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
 --------
 [verse]
-'git imap-send' [-v] [-q] [--[no-]curl] [(--folder|-f) <folder>]
+'git imap-send' [-v] [-q] [--[no-]curl] [--[no-]mark-as-read] [(--folder|-f) <folder>]
 'git imap-send' --list
 
 
@@ -44,6 +44,8 @@ OPTIONS
 --folder=<folder>::
 	Specify the folder in which the emails have to saved.
 	For example: `--folder=[Gmail]/Drafts` or `-f INBOX/Drafts`.
+	If not specified, the folder assigned using `imap.folder`
+	will be used.
 
 --curl::
 	Use libcurl to communicate with the IMAP server, unless tunneling
@@ -58,6 +60,12 @@ OPTIONS
 --list::
 	Run the IMAP LIST command to output a list of all the folders present.
 
+--[no-]mark-as-read::
+	Choose whether to mark the sent message as read or not.
+	`--mark-as-read` will mark the message as read, and `--no-mark-as-read`
+	will mark it as unread. If not specified, the default behaviour will
+	be decided by the value of `imap.markAsRead`.
+
 CONFIGURATION
 -------------
 
diff --git a/imap-send.c b/imap-send.c
index 44de0c5a77..a242119164 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -47,11 +47,12 @@
 
 static int verbosity;
 static int list_folders;
+static int mark_seen = 1;
 static int use_curl = USE_CURL_DEFAULT;
 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-]mark-as-read] [(--folder|-f) <folder>] < <mbox>"),
 	"git imap-send --list",
 	NULL
 };
@@ -61,6 +62,7 @@ static struct option imap_send_options[] = {
 	OPT_BOOL(0, "curl", &use_curl, "use libcurl to communicate with the IMAP server"),
 	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_BOOL(0, "mark-as-read", &mark_seen, "mark messages as read after sending"),
 	OPT_END()
 };
 
@@ -1402,7 +1404,11 @@ 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);
+	if (mark_seen) {
+		ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" (\\Seen) ", prefix, box);
+	} else {
+		ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" ", prefix, box);
+	}
 	imap->caps = imap->rcaps;
 	if (ret != DRV_OK)
 		return ret;
@@ -1513,6 +1519,8 @@ static int git_imap_config(const char *var, const char *val,
 		cfg->ssl_verify = git_config_bool(var, val);
 	} else if (!strcmp("imap.preformattedhtml", var)) {
 		cfg->use_html = git_config_bool(var, val);
+	} else if (!strcmp("imap.markasread", var)) {
+		mark_seen = git_config_bool(var, val);
 	} else if (!strcmp("imap.folder", var)) {
 		FREE_AND_NULL(cfg->folder);
 		return git_config_string(&cfg->folder, var, val);
@@ -1702,6 +1710,12 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server,
 	curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
 	curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
 
+	if (mark_seen) {
+		curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, CURLULFLAG_SEEN);
+	} else {
+		curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, 0L);
+	}
+
 	curl_easy_setopt(curl, CURLOPT_READDATA, &msgbuf);
 
 	fprintf(stderr, "Sending %d message%s to %s folder...\n",
-- 
2.50.1.320.g2ad311502d
Junio C Hamano· Jul 23, 2025, 17:25 UTC · re: Aditya Garg · lore

Re: [PATCH] imap-send: add option to mark sent messages as read or unread

Aditya Garg <gargaditya08@live.com> writes:
> +imap.markAsRead::
> +	Choose whether to mark the sent message as read or not.

Is this something user typically want to use a single setting, or would it often be per invocation? Especially with the new invoker in send-email, wouldn't it become more like "if I use imap-send to stuff things in my outgoing folder, they shouldn't be marked as read, but fcc copies send-email stuffs via imap-send should be marked as read" or something like that?

> +	Default is `true`.

If we never marked these messages as read, then this default is a breaking change, isn't it?

Show 5 quoted lines
> @@ -47,11 +47,12 @@
>  
>  static int verbosity;
>  static int list_folders;
> +static int mark_seen = 1;
IOW, this smells problematic.
Show 5 quoted lines
> +	if (mark_seen) {
> +		ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" (\\Seen) ", prefix, box);
> +	} else {
> +		ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" ", prefix, box);
> +	}
Why so many braces around single-statement blocks?
Show 10 quoted lines
> @@ -1702,6 +1710,12 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server,
>  	curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
>  	curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
>  
> +	if (mark_seen) {
> +		curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, CURLULFLAG_SEEN);
> +	} else {
> +		curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, 0L);
> +	}
> +
Why so many braces around single-statement blocks?
According to
https://github.com/curl/curl/blob/master/docs/libcurl/symbols-in-versions

CURLULFLAG_SEEN first appeared in 8.13.0; INSTALL says we require 7.61.0 or later, so this may be OK.

Aditya Garg· Jul 23, 2025, 17:33 UTC · re: Junio C Hamano · lore

Re: [PATCH] imap-send: add option to mark sent messages as read or unread

Show 13 quoted lines
> On 23 Jul 2025, at 10:55 PM, Junio C Hamano <gitster@pobox.com> wrote:
> 
> Aditya Garg <gargaditya08@live.com> writes:
> 
>> +imap.markAsRead::
>> +    Choose whether to mark the sent message as read or not.
> 
> Is this something user typically want to use a single setting,
> or would it often be per invocation?  Especially with the new
> invoker in send-email, wouldn't it become more like "if I use
> imap-send to stuff things in my outgoing folder, they shouldn't be
> marked as read, but fcc copies send-email stuffs via imap-send
> should be marked as read" or something like that?
So whenever the user changes the folder, he can change this option too?
Also, we have a command line way as well.
Show 5 quoted lines
> 
>> +    Default is `true`.
> 
> If we never marked these messages as read, then this default is a
> breaking change, isn't it?
Curl always marked the messages as read, so how would it be a breaking change? As far as OpenSSL is concerned, it marks the messages as unread, but due to issues with the license, as long as people are compiling git themselves, I doubt people are using it.
Also, were people really using imap-send itself?
Show 16 quoted lines
> 
>> @@ -47,11 +47,12 @@
>> 
>> static int verbosity;
>> static int list_folders;
>> +static int mark_seen = 1;
> 
> IOW, this smells problematic.
> 
>> +    if (mark_seen) {
>> +        ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" (\\Seen) ", prefix, box);
>> +    } else {
>> +        ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" ", prefix, box);
>> +    }
> 
> Why so many braces around single-statement blocks?
Will fix
Show 21 quoted lines
> 
>> @@ -1702,6 +1710,12 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server,
>>    curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
>>    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
>> 
>> +    if (mark_seen) {
>> +        curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, CURLULFLAG_SEEN);
>> +    } else {
>> +        curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, 0L);
>> +    }
>> +
> 
> Why so many braces around single-statement blocks?
> 
> According to
> 
> https://github.com/curl/curl/blob/master/docs/libcurl/symbols-in-versions
> 
> CURLULFLAG_SEEN first appeared in 8.13.0; INSTALL says we require 7.61.0
> or later, so this may be OK.
> 
Aditya Garg· Jul 23, 2025, 17:35 UTC · re: Aditya Garg · lore

Re: [PATCH] imap-send: add option to mark sent messages as read or unread

Show 21 quoted lines
> On 23 Jul 2025, at 11:03 PM, Aditya Garg <gargaditya08@live.com> wrote:
> 
> 
> 
>> On 23 Jul 2025, at 10:55 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> 
>> Aditya Garg <gargaditya08@live.com> writes:
>> 
>>> +imap.markAsRead::
>>> +    Choose whether to mark the sent message as read or not.
>> 
>> Is this something user typically want to use a single setting,
>> or would it often be per invocation?  Especially with the new
>> invoker in send-email, wouldn't it become more like "if I use
>> imap-send to stuff things in my outgoing folder, they shouldn't be
>> marked as read, but fcc copies send-email stuffs via imap-send
>> should be marked as read" or something like that?
> 
> So whenever the user changes the folder, he can change this option too?
> 
> Also, we have a command line way as well.
For send-email integration, maybe add another option over there as well?
Junio C Hamano· Jul 23, 2025, 17:56 UTC · re: Aditya Garg · lore

Re: [PATCH] imap-send: add option to mark sent messages as read or unread

Aditya Garg <gargaditya08@live.com> writes:
> For send-email integration, maybe add another option over there as well?

No, let's scrap this step, as it requires way too new version of cURL.

Aditya Garg· Jul 23, 2025, 18:00 UTC · re: Junio C Hamano · lore

Re: [PATCH] imap-send: add option to mark sent messages as read or unread

Show 8 quoted lines
> On 23 Jul 2025, at 11:26 PM, Junio C Hamano <gitster@pobox.com> wrote:
> 
> Aditya Garg <gargaditya08@live.com> writes:
> 
>> For send-email integration, maybe add another option over there as well?
> 
> No, let's scrap this step, as it requires way too new version of
> cURL.
Yes I got that. Btw, so I just keep the inconsistency that OpenSSL marks it as unread and curl as read that way, or make OpenSSL mark it as read (it doesn't need any new api)?
Junio C Hamano· Jul 23, 2025, 17:55 UTC · re: Aditya Garg · lore

Re: [PATCH] imap-send: add option to mark sent messages as read or unread

Aditya Garg <gargaditya08@live.com> writes:
Show 15 quoted lines
>> On 23 Jul 2025, at 10:55 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> 
>> Aditya Garg <gargaditya08@live.com> writes:
>> 
>>> +imap.markAsRead::
>>> +    Choose whether to mark the sent message as read or not.
>> 
>> Is this something user typically want to use a single setting,
>> or would it often be per invocation?  Especially with the new
>> invoker in send-email, wouldn't it become more like "if I use
>> imap-send to stuff things in my outgoing folder, they shouldn't be
>> marked as read, but fcc copies send-email stuffs via imap-send
>> should be marked as read" or something like that?
>
> So whenever the user changes the folder, he can change this option too?

I am not sure what you mean. If it is primarily per invocation, we do not want a new configuration variable. A new feature should be introduced behind a command line option (disabled by default) first, and then if it proves useful enough to wide audience, a configuration is added for enhanced usability. Adding a new configuration variable at the same time an option is introduced smelled more like a spinal reflection than a well thought out design.

Junio C Hamano· Jul 23, 2025, 17:52 UTC · re: Junio C Hamano · lore

Re: [PATCH] imap-send: add option to mark sent messages as read or unread

Junio C Hamano <gitster@pobox.com> writes:
Show 17 quoted lines
> Aditya Garg <gargaditya08@live.com> writes:
>
>> +	if (mark_seen) {
>> +		curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, CURLULFLAG_SEEN);
>> +	} else {
>> +		curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, 0L);
>> +	}
>> +
>
> Why so many braces around single-statement blocks?
>
> According to
>
> https://github.com/curl/curl/blob/master/docs/libcurl/symbols-in-versions
>
> CURLULFLAG_SEEN first appeared in 8.13.0; INSTALL says we require 7.61.0
> or later, so this may be OK.
It might be obvious, but I meant "may not be OK" here.

← back to recent threads