Send Git Patches to an IMAP Drafts Folder

git imap-send drops a finished patch series into your IMAP Drafts folder, ready for review before you send it. Some review workflows still want patches emailed rather than pushed, and this saves you from copy-pasting diffs into a mail client. The examples match Git 2.43.0 from Ubuntu package git-man 1:2.43.0-1ubuntu7.3, the version checked for this guide. Allow about fifteen minutes, plus time to confirm your mail provider's IMAP settings.

1. Check the installed command

Start with a read-only version and help check. Neither needs elevated privileges:

$ git --version
git version 2.43.0
$ git imap-send -h
usage: git imap-send [-v] [-q] [--[no-]curl] < <mbox>

The input is read from standard input. The mailbox must contain messages with From, Date and Subject fields in that order. Git's format-patch command produces exactly this mailbox, so you can pipe the two together without an intermediate file.

Checkpoint: if git imap-send -h fails, fix the Git installation or use the binary you intend to configure before you touch any IMAP settings.

2. Choose the connection mode

git imap-send needs imap.folder and exactly one connection method:

A harmless tunnel configuration shape:

[imap]
    folder = "INBOX.Drafts"
    tunnel = "ssh -q -C [email protected] /usr/bin/imapd ./Maildir 2> /dev/null"

The exact folder spelling is server-specific. Common examples are INBOX.Drafts, INBOX/Drafts and [Gmail]/Drafts. Do not guess the name from a webmail label; confirm the folder in an IMAP client first.

Direct mode identifies the server with an imap:// or imaps:// URL. Use imaps:// for a TLS connection unless your provider specifically requires something else:

[imap]
    folder = "[Gmail]/Drafts"
    host = "imaps://imap.example.net"
    user = "[email protected]"
    pass = "REPLACE_WITH_A_PROVIDER_APPROVED_SECRET"
    # port = 993
    # sslverify = true

Security warning: imap.pass is a password-bearing Git setting. Do not commit this file, paste a real password into a shared terminal transcript, or leave a copied configuration somewhere world-readable. Prefer a provider-approved credential dedicated to IMAP. The manual's default port is 143 for imap:// and 993 for imaps://; sslverify defaults to true. Do not disable certificate verification as a routine fix.

3. Save only the settings you have verified

Store settings in the scope that matches your use. This writes a per-user configuration, so it changes state in your home directory, but needs no sudo:

$ git config --global imap.folder '[Gmail]/Drafts'
$ git config --global imap.host 'imaps://imap.example.net'
$ git config --global imap.user '[email protected]'
$ git config --global imap.port 993
$ git config --global imap.sslverify true

Add imap.pass only if you have deliberately decided to keep that secret in Git's configuration. A tunnel configuration can instead be written with git config --global imap.tunnel 'YOUR_VERIFIED_TUNNEL_COMMAND'; remove unused direct settings so you never mistake an ignored host for the active connection.

Review the non-secret values before proceeding:

$ git config --global --get-regexp '^imap\.(folder|tunnel|host|user|port|sslverify|authMethod)$'
imap.folder [Gmail]/Drafts
imap.host imaps://imap.example.net
imap.user [email protected]
imap.port 993
imap.sslverify true

Do not run a command that prints imap.pass while troubleshooting. To undo the configuration changes, remove only the keys you added:

$ git config --global --unset-all imap.folder
$ git config --global --unset-all imap.host
$ git config --global --unset-all imap.user
$ git config --global --unset-all imap.port
$ git config --global --unset-all imap.sslverify

Those commands may report a missing key; that is harmless. If you added a tunnel or password, remove those exact keys separately after checking the key name with git config --global --list, taking care not to display the password in shared output.

4. Generate a patch mailbox without sending it

From the repository containing the commits, inspect the range first. This example sends commits reachable from HEAD but not from origin/main:

$ git log --oneline origin/main..HEAD
7f3a1c2 Fix parser error reporting
91d4e88 Add regression coverage

Replace origin/main with the branch your project uses. If the range is empty, stop: there is no patch to upload. If it holds the intended commits, create the mailbox on standard output and pipe it straight to git imap-send:

$ git format-patch --signoff --stdout --attach origin/main..HEAD | git imap-send

--attach produces attached patch messages, matching Git's documented common workflow. Some projects reject attached patches or require a cover letter, so follow the project's contribution rules. For a review series with a cover letter, use the same range and add the option explicitly:

$ git format-patch --cover-letter --signoff --stdout origin/main..HEAD | git imap-send

There is no output to interpret in quiet success mode, so check the exit status immediately:

$ printf 'git imap-send status: %s\n' "$?"
git imap-send status: 0

A zero status means Git completed the upload. Open the Drafts folder in your mail client and inspect the messages before sending them. Keep line wrapping disabled in the client: wrapping or format=flowed transformations can corrupt patches even after a successful upload.

5. Diagnose connection and authentication failures

Repeat the pipeline with --verbose when you need protocol progress. Avoid pasting the resulting transcript into a public issue if it contains account names or server details:

$ git format-patch --signoff --stdout --attach origin/main..HEAD | git imap-send --verbose
$ printf 'git imap-send status: %s\n' "$?"
git imap-send status: 1

Check the least surprising causes first: the folder name, the URL scheme, the port, the username and the provider's IMAP access policy. In direct mode, imaps:// normally selects port 993 and imap:// selects 143. In tunnel mode, imap.port and imap.host are ignored entirely.

imap.authMethod controls authentication. If it is unset, Git uses the basic IMAP LOGIN command. When Git uses its own non-cURL routines, or --no-curl is selected, the manual says the supported method is CRAM-MD5. Do not bolt on an authentication method just because a provider's error mentions authentication; confirm your installed build and provider actually support the same method.

For a TLS certificate error, inspect the server certificate and hostname with your normal mail diagnostics. Do not set imap.sslverify=false just to make the error disappear. If verification is genuinely the problem on a private service, fix the certificate or trust configuration and retry: a successful upload over an unverified connection is not a safe success.

6. Select the transport implementation deliberately

Git 2.43.0 accepts --curl and --no-curl. --curl asks Git to use libcurl for IMAP unless it is tunnelling; --no-curl selects Git's own IMAP routines. These switches affect the transport implementation only, not the folder or patch format:

$ git format-patch --signoff --stdout --attach origin/main..HEAD | git imap-send --curl

If a switch appears to do nothing, the installed Git may have been built without the relevant support: the manual says each option is ignored in some build configurations. Treat the resulting connection behaviour as a build and provider compatibility question, not evidence about whether the patch was accepted.

Done means