mirror of
https://github.com/chatmail/relay.git
synced 2026-05-11 16:34:39 +00:00
Compare commits
4 Commits
cgi
...
hpk/fix_ac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9061cbbb4a | ||
|
|
e27ec22465 | ||
|
|
073f567292 | ||
|
|
d74f3dfeda |
15
README.md
15
README.md
@@ -32,17 +32,10 @@ after which the initially specified password is required for using them.
|
|||||||
5. Run `scripts/generate-dns-zone.sh` and
|
5. Run `scripts/generate-dns-zone.sh` and
|
||||||
transfer the generated DNS records at your DNS provider
|
transfer the generated DNS records at your DNS provider
|
||||||
|
|
||||||
|
6. Start a Delta Chat app and create a new account
|
||||||
### Home page and getting started for users
|
by typing an e-mail address with an arbitrary username
|
||||||
|
and `@<your-chatmail-domain>` appended.
|
||||||
- The `deploy.sh` script deploys a default `index.html`
|
Use an at least 10-character random password.
|
||||||
along with a QR code that users can click to
|
|
||||||
create accounts on the chatmail provider.
|
|
||||||
|
|
||||||
- Start a Delta Chat app and create a new account
|
|
||||||
by typing an e-mail address with an arbitrary username
|
|
||||||
and `@<your-chatmail-domain>` appended.
|
|
||||||
Use an at least 10-character random password.
|
|
||||||
|
|
||||||
|
|
||||||
### Ports
|
### Ports
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
name = "chatmaild"
|
name = "chatmaild"
|
||||||
version = "0.1"
|
version = "0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aiosmtpd",
|
"aiosmtpd"
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
|
|
||||||
""" CGI script for creating new accounts. """
|
|
||||||
|
|
||||||
import json
|
|
||||||
import random
|
|
||||||
|
|
||||||
mailname_path = "/etc/mailname"
|
|
||||||
|
|
||||||
|
|
||||||
def create_newemail_dict(domain):
|
|
||||||
alphanumeric = "abcdefghijklmnopqrstuvwxyz1234567890"
|
|
||||||
user = "".join(random.choices(alphanumeric, k=9))
|
|
||||||
password = "".join(random.choices(alphanumeric, k=12))
|
|
||||||
return dict(email=f"{user}@{domain}", password=f"{password}")
|
|
||||||
|
|
||||||
|
|
||||||
def print_new_account():
|
|
||||||
domain = open(mailname_path).read().strip()
|
|
||||||
creds = create_newemail_dict(domain=domain)
|
|
||||||
|
|
||||||
print("Content-Type: application/json")
|
|
||||||
print("")
|
|
||||||
print(json.dumps(creds))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print_new_account()
|
|
||||||
@@ -7,7 +7,6 @@ name = "deploy-chatmail"
|
|||||||
version = "0.1"
|
version = "0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pyinfra",
|
"pyinfra",
|
||||||
"qrcode",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ from pyinfra.facts.files import File
|
|||||||
from pyinfra.facts.systemd import SystemdEnabled
|
from pyinfra.facts.systemd import SystemdEnabled
|
||||||
from .acmetool import deploy_acmetool
|
from .acmetool import deploy_acmetool
|
||||||
|
|
||||||
from .genqr import gen_qr_png_data
|
|
||||||
|
|
||||||
|
|
||||||
def _install_chatmaild() -> None:
|
def _install_chatmaild() -> None:
|
||||||
chatmaild_filename = "chatmaild-0.1.tar.gz"
|
chatmaild_filename = "chatmaild-0.1.tar.gz"
|
||||||
@@ -27,8 +25,8 @@ def _install_chatmaild() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
apt.packages(
|
apt.packages(
|
||||||
name="apt install python3-aiosmtpd python3-pip python3-venv",
|
name="apt install python3-aiosmtpd",
|
||||||
packages=["python3-aiosmtpd", "python3-pip", "python3-venv"],
|
packages=["python3-aiosmtpd", "python3-pip"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# --no-deps because aiosmtplib is installed with `apt`.
|
# --no-deps because aiosmtplib is installed with `apt`.
|
||||||
@@ -46,8 +44,6 @@ def _install_chatmaild() -> None:
|
|||||||
enabled=False,
|
enabled=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
# install systemd units
|
|
||||||
|
|
||||||
for fn in (
|
for fn in (
|
||||||
"doveauth",
|
"doveauth",
|
||||||
"filtermail",
|
"filtermail",
|
||||||
@@ -137,44 +133,6 @@ def _configure_opendkim(domain: str, dkim_selector: str) -> bool:
|
|||||||
return need_restart
|
return need_restart
|
||||||
|
|
||||||
|
|
||||||
def _install_mta_sts_daemon() -> bool:
|
|
||||||
need_restart = False
|
|
||||||
|
|
||||||
config = files.put(
|
|
||||||
name="upload postfix-mta-sts-resolver config",
|
|
||||||
src=importlib.resources.files(__package__).joinpath(
|
|
||||||
"postfix/mta-sts-daemon.yml"
|
|
||||||
),
|
|
||||||
dest="/etc/mta-sts-daemon.yml",
|
|
||||||
user="root",
|
|
||||||
group="root",
|
|
||||||
mode="644",
|
|
||||||
)
|
|
||||||
need_restart |= config.changed
|
|
||||||
|
|
||||||
server.shell(
|
|
||||||
name="install postfix-mta-sts-resolver with pip",
|
|
||||||
commands=[
|
|
||||||
"python3 -m venv /usr/local/lib/postfix-mta-sts-resolver",
|
|
||||||
"/usr/local/lib/postfix-mta-sts-resolver/bin/pip install postfix-mta-sts-resolver",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
systemd_unit = files.put(
|
|
||||||
name="upload mta-sts-daemon systemd unit",
|
|
||||||
src=importlib.resources.files(__package__).joinpath(
|
|
||||||
"postfix/mta-sts-daemon.service"
|
|
||||||
),
|
|
||||||
dest="/etc/systemd/system/mta-sts-daemon.service",
|
|
||||||
user="root",
|
|
||||||
group="root",
|
|
||||||
mode="644",
|
|
||||||
)
|
|
||||||
need_restart |= systemd_unit.changed
|
|
||||||
|
|
||||||
return need_restart
|
|
||||||
|
|
||||||
|
|
||||||
def _configure_postfix(domain: str, debug: bool = False) -> bool:
|
def _configure_postfix(domain: str, debug: bool = False) -> bool:
|
||||||
"""Configures Postfix SMTP server."""
|
"""Configures Postfix SMTP server."""
|
||||||
need_restart = False
|
need_restart = False
|
||||||
@@ -273,46 +231,6 @@ def _configure_nginx(domain: str, debug: bool = False) -> bool:
|
|||||||
)
|
)
|
||||||
need_restart |= autoconfig.changed
|
need_restart |= autoconfig.changed
|
||||||
|
|
||||||
mta_sts_config = files.template(
|
|
||||||
src=importlib.resources.files(__package__).joinpath("nginx/mta-sts.txt.j2"),
|
|
||||||
dest="/var/www/html/.well-known/mta-sts.txt",
|
|
||||||
user="root",
|
|
||||||
group="root",
|
|
||||||
mode="644",
|
|
||||||
config={"domain_name": domain},
|
|
||||||
)
|
|
||||||
need_restart |= mta_sts_config.changed
|
|
||||||
|
|
||||||
# install CGI newemail script
|
|
||||||
#
|
|
||||||
cgi_dir = "/usr/lib/cgi-bin"
|
|
||||||
files.directory(
|
|
||||||
name=f"Ensure {cgi_dir} exists",
|
|
||||||
path=cgi_dir,
|
|
||||||
user="root",
|
|
||||||
group="root",
|
|
||||||
)
|
|
||||||
|
|
||||||
files.put(
|
|
||||||
name="Upload cgi newemail.py script",
|
|
||||||
src=importlib.resources.files("chatmaild").joinpath("newemail.py").open("rb"),
|
|
||||||
dest=f"{cgi_dir}/newemail.py",
|
|
||||||
user="root",
|
|
||||||
group="root",
|
|
||||||
mode="755",
|
|
||||||
)
|
|
||||||
|
|
||||||
qr_data = gen_qr_png_data(domain)
|
|
||||||
|
|
||||||
files.put(
|
|
||||||
name="Upload QR code for account creation",
|
|
||||||
src=qr_data,
|
|
||||||
dest="/var/www/html/qrcode.png",
|
|
||||||
user="root",
|
|
||||||
group="root",
|
|
||||||
mode="644",
|
|
||||||
)
|
|
||||||
|
|
||||||
return need_restart
|
return need_restart
|
||||||
|
|
||||||
|
|
||||||
@@ -337,7 +255,7 @@ def deploy_chatmail(mail_domain: str, mail_server: str, dkim_selector: str) -> N
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Deploy acmetool to have TLS certificates.
|
# Deploy acmetool to have TLS certificates.
|
||||||
deploy_acmetool(nginx_hook=True, domains=[mail_server, f"mta-sts.{mail_server}"])
|
deploy_acmetool(nginx_hook=True, domains=[mail_server])
|
||||||
|
|
||||||
apt.packages(
|
apt.packages(
|
||||||
name="Install Postfix",
|
name="Install Postfix",
|
||||||
@@ -362,17 +280,11 @@ def deploy_chatmail(mail_domain: str, mail_server: str, dkim_selector: str) -> N
|
|||||||
packages=["nginx"],
|
packages=["nginx"],
|
||||||
)
|
)
|
||||||
|
|
||||||
apt.packages(
|
|
||||||
name="Install fcgiwrap",
|
|
||||||
packages=["fcgiwrap"],
|
|
||||||
)
|
|
||||||
|
|
||||||
_install_chatmaild()
|
_install_chatmaild()
|
||||||
debug = False
|
debug = False
|
||||||
dovecot_need_restart = _configure_dovecot(mail_server, debug=debug)
|
dovecot_need_restart = _configure_dovecot(mail_server, debug=debug)
|
||||||
postfix_need_restart = _configure_postfix(mail_domain, debug=debug)
|
postfix_need_restart = _configure_postfix(mail_domain, debug=debug)
|
||||||
opendkim_need_restart = _configure_opendkim(mail_domain, dkim_selector)
|
opendkim_need_restart = _configure_opendkim(mail_domain, dkim_selector)
|
||||||
mta_sts_need_restart = _install_mta_sts_daemon()
|
|
||||||
nginx_need_restart = _configure_nginx(mail_domain)
|
nginx_need_restart = _configure_nginx(mail_domain)
|
||||||
|
|
||||||
# deploy web pages and info if we have them
|
# deploy web pages and info if we have them
|
||||||
@@ -380,16 +292,6 @@ def deploy_chatmail(mail_domain: str, mail_server: str, dkim_selector: str) -> N
|
|||||||
www_path = pkg_root.joinpath(f"../../../www/{mail_domain}").resolve()
|
www_path = pkg_root.joinpath(f"../../../www/{mail_domain}").resolve()
|
||||||
if www_path.is_dir():
|
if www_path.is_dir():
|
||||||
files.rsync(f"{www_path}/", "/var/www/html", flags=["-avz"])
|
files.rsync(f"{www_path}/", "/var/www/html", flags=["-avz"])
|
||||||
else:
|
|
||||||
index_path = www_path.parent.joinpath("default/index.html.j2")
|
|
||||||
files.template(
|
|
||||||
src=index_path,
|
|
||||||
dest="/var/www/html/index.html",
|
|
||||||
user="root",
|
|
||||||
group="root",
|
|
||||||
mode="644",
|
|
||||||
config={"mail_domain": mail_domain},
|
|
||||||
)
|
|
||||||
|
|
||||||
systemd.service(
|
systemd.service(
|
||||||
name="Start and enable OpenDKIM",
|
name="Start and enable OpenDKIM",
|
||||||
@@ -399,15 +301,6 @@ def deploy_chatmail(mail_domain: str, mail_server: str, dkim_selector: str) -> N
|
|||||||
restarted=opendkim_need_restart,
|
restarted=opendkim_need_restart,
|
||||||
)
|
)
|
||||||
|
|
||||||
systemd.service(
|
|
||||||
name="Start and enable MTA-STS daemon",
|
|
||||||
service="mta-sts-daemon.service",
|
|
||||||
daemon_reload=True,
|
|
||||||
running=True,
|
|
||||||
enabled=True,
|
|
||||||
restarted=mta_sts_need_restart,
|
|
||||||
)
|
|
||||||
|
|
||||||
systemd.service(
|
systemd.service(
|
||||||
name="Start and enable Postfix",
|
name="Start and enable Postfix",
|
||||||
service="postfix.service",
|
service="postfix.service",
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ def deploy_acmetool(nginx_hook=False, email="", domains=[]):
|
|||||||
mode="644",
|
mode="644",
|
||||||
)
|
)
|
||||||
|
|
||||||
server.shell(
|
for domain in domains:
|
||||||
name=f"Request certificate for: { ', '.join(domains) }",
|
server.shell(
|
||||||
commands=[f"acmetool want { ' '.join(domains)}"],
|
name=f"Request certificate for {domain}",
|
||||||
)
|
commands=[f"acmetool want {domain}"],
|
||||||
|
)
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
Binary file not shown.
@@ -1,82 +0,0 @@
|
|||||||
import importlib
|
|
||||||
import qrcode
|
|
||||||
import os
|
|
||||||
from PIL import ImageFont, ImageDraw, Image
|
|
||||||
import io
|
|
||||||
|
|
||||||
|
|
||||||
def gen_qr_png_data(maildomain):
|
|
||||||
url = f"DCACCOUNT:https://{maildomain}/cgi-bin/newemail.py"
|
|
||||||
image = gen_qr(maildomain, url)
|
|
||||||
temp = io.BytesIO()
|
|
||||||
image.save(temp, format="png")
|
|
||||||
temp.seek(0)
|
|
||||||
return temp
|
|
||||||
|
|
||||||
|
|
||||||
def gen_qr(maildomain, url):
|
|
||||||
# taken and modified from
|
|
||||||
# https://github.com/deltachat/mailadm/blob/master/src/mailadm/gen_qr.py
|
|
||||||
|
|
||||||
info = f"{maildomain} invite code"
|
|
||||||
|
|
||||||
# load QR code
|
|
||||||
qr = qrcode.QRCode(
|
|
||||||
version=1,
|
|
||||||
error_correction=qrcode.constants.ERROR_CORRECT_H,
|
|
||||||
box_size=1,
|
|
||||||
border=1,
|
|
||||||
)
|
|
||||||
qr.add_data(url)
|
|
||||||
qr.make(fit=True)
|
|
||||||
qr_img = qr.make_image(fill_color="black", back_color="white")
|
|
||||||
|
|
||||||
# paint all elements
|
|
||||||
ttf_path = str(
|
|
||||||
importlib.resources.files(__package__).joinpath("data/opensans-regular.ttf")
|
|
||||||
)
|
|
||||||
logo_red_path = str(
|
|
||||||
importlib.resources.files(__package__).joinpath("data/delta-chat-bw.png")
|
|
||||||
)
|
|
||||||
|
|
||||||
assert os.path.exists(ttf_path), ttf_path
|
|
||||||
font_size = 16
|
|
||||||
font = ImageFont.truetype(font=ttf_path, size=font_size)
|
|
||||||
|
|
||||||
num_lines = (info).count("\n") + 1
|
|
||||||
|
|
||||||
size = width = 384
|
|
||||||
qr_padding = 6
|
|
||||||
text_height = font_size * num_lines
|
|
||||||
height = size + text_height + qr_padding * 2
|
|
||||||
|
|
||||||
image = Image.new("RGBA", (width, height), "white")
|
|
||||||
|
|
||||||
draw = ImageDraw.Draw(image)
|
|
||||||
|
|
||||||
qr_final_size = width - (qr_padding * 2)
|
|
||||||
|
|
||||||
# draw text
|
|
||||||
if hasattr(font, "getsize"):
|
|
||||||
info_pos = (width - font.getsize(info.strip())[0]) // 2
|
|
||||||
else:
|
|
||||||
info_pos = (width - font.getbbox(info.strip())[3]) // 2
|
|
||||||
|
|
||||||
draw.multiline_text(
|
|
||||||
(info_pos, size - qr_padding // 2), info, font=font, fill="black", align="right"
|
|
||||||
)
|
|
||||||
|
|
||||||
# paste QR code
|
|
||||||
image.paste(
|
|
||||||
qr_img.resize((qr_final_size, qr_final_size), resample=Image.NEAREST),
|
|
||||||
(qr_padding, qr_padding),
|
|
||||||
)
|
|
||||||
|
|
||||||
# background delta logo
|
|
||||||
logo2_img = Image.open(logo_red_path)
|
|
||||||
logo2_width = int(size / 6)
|
|
||||||
logo2 = logo2_img.resize((logo2_width, logo2_width), resample=Image.NEAREST)
|
|
||||||
pos = int((size / 2) - (logo2_width / 2))
|
|
||||||
image.paste(logo2, (pos, pos), mask=logo2)
|
|
||||||
|
|
||||||
return image
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
version: STSv1
|
|
||||||
mode: enforce
|
|
||||||
mx: {{ config.domain_name }}
|
|
||||||
max_age: 2419200
|
|
||||||
@@ -26,6 +26,8 @@ http {
|
|||||||
gzip on;
|
gzip on;
|
||||||
|
|
||||||
server {
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
listen 443 ssl default_server;
|
listen 443 ssl default_server;
|
||||||
listen [::]:443 ssl default_server;
|
listen [::]:443 ssl default_server;
|
||||||
|
|
||||||
@@ -40,16 +42,6 @@ http {
|
|||||||
# as directory, then fall back to displaying a 404.
|
# as directory, then fall back to displaying a 404.
|
||||||
try_files $uri $uri/ =404;
|
try_files $uri $uri/ =404;
|
||||||
}
|
}
|
||||||
|
|
||||||
# add cgi-bin support
|
|
||||||
include /usr/share/doc/fcgiwrap/examples/nginx.conf;
|
|
||||||
}
|
}
|
||||||
server {
|
|
||||||
listen 80 default_server;
|
|
||||||
listen [::]:80 default_server;
|
|
||||||
server_name _;
|
|
||||||
|
|
||||||
return 301 https://$host$request_uri;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Domain {{ config.domain_name }}
|
|||||||
Selector {{ config.opendkim_selector }}
|
Selector {{ config.opendkim_selector }}
|
||||||
KeyFile /etc/dkimkeys/{{ config.opendkim_selector }}.private
|
KeyFile /etc/dkimkeys/{{ config.opendkim_selector }}.private
|
||||||
KeyTable /etc/dkimkeys/KeyTable
|
KeyTable /etc/dkimkeys/KeyTable
|
||||||
SigningTable refile:/etc/dkimkeys/SigningTable
|
SigningTable /etc/dkimkeys/SigningTable
|
||||||
|
|
||||||
# In Debian, opendkim runs as user "opendkim". A umask of 007 is required when
|
# In Debian, opendkim runs as user "opendkim". A umask of 007 is required when
|
||||||
# using a local socket with MTAs that access the socket as a non-privileged
|
# using a local socket with MTAs that access the socket as a non-privileged
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ smtpd_tls_security_level=may
|
|||||||
smtp_tls_CApath=/etc/ssl/certs
|
smtp_tls_CApath=/etc/ssl/certs
|
||||||
smtp_tls_security_level=may
|
smtp_tls_security_level=may
|
||||||
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
|
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
|
||||||
smtp_tls_policy_maps = socketmap:inet:127.0.0.1:8461:postfix
|
|
||||||
|
|
||||||
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
|
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
|
||||||
myhostname = {{ config.domain_name }}
|
myhostname = {{ config.domain_name }}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Postfix MTA-STS resolver daemon
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStart=/usr/local/lib/postfix-mta-sts-resolver/bin/mta-sts-daemon
|
|
||||||
Restart=always
|
|
||||||
RestartSec=30
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
host: 127.0.0.1
|
|
||||||
port: 8461
|
|
||||||
reuse_port: true
|
|
||||||
shutdown_timeout: 20
|
|
||||||
cache:
|
|
||||||
type: internal
|
|
||||||
options:
|
|
||||||
cache_size: 10000
|
|
||||||
proactive_policy_fetching:
|
|
||||||
enabled: true
|
|
||||||
default_zone:
|
|
||||||
strict_testing: false
|
|
||||||
timeout: 4
|
|
||||||
@@ -15,9 +15,6 @@ _submission._tcp.$CHATMAIL_DOMAIN. SRV 0 1 587 $CHATMAIL_DOMAIN.
|
|||||||
_submissions._tcp.$CHATMAIL_DOMAIN. SRV 0 1 465 $CHATMAIL_DOMAIN.
|
_submissions._tcp.$CHATMAIL_DOMAIN. SRV 0 1 465 $CHATMAIL_DOMAIN.
|
||||||
_imap._tcp.$CHATMAIL_DOMAIN. SRV 0 1 143 $CHATMAIL_DOMAIN.
|
_imap._tcp.$CHATMAIL_DOMAIN. SRV 0 1 143 $CHATMAIL_DOMAIN.
|
||||||
_imaps._tcp.$CHATMAIL_DOMAIN. SRV 0 1 993 $CHATMAIL_DOMAIN.
|
_imaps._tcp.$CHATMAIL_DOMAIN. SRV 0 1 993 $CHATMAIL_DOMAIN.
|
||||||
$CHATMAIL_DOMAIN. IN CAA 128 issue "letsencrypt.org;accounturi=$ACME_ACCOUNT_URL"
|
$CHATMAIL_DOMAIN. IN CAA 128 issue "letsencrypt.org; accounturi=$ACME_ACCOUNT_URL"
|
||||||
_mta-sts.$CHATMAIL_DOMAIN. IN TXT "v=STSv1; id=$(date -u '+%Y%m%d%H%M')"
|
|
||||||
mta-sts.$CHATMAIL_DOMAIN. IN CNAME $CHATMAIL_DOMAIN.
|
|
||||||
_smtp._tls.$CHATMAIL_DOMAIN. IN TXT "v=TLSRPTv1;rua=mailto:$EMAIL"
|
|
||||||
EOF
|
EOF
|
||||||
$SSH opendkim-genzone -F | sed 's/^;.*$//;/^$/d'
|
$SSH opendkim-genzone -F | sed 's/^;.*$//;/^$/d'
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
import chatmaild
|
|
||||||
from chatmaild.newemail import create_newemail_dict, print_new_account
|
|
||||||
|
|
||||||
def test_create_newemail_dict():
|
|
||||||
ac1 = create_newemail_dict(domain="example.org")
|
|
||||||
assert "@" in ac1["email"]
|
|
||||||
assert len(ac1["password"]) >= 10
|
|
||||||
|
|
||||||
ac2 = create_newemail_dict(domain="example.org")
|
|
||||||
|
|
||||||
assert ac1["email"] != ac2["email"]
|
|
||||||
assert ac1["password"] != ac2["password"]
|
|
||||||
|
|
||||||
|
|
||||||
def test_print_new_account(capsys, monkeypatch, maildomain, tmpdir):
|
|
||||||
p = tmpdir.join("mailname")
|
|
||||||
p.write(maildomain)
|
|
||||||
monkeypatch.setattr(chatmaild.newemail, "mailname_path", str(p))
|
|
||||||
print_new_account()
|
|
||||||
out, err = capsys.readouterr()
|
|
||||||
lines = out.split("\n")
|
|
||||||
assert lines[0] == "Content-Type: application/json"
|
|
||||||
assert not lines[1]
|
|
||||||
dic = json.loads(lines[2])
|
|
||||||
assert dic["email"].endswith(f"@{maildomain}")
|
|
||||||
assert len(dic["password"]) >= 10
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>chatmail instance</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Welcome to {{ config.mail_domain }}!</h1>
|
|
||||||
<h2>Getting started</h2>
|
|
||||||
<ol>
|
|
||||||
<li>Install <a href="https://get.delta.chat">https://get.delta.chat</a></li>
|
|
||||||
<li>Scan or Tap on the invite QR code</li>
|
|
||||||
<li>Choose Nickname and Avatar</li>
|
|
||||||
<li>Setup contact with others using <a href="https://delta.chat/en/help#howtoe2ee">
|
|
||||||
guaranteed end-to-end encryption via QR code scans</a>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
<a href="DCACCOUNT:https://{{ config.mail_domain }}/cgi-bin/newemail.py">
|
|
||||||
<img class="section" src="qrcode.png" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<h2>Constraints</h2>
|
|
||||||
<ul>
|
|
||||||
<li>You can only send encrypted mails to anyone outside {{config.mail_domain }} </li>
|
|
||||||
<li>You may send up to 60 messages per minute</li>
|
|
||||||
<li>Messages are unconditionally removed 40 days after arrival</li>
|
|
||||||
<li>Max storage per user is 100MB</li>
|
|
||||||
</ul>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -38,22 +38,16 @@
|
|||||||
<div class="section text">
|
<div class="section text">
|
||||||
<h1>Dear Delta Chat users and newcomers,</h1>
|
<h1>Dear Delta Chat users and newcomers,</h1>
|
||||||
<p>
|
<p>
|
||||||
welcome to the first public "chat-mail instance",
|
welcome to the first public "chat-mail instance",
|
||||||
a small and lean e-mail provider for smooth chatting.
|
a small and lean e-mail provider for smooth chatting.
|
||||||
Install Delta Chat and then
|
Install Delta Chat or add an account:
|
||||||
Tap or scan this QR code to obtain a random e-mail address:
|
|
||||||
<a href="DCACCOUNT:https://nine.testrun.org/cgi-bin/newemail.py">
|
|
||||||
<img with=300 src="qrcode.png" /></a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Alternatively, you can manually invent an e-mail address:
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Tap "LOG INTO YOUR E-MAIL ACCOUNT".</li>
|
<li>Tap "LOG INTO YOUR E-MAIL ACCOUNT".</li>
|
||||||
<li>Address: invent a word with <i>exactly</i> nine characters
|
<li>Address: invent a word with <i>exactly</i> nine characters
|
||||||
and append @nine.testrun.org to it.</li>
|
and append @nine.testrun.org to it.</li>
|
||||||
<li>Password: invent at least 10 characters. The first login sets your password.</li>
|
<li>Password: invent at least 10 characters. The first login sets your password.</li>
|
||||||
</ul>
|
</ul>
|
||||||
If the e-mail address is not yet taken, you'll get that account.
|
If the e-mail address is not yet taken, you'll get that account.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<img class="section" src="collage-down.png" />
|
<img class="section" src="collage-down.png" />
|
||||||
|
|||||||
Reference in New Issue
Block a user