Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .github/workflows/build-release-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Build and push the release docker image

on:
push:
tags:
- '*'

jobs:
build-release-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Get tag
run: |
TAG=$(echo $GITHUB_REF | sed 's/refs\/tags\///')
echo "TAG=$TAG" >> $GITHUB_ENV
echo "Releasing version $TAG"

- name: Checkout at tag
run: git checkout tags/${{ env.TAG }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push release
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ env.TAG }}
cache-from: type=gha
cache-to: type=gha,mode=max
42 changes: 42 additions & 0 deletions .github/workflows/build-trunk-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Build and push the trunk docker image

on:
push:
branches:
- trunk

jobs:
build-trunk-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: 'trunk'

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push trunk
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:trunk
cache-from: type=gha
cache-to: type=gha,mode=max
40 changes: 40 additions & 0 deletions .github/workflows/build-unstable-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Build and push the unstable docker image

on:
push:
branches:
- main

jobs:
build-unstable-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push unstable
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:unstable
cache-from: type=gha
cache-to: type=gha,mode=max
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ An alternative is COPR on Fedora:

[![Copr build status](https://copr.fedorainfracloud.org/coprs/mguessan/davmail/package/davmail/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/mguessan/davmail)

### Docker

To run davmail in docker, please read [src/contribs/docker/README.md](https://github.com/mguessan/davmail/blob/master/src/contribs/docker/README.md)
Copy link

@esabol esabol Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Change "davmail in docker" to "DavMail in a Docker container".

Other than this minor change, everything looks good to me. 😄



## Trunk builds
Latest working builds are now available on Appveyor:

Expand Down
43 changes: 23 additions & 20 deletions src/contribs/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
FROM ubuntu:24.10 AS davbase
RUN mkdir -m 1777 -p /home; chmod 1777 /home
RUN mkdir /davmail
RUN apt-get update && apt-get -y dist-upgrade
RUN apt-get install -y iputils-ping iproute2 strace git x11-apps default-jre libcommons-codec-java libcommons-logging-java libhtmlcleaner-java libhttpclient-java libjackrabbit-java libjcifs-java libjettison-java libjna-java liblog4j1.2-java libmail-java libopenjfx-java libservlet-api-java libslf4j-java libstax2-api-java libswt-cairo-gtk-4-jni libswt-gtk-4-java libwoodstox-java
FROM debian:12 AS base
RUN apt-get update

FROM davbase AS davbuild
RUN apt-get install -y debhelper-compat javahelper ant ant-optional

# First we build the jar file
FROM base AS builder
WORKDIR /davmail

FROM davbase AS davupstream
RUN apt-get install -y davmail
RUN apt-get install -y ant git
COPY . .
RUN ant -Dfile.encoding=UTF-8


FROM davbase AS davmail
ADD davmail-compile.tar /davmail
# Then we run the jar file
FROM base AS runner
WORKDIR /davmail

RUN apt-get install -y openjdk-17-jre libcommons-codec-java libcommons-logging-java libhtmlcleaner-java libhttpclient-java libjackrabbit-java libjcifs-java libjettison-java libjna-java liblog4j1.2-java libmail-java libopenjfx-java libservlet-api-java libslf4j-java libstax2-api-java libswt-cairo-gtk-4-jni libswt-gtk-4-java libwoodstox-java

# Copy jar file
COPY --from=builder /davmail/dist/davmail.jar /davmail/davmail.jar

# Copy default davmail.properties and set tokenFilePath
COPY --from=builder /davmail/src/etc/davmail.properties /config/davmail.properties
RUN sed -i 's/#davmail.oauth.tokenFilePath=/davmail.oauth.tokenFilePath=\/config\/.env.oauth/' /config/davmail.properties

VOLUME [ "/config" ]
EXPOSE 1110 1025 1143 1080 1389
COPY entrypoint /entrypoint
ENTRYPOINT [ "/entrypoint" ]
ENV XAUTHORITY=/.Xauthority
ENV DISPLAY=:0
VOLUME [ "/tmp/.X11-unix" ]
VOLUME [ "/.Xauthority" ]
VOLUME [ "/davmail.properties" ]
VOLUME [ "/etc/passwd:/etc/passwd:ro" ]
VOLUME [ "/etc/group:/etc/group:ro" ]

COPY --from=builder /davmail/src/contribs/docker/entrypoint.sh /davmail/entrypoint.sh
ENTRYPOINT [ "/davmail/entrypoint.sh" ]
59 changes: 32 additions & 27 deletions src/contribs/docker/Makefile
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
SUBTAG=:next
DTARGETS=davmail$(SUBTAG) davbuild$(SUBTAG)
LOCATION_OF_DAVMAIL_ROOT=$$PWD/../../..

all: build davmail

davbuild davmail davupstream davbase:
docker build --target $@ -t $@$(SUBTAG) .

clean:
rm -f davmail-compile.tar *~
-docker rmi $(DTARGETS)

build: davbuild indirect

indirect: indirect_compile indirect_archive

indirect_compile:
docker run -it --memory=1.5g --cpus .3 --rm --name davmail-build -u "$$UID" --entrypoint "" -v "${LOCATION_OF_DAVMAIL_ROOT}:/src" -w /src "davbuild$(SUBTAG)" ant -lib /usr/share/java jar

indirect_archive:
tar -cf davmail-compile.tar -C ${LOCATION_OF_DAVMAIL_ROOT}/dist .

test:
docker run -it --memory=1.5g --cpus .3 --network=host --rm --name davmail -v /tmp/.X11-unix:/tmp/.X11-unix -e JAVA_OPT_USER=-Dsun.java2d.uiScale=2.0 -e "DISPLAY=$${DISPLAY}" -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -v "$${XAUTHORITY:-$$HOME/.Xauthority}:/.Xauthority:ro" -v $$HOME/.davmail.properties.core:/davmail.properties:ro -v $$HOME/.davmail.properties.toks:/davmail.properties.tokens:rw -u "$$UID" davmail:next

.PHONY: all build davmail davbuild davupstream clean indirect indirect_compile indirect_archive
IMAGE_NAME = mguessan/davmail
IMAGE_VERSION ?= ""

ifeq ($(IMAGE_VERSION),"")
IMAGE_LABEL ?= $(IMAGE_NAME)
else
IMAGE_LABEL ?= $(IMAGE_NAME):${IMAGE_VERSION}
endif

image:
@echo "Building Docker image ${IMAGE_LABEL}..."
docker build . -t $(IMAGE_LABEL)

tag-latest-without-build:
@echo "Tagging Docker image ${IMAGE_LABEL} with latest..."
docker tag `docker image ls --format '{{.ID}}' $(IMAGE_LABEL)` $(IMAGE_NAME):latest

run:
@echo "Starting davmail"
docker compose up -d

run-gui:
@echo "Running davmail with GUI (to get token)"
docker run --network=host --rm --name davmail --hostname davmail \
-u "$UID" \
-e "DISPLAY=${DISPLAY}" \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v "${XAUTHORITY:-$HOME/.Xauthority}:/.Xauthority:ro" \
-v ./config:/config \
davmail davmail --token

latest: image tag-latest-without-build
90 changes: 90 additions & 0 deletions src/contribs/docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Davmail Docker

To run davmail in Docker, download the `compose.yml` file and run `docker compose up -d`.

Make sure to change the ports in the `compose.yml` file to make sure you are not exposing them to the public (unless you want that, of course).

If you want to set up OAuth2, but your host is headless/does not have access to a GUI, please see below

If you want to set up SSL/certificates, scroll down to SSL

# OAuth2 on headless

Download the `Dockerfile` on your **PC** (needs GUI access) and run the commands below

```
docker build . -t davmail # this might take a bit
docker run --network=host --rm --name davmail --hostname davmail -v /tmp/.X11-unix:/tmp/.X11-unix -e "DISPLAY=${DISPLAY}" -v "${XAUTHORITY:-$HOME/.Xauthority}:/.Xauthority:ro" -v ./config:/config -u "$UID" davmail davmail --token
```

A new window should pop up with a few settings. Please change "Exchange Protocol" from `EWS` to for example `O365Manual` (or whatever method you want to use, see [Exchange protocol](https://davmail.sourceforge.net/gettingstarted.html)) and press "Save"

Next, open your email client, e.g. thunderbird. Add a new account and make sure to click "Configure manually" or something like that.

Set receiving/incoming (IMAP) as following:
- hostname: `localhost`
- port: `1143`
- Connection security: `none`
- Authentication method: `Normal password`

Set sending/outgoing (SMTP) as following:
- hostname: `localhost`
- port: `1025`
- Connection security: `none`
- Authentication method: `Normal password`

Both using username `<email>` and password `<password>`. Note that `<email>` has to match the email you want log in to (using oauth2), and `<password>` can be ANY password, even different than your account password.

After pressing connect on the email client (sometimes you may need to ignore ssl warnings), the GUI from davmail should show instructions on how to authenticate (depending on the Exchange Protocol you set before). Please follow these instructions and confirm that your account is now connected. To move the configuration to your server/headless instance, stop the docker container (Ctrl+C) and type `cat config/davmail.properties`.

At the bottom, there is an entry called `davmail.oauth.<email>.refreshToken={AES}...`. Edit `config/.env.oauth` on your server to include `<email>={AES}...` and restart the container.

You can now configure your email client again using the same steps before, but instead of localhost you should use your server ip (make sure you put in the same `<password>`).

# SSL

Below are two methods described to setup SSL. Either using a service like `letsencrypt` or providing your own certificate, or using `traefik` (a reverse proxy).

## Letsencrypt/own certificate

If you are running davmail on your server, make sure to setup SSL. In order to do this, use a service like letsencrypt or create a self signed certificate. In the case of letsencrypt, go to `certs/live/<DOMAIN>` and run the following command

```
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -certfile cert.pem -out davmail.p12
```

Make sure to set a password `<password2>` and make sure it is different than `<password>` (it can be the same, but for your own sake use a different one, please).

Move the new `davmail.p12` file over to the `config` directory on your server, edit `config/davmail.properties` (make sure to put the correct `<password2>`!).
```
davmail.ssl.keystoreType=PKCS12
davmail.ssl.keyPass=<password2>
davmail.ssl.keystoreFile=/davmail.p12
davmail.ssl.keystorePass=<password2>
```

Restart your container and go to your email client. Go to account settings and enable SSL (keep the same ports) and connect.

## Traefik

Note that communication between your email client and traefik will be encrypted, and then traefik will forward the unencrypted traffic (through the docker's internal network) to your DavMail instance. This way, you don't have to add another certificate manager if you are already using traefik to handle your certificates.

First download the new `compose-traefik.yml` from this directory and rename it to `compose.yml`. Then edit/create a `.env` file and put
```
DOMAIN=domain.com
```

This means that you can access your davmail instance over `davmail.domain.com`, make sure to change domain.com such that traefik can generate a certificate for it.


To use traefik to manage your certificate, change your `traefik.yml` config (or `.toml`, depending on you traefik configuration) and add the following entrypoints:

```
entryPoints:
imap-tls:
address: :1143
smtp-tls:
address: :1025
```

Then change the `compose.yml` where you have you traefik instance, expose port 1143 and 1025 (and others if needed) and make sure that both davmail and traefik share a docker network. At last, run `docker compose up -d` for both traefik and davmail and now you can point your email clients to `davmail.domain.com` and enable SSL (note that the port stays the same).
26 changes: 26 additions & 0 deletions src/contribs/docker/compose-traefik.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
services:
davmail:
container_name: davmail
hostname: davmail
image: ghcr.io/mguessan/davmail:stable
restart: unless-stopped
volumes:
- ./config:/config
labels:
- traefik.enable=true
# Used for SSl cert
- traefik.http.routers.davmail.rule=Host(`davmail.${DOMAIN}`)
- traefik.http.routers.davmail.service=noop@internal
- traefik.http.routers.davmail.middlewares=sso-required@file
# IMAP
- traefik.tcp.routers.imap-tls.rule=HostSNI(`*`)
- traefik.tcp.routers.imap-tls.entrypoints=imap-tls
- traefik.tcp.routers.imap-tls.service=imap-tls
- traefik.tcp.services.imap-tls.loadbalancer.server.port=1143
- traefik.tcp.routers.imap-tls.tls=true
# SMTP
- traefik.tcp.routers.smtp-tls.rule=HostSNI(`*`)
- traefik.tcp.routers.smtp-tls.entrypoints=smtp-tls
- traefik.tcp.routers.smtp-tls.service=smtp-tls
- traefik.tcp.services.smtp-tls.loadbalancer.server.port=1025
- traefik.tcp.routers.smtp-tls.tls=true
13 changes: 13 additions & 0 deletions src/contribs/docker/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# See src/contribs/docker/README.md for instructions

services:
davmail:
container_name: davmail
hostname: davmail
image: ghcr.io/mguessan/davmail:stable
restart: unless-stopped
ports:
- 127.0.0.1:1025:1025 # SMTP
- 127.0.0.1:1143:1143 # IMAP
volumes:
- ./config:/config
Loading