[PATCH v5 0/2] send-email: integrate with git imap-send
From: Aditya Garg <hidden>
Date: 2025-08-12 06:45:08
Hi all
This patch series introduces integration of `git send-email` with `git imap-send`.
The first patch adds the ability to send a copy of sent emails to an IMAP folder
specified by the user, which is useful for email providers that do not support
sending a copy of sent emails to the "Sent" folder via SMTP.
The second patch allows users to copy emails to an IMAP folder without actually
sending them.
v2 - Fix indentation in patch for imap-send.c
- Minor edits to commit message
v3 - Rename imap folder to imap sent folder
- Make an error message shorter by removing unecessary details
v4 - Fix a bug causing emails to be copied to an IMAP folder even if
--dry-run is specified.
- Minor edits to commit messages and docs.
- Add another patch that enables copying emails to an IMAP folder
without actually sending them.
v5 - Avoid using -[no-]parameter.
Aditya Garg (2):
send-email: add ability to send a copy of sent emails to an IMAP
folder
send-email: enable copying emails to an IMAP folder without actually
sending them
Documentation/config/sendemail.adoc | 2 ++
Documentation/git-send-email.adoc | 26 +++++++++++++++++++
git-send-email.perl | 40 +++++++++++++++++++++++++++--
imap-send.c | 26 +++++++++++++------
4 files changed, 84 insertions(+), 10 deletions(-)
Range-diff against v4:
1: 2ad311502d ! 1: 27b5eb33bb send-email: enable copying emails to IMAP folder without actually sending them
@@ Metadata
Author: Aditya Garg [off-list ref]
## Commit message ##
- send-email: enable copying emails to IMAP folder without actually sending them
+ send-email: add ability to send a copy of sent emails to an IMAP folder
- `git imap-send` was built on the idea of copying emails to an IMAP folder
- like drafts, and sending them later using an email client. Currently
- the only way to do it is by piping output of `git format-patch` to IMAP
- send.
+ Some email providers like Apple iCloud Mail do not support sending a copy
+ of sent emails to the "Sent" folder if SMTP server is used. As a
+ workaround, various email clients like Thunderbird which rely on SMTP,
+ use IMAP to send a copy of sent emails to the "Sent" folder. Something
+ similar can be done if sending emails via `git send-email`, by using
+ the `git imap-send` command to send a copy of the sent email to an IMAP
+ folder specified by the user.
- Add another way to do it by using `git send-email` with the
- `--use-imap-only` or `sendmail.useImapOnly` option. This allows users to
- use the advanced features of `git send-email` like tweaking Cc: list
- programmatically, compose the cover letter, etc. and then send the well
- formatted emails to an IMAP folder using `git imap-send`.
-
- While at it, use `` instead of '' for --smtp-encryption ssl in help
- section of `git send-email`.
+ Add this functionality to `git send-email` by introducing a new
+ configuration variable `sendemail.imapfolder` and command line option
+ `--imap-folder` which specifies the IMAP folder to send a copy of the
+ sent emails to. If specified, a copy of the sent emails will be sent
+ by piping the emails to `git imap-send` command, after all emails are
+ sent via SMTP and the SMTP server has been closed.
Signed-off-by: Aditya Garg [off-list ref]
## Documentation/config/sendemail.adoc ##
-@@ Documentation/config/sendemail.adoc: sendemail.smtpServerPort::
+@@ Documentation/config/sendemail.adoc: sendemail.smtpServer::
+ sendemail.smtpServerPort::
sendemail.smtpServerOption::
sendemail.smtpUser::
- sendemail.imapSentFolder::
-+sendemail.useImapOnly::
++sendemail.imapSentFolder::
sendemail.thread::
sendemail.transferEncoding::
sendemail.validate::
## Documentation/git-send-email.adoc ##
@@ Documentation/git-send-email.adoc: must be used for each option.
- This feature requires setting up `git imap-send`. See linkgit:git-imap-send[1]
- for instructions.
+ commands and replies will be printed. Useful to debug TLS
+ connection and authentication problems.
-+--[no-]use-imap-only::
-+ If this is set, all emails will only be copied to the IMAP folder specified
-+ with `--imap-sent-folder` or `sendemail.imapSentFolder` and will not be sent
-+ to the recipients. Useful if you just want to create a draft of the emails
-+ and use another email client to send them.
-+ If disabled with `--no-use-imap-only`, the emails will be sent like usual.
-+ Disabled by default, but the `sendemail.useImapOnly` configuration
-+ variable can be used to enable it.
-+
++--imap-sent-folder=<folder>::
++ Some email providers (e.g. iCloud) do not send a copy of the emails sent
++ using SMTP to the `Sent` folder or similar in your mailbox. Use this option
++ to use `git imap-send` to send a copy of the emails to the folder specified
++ using this option. You can run `git imap-send --list` to get a list of
++ valid folder names, including the correct name of the `Sent` folder in
++ your mailbox. You can also use this option to send emails to a dedicated
++ IMAP folder of your choice.
++
+This feature requires setting up `git imap-send`. See linkgit:git-imap-send[1]
+for instructions.
@@ Documentation/git-send-email.adoc: must be used for each option.
## git-send-email.perl ##
@@ git-send-email.perl: sub usage {
- --smtp-user <str> * Username for SMTP-AUTH.
- --smtp-pass <str> * Password for SMTP-AUTH; not necessary.
- --smtp-encryption <str> * tls or ssl; anything else disables.
-- --smtp-ssl * Deprecated. Use '--smtp-encryption ssl'.
-+ --smtp-ssl * Deprecated. Use `--smtp-encryption ssl`.
- --smtp-ssl-cert-path <str> * Path to ca-certificates (either directory or file).
- Pass an empty string to disable certificate
- verification.
-@@ git-send-email.perl: sub usage {
+ --no-smtp-auth * Disable SMTP authentication. Shorthand for
+ `--smtp-auth=none`
--smtp-debug <0|1> * Disable, enable Net::SMTP debug.
- --imap-sent-folder <str> * IMAP folder where a copy of the emails should be sent.
- Make sure `git imap-send` is set up to use this feature.
-+ --[no-]use-imap-only * Only copy emails to the IMAP folder specified by
-+ `--imap-sent-folder` instead of actually sending them.
++ --imap-sent-folder <str> * IMAP folder where a copy of the emails should be sent.
++ Make sure `git imap-send` is set up to use this feature.
--batch-size <int> * send max <int> message per connection.
--relogin-delay <int> * delay <int> seconds between two successive login.
-@@ git-send-email.perl: sub do_edit {
- my $target_xfer_encoding = 'auto';
- my $forbid_sendmail_variables = 1;
- my $outlook_id_fix = 'auto';
-+my $use_imap_only = 0;
+@@ git-send-email.perl: sub format_2822_time {
- my %config_bool_settings = (
- "thread" => \$thread,
+ # Variables we fill in automatically, or via prompting:
+ my (@to,@cc,@xh,$envelope_sender,
+- $initial_in_reply_to,$reply_to,$initial_subject,@files,
++ $initial_in_reply_to,$reply_to,$initial_subject,@files,@imap_copy,
+ $author,$sender,$smtp_authpass,$annotate,$compose,$time);
+ # Things we either get from config, *or* are overridden on the
+ # command-line.
@@ git-send-email.perl: sub do_edit {
- "forbidsendmailvariables" => \$forbid_sendmail_variables,
- "mailmap" => \$mailmap,
- "outlookidfix" => \$outlook_id_fix,
-+ "useimaponly" => \$use_imap_only,
- );
-
- my %config_settings = (
+ my ($smtp_authuser, $smtp_encryption, $smtp_ssl_cert_path);
+ my ($batch_size, $relogin_delay);
+ my ($identity, $aliasfiletype, @alias_files, $smtp_domain, $smtp_auth);
++my ($imap_sent_folder);
+ my ($confirm);
+ my (@suppress_cc);
+ my ($auto_8bit_encoding);
+@@ git-send-email.perl: sub do_edit {
+ "smtpauth" => \$smtp_auth,
+ "smtpbatchsize" => \$batch_size,
+ "smtprelogindelay" => \$relogin_delay,
++ "imapsentfolder" => \$imap_sent_folder,
+ "to" => \@config_to,
+ "tocmd" => \$to_cmd,
+ "cc" => \@config_cc,
@@ git-send-email.perl: sub config_regexp {
+ "smtp-domain:s" => \$smtp_domain,
"smtp-auth=s" => \$smtp_auth,
"no-smtp-auth" => sub {$smtp_auth = 'none'},
- "imap-sent-folder=s" => \$imap_sent_folder,
-+ "use-imap-only!" => \$use_imap_only,
++ "imap-sent-folder=s" => \$imap_sent_folder,
"annotate!" => \$annotate,
"compose" => \$compose,
"quiet" => \$quiet,
@@ git-send-email.perl: sub send_message {
+ print "\n";
+ }
+
++ if ($imap_sent_folder && !$dry_run) {
++ my $imap_header = $header;
++ if (@initial_bcc) {
++ # Bcc is not a part of $header, so we add it here.
++ # This is only for the IMAP copy, not for the actual email
++ # sent to the recipients.
++ $imap_header .= "Bcc: " . join(", ", @initial_bcc) . "\n";
++ }
++ push @imap_copy, "From git-send-email\n$imap_header\n$message";
++ }
++
+ return 1;
+ }
+
+@@ git-send-email.perl: sub cleanup_compose_files {
+
+ $smtp->quit if $smtp;
+
++if ($imap_sent_folder && @imap_copy && !$dry_run) {
++ my $imap_input = join("\n", @imap_copy);
++ eval {
++ print "\nStarting git imap-send...\n";
++ my ($fh, $ctx) = Git::command_input_pipe(['imap-send', '-f', $imap_sent_folder]);
++ print $fh $imap_input;
++ Git::command_close_pipe($fh, $ctx);
++ 1;
++ } or do {
++ warn "Warning: failed to send messages to IMAP folder $imap_sent_folder: $@";
++ };
++}
++
+ sub apply_transfer_encoding {
+ my $message = shift;
+ my $from = shift;
+
+ ## imap-send.c ##
+@@ imap-send.c: static int count_messages(struct strbuf *all_msgs)
- if ($dry_run) {
- # We don't want to send the email.
-+ } elsif ($use_imap_only) {
-+ die __("The destination IMAP folder is not properly defined.") if !defined $imap_sent_folder;
- } elsif (defined $sendmail_cmd || file_name_is_absolute($smtp_server)) {
- my $pid = open my $sm, '|-';
- defined $pid or die $!;
+ while (1) {
+ if (starts_with(p, "From ")) {
+- p = strstr(p+5, "\nFrom: ");
+- if (!p) break;
+- p = strstr(p+7, "\nDate: ");
+- if (!p) break;
+- p = strstr(p+7, "\nSubject: ");
+- if (!p) break;
+- p += 10;
+- count++;
++ if (starts_with(p, "From git-send-email")) {
++ p = strstr(p+5, "\nFrom: ");
++ if (!p) break;
++ p += 7;
++ p = strstr(p, "\nTo: ");
++ if (!p) break;
++ p += 5;
++ count++;
++ } else {
++ p = strstr(p+5, "\nFrom: ");
++ if (!p) break;
++ p = strstr(p+7, "\nDate: ");
++ if (!p) break;
++ p = strstr(p+7, "\nSubject: ");
++ if (!p) break;
++ p += 10;
++ count++;
++ }
+ }
+ p = strstr(p+5, "\nFrom ");
+ if (!p)
-: ---------- > 2: 1d74a857df send-email: enable copying emails to an IMAP folder without actually sending them
--
2.50.1