Configuration
Korgalore uses a TOML file for its configuration. It defines the following main sections:
targets: can be Gmail accounts, local maildirs, JMAP servers, IMAP servers, pipe commands
feeds: public-inbox locations or lei searches
deliveries: mapping of which feed goes to which target
Configuration File Location
The default configuration file location is:
~/.config/korgalore/korgalore.toml
You can override this with the -c or --cfgfile option:
kgl -c /path/to/config.toml pull
Modular Configuration (conf.d)
In addition to the main configuration file, korgalore automatically loads
additional configuration files from the conf.d/ subdirectory:
~/.config/korgalore/conf.d/*.toml
This is useful for:
Keeping auto-generated configurations separate from your main config
Organizing configurations by purpose (e.g., one file per subsystem)
Easily enabling/disabling configurations by adding/removing files
Files are loaded in alphabetical order and merged into the main configuration.
The targets, feeds, and deliveries sections are merged (new entries
added, existing entries with the same key are overwritten). The gui section
is replaced entirely if present in a conf.d file.
This feature is used by the track-subsystem command to store subsystem
tracking configurations separately from your main configuration file. Each
generated file includes a [subsystem] section with the human-readable
subsystem name, used by track-subsystem --list for display and by
--forget for identification.
The subscribe command also uses conf.d, storing each subscription as
sub-{feed_key}.toml. Paused subscriptions are renamed to
sub-{feed_key}.toml.paused so they are excluded from the *.toml glob.
Gmail Setup
Gmail went out of their way to make it super difficult to access your inbox via an API, so please be prepared to suffer a bit. You will need to download an OAuth 2.0 Client ID file from Google that will authorize your access.
Creating OAuth Credentials
Go to the Google Cloud Console
Create a new project (or select an existing one)
Enable the Gmail API for your project
Create OAuth 2.0 credentials:
Go to “Credentials” in the left sidebar
Click “Create Credentials” > “OAuth client ID”
Choose “Desktop app” as the application type
Download the JSON file
Save the downloaded file and add a target that will be using it in the korgalore.toml configuration file (see below).
For detailed instructions on getting your project set up and obtaining credentials.json, follow Google’s quickstart guide: https://developers.google.com/workspace/gmail/api/quickstart/python#set-up-environment
Authenticating
You should first define your gmail account target in the config file.
After that, the first time you run kgl pull, you will be prompted to
log in to your Google account and authorize the application. You can
also run kgl auth to the same effect.
Once you obtain the token file (usually located at
~/.config/korgalore/gmail-personal-token.json), you can copy it to a
headless node and modify your configuration file to point to it:
[targets.personal]
type = 'gmail'
credentials = '~/.config/korgalore/credentials.json'
token = '~/.config/korgalore/gmail-personal-token.json'
This will let you run korgalore on a headless node as opposed to your workstation.
Maildir Setup
Maildir targets provide a simpler alternative to Gmail for local message storage. They deliver messages to a local maildir directory on your filesystem, which can be read by mail clients like mutt, thunderbird, or any other maildir-compatible application.
Benefits of Maildir Targets
No authentication required: Messages are written directly to your local filesystem
Privacy: All messages stay on your local machine
Offline access: No internet connection needed to read messages
Standard format: Compatible with most Unix mail clients
Easy backup: Just copy the maildir directory
Configuring Maildir Targets
To configure a maildir target, simply specify the path where you want messages stored:
[targets.local]
type = 'maildir'
path = '~/Mail/lkml'
The maildir will be created automatically if it doesn’t exist. The standard maildir structure (cur/, new/, tmp/ subdirectories) is handled automatically.
You can use the subfolder parameter in deliveries to route messages into
subdirectories under the target’s base path. Maildir subfolders additionally
support strftime format codes (e.g., %Y/%m) for date-based directory
organisation. This is particularly useful for high-traffic lists like
linux-kernel, where a single maildir can accumulate tens of thousands of
files and cause filesystem performance penalties:
[targets.archive]
type = 'maildir'
path = '~/Mail'
[deliveries.lkml]
feed = 'lkml'
target = 'archive'
subfolder = 'Lists/LKML' # Results in ~/Mail/Lists/LKML
[deliveries.lkml-archive]
feed = 'lkml'
target = 'archive'
subfolder = '%Y/%m' # Results in ~/Mail/2026/01
Note
Labels are ignored for maildir targets. Maildir doesn’t support Gmail-style labels, so any labels specified in deliveries using maildir targets will be silently ignored.
IMAP Setup
IMAP targets provide a way to deliver messages to any IMAP-compatible mail server (like personal email servers, Office365, generic hosting providers, etc.).
Benefits of IMAP Targets
Wide compatibility: Works with virtually any email provider supporting IMAP
SSL-only security: Always uses encrypted connections on port 993
Simple authentication: Standard password-based authentication
Server-side storage: Messages stored on your mail server
Multiple client access: Access via any IMAP-compatible mail client
Configuring IMAP Targets
To configure an IMAP target, specify the server, credentials, and target folder:
[targets.myserver]
type = 'imap'
server = 'imap.example.com'
username = '[email protected]'
folder = 'INBOX'
password_file = '~/.config/korgalore/imap-password.txt'
Note
Labels are ignored for IMAP targets. Messages are delivered to the single configured folder only. Any labels specified in deliveries using IMAP targets will be silently ignored.
Warning
For security, use password_file instead of inline password in your
configuration file.
IMAP OAuth2 Setup (Microsoft 365)
Microsoft 365 and Office 365 accounts require OAuth2 authentication (Modern Authentication) instead of passwords. Korgalore supports this via the XOAUTH2 IMAP extension using the PKCE authorization flow.
Configuring IMAP OAuth2 Targets
To configure an IMAP target with OAuth2 authentication for Microsoft 365:
[targets.office365]
type = 'imap'
auth_type = 'oauth2'
server = 'outlook.office365.com'
username = '[email protected]'
That’s it! Korgalore includes a built-in Azure AD application, so no additional setup is required for most users.
OAuth2 Target Parameters
auth_type: Must be'oauth2'to enable OAuth2 authenticationclient_id: (Optional) Azure AD Application (client) ID. Korgalore uses a built-in default; only specify this if your organization blocks third-party apps and you need to use your own app registration.tenant: (Optional) Azure AD tenant - use'common'for multi-tenant,'organizations'for any work/school account, or your specific tenant ID. Default:'common'token: (Optional) Path to store the OAuth2 token file. Defaults to~/.config/korgalore/imap-{identifier}-oauth2-token.json
Note
Korgalore includes a default Azure AD application ID. However, some organizations block third-party applications via conditional access policies. If you encounter errors like “AADSTS65001” or “application not approved”, contact your IT department to obtain an approved client ID and specify it in your configuration:
[targets.office365]
type = 'imap'
auth_type = 'oauth2'
server = 'outlook.office365.com'
username = '[email protected]'
client_id = 'client-id-from-it-department'
Authenticating
The first time you access an OAuth2 IMAP target, korgalore will:
Open your default web browser to the Microsoft login page
Prompt you to sign in and grant permissions to the application
Save the refresh token locally for future use
You can trigger authentication explicitly:
kgl auth office365
Once authenticated, the token is stored locally and refreshed automatically. If the token expires or is revoked, korgalore will prompt for re-authentication.
Using on Headless Servers
For headless servers, authenticate on a machine with a browser first, then copy the token file:
On your workstation, run
kgl auth office365Complete the browser authentication
Copy the token file to your server:
scp ~/.config/korgalore/imap-office365-oauth2-token.json \ server:~/.config/korgalore/
Ensure the configuration on the server matches (same
client_id, etc.)
The token will be refreshed automatically without requiring a browser.
Troubleshooting OAuth2
- “AADSTS700016: Application not found”
The
client_idis incorrect or the application was deleted. Verify the Application ID in Azure Portal.- “AADSTS65001: User or administrator has not consented”
The user hasn’t granted permissions. Run
kgl authto trigger the consent flow, or ask your administrator to grant admin consent.- “AUTHENTICATE failed” after successful login
Verify that IMAP.AccessAsUser.All permission is granted and that IMAP is enabled for your mailbox in Microsoft 365 admin settings.
- Token refresh fails repeatedly
The refresh token may have expired (90 days of inactivity) or been revoked. Delete the token file and re-authenticate.
Pipe Setup
Pipe targets provide a way to send raw messages to any external command via stdin. This is useful for custom processing, filtering, or integration with other tools.
Benefits of Pipe Targets
No authentication required: Messages are piped to a local command
Flexibility: Integrate with any tool that accepts email on stdin
Custom processing: Filter, transform, or archive messages your way
Scriptable: Use shell scripts, Python scripts, or any executable
Configuring Pipe Targets
To configure a pipe target, specify the command to pipe messages to:
[targets.filter]
type = 'pipe'
command = '/usr/local/bin/process-email.sh'
The command receives the raw email message (RFC 2822 format) on stdin. The command can include arguments:
[targets.archive]
type = 'pipe'
command = 'gzip >> ~/mail-archive.gz'
Labels specified in deliveries are appended as additional command line arguments:
[targets.processor]
type = 'pipe'
command = '/usr/local/bin/process-mail.sh'
[deliveries.lkml-process]
feed = 'lkml'
target = 'processor'
labels = ['--list=lkml', '--priority=high']
This would execute: /usr/local/bin/process-mail.sh --list=lkml --priority=high
Warning
Ensure the command is trusted and handles email data safely. The raw message bytes are piped directly to the command’s stdin.
Configuration File Format
The configuration file uses TOML format and consists of three main sections:
targets, feeds, and deliveries.
Targets
Targets define where messages will be delivered (Gmail accounts, local maildirs, JMAP servers, IMAP servers, pipe commands, etc.).
[targets.personal]
type = 'gmail'
credentials = '/path/to/personal-credentials.json'
[targets.work]
type = 'gmail'
credentials = '/path/to/work-credentials.json'
[targets.local]
type = 'maildir'
path = '~/Mail/lkml'
Gmail Target Parameters
type: Must be'gmail'credentials: Path to the OAuth credentials JSON filetoken: (Optional) Path to store the OAuth token. Defaults to~/.config/korgalore/gmail-{identifier}-token.json
Maildir Target Parameters
type: Must be'maildir'path: Path to the maildir directory (will be created if it doesn’t exist)
Maildir deliveries also support the subfolder delivery parameter, which
creates subdirectories under the base path. Subfolders can use strftime format
codes for date-based directories (e.g., %Y/%m becomes 2026/01). See
Delivery Parameters for details.
JMAP Targets
JMAP (JSON Meta Application Protocol) is a modern email protocol that provides efficient, JSON-based access to mail servers. Fastmail is the primary provider supporting JMAP.
Benefits:
Modern JSON API (more efficient than IMAP)
Native folder support
Unified authentication
Fast synchronization
Required Parameters:
type: Must bejmapserver: JMAP server URL (e.g.,https://api.fastmail.com)username: Your account email addresstokenortoken_file: API token for authentication
Getting a Fastmail API Token:
Log in to Fastmail
Go to Settings → Privacy & Security → Integrations
Click “New API Token”
Give it a name (e.g., “korgalore”)
Select permissions: Mail (read/write)
Copy the token and save it to a file
Example Configuration:
[targets.fastmail]
type = 'jmap'
server = 'https://api.fastmail.com'
username = '[email protected]'
token_file = '~/.config/korgalore/fastmail-token.txt'
Notes:
Labels are mapped to JMAP mailboxes/folders
Folder names are case-insensitive
Can use folder names (e.g., “INBOX”) or roles (e.g., “inbox”)
Messages are imported with original headers preserved
Authentication uses API bearer tokens only (OAuth is not implemented)
JMAP Target Parameters
type: Must be'jmap'server: JMAP server URL (e.g.,'https://api.fastmail.com')username: Your account email addresstoken: Bearer token provided inline (less secure)token_file: Path to file containing bearer tokentimeout: (Optional) Request timeout in seconds (default:60)
Important
Either token or token_file must be provided.
IMAP Target Parameters
type: Must be'imap'server: IMAP server hostname (e.g.,'imap.example.com')username: Your account username or email addressfolder: Target folder for delivery (default:'INBOX')auth_type: (Optional) Authentication type -'password'(default) or'oauth2'timeout: (Optional) Connection timeout in seconds (default:60)
For password authentication (auth_type = 'password' or omitted):
password: Password provided inline (less secure)password_file: Path to file containing password (recommended)
Important
Either password or password_file must be provided for password auth.
For OAuth2 authentication (auth_type = 'oauth2'):
client_id: (Optional) Azure AD Application (client) ID. Uses built-in default if not specified.tenant: (Optional) Azure AD tenant ID (default:'common')token: (Optional) Path to OAuth2 token file
See IMAP OAuth2 Setup (Microsoft 365) for detailed OAuth2 configuration.
Note
IMAP connections always use SSL on port 993 for security.
Pipe Target Parameters
type: Must be'pipe'command: Command to pipe messages to (can include arguments)
Feeds
Feeds define reusable feed URLs that can be referenced by multiple deliveries. This is useful when you want to import the same mailing list feed into different Gmail accounts with different labels.
[feeds.lkml]
url = 'https://lore.kernel.org/lkml'
[feeds.git]
url = 'https://lore.kernel.org/git'
Feed Parameters
url: The URL of the feed (must start withhttps:for lore feeds orlei:for lei searches)
Deliveries
Deliveries define mailing lists or lei searches to import from. A delivery can
reference a feed by name (defined in the feeds section) or use a direct URL.
Lore.kernel.org Deliveries
Deliveries can reference feeds by name or use direct URLs:
# Using a named feed (defined in the feeds section)
[deliveries.lkml]
feed = 'lkml'
target = 'personal'
labels = ['Lists/LKML']
# Using a direct URL
[deliveries.linux-doc]
feed = 'https://lore.kernel.org/linux-doc'
target = 'work'
labels = ['Lists/Docs', 'UNREAD']
Lei Deliveries
Note
This requires lei to be installed and configured separately.
You will need to first set up a lei query to write into a “v2” output. For example, this queries all messages where someone says “wtf”:
$ lei q --only=https://lore.kernel.org/all \
--output=v2:/home/user/lei/wtf \
--dedupe=mid \
'nq:wtf AND rt:1.week.ago..'
This will create a /home/user/lei/wtf hierarchy with a “git/0.git” subdirectory that korgalore will look at for updates.
You can add this feed into korgalore.conf now:
[deliveries.lei-wtf]
feed = 'lei:/home/user/lei/wtf'
target = 'work'
labels = ['INBOX', 'UNREAD']
Korgalore will run lei up automatically for you.
Delivery Parameters
feed: Name of a feed defined in thefeedssection, or a direct URL of a lore.kernel.org archive or lei search path (prefixed withlei:)target: Identifier of the target (must match a target name defined in thetargetssection)labels: List of labels to apply to imported messages (Gmail/JMAP only; ignored for maildir and IMAP targets)subfolder: (Optional) Subfolder path for IMAP and Maildir targetsFor IMAP: Combined with the target’s base folder (e.g.,
INBOX+Lists/LKML=INBOX/Lists/LKML)For Maildir: Creates a subdirectory under the target’s base path
Ignored for Gmail, JMAP, and pipe targets (use
labelsfor Gmail/JMAP)Must be a string, not a list
Maildir only: Supports strftime format codes for date-based directories (e.g.,
Archive/%Y/%mbecomesArchive/2026/01). The template is validated at startup. For CLI commands, the template is expanded once per invocation. For the GUI, the template is refreshed before each periodic sync to ensure messages are delivered to the correct date-based folder.
Example with subfolder (IMAP):
[targets.imap-server]
type = 'imap'
server = 'imap.example.com'
username = '[email protected]'
folder = 'INBOX' # Base folder
password_file = '~/.config/korgalore/imap-password.txt'
[deliveries.lkml]
feed = 'lkml'
target = 'imap-server'
subfolder = 'Lists/LKML' # Results in INBOX/Lists/LKML
Example with subfolder (Maildir):
[targets.local]
type = 'maildir'
path = '~/Mail' # Base path
[deliveries.lkml]
feed = 'lkml'
target = 'local'
subfolder = 'Lists/LKML' # Results in ~/Mail/Lists/LKML
[deliveries.git]
feed = 'git'
target = 'local'
subfolder = 'Lists/Git' # Results in ~/Mail/Lists/Git
Example with date-based archiving (Maildir only):
[targets.archive]
type = 'maildir'
path = '~/Mail/Archive'
[deliveries.lkml-archive]
feed = 'lkml'
target = 'archive'
subfolder = '%Y/%m' # Results in ~/Mail/Archive/2026/01
Gmail Labels
Note
This section only applies to Gmail targets. Maildir targets ignore labels.
Labels must exist in your Gmail account before importing messages, korgalore will not create them for you. You can list existing labels in your Gmail target by using:
kgl labels [targetname]
Complete Example
Here’s a complete configuration file example showing both Gmail and maildir targets:
### Targets ###
[targets.personal]
type = 'gmail'
credentials = '~/.config/korgalore/personal-credentials.json'
[targets.work]
type = 'gmail'
credentials = '~/.config/korgalore/work-credentials.json'
[targets.archive]
type = 'maildir'
path = '~/Mail/archive'
[targets.myserver]
type = 'imap'
server = 'imap.example.com'
username = '[email protected]'
folder = 'INBOX'
password_file = '~/.config/korgalore/imap-password.txt'
[targets.office365]
type = 'imap'
auth_type = 'oauth2'
server = 'outlook.office365.com'
username = '[email protected]'
[targets.processor]
type = 'pipe'
command = '/usr/local/bin/process-mail.sh'
### Feeds ###
[feeds.lkml]
url = 'https://lore.kernel.org/lkml'
[feeds.linux-doc]
url = 'https://lore.kernel.org/linux-doc'
[feeds.git]
url = 'https://lore.kernel.org/git'
### Deliveries ###
[deliveries.lkml]
feed = 'lkml' # References the feed defined above
target = 'work'
labels = ['Lists/LKML']
[deliveries.linux-doc]
feed = 'linux-doc' # References the feed defined above
target = 'work'
labels = ['Lists/Docs']
[deliveries.git]
feed = 'git' # References the feed defined above
target = 'personal'
labels = ['INBOX', 'UNREAD']
# Deliver the same feed to both Gmail and local maildir
[deliveries.lkml-archive]
feed = 'lkml' # Same feed as above!
target = 'archive' # Maildir target
labels = [] # Ignored for maildir targets
# Deliver to IMAP server (password auth)
[deliveries.lkml-imap]
feed = 'lkml'
target = 'myserver'
labels = [] # Ignored for IMAP targets
# Deliver to Microsoft 365 (OAuth2 auth)
[deliveries.lkml-office365]
feed = 'lkml'
target = 'office365'
labels = [] # Ignored for IMAP targets
# Deliver to pipe command for custom processing
[deliveries.lkml-process]
feed = 'lkml'
target = 'processor'
labels = ['--list=lkml'] # Appended as command line arguments
# Using a direct URL without a feed definition
# [deliveries.example-direct]
# feed = 'https://lore.kernel.org/example'
# target = 'work'
# labels = ['Lists/Example']
### GUI ###
[gui]
sync_interval = 300 # Sync every 5 minutes
# Lei source (commented out - requires lei setup)
# [deliveries.lei-mentions]
# feed = 'lei:/home/user/lei/mentions'
# target = 'work'
# labels = ['INBOX', 'UNREAD']
GUI Configuration
The [gui] section configures the GNOME taskbar application (kgl gui).
[gui]
sync_interval = 300
Parameters
sync_interval: Time in seconds between automatic syncs (default: 300, i.e., 5 minutes)
The GUI automatically reloads the configuration when you edit it via the “Edit Config…” menu item, so changes take effect without restarting.
Data Directory
Korgalore stores data in the XDG data directory:
~/.local/share/korgalore/
This directory contains:
Cloned git repositories for each lore mailing list
Epoch tracking information
Metadata about imported messages
You can override this by setting the XDG_DATA_HOME environment
variable, but then korgalore will lose your existing clones, so this is
not advised.
Main Section
The optional [main] section configures global korgalore behavior.
[main]
user_agent_plus = "abcd1234"
catchall_lists = ["[email protected]", "[email protected]"]
Parameters
user_agent_plus: (Optional) A string appended to the User-Agent header sent to remote servers. This helps server operators identify traffic from specific korgalore installations. The resulting User-Agent will bekorgalore/VERSION+VALUE(e.g.,korgalore/0.5+abcd1234).catchall_lists: (Optional) List of mailing list addresses to exclude fromtrack-subsystemqueries. These are high-volume lists that receive copies of most kernel patches and would flood subsystem-specific queries with irrelevant messages. Default:catchall_lists = [ "[email protected]", "[email protected]", ]
Set to an empty list
[]to include all mailing lists in queries.
Logging
Enable verbose logging with the -v LEVEL option:
kgl -v DEBUG pull
Save logs to a file with --logfile:
kgl --logfile /tmp/korgalore.log pull