Compare commits

..

3 Commits

Author SHA1 Message Date
holger krekel
3fe29be4d9 add a test for imap capabilities offered from chatmail 2024-05-06 15:59:35 +02:00
holger krekel
2ffce508bd add chatmail entry 2024-05-06 14:32:24 +02:00
holger krekel
49b4bad8c3 add XCHATMAIL marker 2024-05-06 14:31:46 +02:00
42 changed files with 151 additions and 407 deletions

View File

@@ -7,9 +7,6 @@ on:
pull_request:
paths-ignore:
- 'scripts/**'
- '**/README.md'
- 'CHANGELOG.md'
- 'LICENSE'
jobs:
deploy:

View File

@@ -2,27 +2,6 @@
## untagged
## 1.3.0 - 2024-06-06
- don't check necessary DNS records on cmdeploy init anymore
([#316](https://github.com/deltachat/chatmail/pull/316))
- ensure cron and acl are installed
([#293](https://github.com/deltachat/chatmail/pull/293),
[#310](https://github.com/deltachat/chatmail/pull/310))
- change default for delete_mails_after from 40 to 20 days
([#300](https://github.com/deltachat/chatmail/pull/300))
- save journald logs only to memory and save nginx logs to journald instead of file
([#299](https://github.com/deltachat/chatmail/pull/299))
- fix writing of multiple obs repositories in `/etc/apt/sources.list`
([#290](https://github.com/deltachat/chatmail/pull/290))
- metadata: add support for `/shared/vendor/deltachat/irohrelay`
([#284](https://github.com/deltachat/chatmail/pull/284))
- Emit "XCHATMAIL" capability from IMAP server
([#278](https://github.com/deltachat/chatmail/pull/278))

View File

@@ -15,8 +15,6 @@ after which the initially specified password is required for using them.
## Deploying your own chatmail server
To deploy chatmail on your own server, you must have set-up ssh authentication and need to use an ed25519 key, due to an [upstream bug in paramiko](https://github.com/paramiko/paramiko/issues/2191). You also need to add your private key to the local ssh-agent, because you can't type in your password during deployment.
We use `chat.example.org` as the chatmail domain in the following steps.
Please substitute it with your own domain.

View File

@@ -36,16 +36,6 @@ log_format = "%(asctime)s %(levelname)s %(message)s"
log_date_format = "%Y-%m-%d %H:%M:%S"
log_level = "INFO"
[tool.ruff]
lint.select = [
"F", # Pyflakes
"I", # isort
"PLC", # Pylint Convention
"PLE", # Pylint Error
"PLW", # Pylint Warning
]
[tool.tox]
legacy_tox_ini = """
[tox]
@@ -57,9 +47,10 @@ skipdist = True
skip_install = True
deps =
ruff
black
commands =
ruff format --quiet --diff src/
ruff check src/
black --quiet --check --diff src/
ruff src/
[testenv]
deps = pytest

View File

@@ -20,7 +20,6 @@ class Config:
self.passthrough_recipients = params["passthrough_recipients"].split()
self.filtermail_smtp_port = int(params["filtermail_smtp_port"])
self.postfix_reinject_port = int(params["postfix_reinject_port"])
self.iroh_relay = params.get("iroh_relay")
self.privacy_postal = params.get("privacy_postal")
self.privacy_mail = params.get("privacy_mail")
self.privacy_pdo = params.get("privacy_pdo")

View File

@@ -1,5 +1,5 @@
import contextlib
import sqlite3
import contextlib
import time
from pathlib import Path

View File

@@ -1,18 +1,18 @@
import crypt
import json
import logging
import os
import sys
import time
import sys
import json
import crypt
from pathlib import Path
from socketserver import (
UnixStreamServer,
StreamRequestHandler,
ThreadingMixIn,
UnixStreamServer,
)
from .config import Config, read_config
from .database import Database
from .config import read_config, Config
NOCREATE_FILE = "/etc/chatmail-nocreate"

View File

@@ -6,11 +6,11 @@ it will echo back any message that has non-empty text and also supports the /hel
import logging
import os
import subprocess
import sys
from pathlib import Path
import subprocess
from deltachat_rpc_client import Bot, DeltaChat, EventType, Rpc, events
from pathlib import Path
from chatmaild.config import read_config
from chatmaild.newemail import create_newemail_dict

View File

@@ -1,9 +1,8 @@
import json
import logging
import os
from contextlib import contextmanager
import logging
import json
import filelock
from contextlib import contextmanager
class FileDict:

View File

@@ -1,14 +1,14 @@
#!/usr/bin/env python3
import asyncio
import logging
import sys
import time
from email import policy
import sys
from email.parser import BytesParser
from email import policy
from email.utils import parseaddr
from smtplib import SMTP as SMTPClient
from aiosmtpd.controller import Controller
from smtplib import SMTP as SMTPClient
from .config import read_config

View File

@@ -18,7 +18,7 @@ max_user_send_per_minute = 60
max_mailbox_size = 100M
# days after which mails are unconditionally deleted
delete_mails_after = 20
delete_mails_after = 40
# minimum length a username must have
username_min_length = 9

View File

@@ -1,17 +1,17 @@
import logging
import os
import sys
from pathlib import Path
from socketserver import (
UnixStreamServer,
StreamRequestHandler,
ThreadingMixIn,
UnixStreamServer,
)
import sys
import logging
import os
from .config import read_config
from .filedict import FileDict
from .notifier import Notifier
DICTPROXY_HELLO_CHAR = "H"
DICTPROXY_LOOKUP_CHAR = "L"
DICTPROXY_ITERATE_CHAR = "I"
@@ -49,40 +49,32 @@ class Metadata:
return mdict.get(self.DEVICETOKEN_KEY, [])
def handle_dovecot_protocol(rfile, wfile, notifier, metadata, iroh_relay=None):
def handle_dovecot_protocol(rfile, wfile, notifier, metadata):
transactions = {}
while True:
msg = rfile.readline().strip().decode()
if not msg:
break
res = handle_dovecot_request(msg, transactions, notifier, metadata, iroh_relay)
res = handle_dovecot_request(msg, transactions, notifier, metadata)
if res:
wfile.write(res.encode("ascii"))
wfile.flush()
def handle_dovecot_request(msg, transactions, notifier, metadata, iroh_relay=None):
def handle_dovecot_request(msg, transactions, notifier, metadata):
# see https://doc.dovecot.org/3.0/developer_manual/design/dict_protocol/
short_command = msg[0]
parts = msg[1:].split("\t")
if short_command == DICTPROXY_LOOKUP_CHAR:
# Lpriv/43f5f508a7ea0366dff30200c15250e3/devicetoken\tlkj123poi@c2.testrun.org
keyparts = parts[0].split("/", 2)
keyparts = parts[0].split("/")
if keyparts[0] == "priv":
keyname = keyparts[2]
addr = parts[1]
if keyname == metadata.DEVICETOKEN_KEY:
res = " ".join(metadata.get_tokens_for_addr(addr))
return f"O{res}\n"
elif keyparts[0] == "shared":
keyname = keyparts[2]
if (
keyname == "vendor/vendor.dovecot/pvt/server/vendor/deltachat/irohrelay"
and iroh_relay
):
# Handle `GETMETADATA "" /shared/vendor/deltachat/irohrelay`
return f"O{iroh_relay}\n"
logging.warning("lookup ignored: %r", msg)
return "N\n"
elif short_command == DICTPROXY_ITERATE_CHAR:
@@ -128,10 +120,7 @@ class ThreadedUnixStreamServer(ThreadingMixIn, UnixStreamServer):
def main():
socket, vmail_dir, config_path = sys.argv[1:]
config = read_config(config_path)
iroh_relay = config.iroh_relay
socket, vmail_dir = sys.argv[1:]
vmail_dir = Path(vmail_dir)
if not vmail_dir.exists():
@@ -147,9 +136,7 @@ def main():
class Handler(StreamRequestHandler):
def handle(self):
try:
handle_dovecot_protocol(
self.rfile, self.wfile, notifier, metadata, iroh_relay
)
handle_dovecot_protocol(self.rfile, self.wfile, notifier, metadata)
except Exception:
logging.exception("Exception in the dovecot dictproxy handler")
raise

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3
import sys
import time
from pathlib import Path
import time
import sys
def main(vmail_dir=None):

View File

@@ -1,13 +1,13 @@
#!/usr/local/lib/chatmaild/venv/bin/python3
"""CGI script for creating new accounts."""
""" CGI script for creating new accounts. """
import json
import random
import secrets
import string
from chatmaild.config import Config, read_config
from chatmaild.config import read_config, Config
CONFIG_PATH = "/usr/local/lib/chatmaild/chatmail.ini"
ALPHANUMERIC = string.ascii_lowercase + string.digits

View File

@@ -25,16 +25,15 @@ The meaning and format of tokens is basically a matter of Delta-Chat Core and
the `notification.delta.chat` service.
"""
import logging
import math
import os
import time
from dataclasses import dataclass
import math
import logging
from uuid import uuid4
from threading import Thread
from pathlib import Path
from queue import PriorityQueue
from threading import Thread
from uuid import uuid4
from dataclasses import dataclass
import requests

View File

@@ -1,14 +1,14 @@
import random
from pathlib import Path
import os
import importlib.resources
import itertools
import os
import random
from email import policy
from email.parser import BytesParser
from pathlib import Path
from email import policy
import pytest
from chatmaild.config import read_config, write_initial_config
from chatmaild.database import Database
from chatmaild.config import read_config, write_initial_config
@pytest.fixture

View File

@@ -24,7 +24,7 @@ def test_read_config_testrun(make_config):
assert config.postfix_reinject_port == 10025
assert config.max_user_send_per_minute == 60
assert config.max_mailbox_size == "100M"
assert config.delete_mails_after == "20"
assert config.delete_mails_after == "40"
assert config.username_min_length == 9
assert config.username_max_length == 9
assert config.password_min_length == 9

View File

@@ -1,18 +1,18 @@
import io
import json
import pytest
import queue
import threading
import traceback
import chatmaild.doveauth
import pytest
from chatmaild.database import DBError
from chatmaild.doveauth import (
get_user_data,
handle_dovecot_protocol,
handle_dovecot_request,
lookup_passdb,
handle_dovecot_request,
handle_dovecot_protocol,
)
from chatmaild.database import DBError
def test_basic(db, example_config):

View File

@@ -1,11 +1,12 @@
import pytest
from chatmaild.filtermail import (
check_encrypted,
BeforeQueueHandler,
SendRateLimiter,
check_encrypted,
check_mdn,
)
import pytest
@pytest.fixture
def maildomain():

View File

@@ -1,12 +1,12 @@
import io
import time
import pytest
import requests
import time
from chatmaild.metadata import (
Metadata,
handle_dovecot_protocol,
handle_dovecot_request,
handle_dovecot_protocol,
Metadata,
)
from chatmaild.notifier import (
Notifier,
@@ -296,17 +296,3 @@ def test_persistent_queue_items(tmp_path, testaddr, token):
item2.delete()
assert not item2.path.exists()
assert not queue_item < item2 and not item2 < queue_item
def test_iroh_relay(metadata):
rfile = io.BytesIO(
b"\n".join(
[
b"H",
b"Lshared/0123/vendor/vendor.dovecot/pvt/server/vendor/deltachat/irohrelay\tuser@example.org",
]
)
)
wfile = io.BytesIO()
handle_dovecot_protocol(rfile, wfile, notifier, metadata, "https://example.org/")
assert wfile.getvalue() == b"Ohttps://example.org/\n"

View File

@@ -16,6 +16,7 @@ dependencies = [
"build",
"tox",
"ruff",
"black",
"pytest",
"pytest-xdist",
"imap_tools",
@@ -30,13 +31,3 @@ cmdeploy = "cmdeploy.cmdeploy:main"
[tool.pytest.ini_options]
addopts = "-v -ra --strict-markers"
[tool.ruff]
lint.select = [
"F", # Pyflakes
"I", # isort
"PLC", # Pylint Convention
"PLE", # Pylint Error
"PLW", # Pylint Warning
]

View File

@@ -2,21 +2,21 @@
Chat Mail pyinfra deploy.
"""
import importlib.resources
import io
import shutil
import subprocess
import sys
import importlib.resources
import subprocess
import shutil
import io
from pathlib import Path
from chatmaild.config import Config, read_config
from pyinfra import host
from pyinfra.operations import apt, files, server, systemd, pip
from pyinfra.facts.files import File
from pyinfra.facts.systemd import SystemdEnabled
from pyinfra.operations import apt, files, pip, server, systemd
from .acmetool import deploy_acmetool
from chatmaild.config import read_config, Config
def _build_chatmaild(dist_dir) -> None:
dist_dir = Path(dist_dir).resolve()
@@ -486,20 +486,19 @@ def deploy_chatmail(config_path: Path) -> None:
# Add our OBS repository for dovecot_no_delay
files.put(
name="Add Deltachat OBS GPG key to apt keyring",
src=importlib.resources.files(__package__).joinpath("obs-home-deltachat.gpg"),
dest="/etc/apt/keyrings/obs-home-deltachat.gpg",
name = "Add Deltachat OBS GPG key to apt keyring",
src = importlib.resources.files(__package__).joinpath("obs-home-deltachat.gpg"),
dest = "/etc/apt/keyrings/obs-home-deltachat.gpg",
user="root",
group="root",
mode="644",
)
files.line(
name="Add DeltaChat OBS home repository to sources.list",
path="/etc/apt/sources.list",
line="deb [signed-by=/etc/apt/keyrings/obs-home-deltachat.gpg] https://download.opensuse.org/repositories/home:/deltachat/Debian_12/ ./",
escape_regex_characters=True,
ensure_newline=True,
name = "Add DeltaChat OBS home repository to sources.list",
path = "/etc/apt/sources.list",
line = "deb [signed-by=/etc/apt/keyrings/obs-home-deltachat.gpg] https://download.opensuse.org/repositories/home:/deltachat/Debian_12/ ./",
ensure_newline = True,
)
apt.update(name="apt update", cache_time=24 * 3600)
@@ -535,12 +534,6 @@ def deploy_chatmail(config_path: Path) -> None:
domains=[mail_domain, f"mta-sts.{mail_domain}", f"www.{mail_domain}"],
)
apt.packages(
# required for setfacl for echobot
name="Install acl",
packages="acl",
)
apt.packages(
name="Install Postfix",
packages="postfix",
@@ -642,12 +635,5 @@ def deploy_chatmail(config_path: Path) -> None:
service="systemd-journald.service",
running=True,
enabled=True,
restarted=journald_conf.changed,
restarted=journald_conf,
)
apt.packages(
name="Ensure cron is installed",
packages=["cron"],
)

View File

@@ -1,8 +1,8 @@
import importlib.resources
from pyinfra.operations import apt, files, systemd, server
from pyinfra import host
from pyinfra.facts.systemd import SystemdStatus
from pyinfra.operations import apt, files, server, systemd
def deploy_acmetool(email="", domains=[]):
@@ -69,8 +69,7 @@ def deploy_acmetool(email="", domains=[]):
restarted=service_file.changed,
)
if str(host) != "staging.testrun.org":
server.shell(
name=f"Request certificate for: { ', '.join(domains) }",
commands=[f"acmetool want --xlog.severity=debug { ' '.join(domains)}"],
)
server.shell(
name=f"Request certificate for: { ', '.join(domains) }",
commands=[f"acmetool want --xlog.severity=debug { ' '.join(domains)}"],
)

View File

@@ -4,18 +4,19 @@ along with command line option and subcommand parsing.
"""
import argparse
import shutil
import subprocess
import importlib.resources
import importlib.util
import os
import shutil
import subprocess
import sys
from pathlib import Path
from chatmaild.config import read_config, write_initial_config
from termcolor import colored
from cmdeploy.dns import check_necessary_dns, show_dns
from termcolor import colored
from chatmaild.config import read_config, write_initial_config
from cmdeploy.dns import show_dns, check_necessary_dns
#
# cmdeploy sub commands and options
@@ -38,6 +39,10 @@ def init_cmd(args, out):
else:
write_initial_config(args.inipath, mail_domain)
out.green(f"created config file for {mail_domain} in {args.inipath}")
check_necessary_dns(
out,
mail_domain,
)
def run_cmd_options(parser):
@@ -152,26 +157,26 @@ def fmt_cmd_options(parser):
def fmt_cmd(args, out):
"""Run formattting fixes on all chatmail source code."""
"""Run formattting fixes (ruff and black) on all chatmail source code."""
sources = [str(importlib.resources.files(x)) for x in ("chatmaild", "cmdeploy")]
format_args = [shutil.which("ruff"), "format"]
check_args = [shutil.which("ruff"), "check"]
black_args = [shutil.which("black")]
ruff_args = [shutil.which("ruff")]
if args.check:
format_args.append("--diff")
black_args.append("--check")
else:
check_args.append("--fix")
ruff_args.append("--fix")
if not args.verbose:
check_args.append("--quiet")
format_args.append("--quiet")
black_args.append("-q")
ruff_args.append("-q")
format_args.extend(sources)
check_args.extend(sources)
black_args.extend(sources)
ruff_args.extend(sources)
out.check_call(" ".join(format_args), quiet=not args.verbose)
out.check_call(" ".join(check_args), quiet=not args.verbose)
out.check_call(" ".join(black_args), quiet=not args.verbose)
out.check_call(" ".join(ruff_args), quiet=not args.verbose)
return 0
@@ -227,7 +232,7 @@ class Out:
if not quiet:
cmdstring = " ".join(args)
self(f"[$ {cmdstring}]", file=sys.stderr)
proc = subprocess.run(args, env=env, check=False)
proc = subprocess.run(args, env=env)
return proc.returncode

View File

@@ -1,8 +1,6 @@
import importlib.resources
import os
import importlib.resources
import pyinfra
from cmdeploy import deploy_chatmail

View File

@@ -1,9 +1,9 @@
import datetime
import importlib
import subprocess
import sys
import requests
import importlib
import subprocess
import datetime
class DNS:
@@ -104,8 +104,8 @@ def show_dns(args, out) -> int:
return 0
except TypeError:
pass
for raw_line in zonefile.splitlines():
line = raw_line.format(
for line in zonefile.splitlines():
line = line.format(
acme_account_url=acme_account_url,
sts_id=datetime.datetime.now().strftime("%Y%m%d%H%M"),
chatmail_domain=args.config.mail_domain,
@@ -183,7 +183,6 @@ def show_dns(args, out) -> int:
def check_necessary_dns(out, mail_domain):
"""Check whether $mail_domain and mta-sts.$mail_domain resolve."""
print("Checking necessary DNS records... ")
dns = DNS(out, mail_domain)
ipv4 = dns.get("A", mail_domain)
ipv6 = dns.get("AAAA", mail_domain)
@@ -205,5 +204,5 @@ def check_necessary_dns(out, mail_domain):
print(line)
print()
else:
dns.out.green("All necessary DNS records seem to be set.")
dns.out.green("\nAll necessary DNS entries seem to be set.")
return True

View File

@@ -1,9 +1,8 @@
import importlib
import io
import os
import qrcode
from PIL import Image, ImageDraw, ImageFont
import os
from PIL import ImageFont, ImageDraw, Image
import io
def gen_qr_png_data(maildomain):

View File

@@ -1,3 +1,2 @@
[Journal]
MaxRetentionSec=3d
Storage=volatile

View File

@@ -1,7 +1,7 @@
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log syslog:server=unix:/dev/log,facility=local3;
error_log /var/log/nginx/error.log;
events {
worker_connections 768;
@@ -35,8 +35,6 @@ http {
server_name _;
access_log syslog:server=unix:/dev/log,facility=local7;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
@@ -82,6 +80,5 @@ http {
listen [::]:443 ssl;
server_name www.{{ config.domain_name }};
return 301 $scheme://{{ config.domain_name }}$request_uri;
access_log syslog:server=unix:/dev/log,facility=local7;
}
}

View File

@@ -2,7 +2,7 @@
Description=Chatmail dict proxy for IMAP METADATA
[Service]
ExecStart={execpath} /run/chatmail-metadata/metadata.socket /home/vmail/mail/{mail_domain} {config_path}
ExecStart={execpath} /run/chatmail-metadata/metadata.socket /home/vmail/mail/{mail_domain}
Restart=always
RestartSec=30
User=vmail

View File

@@ -1,10 +1,9 @@
import pytest
import threading
import queue
import socket
import threading
import pytest
from chatmaild.config import read_config
from cmdeploy.cmdeploy import main

View File

@@ -1,5 +1,4 @@
import smtplib
import pytest
@@ -86,7 +85,6 @@ def test_exceed_rate_limit(cmsetup, gencreds, maildata, chatmail_config):
pytest.fail("Rate limit was not exceeded")
@pytest.mark.slow
def test_expunged(remote, chatmail_config):
outdated_days = int(chatmail_config.delete_mails_after) + 1
find_cmds = [

View File

@@ -1,11 +1,11 @@
import ipaddress
import random
import re
import time
import re
import random
import imap_tools
import pytest
import requests
import ipaddress
import imap_tools
@pytest.fixture

View File

@@ -1,16 +1,17 @@
import imaplib
import io
import itertools
import os
import random
import smtplib
import subprocess
import io
import time
import random
import subprocess
import imaplib
import smtplib
import itertools
from pathlib import Path
import pytest
from chatmaild.config import read_config
from chatmaild.database import Database
from chatmaild.config import read_config
conftestdir = Path(__file__).parent

View File

@@ -1,7 +1,6 @@
import os
import pytest
from cmdeploy.cmdeploy import get_parser, main

View File

@@ -1,14 +1,13 @@
import hashlib
import importlib.resources
import webbrowser
import hashlib
import time
import traceback
import webbrowser
import markdown
from chatmaild.config import read_config
from jinja2 import Template
from .genqr import gen_qr_png_data
from chatmaild.config import read_config
def snapshot_dir_stats(somedir):
@@ -121,8 +120,7 @@ def main():
print(f"watching {src_path} directory for changes")
changenum = 0
count = 0
while True:
for count in range(0, 1000000):
newstats = snapshot_dir_stats(src_path)
if newstats == stats and count % 60 != 0:
count += 1

View File

@@ -1,80 +0,0 @@
## Introduction to custom Dovecot builds
Chatmail servers use a custom Debian build of the IMAP 'dovecot' server software because
a) Dovecot developers did not yet merge a [pull request](https://github.com/dovecot/core/pull/216)
which majorly speeds up message delivery by removing a hardcoded 0.5 second delay
on relaying incoming messages.
b) Even if merged, it would take years for it to reach Debian stable.
c) The modified dovecot has been successfully used since December 2023 without issues
and we see no noticeable downside (theoretically higher CPU usage but not measureable)
but a considerable upside as the delay-removal facilitates end-to-end message
delivery of 200 ms in real networks.
The modified forked dovecot code lives at
[https://github.com/chatmail/dovecot](https://github.com/chatmail/dovecot).
The remainder of this document describes the setup of the Debian repository
containing the patched dovecot version.
## Building Debian packages at build.opensuse.org
Delta Chat developers maintain an [account](https://build.opensuse.org/project/show/home:deltachat)
in the [Open Build Service (OBS)](https://openbuildservice.org/),
where the [resulting package](https://build.opensuse.org/package/show/home:deltachat/dovecot)
is now used in deploying chatmail servers.
The Open Build Service (OBS) is a platform for building and distributing software packages
across various operating systems and architectures.
It supports openSUSE, Fedora, Debian, Ubuntu and Arch.
It's [primary instance](https://build.opensuse.org/) is ran by the openSUSE project
and is part of the pipeline of the creation of SUSE Linux Enterprise.
The OBS provides a mercurial-like interface to create source repositories
that are then automatically built.
While in theory a package can be created entirely over the web interface,
the use of the cli-tool `osc` is more convenient and is described in the [official documentation](https://openbuildservice.org/help/manuals/obs-user-guide/art.obs.bg#sec.obsbg.obsconfig).
### How to build the dovecot debian package on the OBS via our script
In scripts/dovecot/ is a shell script that prepares the required files and pushes them to build.opensuse.org.
Before using the script, you should have osc set up as described in the [official documentation](https://openbuildservice.org/help/manuals/obs-user-guide/art.obs.bg#sec.obsbg.obsconfig).
The script assumes you are on Debian. It automatically installs any needed dependencies and creates the source package. To upload the resulting source package to the OBS you need to enter the username and password for deltachat on build.opensuse.org in the last step of the script.
Use `source build-obs.sh` to run it.
### Adding the resulting OBS repository to Debian 12
Our dovecot fork is automatically installed as part of the chatmail deployment. You can see it in cmdeploy/src/cmdeploy/__init__.py. If you want to add our fork manually to a system, you can do the following:
First add our signing key to your apt keyring:
```
sudo cp cmdeploy/src/cmdeploy/obs-home-deltachat.gpg /etc/apt/keyrings/obs-home-deltachat.gpg`
```
Now add our repository and key to /etc/apt/sources.list with a text editor of your choice:
```
deb [signed-by=/etc/apt/keyrings/obs-home-deltachat.gpg] https://download.opensuse.org/repositories/home:/deltachat/Debian_12/ ./
```
You can now install dovecot like normal.
```
sudo apt update
sudo apt install dovecot-core
```
### Security concerns
The signing of the patched dovecot package is done in the OBS and
in theory SUSE could make changes to the package delivered.
It is probably reasonable to trust SUSE to not mess with the build
process because it would cause serious negative reputation damage for them
if they tried and someone finds out.
Our dovecot fork will receive the same security backports as the dovecot package in Debian Sid.

View File

@@ -1,54 +0,0 @@
#!/bin/bash
# Install dependencies
echo "Installing dependencies for this script:"
sudo apt install -y devscripts build-essential osc curl git debhelper-compat
# Define path of your local OBS repository
SCRIPT_DIR=$PWD
OBS_PATH=$SCRIPT_DIR/obs
REPO_PATH=$OBS_PATH/home:deltachat/dovecot/
# Download Debian Source Files
echo "Downloading precise files from Debian unstable repository..."
mkdir dovecot-build
cd dovecot-build
# taken May 6th 2024, from https://packages.debian.org/unstable/dovecot-core
curl http://deb.debian.org/debian/pool/main/d/dovecot/dovecot_2.3.21+dfsg1-3.debian.tar.xz -O
curl http://deb.debian.org/debian/pool/main/d/dovecot/dovecot_2.3.21+dfsg1.orig.tar.gz -O
curl http://deb.debian.org/debian/pool/main/d/dovecot/dovecot_2.3.21+dfsg1.orig-pigeonhole.tar.gz -O
# Clone the Chatmail Dovecot Repo
echo "Cloning the Chatmail Dovecot fork..."
git clone https://github.com/chatmail/dovecot.git
# Build the source package
echo "Building the source package"
cd dovecot
dpkg-source -b .
# Setting up OSC
echo "Setting up OBS home repository"
mkdir $OBS_PATH
cd $OBS_PATH
rm -rf home:deltachat/dovecot
osc checkout home:deltachat/dovecot
# Copy Files to Your Local OBS Repository,
echo "Copying files to your local OBS repository..."
cd $SCRIPT_DIR/dovecot-build
cp -rf dovecot_2.3.21+dfsg1-3.debian.tar.xz $REPO_PATH
cp -rf dovecot_2.3.21+dfsg1.orig.tar.gz $REPO_PATH
cp -rf dovecot_2.3.21+dfsg1.orig-pigeonhole.tar.gz $REPO_PATH
cp -rf dovecot_2.3.21+dfsg1-3.dsc $REPO_PATH
# Push Changes to OBS
echo "Pushing changes to OBS..."
cd $REPO_PATH
osc up
osc add dovecot_2.3.21+dfsg1-3.debian.tar.xz
osc add dovecot_2.3.21+dfsg1.orig.tar.gz
osc add dovecot_2.3.21+dfsg1.orig-pigeonhole.tar.gz
osc add dovecot_2.3.21+dfsg1-3.dsc
osc commit

Submodule scripts/dovecot/dovecot-build/dovecot deleted from 4b7f802ca1

View File

@@ -1,17 +1,11 @@
<img class="banner" src="collage-top.png"/>
## Dear [Delta Chat](https://get.delta.chat) users and newcomers ...
## Dear [Delta Chat](https://get.delta.chat) users and newcomers,
{% if config.mail_domain != "nine.testrun.org" %}
Welcome to instant, interoperable and [privacy-preserving](privacy.html) messaging :)
{% else %}
Welcome to the default onboarding server ({{ config.mail_domain }})
for Delta Chat users. For details how it avoids storing personal information
please see our [privacy policy](privacy.html).
{% endif %}
👉 **Tap** or scan this QR code to get a `@{{config.mail_domain}}` chat profile
👉 **Tap** or scan this QR code to get a random `@{{config.mail_domain}}` e-mail address
<a href="DCACCOUNT:https://{{ config.mail_domain }}/new">
<img width=300 style="float: none;" src="qr-chatmail-invite-{{config.mail_domain}}.png" /></a>

View File

@@ -1,4 +1,6 @@
<img class="banner" src="collage-info.png"/>
## More information
{{ config.mail_domain }} provides a low-maintenance, resource efficient and
@@ -9,7 +11,7 @@ for the usage in chats, especially DeltaChat.
### Choosing a chatmail address instead of using a random one
In the Delta Chat account setup
you may tap `I already have a profile`
you may tap `LOG INTO YOUR E-MAIL ACCOUNT`
and fill the two fields like this:
- `Address`: invent a word with

View File

@@ -1,41 +1,21 @@
<img class="banner" src="collage-privacy.png"/>
# Privacy Policy for {{ config.mail_domain }}
{% if config.mail_domain == "nine.testrun.org" %}
Welcome to `{{config.mail_domain}}`, the default chatmail onboarding server for Delta Chat users.
It is operated on the side by a small sysops team employed by [merlinux](https://merlinux.eu),
an open-source R&D company also acting as the fiscal sponsor of Delta Chat app developments.
See [other chatmail servers](https://delta.chat/en/chatmail) for alternative server operators.
{% endif %}
## Summary: No personal data asked or collected
This chatmail server neither asks for nor retains personal information.
Chatmail servers exist to reliably transmit (store and deliver) end-to-end encrypted messages
between user's devices running the Delta Chat messenger app.
Technically, you may think of a Chatmail server as
an end-to-end encrypted "messaging router" at Internet-scale.
A chatmail server is very unlike classic e-mail servers (for example Google Mail servers)
that ask for personal data and permanently store messages.
A chatmail server behaves more like the Signal messaging server
but does not know about phone numbers and securely and automatically interoperates
with other chatmail and classic e-mail servers.
In particular, this chatmail server
- unconditionally removes messages after {{ config.delete_mails_after }} days,
- prohibits sending out un-encrypted messages,
- only has temporary log files used for debugging purposes.
Legally, authorities might still regard chatmail as a "classic e-mail" server
which collects and retains personal data.
We do not agree on this interpretation. Nevertheless, we provide more legal details below
to make life easier for data protection specialists and lawyers scrutinizing chatmail operations.
We want to show you in a fair and transparent way
what personal data is processed by us.
We follow a strict privacy-by-design approach
and try to avoid processing your data in the first place,
but as you may know,
the internet,
and in particular sending e-mail messages,
does not work without data.
Still,
it's only fair that you know at all times
what personal data is processed
when you use our service.
If you have any remaining questions about data protection, please contact us.
## 1. Name and contact information
@@ -198,9 +178,8 @@ for the purpose of drawing conclusions about your person.
## 4. Transfer of Data
We do not retain any personal data but e-mail messages waiting to be delivered
may contain personal data.
Any such residual personal data will not be transferred to third parties
Your personal data
will not be transferred to third parties
for purposes other than those listed below:
a) you have given your express consent