Compare commits

..

85 Commits

Author SHA1 Message Date
cef2114520 Merge pull request #41 from DEAM0/patch-19
Update prosody.cfg.lua
2025-02-17 22:02:44 +01:00
4f2e601edf Update prosody.cfg.lua
Fixed
2025-02-17 21:43:43 +01:00
cef6edc9c1 Use domain constants in cron.php 2024-12-20 17:47:35 +01:00
bbfbbbc2a8 Merge branch 'patch-15' 2024-12-20 17:11:39 +01:00
65583296cf Merge pull request #39 from DEAM0/patch-17
Update README.md
2024-12-20 08:11:19 +01:00
948aef1834 Update README.md
Cron.php change domain
2024-12-20 07:58:31 +01:00
a3c1f49d97 enable imap_metadata 2024-11-29 14:35:32 +01:00
85539ce4f0 Enable imap_sieve 2024-11-25 22:26:44 +01:00
e089d34114 Enable IMAP hibernation 2024-11-25 21:31:41 +01:00
55ccf1323a Enable sieve protocol 2024-11-25 21:30:43 +01:00
a63328f7f6 Add sieve suppot 2024-11-25 13:42:55 +01:00
9e1a071965 Update translation
Co-authored-by: Türk Dil Devrimi <bygenc19@gmail.com>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/tr/
Translation: DanWin/Mail Hosting
2024-11-11 22:48:54 +00:00
2aec2c322c Update install_binaries.sh
some linux distribution bug patch.
2024-10-22 20:32:14 +02:00
1dfaf11b6a Auto-create common folders - Fixes #16 2024-08-31 13:13:33 +02:00
caabe0c525 Also copy locale folder 2024-07-20 13:24:39 +02:00
4758464a79 Update translation
Co-authored-by: Weblate Admin <daniel@danwin1210.de>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/de/
Translation: DanWin/Mail Hosting
2024-07-08 13:50:58 +00:00
2735f35883 Update translation
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/
Translation: DanWin/Mail Hosting
2024-07-08 13:48:45 +00:00
fab6459f37 Add user@ to email address 2024-07-08 15:48:25 +02:00
2c705975cb Update translation
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/
Translation: DanWin/Mail Hosting
2024-07-08 13:43:04 +00:00
bd40ddb175 Add support for unlimited quota 2024-07-08 15:41:21 +02:00
c35d47c6c6 Add setting for default quota 2024-07-08 15:28:04 +02:00
d9d7323a9a Set correct submission autodiscovery port 2024-07-01 10:23:13 +02:00
d22fa5e577 Fix redirect to port 0 on squirrelmail 2024-06-16 15:18:25 +02:00
2ff3ea6cea Merge pull request #35 from DEAM0/patch-14
Update install_binaries.sh
2024-06-11 17:15:25 +02:00
e9a8effab5 Update install_binaries.sh 2024-06-11 14:20:36 +02:00
227fb813ef Merge pull request #34 from DEAM0/patch-13
Update install_binaries_proxy.sh
2024-06-11 12:38:33 +02:00
3f067b1f92 Update install_binaries_proxy.sh
Missing Brotli, proxy server not start after restart
2024-06-11 12:16:41 +02:00
8d58282163 Add lua-unbound 2024-06-08 12:35:02 +02:00
6085a0156a Add patch for check quota plugin 2024-06-08 10:55:58 +02:00
c262dbbe9d Add information on improving domain security 2024-06-07 18:21:13 +02:00
527b9e075f Install quota plugin 2024-06-07 17:58:15 +02:00
bef733240f Add primary domain in setup.php 2024-06-06 16:38:45 +02:00
f197f10228 Add resolv.conf 2024-06-06 16:02:37 +02:00
08da5a0623 Add squirrelmail_config.php 2024-06-06 15:58:47 +02:00
93ef4d6220 Add create_admin.php tool 2024-06-06 15:33:01 +02:00
7b21a62ac1 Connect servers with WireGuard 2024-06-06 14:57:36 +02:00
ce1cefe511 Add more dependecies and DNS records 2024-06-06 14:06:55 +02:00
df35dc5e05 Add mta-sts configuration 2024-06-06 13:52:15 +02:00
c79682eb0b Clean nginx config 2024-06-06 11:26:19 +02:00
14d6e21223 Fixed typo 2024-06-05 22:01:01 +02:00
78db852e82 Add dovecot-mysql 2024-06-05 21:56:31 +02:00
a8c633b1d2 Make use of snakeoil certificates in default configuration files 2024-06-05 21:53:17 +02:00
ffac3ea1db Remove unnecessary checks 2024-06-05 20:01:01 +02:00
1a3be77244 Merge pull request #31 from DEAM0/patch-10
Update install_binaries.sh
2024-06-03 15:32:51 +02:00
b4dcf77e0a Update install_binaries.sh 2024-06-03 15:27:21 +02:00
47083691bb Merge pull request #30 from DEAM0/patch-9
Update install_binaries.sh
2024-06-03 15:15:51 +02:00
75e8683238 Update install_binaries.sh 2024-06-03 14:45:41 +02:00
2e4e41bf6e Merge pull request #29 from DEAM0/patch-8
Update install_binaries.sh
2024-06-03 13:11:46 +02:00
dea136d331 Update install_binaries.sh 2024-06-03 13:06:27 +02:00
f5211ff264 Activate firewall 2024-06-02 21:44:19 +02:00
05c78d17c8 Add firewall configuration 2024-06-02 21:41:16 +02:00
236609945c Structure tutorial better 2024-06-02 20:58:10 +02:00
8903832866 Add setup tutorial 2024-06-02 20:50:01 +02:00
e8f64f6913 add mail-cron systemd unit 2024-06-02 20:38:55 +02:00
46a76764ad Updated configs 2024-06-02 15:33:25 +02:00
d13fef662d Upgrade to php8.2 2024-06-02 14:29:51 +02:00
adf6f51993 Update config files 2024-06-02 13:34:21 +02:00
acae5dcd7a Add more install steps 2024-06-02 13:20:53 +02:00
a97b0173f2 Use distro rspamd package 2024-06-02 12:20:28 +02:00
549e753353 Lowercase mailbox before registration 2024-02-23 20:59:01 +01:00
3f6cfe7c14 Add more cleanups 2024-02-23 20:42:02 +01:00
8d54b307ca Update postfix config 2023-12-29 21:32:16 +01:00
c9d61e8aaf Add captcha difficulty hard 2023-12-10 10:17:45 +01:00
44e53b14d2 Update translation
Co-authored-by: Weblate Admin <daniel@danwin1210.de>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/de/
Translation: DanWin/Mail Hosting
2023-11-30 17:37:25 +00:00
a35affe08f Update translation
Co-authored-by: Dai Duong Le <daiduonglebusiness@gmail.com>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/cs/
Translation: DanWin/Mail Hosting
2023-11-21 23:40:36 +00:00
da8013db56 Update translation
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/
Translation: DanWin/Mail Hosting
2023-10-21 09:58:11 +00:00
0bb8ac6590 Add option to disable registration 2023-10-21 11:57:44 +02:00
a6ab6c52e3 Update translation
Co-authored-by: Анонім <g2014test@yandex.com>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/uk/
Translation: DanWin/Mail Hosting
2023-10-14 18:51:41 +00:00
1392a38c9d Add Ukrainian language 2023-10-13 15:48:35 +02:00
c5027b96c6 Update install_binaries.sh 2023-10-13 15:41:28 +02:00
fb3a596289 Update translation
Co-authored-by: Анонім <g2014test@yandex.com>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/uk/
Translation: DanWin/Mail Hosting
2023-10-12 22:51:36 +00:00
ae26e80a25 Update translation
Co-authored-by: Анонім <g2014test@yandex.com>
2023-10-11 21:02:06 +00:00
dc8575615d Update translation
Co-authored-by: Weblate Admin <daniel@danwin1210.de>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/de/
Translation: DanWin/Mail Hosting
2023-10-08 20:29:50 +00:00
bbfcfb76c3 Update translation
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/
Translation: DanWin/Mail Hosting
2023-10-08 19:47:20 +00:00
c10d40b7fd Update translation template 2023-10-08 21:46:54 +02:00
878379dc73 Fix link in menu 2023-10-08 18:12:00 +02:00
37ebdbb66d Add terms of service 2023-10-08 18:05:54 +02:00
8e86cdc73e Update translation
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Weblate Admin <daniel@danwin1210.de>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/de/
Translation: DanWin/Mail Hosting
2023-09-15 23:44:41 +00:00
f247a7a5bf Bugfix 2023-09-12 20:05:38 +02:00
1238f003d6 Bugfix 2023-09-12 20:02:12 +02:00
be717d646d Update translation
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/
Translation: DanWin/Mail Hosting
2023-09-12 17:51:24 +00:00
3b53020bef Update translation template 2023-09-12 19:48:57 +02:00
174978ac3e Escape translations 2023-09-12 19:48:23 +02:00
a0c016887a Update translation
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/mail-hosting/
Translation: DanWin/Mail Hosting
2023-08-27 14:08:16 +00:00
28344bda79 Update translation template 2023-08-27 16:07:45 +02:00
64 changed files with 5626 additions and 2182 deletions

216
README.md
View File

@ -6,7 +6,221 @@ This is a setup for a Tor based email hosting server. It is provided as is and b
Installation Instructions:
--------------------------
TODO
### Primary mail server with Tor:
Uninstall packages that may interfere with this setup:
```
DEBIAN_FRONTEND=noninteractive apt-get purge -y apache2* dnsmasq* eatmydata exim4* imagemagick-6-common mysql-client* mysql-server* nginx* libnginx-mod* php7* resolvconf && systemctl disable systemd-resolved.service && systemctl stop systemd-resolved.service
```
If you have problems resolving hostnames after this step, temporarily switch to a public nameserver like 1.1.1.1 (from CloudFlare) or 8.8.8.8 (from Google)
```
rm /etc/resolv.conf && echo "nameserver 1.1.1.1" > /etc/resolv.conf
```
Install git and clone this repository
```
apt-get update && apt-get install git -y && git clone https://github.com/DanWin/mail-hosting && cd mail-hosting
```
Install files and programs
```
./install_binaries.sh
```
Copy (and modify according to your needs) the site files in `etc` to `/etc` after installation has finished. Then restart some services:
```
systemctl daemon-reload && systemctl restart tor@default.service
```
Replace the default .onion domain with your domain:
```
sed -i "s/danielas3rtn54uwmofdo3x2bsdifr47huasnmbgqzfrec5ubupvtpid.onion/`cat /var/lib/tor/hidden_service/hostname`/g" /etc/prosody/prosody.cfg.lua /etc/nginx/sites-enabled/mail /var/www/mail/common_config.php /etc/postfix/main.cf
```
Replace the default clearnet domain with your domain:
```
sed -i "s/danwin1210.de/YOUR_DOMAIN/g" /etc/prosody/prosody.cfg.lua /etc/postfix/main.cf /etc/dovecot/dovecot.conf /etc/nginx/sites-enabled/* /var/www/mail/common_config.php /var/www/mail/www/squirrelmail/config/config.php
```
Create a mysql users and databases:
```
mysql
CREATE DATABASE postfix;
CREATE DATABASE prosody;
CREATE USER 'postfix'@'%' IDENTIFIED BY 'MY_PASSWORD';
CREATE USER 'postfix_readonly'@'%' IDENTIFIED BY 'MY_PASSWORD';
CREATE USER 'prosody'@'%' IDENTIFIED BY 'MY_PASSWORD';
GRANT ALL PRIVILEGES ON postfix.* TO 'postfix'@'%';
GRANT SELECT ON postfix.* TO 'postfix_readonly'@'%';
GRANT ALL PRIVILEGES ON prosody.* TO 'prosody'@'%';
FLUSH PRIVILEGES;
quit
```
Then update the passwords you've set in your configuration files:
```
nano /etc/dovecot/dovecot-dict-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext /etc/postfix/sql/mysql_* /etc/prosody/prosody.cfg.lua /var/www/mail/common_config.php
```
Generate a keypair for rspamd with `rspamadm keypair gen` and add it to /etc/rspamd/local.d/worker-fuzzy.inc, add the public encryption key to /etc/rspamd/override.d/fuzzy_check.conf
Set a password for the web interface with `rspamadm pw` and add the hash for it to /etc/rspamd/override.d/worker-controller.inc
Generate DKIM signing keys and add them to /etc/rspamd/local.d/arc.conf /etc/rspamd/local.d/dkim_signing.conf, then add the printed DNS records to your domain:
```
rspamadm dkim_keygen -d YOUR_DOMAIN -s $(date +"%Y%m%d")-rsa -b 4096 -t rsa -k /var/lib/rspamd/dkim/YOUR_DOMAIN-rsa
rspamadm dkim_keygen -d YOUR_DOMAIN -s $(date +"%Y%m%d")-ed25519 -t ed25519 -k /var/lib/rspamd/dkim/YOUR_DOMAIN-ed25519
```
Create a password used for your TURN server and replace all `YOUR_SECRET` in `/etc/prosody/prosody.cfg.lua` with it.
Install [acme.sh](https://github.com/acmesh-official/acme.sh) or [certbot](https://certbot.eff.org/) to obtain a free letsencrypt SSL certificate, then update the path to this new certificate in the following files:
```
nano /etc/prosody/prosody.cfg.lua /etc/dovecot/dovecot.conf /etc/postfix/main.cf /etc/nginx/nginx.conf /etc/nginx/sites-enabled/mail /etc/nginx/sites-enabled/openpgpkey
```
Add your other servers IP under `unrestricted access to these IPs` in `/etc/rc.local`
Create database tables, activate firewall and enable cron:
```
postmap /etc/postfix/header_checks
cd /var/www/mail && php setup.php && chmod +x /etc/rc.local && /etc/rc.local && systemctl enable mail-cron.timer
```
Generate a wireguard keypair and add the public key generated here to the primary mail server wireguard config:
```
export PRIV=$(wg genkey)
sed -i "s~YOUR_PRIVATE_KEY~$PRIV~g" /etc/wireguard/wg0.conf
echo $PRIV | wg pubkey
```
Replace `YOUR_IP` with the IP of your other server, then enable and start wireguard:
```
nano /etc/wireguard/wg0.conf
systemctl enable wg-quick@wg0 && systemctl start wg-quick@wg0
```
Final step is to reboot the server and check that everything is working.
### Proxy server:
To send emails to the regular internet, it is necessary to have a static IP to retain a reputation with an IP+Domain mapping. If you try sending via Tor, your emails will most certainly get blocked by spam filters. For this reason we need to setup a proxy server which will hold no user data itself, but simply act as a gateway to reach the less anonymous part of the internet.
Uninstall packages that may interfere with this setup:
```
DEBIAN_FRONTEND=noninteractive apt-get purge -y apache2* dnsmasq* eatmydata exim4* imagemagick-6-common mysql-client* mysql-server* nginx* libnginx-mod* php7* resolvconf && systemctl disable systemd-resolved.service && systemctl stop systemd-resolved.service
```
If you have problems resolving hostnames after this step, temporarily switch to a public nameserver like 1.1.1.1 (from CloudFlare) or 8.8.8.8 (from Google)
```
rm /etc/resolv.conf && echo "nameserver 1.1.1.1" > /etc/resolv.conf
```
Install git and clone this repository
```
apt-get update && apt-get install git -y && git clone https://github.com/DanWin/mail-hosting && cd mail-hosting
```
Install files and programs
```
./install_binaries_proxy.sh
```
Copy (and modify according to your needs) the site files in `etc_clearnet_proxy` to `/etc` after installation has finished.
Add the password for your TURN server you created for prosody in the main server and replace `YOUR_AUTH_SECRET` in `/etc/turnserver.conf` with it.
Install [acme.sh](https://github.com/acmesh-official/acme.sh) or [certbot](https://certbot.eff.org/) to obtain a free letsencrypt SSL certificate, then update the path to this new certificate in the following files:
```
nano /etc/postfix/main.cf /etc/nginx/nginx.conf /etc/turnserver.conf
```
Replace `YOUR_PASSWORD` in `/etc/postfix/sql/mysql_tls_policy_out.cf` with the one you've generated previously on the other server.
Generate a wireguard keypair and add the public key generated here to the primary mail server wireguard config:
```
export PRIV=$(wg genkey)
sed -i "s~YOUR_PRIVATE_KEY~$PRIV~g" /etc/wireguard/wg0.conf
echo $PRIV | wg pubkey
```
Replace `YOUR_IP` with the IP of your other server and `ens3` with your network interface name, then enable and start wireguard:
```
nano /etc/wireguard/wg0.conf
systemctl enable wg-quick@wg0 && systemctl start wg-quick@wg0
```
Edit and create your admin user with the following script:
```
nano /var/www/mail/tools/create_admin.php
php /var/www/mail/tools/create_admin.php
```
Copy the file `/etc/postfix/danwin1210-mail.crt` from your main server to the same location on the proxy server.
Final step is to reboot the server and check that everything is working.
### General Domain settings
Add the following DNS records to your domain, with the IPs of your proxy server:
```
@ IN TXT "v=spf1 ip4:your.ip.v4.address ip6:your:ip:v6:address -all"
_dmarc IN TXT "v=DMARC1;p=quarantine;adkim=r;aspf=r;fo=1;rua=mailto:postmaster@yourdomain;ruf=mailto:postmaster@yourdomain;rf=afrf;ri=86400;pct=100"
_adsp._domainkey IN TXT "dkim=all;"
_domainkey IN TXT "o=-;r=postmaster@yourdomain"
*._report._dmarc IN TXT "v=DMARC1"
_mta-sts IN TXT "v=STSv1; id=2024060601"
_smtp._tls IN TXT "v=TLSRPTv1; rua=mailto:postmaster@yourdomain"
_imaps._tcp IN SRV 0 0 993 yourdomain.
_submission._tcp IN SRV 0 0 587 yourdomain.
@ IN MX 0 yourdomain.
@ IN A your.ip.v4.address
@ IN AAAA your:ip:v6:address
www IN A your.ip.v4.address
www IN AAAA your:ip:v6:address
mta-sts IN A your.ip.v4.address
mta-sts IN AAAA your:ip:v6:address
conference IN A your.ip.v4.address
conference IN AAAA your:ip:v6:address
proxy IN A your.ip.v4.address
proxy IN AAAA your:ip:v6:address
upload IN A your.ip.v4.address
upload IN AAAA your:ip:v6:address
_xmpp-server._tcp.conference IN SRV 5 0 5269 yourdomain.
_xmpp-server._tcp.conference IN SRV 0 0 5269 your_onion_domain.
_xmpp-client._tcp IN SRV 5 0 5222 yourdomain.
_xmpp-client._tcp IN SRV 0 0 5222 your_onion_domain.
_xmpps-client._tcp IN SRV 5 0 5223 yourdomain.
_xmpps-client._tcp IN SRV 0 0 5223 your_onion_domain.
_xmpp-server._tcp IN SRV 5 0 5269 yourdomain.
_xmpp-server._tcp IN SRV 0 0 5269 your_onion_domain.
_stun._udp IN SRV 0 0 3478 yourdomain.
_turn._udp IN SRV 0 0 3478 yourdomain.
_stun._tcp IN SRV 0 0 3478 yourdomain.
_stuns._tcp IN SRV 0 0 3479 yourdomain.
_turn._tcp IN SRV 0 0 3478 yourdomain.
_turns._tcp IN SRV 0 0 5349 yourdomain.
_xmppconnect IN TXT "_xmpp-client-xbosh=https://yourdomain:5281/http-bind"
_xmppconnect IN TXT "_xmpp-client-websocket=wss://yourdomain:5281/xmpp-websocket"
```
Set the PTR record of your proxy servers IPs to your domain. This can usually be done from your hosting panels configuration, but may not be available with every hosting provider, where you can then request them to do it via a support ticket.
Consider registering your domain with [DNSWL](https://www.dnswl.org/), [SNDS](https://sendersupport.olc.protection.outlook.com/snds/), [Google Postmaster Tools](https://postmaster.google.com/) and [YahooCFL](https://senders.yahooinc.com/complaint-feedback-loop/) for valuable insights into your delivery.
Consider enabling DNSSEC on your domain, when available by your Domain registrar. Some registrars may charge extra for it. Once enabled, you can also enable DANE, which increases security. Use [TLSA Record Genearator](https://ssl-tools.net/tlsa-generator) to help you create an appropriate DNS record.
Consider adding your domain to [HSTS Preload List](https://hstspreload.org/) which will prevent browsers from even trying to access your domain on the insecure http:// protocol and automatically upgreade to https://
### Final configuration steps
Follow [SnappyMail installation instructions](https://github.com/the-djmaze/snappymail/wiki/Installation-instructions#now-access-the-admin-page) to finish setting it up at yourdomain/mail/snappymail/?admin
Translating:
------------

View File

@ -11,7 +11,7 @@ const DBPASS = 'YOUR_PASSWORD'; // Database password
const DBNAME = 'postfix'; // Database
const DBVERSION = 1; // Database schema version
const PERSISTENT = true; // persistent database connection
const CAPTCHA_DIFFICULTY = 1; // captcha difficulty from 0 to 3
const CAPTCHA_DIFFICULTY = 1; // captcha difficulty from 0 to 4
const RESERVED_USERNAMES = ['about', 'abuse', 'admin', 'administrator', 'billing', 'contact', 'daemon', 'ftp', 'help', 'hostmaster', 'info', 'legal', 'list', 'list-request', 'lists', 'maildaemon', 'mailerdaemon', 'mailer-daemon', 'marketing', 'media', 'news', 'newsletter', 'nobody', 'noc', 'noreply', 'no-reply', 'notification', 'notifications', 'notify', 'offer', 'offers', 'office', 'official', 'order', 'orders', 'phish', 'phishing', 'postmaster', 'root', 'sale', 'sales', 'security', 'service', 'services', 'shop', 'shopping', 'spam', 'staff', 'support', 'survey', 'system', 'team', 'teams', 'unsbubscribe', 'uucp', 'usenet', 'user', 'username', 'users', 'web', 'webmail', 'webmaster', 'webmasters', 'welcome', 'www']; // list of reserved usernames that can mot be used on public registration
const CANONICAL_URL = 'https://danwin1210.de/mail/'; // our preferred URL prefix for search engines
const PRIVACY_POLICY_URL = '/privacy.php'; // URL to privacy policy
@ -26,6 +26,8 @@ const DBHOST_PROSODY = 'localhost'; // Database host
const DBUSER_PROSODY = 'prosody'; // Database user
const DBPASS_PROSODY = 'YOUR_PASSWORD'; // Database password
const DBNAME_PROSODY = 'prosody'; // Database
const REGISTRATION_ENABLED = true; // Whether registration is enabled
const DEFAULT_QUOTA = 50 * 1024 * 1024; // Default mailbox quota in bytes
const LANGUAGES = [
'cs' => ['name' => 'čeština', 'locale' => 'cs_CZ', 'flag' => '🇨🇿', 'show_in_menu' => true, 'dir' => 'ltr'],
@ -34,6 +36,7 @@ const LANGUAGES = [
'pl' => ['name' => 'Polski', 'locale' => 'pl_PL', 'flag' => '🇵🇱', 'show_in_menu' => true, 'dir' => 'ltr'],
'ru' => ['name' => 'Русский', 'locale' => 'ru_RU', 'flag' => '🇷🇺', 'show_in_menu' => true, 'dir' => 'ltr'],
'tr' => ['name' => 'Türkçe', 'locale' => 'tr_TR', 'flag' => '🇹🇷', 'show_in_menu' => true, 'dir' => 'ltr'],
'uk' => ['name' => 'Українська', 'locale' => 'uk_UA', 'flag' => '🇺🇦', 'show_in_menu' => true, 'dir' => 'ltr'],
];
$language = 'en';
$locale = 'en_GB';
@ -160,6 +163,45 @@ function send_captcha(): void
imagesetpixel( $im, mt_rand( 0, 55 ), mt_rand( 0, 24 ), $dots );
}
echo '<img alt="" width="55" height="24" src="data:image/gif;base64,';
} elseif (CAPTCHA_DIFFICULTY === 3){
$im = imagecreatetruecolor(55, 24);
$bg = imagecolorallocatealpha($im, 0, 0, 0, 127);
$fg = imagecolorallocate($im, 255, 255, 255);
$cc = imagecolorallocate($im, 200, 200, 200);
$cb = imagecolorallocatealpha($im, 0, 0, 0, 127);
imagefill($im, 0, 0, $bg);
$line = imagecolorallocate($im, 255, 255, 255);
$deg = (mt_rand(0,1)*2-1)*mt_rand(10, 20);
$background = imagecreatetruecolor(120, 80);
imagefill($background, 0, 0, $cb);
for ($i=0; $i<20; ++$i) {
$char = imagecreatetruecolor(12, 16);
imagestring($char, 5, 2, 2, $captchachars[mt_rand(0, $length)], $cc);
$char = imagerotate($char, (mt_rand(0,1)*2-1)*mt_rand(10, 20), $cb);
$char = imagescale($char, 24, 32);
imagefilter($char, IMG_FILTER_SMOOTH, 0.6);
imagecopy($background, $char, rand(0, 100), rand(0, 60), 0, 0, 24, 32);
}
imagestring($im, 5, 5, 5, $code, $fg);
$im = imagescale($im, 110, 48);
imagefilter($im, IMG_FILTER_SMOOTH, 0.5);
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
$im = imagerotate($im, $deg, $bg);
$im = imagecrop($im, array('x'=>0, 'y'=>0, 'width'=>120, 'height'=>80));
imagecopy($background, $im, 0, 0, 0, 0, 110, 80);
imagedestroy($im);
$im = $background;
for($i=0; $i<1000; ++$i){
$c = mt_rand(100,230);
$dots = imagecolorallocate($im, $c, $c, $c);
imagesetpixel($im, mt_rand(0, 120), mt_rand(0, 80), $dots);
}
imagedestroy($char);
echo '<img width="120" height="80" src="data:image/png;base64,';
} else {
$im = imagecreatetruecolor( 150, 200 );
$bg = imagecolorallocate( $im, 0, 0, 0 );
@ -256,7 +298,7 @@ function validate_email_list( array $targets, string &$msg = '' ): string
if ( $validator->isValid( $email, new NoRFCWarningsValidation() ) ) {
$alias_goto .= ",$email";
} else {
$msg .= '<div class="red" role="alert">'.sprintf(_('Oops, the email "%s" doesn\' look like a valid email address and thus wasn\'t added to the forwarding list.'), htmlspecialchars( $email ) ) . '</div>';
$msg .= '<div class="red" role="alert">'.sprintf(htmlspecialchars(_('Oops, the email "%s" doesn\' look like a valid email address and thus wasn\'t added to the forwarding list.')), htmlspecialchars( $email ) ) . '</div>';
}
}
return ltrim( $alias_goto, ',' );
@ -282,7 +324,7 @@ function check_domain_access( string &$email, string &$msg = '' ): bool
$managed_domains [] = $tmp[ 'domain' ];
}
if ( ! in_array( $domain, $managed_domains, true ) ) {
$msg .= '<div class="red" role="alert">'._('You are not allowed to manage this domain.').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('You are not allowed to manage this domain.')).'</div>';
return false;
}
}
@ -293,7 +335,7 @@ function check_email_valid( string $email, string &$msg = '' ): bool
{
$validator = new EmailValidator();
if ( ! $validator->isValid( $email, new NoRFCWarningsValidation() ) ) {
$msg .= '<div class="red" role="alert">'._('Invalid email address.').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Invalid email address.')).'</div>';
return false;
}
return true;
@ -310,3 +352,13 @@ function alt_links(): void
echo '<meta property="og:locale:alternate" content="'.$data['locale'].'">';
}
}
function bytes_to_human_readable(int $bytes) : string {
$suffix = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
$size_class=(int) log($bytes, 1024);
if($size_class!==0){
return sprintf('%1.1f', $bytes / pow(1024, $size_class)) . $suffix[$size_class];
}else{
return $bytes . $suffix[0];
}
}

View File

@ -32,9 +32,13 @@ while ( $tmp = $stmt->fetch( PDO::FETCH_ASSOC ) ) {
if ( file_exists( $mail_files ) ) {
exec( 'rm -r ' . escapeshellarg( $mail_files ) );
}
$snapmail_files = '/var/local/snappymail/_data_/_default_/storage/' . $domain_basename . '/' . $local_basename;
if ( file_exists( $snapmail_files ) ) {
exec( 'rm -r ' . escapeshellarg( $snapmail_files ) );
}
$files = glob( '/var/local/squirrelmail/data/' . $local_basename . '@' . $domain_basename . '.{pref,abook,sig}', GLOB_BRACE );
if ( $tmp[ 'domain' ] === 'danwin1210.de' ) {
$files = array_merge( $files, glob( '/var/local/squirrelmail/data/' . $local_basename . '{@danielas3rtn54uwmofdo3x2bsdifr47huasnmbgqzfrec5ubupvtpid.onion,}.{pref,abook,sig}', GLOB_BRACE ) );
if ( $tmp[ 'domain' ] === CLEARNET_SERVER ) {
$files = array_merge( $files, glob( '/var/local/squirrelmail/data/' . $local_basename . '{@'.ONION_SERVER.',}.{pref,abook,sig}', GLOB_BRACE ) );
$delete_prosody->execute( [ $tmp[ 'local_part' ], $tmp[ 'domain' ] ] );
$delete_prosody_archive->execute( [ $tmp[ 'local_part' ], $tmp[ 'domain' ] ] );
}
@ -66,6 +70,10 @@ while ( $tmp = $stmt->fetch( PDO::FETCH_ASSOC ) ) {
if ( file_exists( $mail_files ) ) {
exec( 'rm -r ' . escapeshellarg( $mail_files ) );
}
$snapmail_files = '/var/local/snappymail/_data_/_default_/storage/' . $domain_basename . '/';
if ( file_exists( $snapmail_files ) ) {
exec( 'rm -r ' . escapeshellarg( $snapmail_files ) );
}
if ( is_array( $files ) ) {
foreach ( $files as $file ) {
@unlink( $file );

View File

@ -14,9 +14,11 @@ mail_debug = no
verbose_ssl = no
mail_location = maildir:/var/mail/vmail/%d/%n
mail_home = /var/mail/vmail/%d/%n
mail_plugins = $mail_plugins mail_crypt zlib
mail_plugins = mail_crypt quota zlib
mailbox_list_index = yes
mail_always_cache_fields = date.save
imap_hibernate_timeout = 5s
mail_attribute_dict = file:%h/dovecot-attributes
#plugin setup
plugin {
@ -34,6 +36,9 @@ plugin {
quota_vsizes = yes
last_login_dict = proxy::lastlogin
last_login_key = last-login/%u
sieve = file:~/sieve;active=~/.dovecot.sieve
sieve_plugins = sieve_imapsieve
imapsieve_url = sieve://danwin1210.de
}
#auth settings
@ -47,8 +52,8 @@ auth_mechanisms = plain login
#TLS parameters
ssl = required
ssl_cert = </etc/acme.sh/danwin1210.de_ecc/fullchain.cer
ssl_key = </etc/acme.sh/danwin1210.de_ecc/danwin1210.de.key
ssl_cert = </etc/ssl/certs/ssl-cert-snakeoil.pem
ssl_key = </etc/ssl/private/ssl-cert-snakeoil.key
ssl_client_ca_dir = /etc/ssl/certs
ssl_dh = </etc/dovecot/dh.pem
ssl_min_protocol = TLSv1.2
@ -57,17 +62,17 @@ ssl_curve_list = X448:X25519:secp521r1:secp384r1
ssl_prefer_server_ciphers = yes
#protocol setup
protocols = "imap pop3 lmtp"
protocol lmtp {
postmaster_address = postmaster@danwin1210.de
}
protocols = "imap pop3 lmtp sieve"
protocol imap {
mail_plugins = $mail_plugins quota imap_quota imap_zlib last_login
mail_plugins = $mail_plugins imap_quota imap_zlib imap_sieve last_login
imap_metadata = yes
}
protocol pop3 {
mail_plugins = $mail_plugins last_login
protocol lmtp {
mail_plugins = mail_crypt quota zlib sieve last_login
}
protocol sieve {
mail_plugins =
}
#service setup
service anvil {
unix_listener anvil-auth-penalty {
@ -105,6 +110,9 @@ service auth-worker {
service imap {
service_count = 1000
client_limit = 1
unix_listener imap-master {
user = $default_internal_user
}
}
service imap-login {
inet_listener imap {
@ -112,7 +120,7 @@ service imap-login {
}
service_count = 1000
vsz_limit = 1G
process_min_avail = 4
process_min_avail = 1
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
@ -164,17 +172,20 @@ dict {
namespace inbox {
inbox = yes
mailbox Drafts {
auto = subscribe
special_use = \Drafts
}
mailbox Junk {
special_use = \Junk
}
mailbox Trash {
auto = subscribe
special_use = \Trash
autoexpunge = 30d
}
mailbox Sent {
auto = subscribe
special_use = \Sent
}
mailbox "Sent Messages" {

29
etc/nginx/fastcgi.conf Normal file
View File

@ -0,0 +1,29 @@
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param HTTP_HOST $host;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $php_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
fastcgi_hide_header "X-Powered-By";

View File

@ -4,6 +4,7 @@ pid /run/nginx.pid;
pcre_jit on;
worker_rlimit_nofile 30000;
worker_shutdown_timeout 1m;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 7680;
@ -24,7 +25,7 @@ http {
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
client_max_body_size 50M;
client_max_body_size 50M;
client_body_timeout 10s;
client_header_timeout 10s;
client_body_buffer_size 32k;
@ -51,8 +52,8 @@ http {
ssl_early_data off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_certificate /etc/acme.sh/danwin1210.de_ecc/fullchain.cer;
ssl_certificate_key /etc/acme.sh/danwin1210.de_ecc/danwin1210.de.key;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_dhparam /etc/nginx/dh4096.pem;
##
@ -66,18 +67,10 @@ http {
resolver 127.0.0.1 [::1];
resolver_timeout 2s;
root /var/www/html;
proxy_cache_path /var/lib/nginx/cache levels=2 keys_zone=cache:10m inactive=30d max_size=1g;
proxy_cache_revalidate on;
proxy_cache_use_stale http_503 timeout updating error;
proxy_no_cache $http_pragma $http_authorization;
proxy_cache_bypass $cookie_nocache $arg_nocache;
map $http_upgrade $connection_upgrade {
default upgrade;
'' '';
}
proxy_cache_lock_timeout 2m;
proxy_cache_lock_age 2m;
proxy_cache cache;
proxy_http_version 1.1;
proxy_buffer_size 8k;
proxy_buffering off;
@ -88,8 +81,6 @@ http {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_ignore_client_abort on;
proxy_cache_key $server_name$request_method$host$request_uri;
proxy_read_timeout 3600; #wait up to 60 minutes for e.g. database import
##
# Gzip Settings
@ -123,6 +114,12 @@ http {
}
expires $expires;
map $server_port $php_port {
80 80;
443 443;
default 80;
}
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}

View File

@ -28,13 +28,13 @@ server {
add_header Cross-Origin-Opener-Policy same-origin always;
add_header Cross-Origin-Resource-Policy same-origin always;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
expires off;
}
location ~ \.php$ {
add_header Referrer-Policy no-referrer always;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
expires off;
}
}
@ -45,14 +45,13 @@ server {
add_header Referrer-Policy no-referrer always;
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), geolocation=(), fullscreen=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=(), clipboard-read=(), clipboard-write=(), gamepad=(), speaker-selection=(), conversion-measurement=(), focus-without-user-activation=(), hid=(), idle-detection=(), sync-script=(), vertical-scroll=(), serial=(), trust-token-redemption=(), interest-cohort=(), otp-credentials=()" always;
add_header Onion-Location http://danielas3rtn54uwmofdo3x2bsdifr47huasnmbgqzfrec5ubupvtpid.onion$request_uri always;
add_header Expect-CT "max-age=86400, enforce" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Cross-Origin-Embedder-Policy require-corp always;
add_header Cross-Origin-Opener-Policy same-origin always;
add_header Cross-Origin-Resource-Policy same-origin always;
listen [::]:443 ssl proxy_protocol http2;
ssl_certificate /etc/acme.sh/danwin1210.de_ecc/fullchain.cer;
ssl_certificate_key /etc/acme.sh/danwin1210.de_ecc/danwin1210.de.key;
listen [::]:443 ssl http2 fastopen=100 backlog=2048 ipv6only=off default_server;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
root /var/www/html;
index index.php;
server_name danielas3rtn54uwmofdo3x2bsdifr47huasnmbgqzfrec5ubupvtpid.onion danwin1210.de;
@ -70,22 +69,20 @@ server {
add_header Referrer-Policy no-referrer always;
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), geolocation=(), fullscreen=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=(), clipboard-read=(), clipboard-write=(), gamepad=(), speaker-selection=(), conversion-measurement=(), focus-without-user-activation=(), hid=(), idle-detection=(), sync-script=(), vertical-scroll=(), serial=(), trust-token-redemption=(), interest-cohort=(), otp-credentials=()" always;
add_header Onion-Location http://danielas3rtn54uwmofdo3x2bsdifr47huasnmbgqzfrec5ubupvtpid.onion$request_uri always;
add_header Expect-CT "max-age=86400, enforce" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Cross-Origin-Embedder-Policy require-corp always;
add_header Cross-Origin-Opener-Policy same-origin always;
add_header Cross-Origin-Resource-Policy same-origin always;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
expires off;
}
location ~ \.php$ {
add_header Referrer-Policy no-referrer always;
add_header Onion-Location http://danielas3rtn54uwmofdo3x2bsdifr47huasnmbgqzfrec5ubupvtpid.onion$request_uri always;
add_header Expect-CT "max-age=86400, enforce" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
expires off;
}
}

View File

@ -0,0 +1,18 @@
server {
listen [::]:443 ssl http2;
server_name mta-sts.danwin1210.de;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
location / {
return 404;
}
location = /.well-known/mta-sts.txt {
default_type text/plain;
return 200 "version: STSv1
mode: enforce
mx: danwin1210.de
max_age: 86400
";
}
}

View File

@ -1,6 +1,5 @@
server {
listen [::]:443 ssl proxy_protocol http2;
add_header Expect-CT "max-age=86400, enforce" always;
listen [::]:443 ssl http2;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
root /var/www/html;
location / {
@ -13,9 +12,9 @@ server {
rewrite /.well-known/openpgpkey/(.*)/hu /mail/openpgpkey_wkd.php?domain=$1 last;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
expires off;
}
ssl_certificate /etc/acme.sh/danwin1210.de_ecc/fullchain.cer;
ssl_certificate_key /etc/acme.sh/danwin1210.de_ecc/danwin1210.de.key;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
}

View File

@ -1,2 +1,2 @@
/^To:.*@[^@]*\.de-mail\.de/ REJECT "Sorry, you tried contacting a De-Mail Address. This is a special System by the German government, not compatible with E-Mail. More info here: https://www.cio.bund.de/Web/DE/Innovative-Vorhaben/De-Mail/de_mail_node.html"
/^To:.*@[^@]*\.de-mail\.de/ REJECT "Sorry, you tried contacting a De-Mail Address. This is a special System by the German government, not compatible with E-Mail. More info here: https://de-mail.info/"
/^(To|From).*@example\.com/ REJECT

View File

@ -1 +0,0 @@
DESKTOPRaihan REJECT

View File

@ -24,8 +24,8 @@ compatibility_level = 3.6
smtputf8_autodetect_classes = all
# TLS parameters
smtpd_tls_cert_file = /etc/acme.sh/danwin1210.de_ecc/fullchain.cer
smtpd_tls_key_file = /etc/acme.sh/danwin1210.de_ecc/danwin1210.de.key
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_ciphers = HIGH
smtpd_tls_mandatory_ciphers = HIGH
smtp_tls_ciphers = HIGH
@ -33,12 +33,11 @@ smtp_tls_mandatory_ciphers = HIGH
tls_eecdh_auto_curves = X448 X25519 secp521r1 secp384r1 prime256v1
smtpd_tls_protocols = TLSv1.2 TLSv1.3
smtp_tls_protocols = TLSv1.2 TLSv1.3
smtpd_tls_exclude_ciphers = aNULL MD5 SHA CAMELLIA
smtpd_tls_mandatory_exclude_ciphers = aNULL MD5 SHA CAMELLIA
smtpd_tls_exclude_ciphers = aNULL MD5 SHA CAMELLIA RSA AES+SHA256 AES+SHA384
smtpd_tls_mandatory_exclude_ciphers = aNULL MD5 SHA CAMELLIA RSA AES+SHA256 AES+SHA384
smtp_tls_exclude_ciphers = aNULL MD5 SHA CAMELLIA AES+SHA256 AES+SHA384
smtp_tls_mandatory_exclude_ciphers = aNULL MD5 SHA CAMELLIA AES+SHA256 AES+SHA384
tls_preempt_cipherlist = yes
smtpd_tls_dh1024_param_file = /etc/postfix/dh4096.pem
smtpd_tls_security_level = may
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
@ -50,10 +49,10 @@ smtp_tls_chain_files = /etc/postfix/danwin1210-mail.chain
smtpd_tls_received_header = yes
#lookup maps for domains and email addresses
relay_domains = torbox.danwin1210.me torbox.danwin1210.de
canonical_maps = inline:{{@mail2tor.onion=@mail2tor.com}, {@torbox3uiot6wchz.onion=@torbox36ijlcevujx7mjb4oiusvwgvmue7jfn2cvutwa6kl6to3uyqad.onion}, {@torbox.onion=@torbox36ijlcevujx7mjb4oiusvwgvmue7jfn2cvutwa6kl6to3uyqad.onion}, {@torbox.danwin1210.me=@torbox36ijlcevujx7mjb4oiusvwgvmue7jfn2cvutwa6kl6to3uyqad.onion}, {@torbox.danwin1210.de=@torbox36ijlcevujx7mjb4oiusvwgvmue7jfn2cvutwa6kl6to3uyqad.onion}}
sender_canonical_maps = inline:{{@localhost=@danwin1210.de}, {@danielas3rtn54uwmofdo3x2bsdifr47huasnmbgqzfrec5ubupvtpid.onion=@danwin1210.de}, {@danwin1210.me=@danwin1210.de}}
transport_maps = inline:{{torbox3uiot6wchz.onion=relay:[torbox36ijlcevujx7mjb4oiusvwgvmue7jfn2cvutwa6kl6to3uyqad.onion]:25}, {.onion=smtp}, {mail2tor.com=relay:[xc7tgk2c5onxni2wsy76jslfsitxjbbptejnqhw6gy2ft7khpevhc7ad.onion]:25}, {blackhost.xyz=relay:[blackhost7pws76u6vohksdahnm6adf7riukgcmahrwt43wv2drvyxid.onion]:25}} proxy:mysql:/etc/postfix/sql/mysql_transport_maps.cf inline:{*=relay:[10.9.0.1]:1025}
relay_domains =
canonical_maps = inline:{{@mail2tor.onion=@mail2tor.com}, {@torbox3uiot6wchz.onion=@torbox36ijlcevujx7mjb4oiusvwgvmue7jfn2cvutwa6kl6to3uyqad.onion}, {@torbox.onion=@torbox36ijlcevujx7mjb4oiusvwgvmue7jfn2cvutwa6kl6to3uyqad.onion}}
sender_canonical_maps = inline:{{@localhost=@danwin1210.de}, {@danielas3rtn54uwmofdo3x2bsdifr47huasnmbgqzfrec5ubupvtpid.onion=@danwin1210.de}}
transport_maps = inline:{{.onion=smtp}, {mail2tor.com=relay:[xc7tgk2c5onxni2wsy76jslfsitxjbbptejnqhw6gy2ft7khpevhc7ad.onion]:25}, {blackhost.xyz=relay:[blackhost7pws76u6vohksdahnm6adf7riukgcmahrwt43wv2drvyxid.onion]:25}} proxy:mysql:/etc/postfix/sql/mysql_transport_maps.cf inline:{*=relay:[10.9.0.1]:1025}
virtual_alias_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf
@ -69,20 +68,20 @@ smtpd_recipient_restrictions = check_policy_service inet:127.0.0.1:12340, permit
smtpd_sender_restrictions = reject_sender_login_mismatch, check_sender_access inline:{{<> = REJECT}}, permit_sasl_authenticated
smtpd_relay_restrictions = permit_sasl_authenticated, permit_auth_destination, reject_unauth_destination
smtpd_sender_login_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_auth_maps.cf
smtpd_helo_restrictions = check_helo_access hash:/etc/postfix/helo_checks
# anti-spam settings
smtpd_milters = inet:127.0.0.1:11332
non_smtpd_milters = inet:127.0.0.1:11332
milter_default_action = accept
milter_default_action = tempfail
milter_protocol = 6
header_checks = regexp:/etc/postfix/header_checks
body_checks = regexp:/etc/postfix/body_checks
disable_vrfy_command = yes
smtpd_discard_ehlo_keywords = silent-discard, dsn
smtpd_delay_reject = yes
smtpd_helo_required = yes
strict_rfc821_envelopes = yes
default_destination_concurrency_limit = 2
smtpd_recipient_limit = 10
smtpd_recipient_limit = 5
smtp_pix_workarounds = delay_dotcrlf
smtpd_forbid_bare_newline = yes
smtpd_forbid_unauth_pipelining = yes

View File

@ -96,7 +96,6 @@ modules_enabled = {
"conversejs";
"http_altconnect";
"external_services";
"conversejs";
}
-- These modules are auto-loaded, but should you want
@ -125,8 +124,8 @@ pidfile = "/run/prosody/prosody.pid";
-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.
ssl = {
key = "/etc/acme.sh/danwin1210.de_ecc/danwin1210.de.key";
certificate = "/etc/acme.sh/danwin1210.de_ecc/fullchain.cer";
key = "/etc/ssl/private/ssl-cert-snakeoil.key";
certificate = "/etc/ssl/certs/ssl-cert-snakeoil.pem";
dhparam = "/etc/prosody/dh4096.pem";
curve = "X448:X25519:secp521r1:secp384r1:secp256k1";
ciphers = "HIGH+kEDH:HIGH+kEECDH:HIGH:!RSA:!PSK:!SRP:!3DES:!aNULL:!SHA:!MD5:!CAMELLIA:!ECDHE-RSA-AES256-SHA384:!ECDHE-RSA-AES128-SHA256:!DHE-RSA-AES128-SHA256:!DHE-RSA-AES256-SHA256";
@ -239,7 +238,7 @@ aliases = {
["danielas3rtn54uwmofdo3x2bsdifr47huasnmbgqzfrec5ubupvtpid.onion"] = "danwin1210.de";
}
alias_response = "User $alias can be contacted at $target";
defautl_storage = "sql"
default_storage = "sql"
interfaces = { "0.0.0.0", "::" } -- Listen address
contact_info = {
abuse = { "https://danwin1210.de/contact.php", "mailto:daniel@danwin1210.de" };
@ -248,7 +247,7 @@ contact_info = {
security = { "https://danwin1210.de/contact.php", "mailto:daniel@danwin1210.de" };
support = { "https://danwin1210.de/contact.php", "mailto:daniel@danwin1210.de" };
}
data_path = "/srv/var/lib/prosody"
data_path = "/var/lib/prosody"
legacy_ssl_ports = {5223}
external_services = {
{

73
etc/rc.local Executable file
View File

@ -0,0 +1,73 @@
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
#flush iptables
iptables -F
ip6tables -F
iptables -t nat -F
ip6tables -t nat -F
#accept already established connections
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#allow tor traffic
for tor in bind debian-tor; do(
iptables -t nat -A OUTPUT -m owner --uid-owner $tor -j RETURN
ip6tables -t nat -A OUTPUT -m owner --uid-owner $tor -j RETURN
iptables -A OUTPUT -m owner --uid-owner $tor -j ACCEPT
ip6tables -A OUTPUT -m owner --uid-owner $tor -j ACCEPT
)done
#allow local communication
iptables -A OUTPUT -o lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -i lo -j ACCEPT
#unrestricted access to these IPs
for clearnet in 127.0.0.0/8 10.9.0.0/24; do(
iptables -t nat -A OUTPUT -d $clearnet -j RETURN
iptables -A OUTPUT -d $clearnet -j ACCEPT
) done
for clearnet in ::1; do(
ip6tables -t nat -A OUTPUT -d $clearnet -j RETURN
ip6tables -A OUTPUT -d $clearnet -j ACCEPT
) done
#accet IPv6 ICMP packages required for SLAAC
ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
ip6tables -A OUTPUT -p ipv6-icmp -j ACCEPT
#allow querriying ntp servers
iptables -t nat -A OUTPUT -p udp --dport 123 -j RETURN
iptables -A OUTPUT -p udp --dport 123 -j ACCEPT
ip6tables -t nat -A OUTPUT -p udp --dport 123 -j RETURN
ip6tables -A OUTPUT -p udp --dport 123 -j ACCEPT
#redirect all outgoing DNS querries to our dns server
iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 53
ip6tables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 53
#redirect all other TCP traffic through tor
iptables -t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports 9040
ip6tables -t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports 9040
#reject everything else
iptables -A OUTPUT -j REJECT
ip6tables -A OUTPUT -j REJECT
#uncomment to be able to directly connect with your own IP and allow no one else
#for clearnet in YOUR_IP_HERE;do(
#iptables -A INPUT -s $clearnet -j ACCEPT
#)done
#drop everything else (uncomment after adding your own IP above)
#iptables -A INPUT -j DROP
#ip6tables -A INPUT -j DROP
exit 0

2
etc/resolv.conf Normal file
View File

@ -0,0 +1,2 @@
nameserver 127.0.0.1
options edns0 trust-ad

View File

@ -4,11 +4,11 @@ domain {
danwin1210.de {
selectors [
{
path: "/usr/local/etc/rspamd/dkim_keys/danwin1210.de-rsa";
path: "/var/lib/rspamd/dkim/danwin1210.de-rsa";
selector: "20211204-rsa";
},
{
path: "/usr/local/etc/rspamd/dkim_keys/danwin1210.de-ed25519";
path: "/var/lib/rspamd/dkim/danwin1210.de-ed25519";
selector: "20211204-ed25519";
}
]

View File

@ -8,11 +8,11 @@ domain {
danwin1210.de {
selectors [
{
path: "/usr/local/etc/rspamd/dkim_keys/danwin1210.de-rsa";
path: "/var/lib/rspamd/dkim/danwin1210.de-rsa";
selector: "20211204-rsa";
},
{
path: "/usr/local/etc/rspamd/dkim_keys/danwin1210.de-ed25519";
path: "/var/lib/rspamd/dkim/danwin1210.de-ed25519";
selector: "20211204-ed25519";
}
]

View File

@ -0,0 +1,6 @@
[Unit]
Description=Mail cron
[Service]
Type=simple
ExecStart=/usr/bin/php /var/www/mail/cron.php

View File

@ -0,0 +1,12 @@
[Unit]
Description=Mail cron
[Timer]
# Time to wait after booting before we run first time
OnBootSec=3min
# Time between running each consecutive time
OnUnitActiveSec=5m
Unit=mail-cron.service
[Install]
WantedBy=multi-user.target

View File

@ -4,6 +4,7 @@ pid /run/nginx.pid;
pcre_jit on;
worker_rlimit_nofile 30000;
worker_shutdown_timeout 1m;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 20000;
@ -50,8 +51,8 @@ http {
ssl_early_data off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_certificate /etc/acme.sh/danwin1210.de_ecc/fullchain.cer;
ssl_certificate_key /etc/acme.sh/danwin1210.de_ecc/danwin1210.de.key;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_dhparam /etc/nginx/dh4096.pem;
##
@ -65,18 +66,10 @@ http {
resolver 127.0.0.1 [::1];
resolver_timeout 2s;
root /var/www/html;
proxy_cache_path /var/lib/nginx/cache levels=2 keys_zone=cache:10m inactive=30d max_size=1g;
proxy_cache_revalidate on;
proxy_cache_use_stale http_503 timeout updating error;
proxy_no_cache $http_pragma $http_authorization;
proxy_cache_bypass $cookie_nocache $arg_nocache;
map $http_upgrade $connection_upgrade {
default upgrade;
'' '';
}
proxy_cache_lock_timeout 2m;
proxy_cache_lock_age 2m;
proxy_cache cache;
proxy_http_version 1.1;
proxy_buffer_size 8k;
proxy_buffering on;
@ -87,8 +80,6 @@ http {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_ignore_client_abort on;
proxy_cache_key $server_name$request_method$host$request_uri;
proxy_read_timeout 3600; #wait up to 60 minutes for e.g. database import
##
# Gzip Settings
@ -119,22 +110,17 @@ stream {
ssl_ecdh_curve X448:X25519:secp521r1:secp384r1:secp256k1;
ssl_ciphers HIGH:!PSK:!RSA:!aNULL:!MD5:!SHA:!CAMELLIA:!AES+SHA256:!AES+SHA384;
ssl_session_cache shared:SSLSTREAM:10m;
ssl_certificate /etc/acme.sh/danwin1210.de_ecc/fullchain.cer;
ssl_certificate_key /etc/acme.sh/danwin1210.de_ecc/danwin1210.de.key;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_dhparam /etc/nginx/dh4096.pem;
#smtp
server {
listen [::]:25 fastopen=100 ipv6only=off;
proxy_pass smtp_backend_servers;
deny 51.254.78.246;
}
server {
listen [::]:587 fastopen=100 ipv6only=off;
proxy_pass smtp_auth_backend_servers;
deny 49.70.67.204;
deny 87.246.7.212;
deny 37.49.225.155;
deny 103.151.123.103;
}
server {
listen [::]:465 fastopen=100 ipv6only=off;
@ -166,93 +152,59 @@ stream {
#xmpp
server {
listen [::]:5269 fastopen=100 ipv6only=off;
proxy_pass 10.9.0.3:5269;
proxy_pass 10.9.0.2:5269;
}
server {
listen [::]:5000 fastopen=100 ipv6only=off;
proxy_pass 10.9.0.3:5000;
proxy_pass 10.9.0.2:5000;
}
server {
listen [::]:5222 fastopen=100 ipv6only=off;
proxy_pass 10.9.0.3:5222;
proxy_pass 10.9.0.2:5222;
}
server {
listen [::]:5223 fastopen=100 ipv6only=off;
proxy_pass 10.9.0.3:5223;
proxy_pass 10.9.0.2:5223;
}
server {
listen [::]:5280 fastopen=100 ipv6only=off;
proxy_pass 10.9.0.3:5280;
proxy_pass 10.9.0.2:5280;
}
server {
listen [::]:5281 fastopen=100 ipv6only=off;
proxy_pass 10.9.0.3:5281;
proxy_pass 10.9.0.2:5281;
}
#https
server {
listen [::]:443 fastopen=100 ipv6only=off;
# limit_conn addr 2;
# proxy_upload_rate 4k;
proxy_protocol on;
proxy_pass https_backend_servers;
}
#upstream servers
upstream https_backend_servers {
server 10.9.0.2:443;
server 10.9.0.3:443;
server 10.9.0.4:443;
server 10.9.0.5:443;
}
upstream imaps_backend_servers {
server 10.9.0.2:993;
server 10.9.0.3:993;
server 10.9.0.4:993;
server 10.9.0.5:993;
}
upstream imap_backend_servers {
server 10.9.0.2:143;
server 10.9.0.3:143;
server 10.9.0.4:143;
server 10.9.0.5:143;
}
upstream pop3s_backend_servers {
server 10.9.0.2:995;
server 10.9.0.3:995;
server 10.9.0.4:995;
server 10.9.0.5:995;
}
upstream pop3_backend_servers {
server 10.9.0.2:110;
server 10.9.0.3:110;
server 10.9.0.4:110;
server 10.9.0.5:110;
}
upstream dns_backend_server {
server [::1]:53;
server 127.0.0.1:53;
}
upstream smtp_backend_servers {
server 10.9.0.2:25;
server 10.9.0.3:25;
server 10.9.0.4:25;
server 10.9.0.5:25;
}
upstream smtp_auth_backend_servers {
server 10.9.0.2:587;
server 10.9.0.3:587;
server 10.9.0.4:587;
server 10.9.0.5:587;
}
upstream smtps_backend_servers {
server 10.9.0.2:465;
server 10.9.0.3:465;
server 10.9.0.4:465;
server 10.9.0.5:465;
}
upstream mysql_backend_servers {
server 10.9.0.2:3306;
server 10.9.0.3:3306;
server 10.9.0.4:3306;
server 10.9.0.5:3306;
}
}

View File

@ -15,8 +15,8 @@ readme_directory = no
compatibility_level=3.6
# TLS parameters
smtpd_tls_cert_file=/etc/acme.sh/danwin1210.de_ecc/fullchain.cer
smtpd_tls_key_file=/etc/acme.sh/danwin1210.de_ecc/danwin1210.de.key
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_ciphers = HIGH

View File

@ -0,0 +1,2 @@
nameserver 127.0.0.1
options edns0 trust-ad

View File

@ -457,7 +457,7 @@ realm=danwin1210.de
# Use PEM file format.
#
#cert=/usr/local/etc/turn_server_cert.pem
cert=/etc/acme.sh/danwin1210.de_ecc/fullchain.cer
cert=/etc/ssl/certs/ssl-cert-snakeoil.pem
# Private key file.
# Use an absolute path or path relative to the
@ -465,7 +465,7 @@ cert=/etc/acme.sh/danwin1210.de_ecc/fullchain.cer
# Use PEM file format.
#
#pkey=/usr/local/etc/turn_server_pkey.pem
pkey=/etc/acme.sh/danwin1210.de_ecc/danwin1210.de.key
pkey=/etc/ssl/private/ssl-cert-snakeoil.key
# Private key file password, if it is in encoded format.
# This option has no default value.

View File

@ -8,53 +8,51 @@ workingdir=$(pwd)
# install all required packages
DEBIAN_FRONTEND=noninteractive apt-get update
DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -y apt-transport-tor bash-completion bind9 ca-certificates clamav-daemon clamav-freshclam curl dovecot-imapd dovecot-lmtpd dovecot-pop3d git gnupg haveged iptables libsasl2-modules locales locales-all logrotate lsb-release mariadb-server mercurial nano nginx openssl php8.1-cli php8.1-curl php8.1-fpm php8.1-gd php8.1-gmp php8.1-gnupg php8.1-imap php8.1-intl php8.1-mbstring php8.1-mysql php8.1-pspell php8.1-readline postfix postfix-mysql prosody redis tor vim wget unzip wireguard wireguard-tools
# build dependencies
DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -y autoconf automake cmake g++ gcc libcurl4-openssl-dev libglib2.0-dev libicu-dev libluajit-5.1-dev libpcre3-dev libsodium-dev libsqlite3-dev libssl-dev libtool make ragel zlib1g-dev
# initial repository clones
if [ ! -e rspamd ]; then
git clone --recurse-submodules https://github.com/rspamd/rspamd.git
fi
export PROC_LIMIT=`free -g | grep Mem | awk -v nproc=$(nproc) '{print (($2 + 1) < nproc) ? ($2 + 1) : nproc;}'`
# start build
cd rspamd
git fetch --all --recurse-submodules
git checkout 3.5 --recurse-submodules
cd ..
mkdir -p rspamd_build
cd rspamd_build
cmake ../rspamd -DENABLE_LUAJIT=ON -DCMAKE_BUILD_TYPE=Release
make -j $PROC_LIMIT
make install
cd ..
rm -rf rspamd_build
ldconfig
DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -y apt-transport-tor bash-completion bind9 ca-certificates clamav-daemon clamav-freshclam curl dovecot-imapd dovecot-lmtpd dovecot-managesieved dovecot-mysql dovecot-pop3d dovecot-sieve git gnupg haveged iptables libnginx-mod-http-brotli-filter libsasl2-modules locales locales-all logrotate lsb-release lua-dbi-mysql lua-event lua-unbound mariadb-server mercurial nano nginx openssl patch php8.2-cli php8.2-curl php8.2-fpm php8.2-gd php8.2-gmp php8.2-gnupg php8.2-imap php8.2-intl php8.2-mbstring php8.2-mysql php8.2-pspell php8.2-readline php8.2-tidy php8.2-uuid php8.2-xml php8.2-zip postfix postfix-mysql prosody redis rng-tools5 rspamd tor vim wget unzip wireguard wireguard-tools
# install composer
curl -sSL https://github.com/composer/composer/releases/download/2.3.8/composer.phar > /usr/bin/composer
curl -sSL https://github.com/composer/composer/releases/download/2.8.3/composer.phar > /usr/bin/composer
chmod +x /usr/bin/composer
composer self-update
# rspamd user
id -u _rspamd >/dev/null 2>&1 ||useradd -M -r -s /bin/false -d /var/lib/rspamd _rspamd
mkdir -p /var/lib/rspamd
chown _rspamd: /var/lib/rspamd
# mysql encryption
if [ ! -e /etc/mysql/encryption/keyfile.enc ]; then
mkdir -p /etc/mysql/encryption/
openssl rand -hex 128 > /etc/mysql/encryption/keyfile.key
echo "1;"$(openssl rand -hex 32) | openssl enc -aes-256-cbc -md sha1 -pass file:/etc/mysql/encryption/keyfile.key -out /etc/mysql/encryption/keyfile.enc
fi
# dovecot encryption
if [ ! -e /etc/dovecot/ecprivkey.pem ]; then
mkdir -p /etc/dovecot/
openssl ecparam -name secp521r1 -genkey | openssl pkey -out /etc/dovecot/ecprivkey.pem
openssl pkey -in /etc/dovecot/ecprivkey.pem -pubout -out /etc/dovecot/ecpubkey.pem
fi
# postifx certificates
if [ ! -e /etc/postfix/danwin1210-mail.chain ]; then
openssl req -x509 -nodes -days 3650 -newkey ed448 -subj "/" -keyout /etc/postfix/danwin1210-mail.key -out /etc/postfix/danwin1210-mail.crt && cat /etc/postfix/danwin1210-mail.key >> /etc/postfix/danwin1210-mail.chain && cat /etc/postfix/danwin1210-mail.crt >> /etc/postfix/danwin1210-mail.chain
fi
# dhparams
for file in /etc/nginx/dh4096.pem /etc/dovecot/dh.pem /etc/prosody/dh4096.pem; do
if [ ! -e "$file" ]; then
openssl dhparam -out "$file" 4096
fi
done
# vmail user
id -u vmail > /dev/null 2>&1 || (groupadd -g 5000 -r vmail && useradd -g 5000 -M -r -s /bin/false -u 5000 vmail -d /var/mail/vmail)
mkdir -p /var/mail/vmail
chown vmail: /var/mail/vmail
#install scripts
mkdir -p /var/www/mail
mkdir -p /var/www/html
mkdir -p /var/lib/rspamd/dkim
chown _rspamd: /var/lib/rspamd/dkim
if [ ! -e /var/www/html/mail ]; then
ln -s ../mail/www /var/www/html/mail
fi
cp -r composer.json cron.php setup.php www /var/www/mail/
cp -r composer.json cron.php setup.php www tools locale /var/www/mail/
cd /var/www/mail/
composer install --no-dev
@ -66,12 +64,58 @@ if [ ! -e /var/www/mail/www/squirrelmail ]; then
git clone https://github.com/RealityRipple/squirrelmail .
mkdir -p /var/local/squirrelmail/data /var/local/squirrelmail/attach
chown www-data:www-data -R /var/local/squirrelmail
cd $workingdir
cp squirrelmail_config.php /var/www/mail/www/squirrelmail/config/config.php
else
cd /var/www/mail/www/squirrelmail
git fetch --all
git pull
fi
if [ ! -e /var/www/mail/www/squirrelmail/plugins/check_quota/ ]; then
cd /var/www/mail/www/squirrelmail/plugins/
wget https://www.squirrelmail.org/plugins/check_quota-2.2-1.4.0.tar.gz
tar -zxf check_quota-2.2-1.4.0.tar.gz
rm check_quota-2.2-1.4.0.tar.gz
cd $workingdir
cp squirrelmail_plugin_hooks.php /var/www/mail/www/squirrelmail/config/plugin_hooks.php
patch -p1 -d /var/www/html/mail/squirrelmail/plugins/check_quota/ < squirrelmail_check_quota.patch
fi
# install snappymail
mkdir -p /var/www/mail/www/snappymail
cd /var/www/mail/www/snappymail
VERSION=$(curl -s https://api.github.com/repos/the-djmaze/snappymail/releases/latest | grep tag_name | cut -d '"' -f 4)
wget https://github.com/the-djmaze/snappymail/releases/download/${VERSION}/snappymail-${VERSION:1}.zip
unzip -o snappymail-${VERSION:1}.zip
rm snappymail-${VERSION:1}.zip
mkdir -p /var/local/snappymail
chown www-data:www-data -R /var/local/snappymail
if [ ! -e include.php ]; then
cp _include.php include.php
echo "define('APP_DATA_FOLDER_PATH', '/var/local/snappymail/');" >> include.php
echo "define('SNAPPYMAIL_UPDATE_PLUGINS', 1);" >> include.php
fi
# install converse.js
rm -rf /srv/conversejs
mkdir -p /srv/conversejs
cd /srv/conversejs
VERSION=$(curl -s https://api.github.com/repos/conversejs/converse.js/releases/latest | grep tag_name | cut -d '"' -f 4)
wget https://github.com/conversejs/converse.js/releases/download/${VERSION}/converse.js-${VERSION:1}.tgz
tar xzf converse.js-${VERSION:1}.tgz --strip-components=1
rm converse.js-${VERSION:1}.tgz
rm -f /etc/nginx/sites-enabled/default
# install prosody modules
if [ ! -e /srv/prosody-modules ]; then
hg clone https://hg.prosody.im/prosody-modules/ /srv/prosody-modules
else
cd /srv/prosody-modules
hg pull --update
fi
# copy configuration file
cd $workingdir
if [ ! -e /var/www/mail/common_config.php ]; then

View File

@ -5,4 +5,13 @@ export LANG=C.UTF-8
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
# install all required packages
DEBIAN_FRONTEND=noninteractive apt-get update
DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -y bash-completion bind9 ca-certificates coturn curl git gnupg haveged iptables libsasl2-modules logrotate lsb-release nano nginx openssl postfix postfix-mysql postfix-mta-sts-resolver vim wget wireguard wireguard-tools
DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -y bash-completion bind9 ca-certificates coturn curl git gnupg haveged iptables libnginx-mod-stream libnginx-mod-http-brotli-filter libsasl2-modules logrotate lsb-release nano nginx openssl postfix postfix-mysql postfix-mta-sts-resolver rng-tools5 vim wget wireguard wireguard-tools
# dhparams
for file in /etc/nginx/dh4096.pem; do
if [ ! -e "$file" ]; then
openssl dhparam -out "$file" 4096
fi
done
rm -f /etc/nginx/sites-enabled/default

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -60,3 +60,13 @@ try{
echo $e->getMessage() . PHP_EOL;
}
}
try {
$stmt = $db->prepare( 'INSERT IGNORE INTO domain (domain, created, modified) VALUES (?, NOW(), NOW())' );
$stmt->execute( [ CLEARNET_SERVER ] );
$stmt->execute( [ ONION_SERVER ] );
$stmt = $db->prepare( 'INSERT IGNORE INTO alias_domain (alias_domain, target_domain, created, modified) VALUES (?, ?, NOW(), NOW())' );
$stmt->execute( [ ONION_SERVER, CLEARNET_SERVER ] );
} catch( PDOException $e ) {
echo _('Error adding primary domain:') . PHP_EOL;
echo $e->getMessage() . PHP_EOL;
}

View File

@ -0,0 +1,458 @@
diff -ruN check_quota_old/config.php check_quota/config.php
--- check_quota_old/config.php 1970-01-01 01:00:00.000000000 +0100
+++ check_quota/config.php 2023-05-22 08:47:49.000000000 +0200
@@ -0,0 +1,409 @@
+<?php
+
+/*
+ * This is the configuration file for Check Quota Plugin.
+ * You can edit the options here to suit your needs.
+ * Please make sure you read the INSTALL file before configuring
+ * these options.
+*/
+
+global $settings;
+$settings = array();
+
+
+/*******************************
+ * Quota Configuration Options *
+ *******************************/
+
+/*
+ * Use UNIX (filesystem), IMAP-based or cPanel (experimental) quotas?
+ * If you use UNIX (filesystem) quotas, you should set this to 0.
+ * If you use IMAP-based quotas, you should set this to 1.
+ * If you use cPanel quotas, you should set this to 2.
+ *
+ * Default: UNIX (filesystem) quotas
+ * 0: UNIX / 1: IMAP / 2: cPanel
+*/
+
+$settings['quota_type'] = 1;
+
+
+/*
+ * If you are using UNIX (filesystem) quotas, set the path
+ * to the "sudo" binary here. See INSTALL for instructions.
+*/
+
+$settings['sudo_binary'] = '/usr/bin/sudo';
+
+
+/*
+ * If you are using UNIX quotas, set the path to the "quota"
+ * binary here. See INSTALL for instructions.
+*/
+
+$settings['quota_binary'] = '/usr/bin/quota';
+
+
+/*
+ * If you are using UNIX quotas and your IMAP server and web server
+ * are on different physical machines (i.e. you want to check UNIX
+ * quotas remotely) set this to 1. See INSTALL for instructions.
+ *
+ * This setting is only used for UNIX quotas.
+ *
+ * Default: Check on local server
+ * 0: Check on local server / 1: Check on remote server
+*/
+
+$settings['check_unix_on_remote_server'] = 0;
+
+
+/*
+ * If you are using UNIX quotas and your IMAP server and web server
+ * are on different physical machines (i.e. you want to check UNIX
+ * quotas remotely) set the path to the "ssh" binary here. See INSTALL
+ * for instructions.
+ *
+ * This setting is only used for remote UNIX quotas.
+*/
+
+$settings['ssh_binary'] = '/usr/bin/ssh';
+
+
+/*
+ * If you are using UNIX quotas and your IMAP server and web server
+ * are on different physical machines (i.e. you want to check UNIX
+ * quotas remotely) set the username that will check quotas on your
+ * IMAP server here. See INSTALL for instructions.
+ *
+ * This setting is only used for remote UNIX quotas.
+*/
+
+$settings['remote_unix_user'] = 'cquotauser';
+
+
+/*
+ * If you are using UNIX quotas and your IMAP server and web server
+ * are on different physical machines (i.e. you want to check UNIX
+ * quotas remotely) set the IP address or hostname of your IMAP
+ * server here. See INSTALL for instructions.
+ *
+ * This setting is only used for remote UNIX quotas.
+*/
+
+$settings['remote_unix_server'] = '192.168.1.1';
+
+
+/*
+ * If you are using cPanel quotas, set the path to the "du" binary
+ * here. See INSTALL for instructions.
+*/
+
+$settings['du_binary'] = '/usr/bin/du';
+
+
+/*
+ * If you are using cPanel quotas, set the cPanel root path here.
+ * See INSTALL for instructions.
+*/
+
+$settings['cpanel_root'] = '/path/to/cpanel/root';
+
+
+/*
+ * If you want to use a separate IMAP connection when checking your
+ * quota, set this variable to 1, else, set it to 0
+ *
+ * This will be a waste of resources if there already is an open
+ * IMAP connection to your server. So, most probably you will not need
+ * to adjust this variable in most occasions.
+ *
+ * Default: Do not use separate IMAP connection
+ * 0: Do not use separate connection / 1: Use separate connection
+*/
+
+$settings['use_separate_imap_connection'] = 0;
+
+/***************************
+ * General Display Options *
+ ***************************/
+
+/*
+ * Which graph type do you prefer?
+ *
+ * You have three options here. You can use HTML tables, GD images,
+ * or Flash graphics.
+ *
+ * GD images can only be generated if you have GD support built into
+ * PHP (--with-gd). For more information on how to install GD support
+ * in PHP, see:
+ *
+ * http://www.php.net/manual/ref.image.php
+ *
+ * If your server doesn't have GD png, gif or jpg support but you enable GD
+ * graphics, the plugin will revert to HTML tables.
+ *
+ * As SquirrelMail is a pure PHP-driven webmail program, and some people do
+ * not have GD support in PHP, default is HTML tables.
+ *
+ * You will get the most satisfying graph output with GD or Flash graphs.
+ *
+ * Default: Use HTML
+ * 0: Use HTML / 1: Use GD / 2: Use Flash
+*/
+
+$settings['graph_type'] = 0;
+
+
+/*
+ * Will the quota information be shown above or below the folders list?
+ *
+ * Default: Above
+ * 0: Below / 1: Above
+*/
+
+$settings['info_above_folders_list'] = 1;
+
+
+/*
+ * Font size for quota information displayed on the folder pane.
+ * Must be a positive or negative integer value.
+ *
+ * Default: -2
+*/
+
+$settings['font_size'] = -2;
+
+
+/*
+ * Alignment for the graph and text information on the folder pane.
+ * This can be "left", "center" or "right".
+ *
+ * Default: "left"
+*/
+
+$settings['graph_alignment'] = 'left';
+
+
+/*
+ * Whether or not to use horizontal rules to seperate quota information
+ * from other information on the folder pane.
+ *
+ * Default: No
+ * 0: No / 1: Yes
+*/
+
+$settings['use_hr'] = 0;
+
+
+/*
+ * Whether or not to show the introductory "Quota Usage" text for
+ * size-based quotas and the "File Usage" text for count-based quotas
+ * displayed on the folder pane.
+ *
+ * Default: On
+ * 0: Off / 1: On
+*/
+
+$settings['show_intro_texts'] = 1;
+
+
+/*
+ * Show the quota details above or below the quota graph?
+ *
+ * Default: Below
+ * 0: Below / 1: Above
+*/
+
+$settings['details_above_graph'] = 0;
+
+
+/*
+ * Whether to show used space (in KB, MB or GB depending on usage) for
+ * size-based quotas and file count for count-based quotas instead of
+ * percent usage in the information displayed on the folder pane.
+ *
+ * Default: Show percent
+ * 0: Show percent / 1: Show size/count
+*/
+
+$settings['show_quantity_instead_of_percent'] = 0;
+
+
+/*
+ * Quota percent thresholds. If the user's usage is more than one
+ * of these, the graph will use a different color and you also have
+ * the option to show a warning in the SquirrelMail "MOTD" display
+ * area when the user logs in.
+ *
+ * These must be positive integers.
+ *
+ * Defaults: Yellow: 70% / Red: 90%
+*/
+
+$settings['yellow_alert_limit'] = 70;
+$settings['red_alert_limit'] = 90;
+
+
+/*
+ * Yellow alert login warning option. When turned on and when the
+ * user's usage exceeds the yellow alert threshold (see above), a
+ * warning message will be displayed in the SquirrelMail "MOTD" area
+ * when he/she logs on.
+ *
+ * Default: On
+ * 0: Off / 1: On
+*/
+
+$settings['show_yellow_alert_motd'] = 1;
+
+
+/*
+ * Red alert login warning option. When turned on and when the
+ * user's usage exceeds the red alert threshold (see above), a
+ * warning message will be displayed in the SquirrelMail "MOTD" area
+ * when he/she logs on.
+ *
+ * Default: On
+ * 0: Off / 1: On
+*/
+
+$settings['show_red_alert_motd'] = 1;
+
+
+/*
+ * If your quotas are set based on 1 MB = 1000 KB, you may want to
+ * turn this option on. Otherwise, 1 MB = 1024 KB will be used for
+ * all quota calculations, which is the generally accepted convention.
+ *
+ * Default: Off
+ * 0: Off (1MB = 1024KB) / 1: On (1MB = 1000KB)
+*/
+
+$settings['use_1000KB_per_MB'] = 0;
+
+
+/*
+ * Whether or not to show filesystem names. This setting
+ * is only used for UNIX (filesystem) quotas.
+ *
+ * This is useful when you have more than one filesystem
+ * which have quotas for your users.
+ *
+ * When set to "1" filesystem aliases override filesystem names.
+ *
+ * Default: Off
+ * 0: Off
+ * 1: Show filesystem name or alias if an alias is set for that filesystem
+*/
+
+$settings['show_filesystems'] = 0;
+
+
+/********************
+ * Override Options *
+ ********************/
+
+/*
+ * You can use this list to map different names to your filesystems. For
+ * example, you can display "Mail Folder" instead of the filesystem name
+ * "/dev/hda4". Leave this empty if you don't want to set up any such
+ * aliases. If "show_filesystems" is set to "0" this list will have no
+ * meaning.
+ *
+ * This setting is only used for UNIX quotas.
+ *
+ * If you use this setting, make sure to replace "/dev/hda8" and "/dev/sda1"
+ * below with the filesystems that are appropriate on your system.
+*/
+
+$settings['fs_alias'] = array (
+ '/dev/hda8' => 'Mail',
+ '/dev/sda6' => 'Data',
+ );
+
+
+/*
+ * You can use this list to exclude some filesystems in your quota output.
+ * This allows you to only show quota information for the filesystem that
+ * your mail accounts reside on, to avoid confusion.
+ *
+ * You don't need to add filesystems which do not have any
+ * quota support here.
+ *
+ * You will need to write the exact filesystem name and, if you want to
+ * hide that filesystem, you will need to set its value to 1. If you want
+ * to show that filesystem, you can remove its entry from this list, or
+ * you can set its value to 0.
+ *
+ * This setting is only used for UNIX quotas.
+ *
+ * If you use this setting, make sure to replace "/dev/hda8" and "/dev/sda1"
+ * below with the filesystems that are appropriate on your system.
+*/
+
+$settings['exclude_fs'] = array (
+ '/dev/hda8' => 1,
+ '/dev/sda6' => 0,
+ );
+
+
+/*
+ * Some IMAP servers use dynamic quotas, so the users may not be able to
+ * see their true quotas. In this situation you can override the max quota
+ * information returned by the plugin with these variables. For size-based
+ * quotas, change "imap_size_quota", for count-based quotas, change
+ * "imap_count_quota".
+ *
+ * Leave blank for server returned quota information to be displayed.
+ *
+ * This setting is only used for IMAP quotas.
+ *
+ * NOTE: Values must be entered in Kilobytes.
+*/
+
+$settings['imap_size_quota'] = '';
+$settings['imap_count_quota'] = '';
+
+
+/*
+ * As cPanel quotas work differently from UNIX or IMAP quotas, we have to
+ * use "du" to calculate these type of quotas. Using "du" can be very
+ * exhaustive for a slow or loaded server. So as a default, we calculate
+ * cPanel quotas only once for a logged in user. To refresh the quota
+ * information the user has to log out and log in again. This option
+ * overrides this behavior and refreshes cPanel quota information on every
+ * refresh of the folders list.
+ *
+ * CAUTION: enabling this may place unnecessarily high load on your server.
+ *
+ * cPanel quota information is always refreshed on the troubleshooting page,
+ * regardless of this option.
+ *
+ * This setting is only used for cPanel quotas.
+ *
+ * Default: Off
+ * 0: Off; calculate quota once at time of login
+ * 1: Always refresh cPanel information
+*/
+
+$settings['always_refresh_cpanel'] = 0;
+
+
+/********************
+ * Troubleshooting *
+ ********************/
+
+/*
+ * Turn this on to see troubleshooting output from server for help
+ * debugging your Check Quota settings. This will add a link to
+ * the "Options" page with the name "Check Quota Troubleshooting".
+ * You should always turn this off when Check Quota is working as
+ * intended.
+ *
+ * Default: Off
+ * 0: Off / 1: On
+*/
+
+$settings['troubleshoot'] = 1;
+
diff -ruN check_quota_old/functions.php check_quota/functions.php
--- check_quota_old/functions.php 2007-08-04 16:58:53.000000000 +0200
+++ check_quota/functions.php 2023-05-22 08:14:04.000000000 +0200
@@ -143,10 +143,11 @@
*/
function check_quota_motd($args)
{
+ global $currentHookName;
if ( !sqgetGlobalVar('just_logged_in', $just_logged_in, SQ_SESSION) || empty($just_logged_in) )
return FALSE;
- if ( get_current_hook_name($args) != 'right_main_after_header' || !sqGetGlobalVar('check_quota_motd_displayed', $check_quota_motd_displayed, SQ_SESSION) || empty($check_quota_motd_displayed) )
+ if ( $currentHookName !== 'right_main_after_header' || !sqGetGlobalVar('check_quota_motd_displayed', $check_quota_motd_displayed, SQ_SESSION) || empty($check_quota_motd_displayed) )
{
global $check_quota;
@@ -214,7 +215,7 @@
* settings and checks the user's quota.
*
*/
- function CheckQuota()
+ function __construct()
{
$this->reset_debug();
$this->load_settings();
@@ -230,7 +231,6 @@
global $settings;
include_once(SM_PATH . 'plugins/check_quota/config.php');
-
$this->settings = $settings;
unset ($settings);
}
diff -ruN check_quota_old/troubleshoot.php check_quota/troubleshoot.php
--- check_quota_old/troubleshoot.php 2007-08-06 11:16:29.000000000 +0200
+++ check_quota/troubleshoot.php 2023-05-22 07:55:31.000000000 +0200
@@ -42,7 +42,7 @@
if ( empty($check_quota->settings['troubleshoot']) )
{
unset($check_quota);
- exit();
+// exit();
}
$cq_to = '<tr><td colspan="2" bgcolor="' . $color[4] . '" align="center"><font color="' . $color[8] . '"><b>';

200
squirrelmail_config.php Executable file
View File

@ -0,0 +1,200 @@
<?php
/**
* SquirrelMail Configuration File
* Created using the configure script, conf.pl
*/
$config_version = '1.5.0';
$config_use_color = 1;
$org_name = "SquirrelMail";
$org_logo = SM_PATH . 'images/sm_logo.png';
$org_logo_width = '308';
$org_logo_height = '111';
$org_title = "SquirrelMail";
$signout_page = '';
$frame_top = '_top';
$provider_uri = '';
$provider_name = '';
$motd = "";
$squirrelmail_default_language = 'en_US';
$default_charset = 'utf-8';
$show_alternative_names = true;
$aggressive_decoding = true;
$lossy_encoding = false;
$domain = 'danwin1210.de';
$imapServerAddress = 'danwin1210.de';
$imapPort = 993;
$useSendmail = false;
$smtpServerAddress = 'danwin1210.de';
$smtpPort = 465;
$sendmail_path = '/usr/sbin/sendmail';
$sendmail_args = '-i -t';
$pop_before_smtp = false;
$pop_before_smtp_host = '';
$imap_server_type = 'dovecot';
$invert_time = false;
$optional_delimiter = 'detect';
$encode_header_key = '';
$default_folder_prefix = '';
$trash_folder = 'Trash';
$sent_folder = 'Sent';
$draft_folder = 'Drafts';
$default_move_to_trash = true;
$default_move_to_sent = true;
$default_save_as_draft = true;
$show_prefix_option = false;
$list_special_folders_first = true;
$use_special_folder_color = true;
$auto_expunge = true;
$default_sub_of_inbox = false;
$show_contain_subfolders_option = false;
$default_unseen_notify = 2;
$default_unseen_type = 1;
$auto_create_special = true;
$delete_folder = false;
$noselect_fix_enable = false;
$data_dir = '/var/local/squirrelmail/data/';
$attachment_dir = '/var/local/squirrelmail/attach/';
$dir_hash_level = 0;
$default_left_size = '150';
$force_username_lowercase = true;
$default_use_priority = false;
$hide_sm_attributions = false;
$default_use_mdn = false;
$edit_identity = false;
$edit_name = true;
$edit_reply_to = true;
$hide_auth_header = true;
$disable_thread_sort = false;
$disable_server_sort = false;
$allow_charset_search = true;
$allow_advanced_search = 0;
$time_zone_type = 0;
$config_location_base = '';
$disable_plugins = false;
$disable_plugins_user = '';
$plugins[] = 'check_quota';
$user_theme_default = 0;
$user_themes[0]['PATH'] = 'none';
$user_themes[0]['NAME'] = 'Default';
$user_themes[1]['PATH'] = SM_PATH . 'css/blue_gradient/';
$user_themes[1]['NAME'] = 'Blue Options';
$user_themes[2]['PATH'] = SM_PATH . 'css/alien_glow/';
$user_themes[2]['NAME'] = 'Alien Glow';
$user_themes[3]['PATH'] = SM_PATH . 'css/autumn/';
$user_themes[3]['NAME'] = 'Autumn';
$user_themes[4]['PATH'] = SM_PATH . 'css/autumn2/';
$user_themes[4]['NAME'] = 'Autumn2';
$user_themes[5]['PATH'] = SM_PATH . 'css/black_bean_burrito/';
$user_themes[5]['NAME'] = 'Black Bean Burrito';
$user_themes[6]['PATH'] = SM_PATH . 'css/blue_grey/';
$user_themes[6]['NAME'] = 'Blue Grey';
$user_themes[7]['PATH'] = SM_PATH . 'css/blue_on_blue/';
$user_themes[7]['NAME'] = 'Blue On Blue';
$user_themes[8]['PATH'] = SM_PATH . 'css/bluesnews/';
$user_themes[8]['NAME'] = 'Bluesnews';
$user_themes[9]['PATH'] = SM_PATH . 'css/bluesome/';
$user_themes[9]['NAME'] = 'Bluesome';
$user_themes[10]['PATH'] = SM_PATH . 'css/bluesteel/';
$user_themes[10]['NAME'] = 'Bluesteel';
$icon_theme_def = 1;
$icon_theme_fallback = 3;
$icon_themes[0]['PATH'] = 'none';
$icon_themes[0]['NAME'] = 'No Icons';
$icon_themes[1]['PATH'] = 'template';
$icon_themes[1]['NAME'] = 'Template Default Icons';
$icon_themes[2]['PATH'] = SM_PATH . 'images/themes/default/';
$icon_themes[2]['NAME'] = 'Default Icon Set';
$icon_themes[3]['PATH'] = SM_PATH . 'images/themes/xp/';
$icon_themes[3]['NAME'] = 'XP Style Icons';
$templateset_default = 'default';
$templateset_fallback = 'default';
$rpc_templateset = 'default_rpc';
$aTemplateSet[0]['ID'] = 'default';
$aTemplateSet[0]['NAME'] = 'Default';
$aTemplateSet[1]['ID'] = 'default_advanced';
$aTemplateSet[1]['NAME'] = 'Advanced';
$default_fontsize = '';
$default_fontset = '';
$fontsets = array();
$fontsets['verasans'] = 'bitstream vera sans,verdana,sans-serif';
$fontsets['sans'] = 'helvetica,arial,sans-serif';
$fontsets['comicsans'] = 'comic sans ms,sans-serif';
$fontsets['tahoma'] = 'tahoma,sans-serif';
$fontsets['serif'] = 'serif';
$default_use_javascript_addr_book = false;
$addrbook_dsn = '';
$addrbook_table = 'address';
$prefs_dsn = '';
$prefs_table = 'userprefs';
$prefs_user_field = 'user';
$prefs_user_size = 128;
$prefs_key_field = 'prefkey';
$prefs_key_size = 64;
$prefs_val_field = 'prefval';
$prefs_val_size = 65536;
$addrbook_global_dsn = '';
$addrbook_global_table = 'global_abook';
$addrbook_global_writeable = false;
$addrbook_global_listing = false;
$abook_global_file = '';
$abook_global_file_writeable = false;
$abook_global_file_listing = true;
$abook_file_line_length = 2048;
$no_list_for_subscribe = false;
$smtp_auth_mech = 'plain';
$smtp_sitewide_user = '';
$smtp_sitewide_pass = '';
$imap_auth_mech = 'plain';
$use_imap_tls = 1;
$use_smtp_tls = 1;
$display_imap_login_error = false;
$session_name = 'SQMSESSID';
$only_secure_cookies = true;
$disable_security_tokens = false;
$check_referrer = '';
$use_transparent_security_image = true;
$allow_svg_display = false;
$block_svg_download = false;
$fix_broken_base64_encoded_messages = false;
$use_iframe = false;
$ask_user_info = false;
$use_icons = false;
$use_php_recode = false;
$use_php_iconv = true;
$buffer_output = false;
$allow_remote_configtest = false;
$secured_config = true;
$sq_https_port = 443;
$sq_ignore_http_x_forwarded_headers = true;
$sm_debug_mode = SM_DEBUG_MODE_OFF;

View File

@ -0,0 +1,25 @@
<?php
/**
* SquirrelMail Plugin Hook Registration File
* Auto-generated using the configure script, conf.pl
*/
global $squirrelmail_plugin_hooks;
$squirrelmail_plugin_hooks['left_main_before']['check_quota']
= 'check_quota_graph_before_do';
$squirrelmail_plugin_hooks['left_main_after']['check_quota']
= 'check_quota_graph_after_do';
$squirrelmail_plugin_hooks['right_main_after_header']['check_quota']
= 'check_quota_motd_do';
$squirrelmail_plugin_hooks['template_construct_left_main.tpl']['check_quota']
= 'check_quota_graph_do';
$squirrelmail_plugin_hooks['template_construct_motd.tpl']['check_quota']
= 'check_quota_motd_do';
$squirrelmail_plugin_hooks['optpage_register_block']['check_quota']
= 'check_quota_optpage_register_block_do';
$squirrelmail_plugin_hooks['configtest']['check_quota']
= 'check_quota_check_configuration_do';

9
tools/create_admin.php Normal file
View File

@ -0,0 +1,9 @@
<?php
const ADMIN_USER='admin';
const ADMIN_PASS='YOUR_PASSWORD';
require_once __DIR__ . '/../common_config.php';
$db = get_db_instance();
$hash = password_hash( ADMIN_PASS, PASSWORD_ARGON2ID );
$stmt = $db->prepare( 'INSERT INTO admin (password_hash_type, password, superadmin, username, created, modified) VALUES ("{ARGON2ID}", ?, 1, ?, NOW(), NOW());' );
$stmt->execute( [ $hash, ADMIN_USER ] );

View File

@ -25,3 +25,36 @@ foreach ( $domains as $domain ) {
}
}
}
$domains = array_diff( scandir( '/var/local/snappymail/_data_/_default_/storage/' ), array( '..', '.', '__nobody__' ) );
$dirs = [];
foreach ( $domains as $domain ) {
if ( is_dir( '/var/local/snappymail/_data_/_default_/storage/' . basename( $domain ) ) ) {
if ( ! isset( $mailboxes[ $domain ] ) ) {
echo sprintf(_('%s does not seem to have any accounts, but has a snappymail directory. Consider deleting it.'), $domain).PHP_EOL;
} else {
$accounts = array_diff( scandir( '/var/local/snappymail/_data_/_default_/storage/' . basename( $domain ) ), array( '..', '.' ) );
foreach ( $accounts as $account ) {
if ( ! isset( $mailboxes[ $domain ][ $account ] ) && is_dir( '/var/local/snappymail/_data_/_default_/storage/' . basename( $domain ) . '/' . basename( $account ) ) ) {
exec( 'rm -r ' . escapeshellarg('/var/local/snappymail/_data_/_default_/storage/' . basename( $domain ) . '/' . basename( $account )));
echo sprintf(_('Deleted: %s'), '/var/local/snappymail/_data_/_default_/storage/' . basename( $domain ) . '/' . basename( $account )) . PHP_EOL;
} elseif( is_file('/var/local/snappymail/_data_/_default_/storage/' . basename( $domain ) . '/' . basename( $account ))){
echo sprintf(_('File found in mail directory location: "%s". Consider deleting it.'), '/var/local/snappymail/_data_/_default_/storage/'. basename( $domain ) . '/' . basename( $account ) ) . PHP_EOL;
}
}
}
}
}
$accout_files = array_diff( scandir( '/var/local/squirrelmail/data/' ), array( '..', '.' ) );
foreach( $accout_files as $file ){
if(preg_match( '/^(.+?)(@(.+))?\.(pref|abook|sig)$/', $file, $matches )){
$domain = $matches[ 3 ];
if(in_array($domain, ['', 'danielas3rtn54uwmofdo3x2bsdifr47huasnmbgqzfrec5ubupvtpid.onion'], true)){
$domain = 'danwin1210.de';
}
$account = $matches[ 1 ];
if ( ! isset( $mailboxes[ $domain ][ $account ] )){
unlink('/var/local/squirrelmail/data/' . $file);
echo sprintf(_('Deleted: %s'), '/var/local/squirrelmail/data/' . $file) . PHP_EOL;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -3,41 +3,43 @@ include_once('../common_config.php');
global $language, $dir, $locale;
?>
<!DOCTYPE html><html lang="<?php echo $language; ?>" dir="<?php echo $dir; ?>"><head>
<title><?php echo _('E-Mail and XMPP'); ?></title>
<title><?php echo htmlspecialchars(_('E-Mail and XMPP')); ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="<?php echo _('Get a free and anonymous E-Mail address and an XMPP/Jabber account'); ?>">
<meta name="description" content="<?php echo htmlspecialchars(_('Get a free and anonymous E-Mail address and an XMPP/Jabber account')); ?>">
<link rel="canonical" href="<?php echo CANONICAL_URL; ?>">
<link rel="alternate" href="<?php echo CANONICAL_URL; ?>" hreflang="x-default">
<?php alt_links(); ?>
<meta property="og:type" content="website">
<meta property="og:title" content="<?php echo _('E-Mail and XMPP'); ?>">
<meta property="og:description" content="<?php echo _('Get a free and anonymous E-Mail address and an XMPP/Jabber account'); ?>">
<meta property="og:title" content="<?php echo htmlspecialchars(_('E-Mail and XMPP')); ?>">
<meta property="og:description" content="<?php echo htmlspecialchars(_('Get a free and anonymous E-Mail address and an XMPP/Jabber account')); ?>">
<meta property="og:url" content="<?php echo CANONICAL_URL; ?>">
<meta property="og:locale" content="<?php echo $locale; ?>">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"Service","name":"<?php echo _('E-Mail and XMPP'); ?>", "description": "<?php echo _('Get a free and anonymous E-Mail address and an XMPP/Jabber account'); ?>", "availableChannel": {"@type": "ServiceChannel", "serviceUrl": "<?php echo CANONICAL_URL; ?>"}}</script>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"Service","name":"<?php echo htmlspecialchars(_('E-Mail and XMPP')); ?>", "description": "<?php echo htmlspecialchars(_('Get a free and anonymous E-Mail address and an XMPP/Jabber account')); ?>", "availableChannel": {"@type": "ServiceChannel", "serviceUrl": "<?php echo CANONICAL_URL; ?>"}, "termsOfService": "<?php echo CANONICAL_URL; ?>terms.php"}</script>
</head><body>
<main>
<p><?php echo _('Info'); ?> | <a href="<?php echo ROOT_URL; ?>register.php"><?php echo _('Register'); ?></a> | <a href="<?php echo ROOT_URL; ?>manage_account.php"><?php echo _('Manage account'); ?></a> | <a href="<?php echo ROOT_URL; ?>squirrelmail/src/login.php" target="_blank"><?php echo _('SquirrelMail'); ?></a> | <a href="<?php echo ROOT_URL; ?>snappymail/" target="_blank"><?php echo _('SnappyMail'); ?></a> | <a href="<?php echo WEB_XMPP_URL; ?>" target="_blank" rel="noopener"><?php echo _('Web-XMPP'); ?></a></p>
<h2><?php echo _('What you will get'); ?></h2>
<p><?php printf(_('You get a free anonymous E-Mail address and an XMPP/Jabber account using the same details. Your Jabber ID is user@%1$s and can be connected to directly from clearnet or via Tor hidden service (%2$s).'), CLEARNET_SERVER, ONION_SERVER); ?></p>
<p><?php printf(_('You will have 50MB of disk space available for your mails. If you need more space, just <a href="%1$s">contact me</a>. Your E-Mail address will be %2$s'), CONTACT_URL, CLEARNET_SERVER); ?></p>
<p><?php echo _('For privacy, please use PGP mail encryption, if you can. This prevents others from reading your mails to protect your privacy. You can <a href="https://gnupg.org/download/index.html" target="_blank" rel="noopener noreferrer">download GnuPG</a> or similar software for it. Once you have generated your PGP key, you can <a href="manage_account.php">add it to your account</a> to make use of WKD automatic discovery for mail clients.'); ?></p>
<p><?php echo _('You can choose between two Web-Mail clients installed on the server. <a href="squirrelmail/src/login.php">SquirrelMail</a> is a very old mail client which works without any JavaScript and is thus the most popular mail client among darknet users. However, it hasn\'t been under development for many years and does not support all features that mail has to offer. You may see strange attachments that should have been inlined in your email, such as PGP/MIME encrypted email messages. A more modern client is <a href="snappymail/">SnappyMail</a>, which also supports PGP encryption within your browser and is more similar to what you may be used to from other mail services. SnappyMail requires JavaScript though, so SquirrelMail is for you if you do not trust executing JavaScript in your browser. Alternatively, you can simply use your favourite desktop mail client and configure it with the settings given below.'); ?></p>
<p><?php echo _('The XMPP service provides message archiving and HTTP upload, which can keep your messages and files for up to 1 week. Up to 100MB of file storage is available per user.'); ?></p>
<h2><?php echo _('E-Mail Setup'); ?></h2>
<p><?php echo htmlspecialchars(_('Info')); ?> | <a href="<?php echo ROOT_URL; ?>register.php"><?php echo htmlspecialchars(_('Register')); ?></a> | <a href="<?php echo ROOT_URL; ?>manage_account.php"><?php echo htmlspecialchars(_('Manage account')); ?></a> | <a href="<?php echo ROOT_URL; ?>squirrelmail/src/login.php" target="_blank"><?php echo htmlspecialchars(_('SquirrelMail')); ?></a> | <a href="<?php echo ROOT_URL; ?>snappymail/" target="_blank"><?php echo htmlspecialchars(_('SnappyMail')); ?></a> | <a href="<?php echo WEB_XMPP_URL; ?>" target="_blank" rel="noopener"><?php echo htmlspecialchars(_('Web-XMPP')); ?></a></p>
<h2><?php echo htmlspecialchars(_('What you will get')); ?></h2>
<p><?php printf(htmlspecialchars(_('You get a free anonymous E-Mail address and an XMPP/Jabber account using the same details. Your Jabber ID is user@%1$s and can be connected to directly from clearnet or via Tor hidden service (%2$s).')), CLEARNET_SERVER, ONION_SERVER); ?></p>
<?php if(DEFAULT_QUOTA > 0) { ?>
<p><?php printf(htmlspecialchars(_('You will have %1$s disk space available for your mails. If you need more space, %2$s.')), bytes_to_human_readable(DEFAULT_QUOTA), '<a href="'.CONTACT_URL.'">'.htmlspecialchars(_('contact me')).'</a>'); ?></p>
<?php } ?>
<p><?php printf(htmlspecialchars(_('Your E-Mail address will be user@%s')), CLEARNET_SERVER); ?></p>
<p><?php printf(htmlspecialchars(_('For privacy, please use PGP mail encryption, if you can. This prevents others from reading your mails to protect your privacy. You can %1$s or similar software for it. Once you have generated your PGP key, you can %2$s to make use of WKD automatic discovery for mail clients.')), '<a href="https://gnupg.org/download/index.html" target="_blank" rel="noopener noreferrer">'.htmlspecialchars(_('download GnuPG')).'</a>', '<a href="manage_account.php">'.htmlspecialchars(_('add it to your account')).'</a>'); ?></p>
<p><?php printf(htmlspecialchars(_('You can choose between two Web-Mail clients installed on the server. %1$s is a very old mail client which works without any JavaScript and is thus the most popular mail client among darknet users. However, it hasn\'t been under development for many years and does not support all features that mail has to offer. You may see strange attachments that should have been inlined in your email, such as PGP/MIME encrypted email messages. A more modern client is %2$s, which also supports PGP encryption within your browser and is more similar to what you may be used to from other mail services. SnappyMail requires JavaScript though, so SquirrelMail is for you if you do not trust executing JavaScript in your browser. Alternatively, you can simply use your favourite desktop mail client and configure it with the settings given below.')), '<a href="squirrelmail/src/login.php">'.htmlspecialchars(_('SquirrelMail')).'</a>', '<a href="snappymail/">'.htmlspecialchars(_('SnappyMail')).'</a>'); ?></p>
<h2><?php echo htmlspecialchars(_('E-Mail Setup')); ?></h2>
<p>
<?php printf(_('SMTP: %s Port 465 (SSL/TLS) or 587 (StartTLS)'), CLEARNET_SERVER); ?><br>
<?php printf(_('IMAP: %s Port 993 (SSL/TLS) or 143 (StartTLS)'), CLEARNET_SERVER); ?><br>
<?php printf(_('POP3: %s Port 995 (SSL/TLS) or 110 (StartTLS)'), CLEARNET_SERVER); ?><br>
<?php echo _('Authentication: PLAIN, LOGIN'); ?>
<?php printf(htmlspecialchars(_('SMTP: %s Port 465 (SSL/TLS) or 587 (StartTLS)')), CLEARNET_SERVER); ?><br>
<?php printf(htmlspecialchars(_('IMAP: %s Port 993 (SSL/TLS) or 143 (StartTLS)')), CLEARNET_SERVER); ?><br>
<?php printf(htmlspecialchars(_('POP3: %s Port 995 (SSL/TLS) or 110 (StartTLS)')), CLEARNET_SERVER); ?><br>
<?php echo htmlspecialchars(_('Authentication: PLAIN, LOGIN')); ?>
</p>
<p><?php printf(_('You can also connect on the same ports via the Tor onion address %s, but you will have to accept an SSL certificate only valid for the clearnet domain.'), ONION_SERVER); ?></p>
<h2><?php echo _('XMPP setup'); ?></h2>
<p><?php printf(_('Domain: %s'), CLEARNET_SERVER); ?><br>
<?php printf(_('Connect server: %s (optional for torification)'), ONION_SERVER); ?><br>
<?php printf(_('File transfer proxy: %s'), XMPP_FILE_PROXY); ?><br>
<?php printf(_('BOSH URL: %s (only enable if you have to, as it is slower than directly using xmpp)'), XMPP_BOSH_URL); ?></p>
<p><?php printf(htmlspecialchars(_('You can also connect on the same ports via the Tor onion address %s, but you will have to accept an SSL certificate only valid for the clearnet domain.')), ONION_SERVER); ?></p>
<h2><?php echo htmlspecialchars(_('XMPP setup')); ?></h2>
<p><?php printf(htmlspecialchars(_('Domain: %s')), CLEARNET_SERVER); ?><br>
<?php printf(htmlspecialchars(_('Connect server: %s (optional for torification)')), ONION_SERVER); ?><br>
<?php printf(htmlspecialchars(_('File transfer proxy: %s')), XMPP_FILE_PROXY); ?><br>
<?php printf(htmlspecialchars(_('BOSH URL: %s (only enable if you have to, as it is slower than directly using xmpp)')), XMPP_BOSH_URL); ?></p>
</main>
</body></html>

View File

@ -14,7 +14,7 @@ if ( ! empty( $_SESSION[ 'email_user' ] ) ) {
$_SESSION = [];
session_regenerate_id( true );
$_SESSION[ 'csrf_token' ] = sha1( uniqid() );
$msg .= '<div class="red" role="alert">'._('It looks like your user no longer exists!').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('It looks like your user no longer exists!')).'</div>';
}
}
@ -27,7 +27,7 @@ if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) {
unset( $_SESSION[ '2fa_code' ] );
unset( $_SESSION[ 'pgp_key' ] );
} else {
$msg .= '<p style="color:red">'._('Wrong 2FA code').'</p>';
$msg .= '<p style="color:red">'.htmlspecialchars(_('Wrong 2FA code')).'</p>';
}
}
if ( ! isset( $_SESSION[ '2fa_code' ] ) && isset( $_POST[ 'action' ] ) ) {
@ -35,21 +35,21 @@ if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) {
$_SESSION = [];
session_regenerate_id( true );
$_SESSION[ 'csrf_token' ] = sha1( uniqid() );
$msg .= '<div class="green" role="alert">'._('Successfully logged out').'</div>';
$msg .= '<div class="green" role="alert">'.htmlspecialchars(_('Successfully logged out')).'</div>';
} elseif ( $_POST[ 'action' ] === 'login' ) {
$ok = true;
if ( ! check_captcha( $_POST[ 'challenge' ] ?? '', $_POST[ 'captcha' ] ?? '' ) ) {
$ok = false;
$msg .= '<div class="red" role="alert">'._('Invalid captcha').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Invalid captcha')).'</div>';
}
if ( empty( $_POST[ 'user' ] ) || ! preg_match( '/^([^+]+?)(@([^@]+))?$/i', $_POST[ 'user' ], $match ) ) {
$ok = false;
$msg .= '<div class="red" role="alert">'._('Invalid username').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Invalid username')).'</div>';
}
if ( $ok ) {
$db = get_db_instance();
$user = $match[ 1 ];
$domain = $match[ 3 ] ?? 'danwin1210.de';
$domain = $match[ 3 ] ?? CLEARNET_SERVER;
$stmt = $db->prepare( 'SELECT target_domain FROM alias_domain WHERE alias_domain = ? AND active=1;' );
$stmt->execute( [ $domain ] );
if ( $tmp = $stmt->fetch( PDO::FETCH_ASSOC ) ) {
@ -60,7 +60,7 @@ if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) {
if ( $tmp = $stmt->fetch( PDO::FETCH_ASSOC ) ) {
if ( empty( $_POST[ 'pwd' ] ) || ! password_verify( $_POST[ 'pwd' ], $tmp[ 'password' ] ) ) {
$ok = false;
$msg .= '<div class="red" role="alert">'._('Incorrect username or password').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Incorrect username or password')).'</div>';
} else {
$_SESSION[ 'email_user' ] = $tmp[ 'username' ];
$stmt = $db->prepare( 'UPDATE mailbox SET last_login = ? WHERE username = ? AND active = 1;' );
@ -78,7 +78,7 @@ if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) {
}
}
} else {
$msg .= '<div class="red" role="alert">'._('Incorrect username or password').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Incorrect username or password')).'</div>';
}
}
} elseif ( ! empty( $_SESSION[ 'email_user' ] ) && $_POST[ 'action' ] === 'update_settings' ) {
@ -97,21 +97,21 @@ if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) {
$stmt->execute( [ ( isset( $_POST[ 'enforce_tls_in' ] ) ? 1 : 0 ), ( isset( $_POST[ 'enforce_tls_out' ] ) ? 1 : 0 ), $_SESSION[ 'email_user' ] ] );
} elseif ( ! empty( $_SESSION[ 'email_user' ] ) && $_POST[ 'action' ] === 'update_password' ) {
if ( empty( $_POST[ 'pass_update' ] ) || empty( $_POST[ 'pass_update2' ] ) || $_POST[ 'pass_update' ] !== $_POST[ 'pass_update2' ] ) {
$msg .= '<div class="red" role="alert">'._('Passwords empty or don\'t match').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Passwords empty or don\'t match')).'</div>';
} else {
$hash = password_hash( $_POST[ 'pass_update' ], PASSWORD_ARGON2ID );
$stmt = $db->prepare( 'UPDATE mailbox SET password_hash_type = "{ARGON2ID}", password = ? WHERE username = ? AND active = 1;' );
$stmt->execute( [ $hash, $_SESSION[ 'email_user' ] ] );
$msg .= '<div class="green" role="alert">'._('Successfully updated password').'</div>';
$msg .= '<div class="green" role="alert">'.htmlspecialchars(_('Successfully updated password')).'</div>';
}
} elseif ( ! empty( $_SESSION[ 'email_user' ] ) && $_POST[ 'action' ] === 'delete_account' ) {
$msg .= '<div class="red" role="alert">'._('Warning: This will permenently delete your account and all your data. Anyone can immediately register with this user again. It cannot be reversed. Are you absolutely sure?').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Warning: This will permenently delete your account and all your data. Anyone can immediately register with this user again. It cannot be reversed. Are you absolutely sure?')).'</div>';
$msg .= '<form method="post"><input type="hidden" name="csrf_token" value="' . $_SESSION[ 'csrf_token' ] . '">';
$msg .= '<button type="submit" name="action" value="delete_account2">'._('Yes, I want to permanently delete my account').'</button></form>';
$msg .= '<button type="submit" name="action" value="delete_account2">'.htmlspecialchars(_('Yes, I want to permanently delete my account')).'</button></form>';
} elseif ( ! empty( $_SESSION[ 'email_user' ] ) && $_POST[ 'action' ] === 'disable_account' ) {
$msg .= '<div class="red" role="alert">'._('Warning: This will disable your account for a year and delete all your data. After a year it is available for registrations again. It cannot be reversed. Are you absolutely sure?').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Warning: This will disable your account for a year and delete all your data. After a year it is available for registrations again. It cannot be reversed. Are you absolutely sure?')).'</div>';
$msg .= '<form method="post"><input type="hidden" name="csrf_token" value="' . $_SESSION[ 'csrf_token' ] . '">';
$msg .= '<button type="submit" name="action" value="disable_account2">'._('Yes, I want to disable my account').'</button></form>';
$msg .= '<button type="submit" name="action" value="disable_account2">'.htmlspecialchars(_('Yes, I want to disable my account')).'</button></form>';
} elseif ( ! empty( $_SESSION[ 'email_user' ] ) && $_POST[ 'action' ] === 'delete_account2' ) {
$stmt = $db->prepare( 'DELETE FROM alias WHERE address = ?;' );
$stmt->execute( [ $_SESSION[ 'email_user' ] ] );
@ -120,7 +120,7 @@ if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) {
$_SESSION = [];
session_regenerate_id( true );
$_SESSION[ 'csrf_token' ] = sha1( uniqid() );
$msg .= '<div class="green" role="alert">'._('Successfully deleted account').'</div>';
$msg .= '<div class="green" role="alert">'.htmlspecialchars(_('Successfully deleted account')).'</div>';
} elseif ( ! empty( $_SESSION[ 'email_user' ] ) && $_POST[ 'action' ] === 'disable_account2' ) {
$stmt = $db->prepare( 'UPDATE alias SET active = 0 WHERE address = ?;' );
$stmt->execute( [ $_SESSION[ 'email_user' ] ] );
@ -129,11 +129,11 @@ if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) {
$_SESSION = [];
session_regenerate_id( true );
$_SESSION[ 'csrf_token' ] = sha1( uniqid() );
$msg .= '<div class="green" role="alert">'._('Successfully disabled account').'</div>';
$msg .= '<div class="green" role="alert">'.htmlspecialchars(_('Successfully disabled account')).'</div>';
} elseif ( isset( $_POST[ 'pgp_key' ] ) && ! empty( $_SESSION[ 'email_user' ] ) && $_POST[ 'action' ] === 'update_pgp_key' ) {
$pgp_key = trim( $_POST[ 'pgp_key' ] );
if ( empty( $pgp_key ) ) {
$msg .= '<p class="green">'._('Successfully removed the key').'</p>';
$msg .= '<p class="green">'.htmlspecialchars(_('Successfully removed the key')).'</p>';
$stmt = $db->prepare( 'UPDATE mailbox SET pgp_key = "", tfa = 0, pgp_verified = 0 WHERE username = ?;' );
$stmt->execute( [ $_SESSION[ 'email_user' ] ] );
} else {
@ -142,7 +142,7 @@ if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) {
gnupg_setarmor( $gpg, 1 );
$imported_key = gnupg_import( $gpg, $pgp_key );
if ( ! $imported_key ) {
$msg .= '<p class="red">'._('There was an error importing the key').'</p>';
$msg .= '<p class="red">'.htmlspecialchars(_('There was an error importing the key')).'</p>';
} else {
$has_this_email = false;
$key_info = gnupg_keyinfo( $gpg, $imported_key[ 'fingerprint' ] );
@ -155,21 +155,21 @@ if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) {
}
}
if ( $has_this_email ) {
$msg .= '<p class="green">'._('Successfully imported the key').'</p>';
$msg .= '<p class="green">'.htmlspecialchars(_('Successfully imported the key')).'</p>';
$stmt = $db->prepare( 'UPDATE mailbox SET pgp_key = ?, tfa = 0, pgp_verified = 0 WHERE username = ?;' );
$stmt->execute( [ $pgp_key, $_SESSION[ 'email_user' ] ] );
} else {
$msg .= '<p class="red">' . sprintf( _('Oops, looks like the key is missing this email address as user id. Please add your address "%s" as user ID to your pgp key or create a new key pair.'), htmlspecialchars( $_SESSION[ 'email_user' ] ) ) . '</p>';
$msg .= '<p class="red">' . sprintf( htmlspecialchars(_('Oops, looks like the key is missing this email address as user id. Please add your address "%s" as user ID to your pgp key or create a new key pair.')), htmlspecialchars( $_SESSION[ 'email_user' ] ) ) . '</p>';
}
}
}
} elseif ( isset( $_POST[ 'enable_2fa_code' ] ) && ! empty( $_SESSION[ 'email_user' ] ) && $_POST[ 'action' ] === 'enable_2fa' ) {
if ( $_POST[ 'enable_2fa_code' ] !== $_SESSION[ 'enable_2fa_code' ] ) {
$msg .= '<p class="red">'._('Sorry, the code was incorrect').'</p>';
$msg .= '<p class="red">'.htmlspecialchars(_('Sorry, the code was incorrect')).'</p>';
} else {
$stmt = $db->prepare( 'UPDATE mailbox SET tfa = 1, pgp_verified = 1 WHERE username = ?;' );
$stmt->execute( [ $_SESSION[ 'email_user' ] ] );
$msg .= '<p class="green">'._('Successfully enabled 2FA').'</p>';
$msg .= '<p class="green">'.htmlspecialchars(_('Successfully enabled 2FA')).'</p>';
}
}
}
@ -178,21 +178,21 @@ if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) {
<!DOCTYPE html>
<html lang="<?php echo $language; ?>" dir="<?php echo $dir; ?>">
<head>
<title><?php echo _('E-Mail and XMPP - Manage account'); ?></title>
<title><?php echo htmlspecialchars(_('E-Mail and XMPP - Manage account')); ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description"
content="<?php echo _('Manage your free and anonymous E-Mail address and an XMPP/Jabber account. Add forwarding addresses, change your password or disable/delete your account.'); ?>">
content="<?php echo htmlspecialchars(_('Manage your free and anonymous E-Mail address and an XMPP/Jabber account. Add forwarding addresses, change your password or disable/delete your account.')); ?>">
<link rel="canonical" href="<?php echo CANONICAL_URL; ?>manage_account.php">
<link rel="alternate" href="<?php echo CANONICAL_URL; ?>manage_account.php" hreflang="x-default">
<?php alt_links(); ?>
<meta property="og:type" content="website">
<meta property="og:title" content="<?php echo _('E-Mail and XMPP - Manage account'); ?>">
<meta property="og:description" content="<?php echo _('Manage your free and anonymous E-Mail address and an XMPP/Jabber account. Add forwarding addresses, change your password or disable/delete your account.'); ?>">
<meta property="og:title" content="<?php echo htmlspecialchars(_('E-Mail and XMPP - Manage account')); ?>">
<meta property="og:description" content="<?php echo htmlspecialchars(_('Manage your free and anonymous E-Mail address and an XMPP/Jabber account. Add forwarding addresses, change your password or disable/delete your account.')); ?>">
<meta property="og:url" content="<?php echo CANONICAL_URL; ?>manage_account.php">
<meta property="og:locale" content="<?php echo $locale; ?>">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"<?php echo _('E-Mail and XMPP - Manage account'); ?>", "description": "<?php echo _('Manage your free and anonymous E-Mail address and an XMPP/Jabber account. Add forwarding addresses, change your password or disable/delete your account.'); ?>"}</script>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"<?php echo htmlspecialchars(_('E-Mail and XMPP - Manage account')); ?>", "description": "<?php echo htmlspecialchars(_('Manage your free and anonymous E-Mail address and an XMPP/Jabber account. Add forwarding addresses, change your password or disable/delete your account.')); ?>"}</script>
</head>
<body>
<main>
@ -213,15 +213,15 @@ foreach ( $key_info as $key ) {
}
$encrypted = gnupg_encrypt( $gpg, _('To login, please enter the following code to confirm ownership of your key:')."\n\n" . $_SESSION[ '2fa_code' ] . "\n" );
echo $msg;
echo '<p>'._('To login, please decrypt the following PGP encrypted message and confirm the code:').'</p>';
echo '<p>'.htmlspecialchars(_('To login, please decrypt the following PGP encrypted message and confirm the code:')).'</p>';
echo "<pre>$encrypted</pre>";
?>
<form class="form_limit" action="manage_account.php" method="post">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION[ 'csrf_token' ]; ?>">
<div class="row">
<div class="col"><input type="text" name="2fa_code" aria-label="<?php echo _('2FA code'); ?>"></div>
<div class="col"><input type="text" name="2fa_code" aria-label="<?php echo htmlspecialchars(_('2FA code')); ?>"></div>
<div class="col">
<button type="submit"><?php echo _('Confirm'); ?></button>
<button type="submit"><?php echo htmlspecialchars(_('Confirm')); ?></button>
</div>
</div>
</form>
@ -234,36 +234,36 @@ exit;
if ( ! empty( $_SESSION[ 'email_user' ] ) ){ ?>
<form method="post"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION[ 'csrf_token' ]; ?>">
<?php } ?>
<p><a href="<?php echo ROOT_URL; ?>"><?php echo _('Info'); ?></a> |<?php
<p><a href="<?php echo ROOT_URL; ?>"><?php echo htmlspecialchars(_('Info')); ?></a> |<?php
if ( ! empty( $_SESSION[ 'email_user' ] ) ) {
printf(_('Logged in as %s'), htmlspecialchars( $_SESSION[ 'email_user' ] ) );
printf(htmlspecialchars(_('Logged in as %s')), htmlspecialchars( $_SESSION[ 'email_user' ] ) );
} else { ?>
<a href="<?php echo ROOT_URL; ?>register.php"><?php echo _('Register'); ?></a>
<a href="<?php echo ROOT_URL; ?>register.php"><?php echo htmlspecialchars(_('Register')); ?></a>
<?php }
if ( ! empty( $_SESSION[ 'email_user' ] ) ) { ?>
|
<button name="action" value="logout" type="submit"><?php echo _('Logout'); ?></button>
<button name="action" value="logout" type="submit"><?php echo htmlspecialchars(_('Logout')); ?></button>
<?php } else { ?>
| <?php echo _('Manage account');
} ?> | <a href="<?php echo ROOT_URL; ?>squirrelmail/src/login.php" target="_blank"><?php echo _('SquirrelMail'); ?></a> | <a href="<?php echo ROOT_URL; ?>snappymail/" target="_blank"><?php echo _('SnappyMail'); ?></a> | <a href="<?php echo WEB_XMPP_URL; ?>" target="_blank" rel="noopener"><?php echo _('Web-XMPP'); ?></a></p>
| <?php echo htmlspecialchars(_('Manage account'));
} ?> | <a href="<?php echo ROOT_URL; ?>squirrelmail/src/login.php" target="_blank"><?php echo htmlspecialchars(_('SquirrelMail')); ?></a> | <a href="<?php echo ROOT_URL; ?>snappymail/" target="_blank"><?php echo htmlspecialchars(_('SnappyMail')); ?></a> | <a href="<?php echo WEB_XMPP_URL; ?>" target="_blank" rel="noopener"><?php echo htmlspecialchars(_('Web-XMPP')); ?></a></p>
<?php if ( ! empty( $_SESSION[ 'email_user' ] ) ){ ?></form><?php }
echo "<p>$msg</p>";
if ( empty( $_SESSION[ 'email_user' ] ) ) { ?>
<form class="form_limit" action="manage_account.php" method="post">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION[ 'csrf_token' ]; ?>">
<div class="row">
<div class="col"><label for="user"><?php echo _('Username'); ?></label></div>
<div class="col"><label for="user"><?php echo htmlspecialchars(_('Username')); ?></label></div>
<div class="col"><input type="text" name="user" id="user" autocomplete="username" required
value="<?php echo htmlspecialchars( $_POST[ 'user' ] ?? '' ); ?>"></div>
</div>
<div class="row">
<div class="col"><label for="pwd"><?php echo _('Password'); ?></label></div>
<div class="col"><label for="pwd"><?php echo htmlspecialchars(_('Password')); ?></label></div>
<div class="col"><input type="password" name="pwd" id="pwd" autocomplete="new-password" required></div>
</div>
<?php send_captcha(); ?>
<div class="row">
<div class="col">
<button name="action" value="login" type="submit"><?php echo _('Login'); ?></button>
<button name="action" value="login" type="submit"><?php echo htmlspecialchars(_('Login')); ?></button>
</div>
</div>
</form>
@ -280,58 +280,58 @@ if ( empty( $_SESSION[ 'email_user' ] ) ) { ?>
$tls_status = $stmt->fetch( PDO::FETCH_ASSOC );
?>
<form class="form_limit" action="manage_account.php" method="post">
<h2><?php echo _('Settings'); ?></h2>
<h3><?php echo _('Delivery'); ?></h3>
<p><?php echo _('Change how your mail is delivered. You can add forwarding addresses one per line, or comma seperated. When you disable the "keep a local copy" checkbox, your mail will only be sent to your forwarding addresses.'); ?></p>
<h2><?php echo htmlspecialchars(_('Settings')); ?></h2>
<h3><?php echo htmlspecialchars(_('Delivery')); ?></h3>
<p><?php echo htmlspecialchars(_('Change how your mail is delivered. You can add forwarding addresses one per line, or comma seperated. When you disable the "keep a local copy" checkbox, your mail will only be sent to your forwarding addresses.')); ?></p>
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION[ 'csrf_token' ]; ?>">
<div class="row">
<div class="col"><label for="alias_to"><?php echo _('Forward to'); ?></label></div>
<div class="col"><label for="alias_to"><?php echo htmlspecialchars(_('Forward to')); ?></label></div>
<div class="col"><textarea name="alias_to"
id="alias_to"><?php echo htmlspecialchars( $aliases_to ); ?></textarea></div>
</div>
<div class="row">
<div class="col"><label for="alias_keep_copy"><?php echo _('Keep a local copy'); ?></label></div>
<div class="col"><label for="alias_keep_copy"><?php echo htmlspecialchars(_('Keep a local copy')); ?></label></div>
<div class="col"><input type="checkbox" name="alias_keep_copy"
id="alias_keep_copy"<?php echo in_array( $_SESSION[ 'email_user' ], $aliases, true ) ? ' checked' : ''; ?>>
</div>
</div>
<h3><?php echo _('Encryption'); ?></h3>
<p><?php echo _('If you are having issues sending or receiving mails with some other provider, you can try disabling forced encryption here. But be aware, that this makes it possible for 3rd parties on the network to read your emails. Make sure to ask your correspondent to demand encryption support from their provider for a safer internet.'); ?></p>
<h3><?php echo htmlspecialchars(_('Encryption')); ?></h3>
<p><?php echo htmlspecialchars(_('If you are having issues sending or receiving mails with some other provider, you can try disabling forced encryption here. But be aware, that this makes it possible for 3rd parties on the network to read your emails. Make sure to ask your correspondent to demand encryption support from their provider for a safer internet.')); ?></p>
<div class="row">
<div class="col"><label for="enforce_tls_in"><?php echo _('Enforce encryption for incoming mail'); ?></label></div>
<div class="col"><label for="enforce_tls_in"><?php echo htmlspecialchars(_('Enforce encryption for incoming mail')); ?></label></div>
<div class="col"><input type="checkbox" name="enforce_tls_in"
id="enforce_tls_in"<?php echo ! empty( $tls_status[ 'enforce_tls_in' ] ) ? ' checked' : ''; ?>>
</div>
</div>
<div class="row">
<div class="col"><label for="enforce_tls_out"><?php echo _('Enforce encryption for outgoing mail'); ?></label></div>
<div class="col"><label for="enforce_tls_out"><?php echo htmlspecialchars(_('Enforce encryption for outgoing mail')); ?></label></div>
<div class="col"><input type="checkbox" name="enforce_tls_out"
id="enforce_tls_out"<?php echo ! empty( $tls_status[ 'enforce_tls_out' ] ) ? ' checked' : ''; ?>>
</div>
</div>
<div class="row">
<div class="col">
<button name="action" value="update_settings" type="submit"><?php echo _('Update settings'); ?></button>
<button name="action" value="update_settings" type="submit"><?php echo htmlspecialchars(_('Update settings')); ?></button>
</div>
</div>
</form>
<h2><?php echo _('Change password'); ?></h2>
<h2><?php echo htmlspecialchars(_('Change password')); ?></h2>
<form class="form_limit" action="manage_account.php" method="post">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION[ 'csrf_token' ]; ?>">
<div class="row">
<div class="col"><label for="pass_update"><?php echo _('Password'); ?></label></div>
<div class="col"><label for="pass_update"><?php echo htmlspecialchars(_('Password')); ?></label></div>
<div class="col"><input type="password" name="pass_update" id="pass_update" autocomplete="new-password"
required></div>
</div>
<div class="row">
<div class="col"><label for="pass_update2"><?php echo _('Password again'); ?></label></div>
<div class="col"><label for="pass_update2"><?php echo htmlspecialchars(_('Password again')); ?></label></div>
<div class="col"><input type="password" name="pass_update2" id="pass_update2" autocomplete="new-password"
required></div>
</div>
<div class="row">
<div class="col">
<button name="action" value="update_password" type="submit"><?php echo _('Change password'); ?></button>
<button name="action" value="update_password" type="submit"><?php echo htmlspecialchars(_('Change password')); ?></button>
</div>
</div>
</form>
@ -342,7 +342,7 @@ if ( empty( $_SESSION[ 'email_user' ] ) ) { ?>
$pgp_status = $stmt->fetch( PDO::FETCH_ASSOC );
if ( ! empty( $pgp_status[ 'pgp_key' ] ) ) {
if ( $pgp_status[ 'tfa' ] === 1 ) {
echo '<p class="green">'._('Yay, PGP based 2FA is enabled!').'</p>';
echo '<p class="green">'.htmlspecialchars(_('Yay, PGP based 2FA is enabled!')).'</p>';
} else {
$gpg = gnupg_init();
gnupg_seterrormode( $gpg, GNUPG_ERROR_WARNING );
@ -352,7 +352,7 @@ if ( empty( $_SESSION[ 'email_user' ] ) ) { ?>
$key_info = gnupg_keyinfo( $gpg, $imported_key[ 'fingerprint' ] );
foreach ( $key_info as $key ) {
if ( ! $key[ 'can_encrypt' ] ) {
echo '<p>'._('Sorry, this key can\'t be used to encrypt a message to you. Your key may have expired or has been revoked.').'</p>';
echo '<p>'.htmlspecialchars(_('Sorry, this key can\'t be used to encrypt a message to you. Your key may have expired or has been revoked.')).'</p>';
} else {
foreach ( $key[ 'subkeys' ] as $subkey ) {
gnupg_addencryptkey( $gpg, $subkey[ 'fingerprint' ] );
@ -361,16 +361,16 @@ if ( empty( $_SESSION[ 'email_user' ] ) ) { ?>
}
$_SESSION[ 'enable_2fa_code' ] = bin2hex( random_bytes( 3 ) );
if ( $encrypted = gnupg_encrypt( $gpg, _('To enable 2FA, please enter the following code to confirm ownership of your key:'). "\n\n$_SESSION[enable_2fa_code]\n" ) ) {
echo '<h2>'._( 'Enable 2FA').'</h2>';
echo '<p>'._('To enable 2FA using your PGP key, please decrypt the following PGP encrypted message and confirm the code:').'</p>';
echo '<h2>'.htmlspecialchars(_( 'Enable 2FA')).'</h2>';
echo '<p>'.htmlspecialchars(_('To enable 2FA using your PGP key, please decrypt the following PGP encrypted message and confirm the code:')).'</p>';
echo "<pre>$encrypted</pre>";
?>
<form class="form_limit" action="manage_account.php" method="post">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION[ 'csrf_token' ]; ?>">
<div class="row">
<div class="col"><input type="text" name="enable_2fa_code" aria-label="<?php echo _('2FA code'); ?>"></div>
<div class="col"><input type="text" name="enable_2fa_code" aria-label="<?php echo htmlspecialchars(_('2FA code')); ?>"></div>
<div>
<button type="submit" name="action" value="enable_2fa"><?php echo _('Confirm'); ?></button>
<button type="submit" name="action" value="enable_2fa"><?php echo htmlspecialchars(_('Confirm')); ?></button>
</div>
</div>
</form>
@ -381,33 +381,33 @@ if ( empty( $_SESSION[ 'email_user' ] ) ) { ?>
}
?>
<h2><?php echo _('Add PGP key for 2FA and end-to-end encryption'); ?></h2>
<h2><?php echo htmlspecialchars(_('Add PGP key for 2FA and end-to-end encryption')); ?></h2>
<form class="form_limit" action="manage_account.php" method="post">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION[ 'csrf_token' ]; ?>">
<div class="row">
<div class="col"><textarea name="pgp_key" rows="10" cols="50"
aria-label="<?php echo _('PGP key'); ?>"><?php echo htmlspecialchars( $pgp_status[ 'pgp_key' ] ?? '' ); ?></textarea>
aria-label="<?php echo htmlspecialchars(_('PGP key')); ?>"><?php echo htmlspecialchars( $pgp_status[ 'pgp_key' ] ?? '' ); ?></textarea>
</div>
</div>
<div>
<div>
<button type="submit" name="action" value="update_pgp_key"><?php echo _('Update PGP key'); ?></button>
<button type="submit" name="action" value="update_pgp_key"><?php echo htmlspecialchars(_('Update PGP key')); ?></button>
</div>
</div>
</form>
<form class="form_limit" action="manage_account.php" method="post">
<h2><?php echo _('Disable/Delete account'); ?></h2>
<p><?php echo _('Warning, this is permanent and cannot be undone. Disabling an account will delete your email data from the server, but leave the account blocked in the database for a year, so no one else can use it. Deleting your account will completely wipe all records of it and it will be available for new registrations again.'); ?></p>
<h2><?php echo htmlspecialchars(_('Disable/Delete account')); ?></h2>
<p><?php echo htmlspecialchars(_('Warning, this is permanent and cannot be undone. Disabling an account will delete your email data from the server, but leave the account blocked in the database for a year, so no one else can use it. Deleting your account will completely wipe all records of it and it will be available for new registrations again.')); ?></p>
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION[ 'csrf_token' ]; ?>">
<div class="row">
<div class="col">
<button type="submit" name="action" value="disable_account"><?php echo _('Disable account'); ?></button>
<button type="submit" name="action" value="disable_account"><?php echo htmlspecialchars(_('Disable account')); ?></button>
</div>
</div>
<div class="row">
<div class="col">
<button type="submit" name="action" value="delete_account"><?php echo _('Delete account'); ?></button>
<button type="submit" name="action" value="delete_account"><?php echo htmlspecialchars(_('Delete account')); ?></button>
</div>
</div>
</form>

View File

@ -13,24 +13,28 @@ if ( empty( $_SESSION[ 'csrf_token' ] ) || $_SESSION[ 'UA' ] !== $_SERVER[ 'HTTP
$msg = '';
if ( isset( $_POST[ 'user' ] ) ) {
$ok = true;
if( ! REGISTRATION_ENABLED ) {
$ok = false;
$msg .= '<div class="red" role="alert">'.sprintf(htmlspecialchars(_('Registration is disabled due to too many violations of the %s')), '<a href="'.ROOT_URL.'terms.php" target="_blank">'.htmlspecialchars(_('Terms of Service')).'</a>').'</div>';
}
if ( $_SESSION[ 'csrf_token' ] !== $_POST[ 'csrf_token' ] ?? '' ) {
$ok = false;
$msg .= '<div class="red" role="alert">'._('Invalid CSRF token').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Invalid CSRF token')).'</div>';
}
if ( ! check_captcha( $_POST[ 'challenge' ] ?? '', $_POST[ 'captcha' ] ?? '' ) ) {
$ok = false;
$msg .= '<div class="red" role="alert">'._('Invalid captcha').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Invalid captcha')).'</div>';
}
$db = get_db_instance();
if ( ! preg_match( '/^([^+\/\'"]+?)(@([^@]+))?$/iu', $_POST[ 'user' ], $match ) ) {
$ok = false;
$msg .= '<div class="red" role="alert">'._('Invalid username. It may not contain a +, \', " or /.').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Invalid username. It may not contain a +, \', " or /.')).'</div>';
}
$user = mb_strtolower( $match[ 1 ] ?? '' );
$domain = $match[ 3 ] ?? 'danwin1210.de';
$domain = $match[ 3 ] ?? CLEARNET_SERVER;
if ( $ok && ( empty( $_POST[ 'pwd' ] ) || empty( $_POST[ 'pwd2' ] ) || $_POST[ 'pwd' ] !== $_POST[ 'pwd2' ] ) ) {
$ok = false;
$msg .= '<div class="red" role="alert">'._('Passwords empty or don\'t match').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('Passwords empty or don\'t match')).'</div>';
} elseif ( $ok ) {
$stmt = $db->prepare( 'SELECT target_domain FROM alias_domain WHERE alias_domain = ? AND active=1;' );
$stmt->execute( [ $domain ] );
@ -41,15 +45,15 @@ if ( isset( $_POST[ 'user' ] ) ) {
$stmt->execute( [ $domain ] );
if ( ! $stmt->fetch() ) {
$ok = false;
$msg .= '<div class="red" role="alert">'._('The domain you specified is not allowed').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('The domain you specified is not allowed')).'</div>';
} else {
$validator = new EmailValidator();
if ( ! $validator->isValid( "$user@$domain", new NoRFCWarningsValidation() ) ) {
$ok = false;
$msg .= '<div class="red" role="alert">'._('The email address you specified is not valid').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('The email address you specified is not valid')).'</div>';
} elseif(in_array($user, RESERVED_USERNAMES, true)){
$ok = false;
$msg .= '<div class="red" role="alert">'._('The username you specified is reserved').'</div>';
$msg .= '<div class="red" role="alert">'.htmlspecialchars(_('The username you specified is reserved')).'</div>';
}
}
@ -65,9 +69,9 @@ if ( isset( $_POST[ 'user' ] ) ) {
$hash = password_hash( $_POST[ 'pwd' ], PASSWORD_ARGON2ID );
$stmt = $db->prepare( 'INSERT INTO alias (address, goto, domain, created, modified) VALUES (?, ?, ?, NOW(), NOW());' );
$stmt->execute( [ "$user@$domain", "$user@$domain", $domain ] );
$stmt = $db->prepare( 'INSERT INTO mailbox (username, password, quota, local_part, domain, created, modified, password_hash_type, openpgpkey_wkd) VALUES(?, ?, 51200000, ?, ?, NOW(), NOW(), ?, ?);' );
$stmt->execute( [ "$user@$domain", $hash, $user, $domain, '{ARGON2ID}', z_base32_encode( hash( 'sha1', mb_strtolower( $user ), true ) ) ] );
$msg .= '<div class="green" role="alert">'._('Successfully created new mailbox!').'</div>';
$stmt = $db->prepare( 'INSERT INTO mailbox (username, password, quota, local_part, domain, created, modified, password_hash_type, openpgpkey_wkd) VALUES(?, ?, ?, ?, ?, NOW(), NOW(), ?, ?);' );
$stmt->execute( [ "$user@$domain", $hash, DEFAULT_QUOTA, $user, $domain, '{ARGON2ID}', z_base32_encode( hash( 'sha1', mb_strtolower( $user ), true ) ) ] );
$msg .= '<div class="green" role="alert">'.htmlspecialchars(_('Successfully created new mailbox!')).'</div>';
}
}
}
@ -75,53 +79,59 @@ if ( isset( $_POST[ 'user' ] ) ) {
<!DOCTYPE html>
<html lang="<?php echo $language; ?>" dir="<?php echo $dir; ?>">
<head>
<title><?php echo _('E-Mail and XMPP - Register'); ?></title>
<title><?php echo htmlspecialchars(_('E-Mail and XMPP - Register')); ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="<?php echo _('Register for a free and anonymous E-Mail address and an XMPP/Jabber account'); ?>">
<meta name="description" content="<?php echo htmlspecialchars(_('Register for a free and anonymous E-Mail address and an XMPP/Jabber account')); ?>">
<link rel="canonical" href="<?php echo CANONICAL_URL; ?>register.php">
<link rel="alternate" href="<?php echo CANONICAL_URL; ?>register.php" hreflang="x-default">
<?php alt_links(); ?>
<meta property="og:type" content="website">
<meta property="og:title" content="<?php echo _('E-Mail and XMPP - Register'); ?>">
<meta property="og:description" content="<?php echo _('Register for a free and anonymous E-Mail address and an XMPP/Jabber account'); ?>">
<meta property="og:title" content="<?php echo htmlspecialchars(_('E-Mail and XMPP - Register')); ?>">
<meta property="og:description" content="<?php echo htmlspecialchars(_('Register for a free and anonymous E-Mail address and an XMPP/Jabber account')); ?>">
<meta property="og:url" content="<?php echo CANONICAL_URL; ?>register.php">
<meta property="og:locale" content="<?php echo $locale; ?>">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"<?php echo _('E-Mail and XMPP - Register'); ?>", "description": "<?php echo _('Register for a free and anonymous E-Mail address and an XMPP/Jabber account'); ?>"}</script>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"<?php echo htmlspecialchars(_('E-Mail and XMPP - Register')); ?>", "description": "<?php echo htmlspecialchars(_('Register for a free and anonymous E-Mail address and an XMPP/Jabber account')); ?>"}</script>
</head>
<body>
<main>
<p><a href="<?php echo ROOT_URL; ?>"><?php echo _('Info'); ?></a> | <?php echo _('Register'); ?> | <a href="<?php echo ROOT_URL; ?>manage_account.php"><?php echo _('Manage account'); ?></a> | <a href="<?php echo ROOT_URL; ?>squirrelmail/src/login.php" target="_blank"><?php echo _('SquirrelMail'); ?></a> | <a href="<?php echo ROOT_URL; ?>snappymail/" target="_blank"><?php echo _('SnappyMail'); ?></a> | <a href="<?php echo WEB_XMPP_URL; ?>" target="_blank" rel="noopener"><?php echo _('Web-XMPP'); ?></a>
<p><a href="<?php echo ROOT_URL; ?>"><?php echo htmlspecialchars(_('Info')); ?></a> | <?php echo htmlspecialchars(_('Register')); ?> | <a href="<?php echo ROOT_URL; ?>manage_account.php"><?php echo htmlspecialchars(_('Manage account')); ?></a> | <a href="<?php echo ROOT_URL; ?>squirrelmail/src/login.php" target="_blank"><?php echo htmlspecialchars(_('SquirrelMail')); ?></a> | <a href="<?php echo ROOT_URL; ?>snappymail/" target="_blank"><?php echo htmlspecialchars(_('SnappyMail')); ?></a> | <a href="<?php echo WEB_XMPP_URL; ?>" target="_blank" rel="noopener"><?php echo htmlspecialchars(_('Web-XMPP')); ?></a>
</p>
<?php echo "<p>$msg</p>"; ?>
<form class="form_limit" action="register.php" method="post"><input type="hidden" name="csrf_token"
value="<?php echo $_SESSION[ 'csrf_token' ] ?>">
<div class="row">
<div class="col"><label for="user"><?php echo _('Username'); ?></label></div>
<div class="col"><input type="text" name="user" id="user" autocomplete="username" required
value="<?php echo htmlspecialchars( $_POST[ 'user' ] ?? '' ); ?>"></div>
</div>
<div class="row">
<div class="col"><label for="pwd"><?php echo _('Password'); ?></label></div>
<div class="col"><input type="password" name="pwd" id="pwd" autocomplete="new-password" required></div>
</div>
<div class="row">
<div class="col"><label for="pwd2"><?php echo _('Password again'); ?></label></div>
<div class="col"><input type="password" name="pwd2" id="pwd2" autocomplete="new-password" required></div>
</div>
<div class="row">
<div class="col"><label for="accept_privacy"><?php printf(_('I have read and agreed to the <a href="%s" target="_blank">Privacy Policy</a>'), PRIVACY_POLICY_URL); ?></label>
</div>
<div class="col"><input type="checkbox" id="accept_privacy" name="accept_privacy" required></div>
</div>
<?php send_captcha(); ?>
<div class="row">
<div class="col">
<button type="submit"><?php echo _('Register'); ?></button>
</div>
</div>
</form>
<?php echo "<p>$msg</p>";
if( ! REGISTRATION_ENABLED ) {
echo '<p>'.sprintf(htmlspecialchars(_('Registration is disabled due to too many violations of the %s')), '<a href="'.ROOT_URL.'terms.php" target="_blank">'.htmlspecialchars(_('Terms of Service')).'</a>').'</p>';
} else {
?>
<form class="form_limit" action="register.php" method="post"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION[ 'csrf_token' ] ?>">
<div class="row">
<div class="col"><label for="user"><?php echo htmlspecialchars(_('Username')); ?></label></div>
<div class="col"><input type="text" name="user" id="user" autocomplete="username" required value="<?php echo htmlspecialchars( $_POST[ 'user' ] ?? '' ); ?>"></div>
</div>
<div class="row">
<div class="col"><label for="pwd"><?php echo htmlspecialchars(_('Password')); ?></label></div>
<div class="col"><input type="password" name="pwd" id="pwd" autocomplete="new-password" required></div>
</div>
<div class="row">
<div class="col"><label for="pwd2"><?php echo htmlspecialchars(_('Password again')); ?></label></div>
<div class="col"><input type="password" name="pwd2" id="pwd2" autocomplete="new-password" required></div>
</div>
<div class="row">
<div class="col"><label for="accept_privacy"><?php printf(htmlspecialchars(_('I have read and agreed to the %s')), '<a href="'.PRIVACY_POLICY_URL.'" target="_blank">'.htmlspecialchars(_('Privacy Policy')).'</a>'); ?></label></div>
<div class="col"><input type="checkbox" id="accept_privacy" name="accept_privacy" required></div>
</div>
<div class="row">
<div class="col"><label for="accept_terms"><?php printf(htmlspecialchars(_('I have read and agreed to the %s')), '<a href="'.ROOT_URL.'terms.php" target="_blank">'.htmlspecialchars(_('Terms of Service')).'</a>'); ?></label></div>
<div class="col"><input type="checkbox" id="accept_terms" name="accept_terms" required></div>
</div>
<?php send_captcha(); ?>
<div class="row">
<div class="col">
<button type="submit"><?php echo htmlspecialchars(_('Register')); ?></button>
</div>
</div>
</form>
<?php } ?>
</main>
</body>
</html>

41
www/terms.php Normal file
View File

@ -0,0 +1,41 @@
<?php
include_once('../common_config.php');
global $language, $dir, $locale;
?>
<!DOCTYPE html><html lang="<?php echo $language; ?>" dir="<?php echo $dir; ?>"><head>
<title><?php echo htmlspecialchars(_('E-Mail and XMPP - Terms of Service')); ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="<?php echo htmlspecialchars(_('Terms of Service for E-Mail and XMPP accounts')); ?>">
<link rel="canonical" href="<?php echo CANONICAL_URL; ?>terms.php">
<link rel="alternate" href="<?php echo CANONICAL_URL; ?>terms.php" hreflang="x-default">
<?php alt_links(); ?>
<meta property="og:type" content="website">
<meta property="og:title" content="<?php echo htmlspecialchars(_('E-Mail and XMPP - Terms of Service')); ?>">
<meta property="og:description" content="<?php echo htmlspecialchars(_('Terms of Service for E-Mail and XMPP accounts')); ?>">
<meta property="og:url" content="<?php echo CANONICAL_URL; ?>terms.php">
<meta property="og:locale" content="<?php echo $locale; ?>">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"<?php echo htmlspecialchars(_('E-Mail and XMPP - Terms of Service')); ?>", "description": "<?php echo htmlspecialchars(_('Terms of Service for E-Mail and XMPP accounts')); ?>"}</script>
</head><body>
<main>
<p><a href="<?php echo ROOT_URL; ?>"><?php echo htmlspecialchars(_('Info')); ?></a> | <a href="<?php echo ROOT_URL; ?>register.php"><?php echo htmlspecialchars(_('Register')); ?></a> | <a href="<?php echo ROOT_URL; ?>manage_account.php"><?php echo htmlspecialchars(_('Manage account')); ?></a> | <a href="<?php echo ROOT_URL; ?>squirrelmail/src/login.php" target="_blank"><?php echo htmlspecialchars(_('SquirrelMail')); ?></a> | <a href="<?php echo ROOT_URL; ?>snappymail/" target="_blank"><?php echo htmlspecialchars(_('SnappyMail')); ?></a> | <a href="<?php echo WEB_XMPP_URL; ?>" target="_blank" rel="noopener"><?php echo htmlspecialchars(_('Web-XMPP')); ?></a></p>
<ol>
<li><?php echo htmlspecialchars(_('I provide this service as is. I do not offer any uptime guarantee.')); ?></li>
<li><?php echo htmlspecialchars(_('Inactive accounts get automatically deleted after one year of inactivity.')); ?></li>
<li><?php echo htmlspecialchars(_('Spamming is not allowed, and you will be blocked if you do.')); ?></li>
<li><?php echo htmlspecialchars(_('Using your account for illegal purposes is not allowed, and you will be blocked if you do.')); ?></li>
<li><?php echo htmlspecialchars(_('Mass mailing is not allowed, and you will be blocked if you do.')); ?></li>
<li><?php echo htmlspecialchars(_('Please refrain from sending threats of violence or any harmful content. Dealing with law enforcement requests related to such incidents consumes a significant amount of time.')); ?></li>
<li><?php echo htmlspecialchars(_('If you lose your password, I will not reset it unless you can prove ownership of the account. You could do so by signing an email with the same PGP key that you use in your account.')); ?></li>
<li><?php echo htmlspecialchars(_('You are responsible for the security of your account and password.')); ?></li>
<?php if(DEFAULT_QUOTA > 0) { ?>
<li><?php printf(htmlspecialchars(_('Your email account has %1$s of disk space by default. If you need more, you can %2$s, and I will increase it for free.')), bytes_to_human_readable(DEFAULT_QUOTA), '<a href="'.CONTACT_URL.'">'.htmlspecialchars(_('contact me')).'</a>'); ?></li>
<?php } ?>
<li><?php echo htmlspecialchars(_('The XMPP service provides message archiving and HTTP upload, which can keep your messages and files for up to 1 week. Up to 100MB of file storage is available per user.')); ?></li>
<li><?php echo htmlspecialchars(_('I reserve the right to block or delete your account without prior notice.')); ?></li>
<li><?php echo htmlspecialchars(_('I reserve the right to change these terms without prior notice.')); ?></li>
<li><?php echo htmlspecialchars(_('Continued violations may necessitate the closure of registration.')); ?></li>
</ol>
</main>
</body></html>