
Some companies still run Exchange or Microsoft 365 and block plain IMAP. Meanwhile, you live in Thunderbird, Evolution, mutt, aerc or a cron job that needs to fetch mail. That mismatch causes a surprising amount of daily friction for Linux users in corporate environments. DavMail closes the gap. It is a small Java gateway that talks to Exchange (EWS, and increasingly Graph and OAuth flows) on one side and exposes standard POP, IMAP, SMTP, CalDAV, CardDAV and LDAP on the other.
Fedora 44 is a good host for it, with a few caveats. The distribution moves fast, and its Java situation differs from Ubuntu LTS or AlmaLinux. Fedora’s default OpenJDK line is 25, and older Java 21 package names no longer resolve in the standard repositories. Anyone copying a three-year-old tutorial that says dnf install java-11-openjdk will hit a wall within a minute.
This guide covers the whole path, in the order a production admin would actually do it. It starts with choosing an install method, then moves to installation, first-run configuration for Office 365 with modern authentication, and running DavMail as a locked-down systemd service. After that come client setup, tuning, troubleshooting and the mistakes that cost people hours. The commands are written for Fedora 44, with notes where Debian, Ubuntu or AlmaLinux behave differently.
What DavMail Does and When You Need It
DavMail is a gateway, not a mail server. It stores nothing permanently. A client connects to localhost on a port such as 1143 for IMAP, and DavMail translates the request into Exchange calls, then translates the response back. The project describes itself as a POP/IMAP/SMTP/CalDAV/CardDAV/LDAP gateway, with packages for macOS, Linux and Windows.
The typical reasons to deploy it:
- The organization disabled basic IMAP and SMTP AUTH on Exchange Online, and the mail client you prefer has no native modern-auth support.
- You want calendar and contacts in a CalDAV/CardDAV client such as Thunderbird, GNOME Calendar or Evolution, without paying for a proprietary connector.
- A script needs to pull mail, for example a DMARC aggregate report parser. The parsedmarc documentation describes DavMail as a local EWS/OWA IMAP gateway that can work where modern authentication or MFA is required.
- You run a terminal mail stack (mbsync, msmtp, notmuch, neomutt) and need an IMAP endpoint.
If your IT department already offers IMAP with OAuth2 and your client supports it, you may not need DavMail. If neither is true, it is probably the least painful route.
Choosing an Install Method on Fedora 44
There are three realistic options. Each has a different maintenance cost.
| Method | Best for | Updates | Notes |
|---|---|---|---|
Fedora COPR (mguessan/davmail) |
Desktops and servers on Fedora | Through dnf upgrade |
Maintained by the DavMail author, per the project’s Linux setup page |
| Flathub | Desktop users who like sandboxing | flatpak update |
Sandboxing complicates headless use and file access |
| Upstream zip/tarball | Isolated daemon, custom paths | Manual | Total control, you own the update process |
For most Fedora 44 machines, COPR is the right answer. The DavMail download page lists Fedora and RedHat packages on COPR, and the official Linux setup page tells Fedora and CentOS users to enable the COPR repository and install the davmail package. You get dependency resolution and routine upgrades. The tradeoff is that COPR is a third-party repository. It is not signed by Fedora’s main infrastructure, so treat it like any external repo and review what it installs.
Flathub is fine for a laptop. For a server-mode daemon feeding scripts, skip it. Flatpak sandboxing adds friction around ports and persistent config paths.
Prerequisites Before You Touch dnf
Spend two minutes here and you save twenty later.
Check the release and the state of the system:
cat /etc/fedora-release
sudo dnf upgrade --refresh -y
sudo systemctl reboot
Rebooting after a big upgrade is not superstition. A newer kernel plus a replaced Java runtime means stale processes may still hold old libraries.
Collect this information from the mailbox owner or your IT team:
- Whether the mailbox is Exchange Online (Office 365), on-premises Exchange, or a sovereign cloud such as GCC High.
- Whether MFA is enforced. Almost certainly yes for Exchange Online.
- Whether the tenant allows the default DavMail OAuth application, or whether a tenant admin must approve consent.
- The tenant ID, if the organization restricts third-party apps.
That last point is where many installations stall. The software may be perfect while a conditional access policy blocks the client ID. Knowing this beforehand turns a mystery into a ticket.
Step 1: Install Java on Fedora 44
The COPR RPM should pull in a Java runtime as a dependency. Installing one explicitly lets you control which Java is used and makes later troubleshooting simpler.
On Fedora 44, the Java situation looks like this. The java-25-openjdk packages exist in the updates repository, and java-latest-openjdk tracks the newest release, with an August update bringing it to version 26.0.2.1.0. For a gateway that runs continuously, prefer the long-term-support line (25) over the rolling java-latest package. A rolling runtime can change major version between updates.
sudo dnf install -y java-25-openjdk-headless
java -version
Headless is enough for server mode, where nobody needs a tray icon or a login window. If you plan to use interactive OAuth sign-in (the browser-like window), you need a Java build with a UI toolkit available. The upstream properties file notes that O365Interactive requires OpenJFX or SWT and is not available in headless mode. For that first login, run DavMail on a machine with a desktop session, then move the token to your server. More on that later.
For a desktop install, install the full runtime:
sudo dnf install -y java-25-openjdk
Should multiple Java versions be present, pick the default deliberately:
sudo alternatives --config java
Step 2: Enable COPR and Install DavMail
First make sure the COPR plugin is available. On a minimal Fedora Server install it may not be:
sudo dnf install -y dnf-plugins-core
Then enable the repository and install, exactly as the project documents:
sudo dnf copr enable mguessan/davmail
sudo dnf install -y davmail
You will be asked to confirm that COPR repositories are third-party. Read the prompt, accept it, and then verify what you installed:
rpm -qi davmail
rpm -ql davmail | head -40
The rpm -ql output is the part many people skip. It shows you where the launcher script, the jar files, any systemd unit, and the sample properties file landed. Packaging details vary between releases, so do not assume a particular path from a blog post, including this one. Confirm on your own system.
Confirm the launcher exists:
command -v davmail
A Note on Desktop Tray Icons
On GNOME, a stock Fedora desktop has no system tray. The DavMail Linux page specifically says tray icon support is not available by default on Fedora with GNOME, and suggests either running in window mode or installing AppIndicator and KStatusNotifierItem support. Many first-time users launch DavMail, see nothing, and conclude it crashed. It did not. It is sitting in a tray that does not exist.
sudo dnf install -y gnome-shell-extension-appindicator
Log out and back in, then enable the extension in the Extensions app.
Step 3: Decide Between Desktop Mode and Server Mode
DavMail runs in two broad modes, and mixing them up leads to the strangest bugs.
Desktop mode runs under your user account. Settings go to ~/.davmail.properties, a hidden file in your home directory, as the FAQ explains. A GUI settings window and tray icon are available. This is ideal for a single person on a laptop.
Server mode runs as a daemon with davmail.server=true and an explicit properties file. The server setup documentation notes that on first start the service creates a default properties file in the DavMail directory, which is different from user mode. Use it for shared machines, headless boxes, and anything that feeds cron jobs.
Pick one per instance. Running both with overlapping ports yields “address already in use” errors that look like a firewall problem and are nothing of the sort.
Step 4: Configure DavMail for Office 365 With Modern Authentication
The old WebDAV and form-based OWA paths are largely irrelevant for Exchange Online today. The FAQ states that the Office 365 EWS endpoint is standard for all customers: https://outlook.office365.com/EWS/Exchange.asmx, with the mode set to EWS. Modern authentication then comes in several flavors:
- O365Interactive: opens an authentication window so you can enter credentials and pass MFA and consent.
- O365Modern: same logic, but it uses client-provided credentials for OAuth negotiation and triggers the phone app MFA check transparently.
- O365Manual: you copy a URL, authenticate in any browser, and paste the resulting code back. This one suits headless servers.
Desktop Walkthrough
- Launch DavMail from the application menu or run
davmailin a terminal. - In settings, set the OWA/EWS URL to
https://outlook.office365.com/EWS/Exchange.asmx. - Choose the Office 365 interactive authentication mode.
- Leave the ports at their defaults unless something else owns them.
- Open Thunderbird or another client, point it at localhost, and attempt to fetch mail. The login window appears at that moment.
- Complete sign-in and consent.
The first connection triggers authentication, not the launch itself. Plenty of users wait for a prompt that never appears because no client has connected yet.
Server Walkthrough With a Properties File
Create a dedicated system account. This follows the pattern shown in the parsedmarc DavMail guide:
sudo useradd --system --home-dir /var/lib/davmail --create-home --shell /usr/sbin/nologin davmail
sudo install -d -o root -g davmail -m 0750 /etc/davmail
Now write a minimal configuration. The key names below come from upstream’s sample properties. Anything you do not set falls back to a default:
# /etc/davmail/davmail.properties
davmail.server=true
davmail.mode=O365Manual
davmail.url=https://outlook.office365.com/EWS/Exchange.asmx
# Listeners (localhost only)
davmail.bindAddress=127.0.0.1
davmail.allowRemote=false
davmail.imapPort=1143
davmail.smtpPort=1025
davmail.caldavPort=1080
davmail.popPort=
davmail.ldapPort=
# TLS to clients disabled because traffic never leaves loopback
davmail.ssl.nosecureimap=true
davmail.ssl.nosecuresmtp=true
davmail.ssl.nosecurecaldav=true
# OAuth token persistence
davmail.oauth.persistToken=true
# Keepalive during large downloads
davmail.enableKeepalive=true
davmail.folderSizeLimit=0
Leaving davmail.popPort and davmail.ldapPort empty disables those listeners, which cuts your attack surface. If you want them, set a port. Do not run listeners you do not use.
Lock the file down. It can end up containing a refresh token, which is effectively a long-lived credential for the mailbox:
sudo chown root:davmail /etc/davmail/davmail.properties
sudo chmod 0640 /etc/davmail/davmail.properties
There is a catch. With persistToken=true, DavMail writes the token back into the properties file. The write is performed by the service user, so the service account needs write access. Adjust the file mode to 0660 with group davmail, or place the file in a directory the service account owns. One reader-friendly writeup of this pattern notes that the persistToken flag, which defaults to true, appends a refresh token to the end of the properties file after the first successful connection, and that token handles later automatic authentication. Plan permissions around that behavior so that restarts do not fail with a write error.
Getting the First Token on a Headless Server
This is the part that distinguishes people who have deployed DavMail from those who have only read about it. A headless host cannot show a login window, so you do it in two phases. The procedure documented by one admin who runs DavMail as a daemon looks like this:
- Stop the service if it is running.
- Set the mode to
O365Manualin the properties file. - Run DavMail manually with the properties file as the argument.
- Force a connection to the listening port, for instance by fetching mail or sending a message.
- Follow the instructions printed to the terminal where DavMail was started.
- Switch the mode to
O365Modernand restart the systemd service.
In practice that looks like:
sudo systemctl stop davmail 2>/dev/null
sudo -u davmail davmail /etc/davmail/davmail.properties
From another terminal, trigger a connection:
curl -v telnet://127.0.0.1:1143
Or, more usefully, point a real client at it. DavMail prints a URL. Open that URL in any browser on any machine, sign in, approve MFA and consent, and copy back the code or redirected address as instructed. The token lands in the properties file. Afterwards change davmail.mode to O365Modern and start the daemon normally.
Client ID and Tenant ID
The default client application ID ships with DavMail, and the sample properties show it commented out, with redirect URI https://localhost/common/oauth2/nativeclient and tenant common. The FAQ explains you can substitute your own application registered in Azure AD if you have the rights, using davmail.oauth.clientId and davmail.oauth.redirectUri, and optionally davmail.oauth.tenantId.
Why would you do that? Two reasons. Some tenants block or restrict unknown multi-tenant apps, and a tenant admin may register a first-party-approved app instead. Others want audit trails tied to an application they own. In both cases, coordinate with whoever administers Entra ID. The scope for EWS access, which appears in the upstream sample, is openid profile offline_access https://outlook.office365.com/EWS.AccessAsUser.All.
Sovereign clouds are a separate case. A Mozilla bug report on GCC High describes a workaround in which the user adds davmail.tld=us to the properties file and uses one of the O365Modern, O365Manual, or O365Interactive modes. If your tenant is not the commercial cloud, search for the equivalent setting before spending an afternoon on opaque login errors.
Step 5: Run DavMail as a Hardened systemd Service
Check first whether the RPM already ships a unit file (rpm -ql davmail | grep -i service). If it does, use a drop-in override instead of replacing it. If not, here is a unit written for server mode. Adjust ExecStart to the actual launcher path from command -v davmail:
# /etc/systemd/system/davmail.service
[Unit]
Description=DavMail Exchange gateway
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=davmail
Group=davmail
ExecStart=/usr/bin/davmail /etc/davmail/davmail.properties
Restart=on-failure
RestartSec=10
# Hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectControlGroups=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
ReadWritePaths=/etc/davmail /var/lib/davmail /var/log/davmail
LogsDirectory=davmail
StateDirectory=davmail
[Install]
WantedBy=multi-user.target
Why each hardening line matters:
ProtectSystem=strictmakes almost the whole filesystem read-only for this service, so a compromised process cannot modify binaries.ReadWritePathscarves out only the places DavMail genuinely needs, including the properties file for token persistence.RestrictAddressFamiliesblocks exotic socket types.NoNewPrivilegesprevents privilege escalation through setuid binaries.
Enable and start it:
sudo systemctl daemon-reload
sudo systemctl enable --now davmail
sudo systemctl status davmail --no-pager
journalctl -u davmail -f
The parsedmarc guide follows the same overall flow of daemon-reload, enable, restart. Check the listeners afterward:
ss -tlnp | grep -E '1143|1025|1080'
You should see them bound to 127.0.0.1. If you see 0.0.0.0 or *, something in your configuration overrides the bind address, and that needs fixing before anything else.
SELinux on Fedora
Fedora ships with SELinux enforcing. A service started from a custom path may be denied access to files, or denied binding to unusual ports. Check for denials rather than disabling SELinux:
sudo ausearch -m avc -ts recent
sudo journalctl -t setroubleshoot --since "10 min ago"
If a file you created lives in a non-standard location, restorecon -Rv /etc/davmail often fixes the label. Turning SELinux off to make a gateway start is a bad trade, and it rarely turns out to be necessary.
Step 6: Open the Firewall Only If You Must
By default, DavMail should talk to clients on loopback only. In that case, firewalld needs no changes at all. That is the safest configuration and the correct one for most setups.
If a second machine on your LAN truly must reach the gateway, there is a smarter approach than opening the ports broadly. First set davmail.allowRemote=true and a specific davmail.bindAddress. Then restrict by source with a rich rule:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port port="1143" protocol="tcp" accept'
sudo firewall-cmd --reload
Also turn on TLS for those listeners, because IMAP and SMTP to a remote client would otherwise carry the mailbox password and mail content in cleartext. Configure a keystore with davmail.ssl.keystoreFile and related options, and remove the nosecure* settings. Exposing an Exchange gateway to a network without TLS counts as a real incident waiting to happen.
Step 7: Connect a Mail Client
Thunderbird
Create a new account manually using these values:
- Incoming: IMAP, server
127.0.0.1, port1143, security “None”, authentication “Normal password”. - Outgoing: SMTP, server
127.0.0.1, port1025, security “None”, authentication “Normal password”. - Username: your full Exchange address.
“None” for security sounds alarming. On loopback, the traffic never leaves the machine, and DavMail handles the encrypted connection to Microsoft on its own side. Thunderbird may complain that the connection is insecure. That warning is expected here.
For calendars, add a CalDAV network calendar at http://127.0.0.1:1080/users/you@example.com/calendar. Contacts through CardDAV use the same host and port.
Terminal Stack
A minimal msmtp entry:
account work
host 127.0.0.1
port 1025
from you@example.com
user you@example.com
auth plain
tls off
passwordeval "secret-tool lookup service davmail user you@example.com"
With mbsync, set SSLType None for the local IMAP account and use PassCmd with the same secrets backend. Do not store passwords in plaintext dotfiles. With OAuth-based modes, the password you supply to the client is often irrelevant to Microsoft, because the token does the real authentication. Many clients still demand a non-empty field.
Performance Tuning
DavMail is light, but “light” gets relative when someone points a mailbox with 80,000 messages at it. A few things matter in practice.
Memory. Java heap defaults may be too small for large mailboxes or too greedy on a tiny VPS. Cap it deliberately. If the launcher respects JAVA_OPTS or a davmail.conf-style file (check the script), set something like -Xms64m -Xmx512m. Watch real usage with systemctl status davmail and ps -o rss,cmd -C java for a week before settling on a number.
Initial sync storms. The first IMAP sync from a fresh client enumerates every folder. This hammers EWS and risks throttling. Exchange Online throttles per-user, and aggressive clients can trigger throttling responses that surface as odd timeouts. Syncing a handful of folders first, and increasing parallelism cautiously, is much kinder. In mbsync, limit MaxMessages or sync only selected channels initially.
Folder size limits. The sample config exposes davmail.folderSizeLimit as a cap on message count during folder retrieval, with 0 meaning no limit. If a client chokes on a giant folder like “Archive”, a limit can keep it responsive, with the tradeoff that older messages will not appear.
Keepalive. davmail.enableKeepalive=true sends keepalive characters during large downloads so clients do not time out. Enable it for large attachments over slow VPN links.
Disk I/O. DavMail itself writes little. Your mail client’s local cache is the real I/O consumer. Put Maildir or the Thunderbird profile on SSD storage and keep noatime in mind for Maildir trees with huge file counts.
Network. If you reach Microsoft through a corporate proxy, configure it explicitly. The sample properties include proxy settings such as davmail.enableProxy, davmail.proxyHost, davmail.proxyPort, and a davmail.noProxyFor exclusion list. Verify DNS resolution and outbound 443 first. Half of “DavMail is slow” tickets turn out to be a congested VPN.
Troubleshooting Common DavMail Errors on Fedora 44
“Package davmail not found” after enabling COPR
Confirm the repository is active and the release is supported:
dnf copr list
dnf repolist | grep -i davmail
sudo dnf clean all && sudo dnf makecache
COPR builds for a brand-new Fedora release sometimes lag by days or weeks. Check the COPR project page for a Fedora 44 chroot. If it is missing, fall back to the upstream zip, or a Flatpak, until the build appears.
Java errors, “Unable to locate a Java Runtime”
You probably installed a Java package name that no longer exists on Fedora 44. Use the 25 line or java-latest-openjdk:
dnf search openjdk | grep -E 'java-(25|latest)'
sudo dnf install -y java-25-openjdk-headless
DavMail starts but nothing appears on the desktop
The GNOME tray problem described earlier. Install AppIndicator support or switch to window mode.
Login window never opens
Interactive mode needs a graphical Java stack, and the authentication UI is unavailable in headless mode. On a server, use O365Manual. On a desktop, make sure a client actually attempted a connection, because authentication begins on demand.
“Address already in use”
sudo ss -tlnp | grep -E '1143|1025|1080'
ps aux | grep -i davmail
Typically a desktop DavMail instance and a server-mode daemon are both trying to start. Stop one. Alternatively change the ports.
Authentication loops, AADSTS errors, or consent denied
These come from Microsoft’s side. Read the exact AADSTS code in the DavMail log. Common causes include a tenant that requires admin consent, conditional access blocking legacy flows, or a client ID not permitted in the tenant. The FAQ describes giving consent on first call, and says that with O365Modern you can obtain the actual URL from the DavMail log. If consent is blocked at the tenant level, request approval or ask for your own app registration with the right redirect URI.
Token not persisted, login required after every restart
Check that davmail.oauth.persistToken=true and that the service account can write to the properties file. With ProtectSystem=strict, an omitted ReadWritePaths entry produces this exact symptom. Look for permission denied messages in the journal.
Works for a while, then fails
A refresh token can expire after long inactivity, or get revoked after a password change or a security policy event. Repeat the manual token procedure. Also confirm that system time is accurate (timedatectl), since clock drift breaks token validation.
Thunderbird says the certificate or connection is untrusted
You enabled TLS on the local listener with a self-signed certificate. Either import that certificate into the client’s trust store or, for loopback only, disable TLS on the listeners and keep them bound to localhost.
Slow folder listing or timeouts
Reduce the folder scope, increase client timeouts, set the keepalive option, and inspect the journal for throttling messages. Exchange Online imposes limits, and hammering it with parallel connections rarely helps.
Enabling debug logs
Raise the log level in the properties file (the log4j.logger.davmail setting is documented in the upstream sample) and reproduce the issue once. Do not leave debug logging on permanently, because logs at that level can contain sensitive data.