mirror of
https://github.com/chatmail/relay.git
synced 2026-05-14 09:54:38 +00:00
Compare commits
1 Commits
tweak-read
...
refine-rea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c21f0e8572 |
18
README.md
18
README.md
@@ -15,8 +15,8 @@ after which the initially specified password is required for using them.
|
|||||||
|
|
||||||
## Deploying your own chatmail server
|
## Deploying your own chatmail server
|
||||||
|
|
||||||
We use `chat.example.org` as the chatmail domain in the following steps.
|
We subsequently use `CHATMAIL_DOMAIN` as a placeholder for your fully qualified
|
||||||
Please substitute it with your own domain.
|
DNS domain name (FQDN), for example `chat.example.org`.
|
||||||
|
|
||||||
1. Install the `cmdeploy` command in a virtualenv
|
1. Install the `cmdeploy` command in a virtualenv
|
||||||
|
|
||||||
@@ -25,19 +25,19 @@ Please substitute it with your own domain.
|
|||||||
cd chatmail
|
cd chatmail
|
||||||
scripts/initenv.sh
|
scripts/initenv.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Create chatmail configuration file `chatmail.ini`:
|
2. Create chatmail configuration file `chatmail.ini`:
|
||||||
|
|
||||||
```
|
```
|
||||||
scripts/cmdeploy init chat.example.org # <-- use your domain
|
scripts/cmdeploy init CHATMAIL_DOMAIN
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Setup first DNS records for your chatmail domain,
|
3. Setup first DNS records for your `CHATMAIL_DOMAIN`,
|
||||||
according to the hints provided by `cmdeploy init`.
|
according to the hints provided by `cmdeploy init`.
|
||||||
Verify that SSH root login works:
|
Verify that SSH root login works:
|
||||||
|
|
||||||
```
|
```
|
||||||
ssh root@chat.example.org # <-- use your domain
|
ssh root@CHATMAIL_DOMAIN
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Deploy to the remote chatmail server:
|
4. Deploy to the remote chatmail server:
|
||||||
@@ -75,7 +75,7 @@ scripts/cmdeploy bench
|
|||||||
|
|
||||||
## Overview of this repository
|
## Overview of this repository
|
||||||
|
|
||||||
This repository drives the development of chatmail services,
|
This repository drives the development of "chatmail instances",
|
||||||
comprised of minimal setups of
|
comprised of minimal setups of
|
||||||
|
|
||||||
- [postfix smtp server](https://www.postfix.org)
|
- [postfix smtp server](https://www.postfix.org)
|
||||||
@@ -91,7 +91,7 @@ as well as custom services that are integrated with these two:
|
|||||||
to send mails for them.
|
to send mails for them.
|
||||||
|
|
||||||
- `chatmaild/src/chatmaild/filtermail.py` prevents
|
- `chatmaild/src/chatmaild/filtermail.py` prevents
|
||||||
unencrypted e-mail from leaving the chatmail service
|
unencrypted e-mail from leaving the chatmail instance
|
||||||
and is integrated into postfix's outbound mail pipelines.
|
and is integrated into postfix's outbound mail pipelines.
|
||||||
|
|
||||||
There is also the `cmdeploy/src/cmdeploy/cmdeploy.py` command line tool
|
There is also the `cmdeploy/src/cmdeploy/cmdeploy.py` command line tool
|
||||||
@@ -104,7 +104,7 @@ to automatically install all chatmail components on a server.
|
|||||||
### Home page and getting started for users
|
### Home page and getting started for users
|
||||||
|
|
||||||
`cmdeploy run` also creates default static Web pages and deploys them
|
`cmdeploy run` also creates default static Web pages and deploys them
|
||||||
to a nginx web server with:
|
to an nginx web server under `https://CHATMAIL_DOMAIN`.
|
||||||
|
|
||||||
- a default `index.html` along with a QR code that users can click to
|
- a default `index.html` along with a QR code that users can click to
|
||||||
create accounts on your chatmail provider,
|
create accounts on your chatmail provider,
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ version = "0.2"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aiosmtpd",
|
"aiosmtpd",
|
||||||
"iniconfig",
|
"iniconfig",
|
||||||
"deltachat-rpc-server",
|
|
||||||
"deltachat-rpc-client",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.setuptools]
|
[tool.setuptools]
|
||||||
@@ -21,7 +19,6 @@ where = ['src']
|
|||||||
[project.scripts]
|
[project.scripts]
|
||||||
doveauth = "chatmaild.doveauth:main"
|
doveauth = "chatmaild.doveauth:main"
|
||||||
filtermail = "chatmaild.filtermail:main"
|
filtermail = "chatmaild.filtermail:main"
|
||||||
echobot = "chatmaild.echo:main"
|
|
||||||
|
|
||||||
[project.entry-points.pytest11]
|
[project.entry-points.pytest11]
|
||||||
"chatmaild.testplugin" = "chatmaild.tests.plugin"
|
"chatmaild.testplugin" = "chatmaild.tests.plugin"
|
||||||
|
|||||||
@@ -46,14 +46,13 @@ def is_allowed_to_create(config: Config, user, cleartext_password) -> bool:
|
|||||||
len(localpart) > config.username_max_length
|
len(localpart) > config.username_max_length
|
||||||
or len(localpart) < config.username_min_length
|
or len(localpart) < config.username_min_length
|
||||||
):
|
):
|
||||||
if localpart != "echo":
|
logging.warning(
|
||||||
logging.warning(
|
"localpart %s has to be between %s and %s chars long",
|
||||||
"localpart %s has to be between %s and %s chars long",
|
localpart,
|
||||||
localpart,
|
config.username_min_length,
|
||||||
config.username_min_length,
|
config.username_max_length,
|
||||||
config.username_max_length,
|
)
|
||||||
)
|
return False
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Advanced echo bot example.
|
|
||||||
|
|
||||||
it will echo back any message that has non-empty text and also supports the /help command.
|
|
||||||
"""
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from threading import Thread
|
|
||||||
|
|
||||||
from deltachat_rpc_client import Bot, DeltaChat, EventType, Rpc, events
|
|
||||||
|
|
||||||
from chatmaild.newemail import create_newemail_dict
|
|
||||||
from chatmaild.config import read_config
|
|
||||||
|
|
||||||
hooks = events.HookCollection()
|
|
||||||
|
|
||||||
|
|
||||||
@hooks.on(events.RawEvent)
|
|
||||||
def log_event(event):
|
|
||||||
if event.kind == EventType.INFO:
|
|
||||||
logging.info(event.msg)
|
|
||||||
elif event.kind == EventType.WARNING:
|
|
||||||
logging.warning(event.msg)
|
|
||||||
|
|
||||||
|
|
||||||
@hooks.on(events.RawEvent(EventType.ERROR))
|
|
||||||
def log_error(event):
|
|
||||||
logging.error(event.msg)
|
|
||||||
|
|
||||||
|
|
||||||
@hooks.on(events.MemberListChanged)
|
|
||||||
def on_memberlist_changed(event):
|
|
||||||
logging.info(
|
|
||||||
"member %s was %s", event.member, "added" if event.member_added else "removed"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@hooks.on(events.GroupImageChanged)
|
|
||||||
def on_group_image_changed(event):
|
|
||||||
logging.info("group image %s", "deleted" if event.image_deleted else "changed")
|
|
||||||
|
|
||||||
|
|
||||||
@hooks.on(events.GroupNameChanged)
|
|
||||||
def on_group_name_changed(event):
|
|
||||||
logging.info("group name changed, old name: %s", event.old_name)
|
|
||||||
|
|
||||||
|
|
||||||
@hooks.on(events.NewMessage(func=lambda e: not e.command))
|
|
||||||
def echo(event):
|
|
||||||
snapshot = event.message_snapshot
|
|
||||||
if snapshot.text or snapshot.file:
|
|
||||||
snapshot.chat.send_message(text=snapshot.text, file=snapshot.file)
|
|
||||||
|
|
||||||
|
|
||||||
@hooks.on(events.NewMessage(command="/help"))
|
|
||||||
def help_command(event):
|
|
||||||
snapshot = event.message_snapshot
|
|
||||||
snapshot.chat.send_text("Send me any message and I will echo it back")
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
path = os.environ.get("PATH")
|
|
||||||
venv_path = sys.argv[0].strip("echobot")
|
|
||||||
os.environ["PATH"] = path + ":" + venv_path
|
|
||||||
with Rpc() as rpc:
|
|
||||||
deltachat = DeltaChat(rpc)
|
|
||||||
system_info = deltachat.get_system_info()
|
|
||||||
logging.info("Running deltachat core %s", system_info.deltachat_core_version)
|
|
||||||
|
|
||||||
accounts = deltachat.get_all_accounts()
|
|
||||||
account = accounts[0] if accounts else deltachat.add_account()
|
|
||||||
|
|
||||||
bot = Bot(account, hooks)
|
|
||||||
if not bot.is_configured():
|
|
||||||
config = read_config(sys.argv[1])
|
|
||||||
password = create_newemail_dict(config).get("password")
|
|
||||||
email = "echo@" + config.mail_domain
|
|
||||||
configure_thread = Thread(
|
|
||||||
target=bot.configure, kwargs={"email": email, "password": password}
|
|
||||||
)
|
|
||||||
configure_thread.start()
|
|
||||||
bot.run_forever()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
|
||||||
main()
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Chatmail echo bot for testing it works
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStart={execpath} {config_path}
|
|
||||||
Environment="PATH={remote_venv_dir}:$PATH"
|
|
||||||
Restart=always
|
|
||||||
RestartSec=30
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
@@ -4,22 +4,16 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
import secrets
|
|
||||||
import string
|
|
||||||
|
|
||||||
from chatmaild.config import read_config, Config
|
from chatmaild.config import read_config, Config
|
||||||
|
|
||||||
CONFIG_PATH = "/usr/local/lib/chatmaild/chatmail.ini"
|
CONFIG_PATH = "/usr/local/lib/chatmaild/chatmail.ini"
|
||||||
ALPHANUMERIC = string.ascii_lowercase + string.digits
|
|
||||||
ALPHANUMERIC_PUNCT = string.ascii_letters + string.digits + string.punctuation
|
|
||||||
|
|
||||||
|
|
||||||
def create_newemail_dict(config: Config):
|
def create_newemail_dict(config: Config):
|
||||||
user = "".join(random.choices(ALPHANUMERIC, k=config.username_min_length))
|
alphanumeric = "abcdefghijklmnopqrstuvwxyz1234567890"
|
||||||
password = "".join(
|
user = "".join(random.choices(alphanumeric, k=config.username_min_length))
|
||||||
secrets.choice(ALPHANUMERIC_PUNCT)
|
password = "".join(random.choices(alphanumeric, k=config.password_min_length + 3))
|
||||||
for _ in range(config.password_min_length + 3)
|
|
||||||
)
|
|
||||||
return dict(email=f"{user}@{config.mail_domain}", password=f"{password}")
|
return dict(email=f"{user}@{config.mail_domain}", password=f"{password}")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -88,12 +88,10 @@ def _install_remote_venv_with_chatmaild(config) -> None:
|
|||||||
for fn in (
|
for fn in (
|
||||||
"doveauth",
|
"doveauth",
|
||||||
"filtermail",
|
"filtermail",
|
||||||
"echobot",
|
|
||||||
):
|
):
|
||||||
params = dict(
|
params = dict(
|
||||||
execpath=f"{remote_venv_dir}/bin/{fn}",
|
execpath=f"{remote_venv_dir}/bin/{fn}",
|
||||||
config_path=remote_chatmail_inipath,
|
config_path=remote_chatmail_inipath,
|
||||||
remote_venv_dir=remote_venv_dir,
|
|
||||||
)
|
)
|
||||||
source_path = importlib.resources.files("chatmaild").joinpath(f"{fn}.service.f")
|
source_path = importlib.resources.files("chatmaild").joinpath(f"{fn}.service.f")
|
||||||
content = source_path.read_text().format(**params).encode()
|
content = source_path.read_text().format(**params).encode()
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ Welcome to instant, interoperable and [privacy-preserving](privacy.html) messagi
|
|||||||
|
|
||||||
💬 **Start** chatting with any Delta Chat contacts using [QR invite codes](https://delta.chat/en/help#howtoe2ee)
|
💬 **Start** chatting with any Delta Chat contacts using [QR invite codes](https://delta.chat/en/help#howtoe2ee)
|
||||||
|
|
||||||
{% if config.mail_domain != "nine.testrun.org" %}
|
<div class="experimental">Note: this is an experimental service</div>
|
||||||
<div class="experimental">Note: this is only a temporary development chatmail service</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ we process the following data and details:
|
|||||||
Creating an account happens in one of two ways on our mail servers:
|
Creating an account happens in one of two ways on our mail servers:
|
||||||
|
|
||||||
- with a QR invitation token
|
- with a QR invitation token
|
||||||
which is scanned using the Delta Chat app
|
which is scanned using the DeltaChat app
|
||||||
and then the account is created.
|
and then the account is created.
|
||||||
|
|
||||||
- by letting Delta Chat otherwise create an account
|
- by letting Delta Chat otherwise create an account
|
||||||
|
|||||||
Reference in New Issue
Block a user