init: projet complet copymail pour Raspberry Pi
Stack: Nginx + PHP 8.2 + MariaDB + Postfix + Dovecot + Samba - install.sh: script installation automatisé pour RPi OS Bookworm - Interface web: visionneuse mails + admin (comptes, domaine, dashboard) - Chaque compte mail génère automatiquement un share Samba - Processeur cron: extraction pièces jointes via zbateson/mail-mime-parser - Zéro injection SQL (PDO + prepared statements) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
126
scripts/apply_config.sh
Normal file
126
scripts/apply_config.sh
Normal file
@@ -0,0 +1,126 @@
|
||||
#!/bin/bash
|
||||
# apply_config.sh
|
||||
# Régénère les configs Postfix/Dovecot/Samba depuis les valeurs en BDD et recharge les services
|
||||
|
||||
set -e
|
||||
|
||||
PHP=/usr/bin/php
|
||||
|
||||
# Récupère les valeurs depuis la BDD via PHP
|
||||
DOMAIN=$($PHP -r "require '/opt/copymail/web/includes/db.php'; echo cfg('domain');")
|
||||
HOSTNAME=$($PHP -r "require '/opt/copymail/web/includes/db.php'; echo cfg('hostname');")
|
||||
SMTP_PORT=$($PHP -r "require '/opt/copymail/web/includes/db.php'; echo cfg('smtp_port');")
|
||||
SUBM_PORT=$($PHP -r "require '/opt/copymail/web/includes/db.php'; echo cfg('submission_port');")
|
||||
IMAP_PORT=$($PHP -r "require '/opt/copymail/web/includes/db.php'; echo cfg('imap_port');")
|
||||
IMAPS_PORT=$($PHP -r "require '/opt/copymail/web/includes/db.php'; echo cfg('imaps_port');")
|
||||
WORKGROUP=$($PHP -r "require '/opt/copymail/web/includes/db.php'; echo cfg('smb_workgroup');")
|
||||
|
||||
# --- Postfix main.cf ---
|
||||
cat > /etc/postfix/main.cf << POSTFIX
|
||||
# CopyMail - généré automatiquement
|
||||
myhostname = ${HOSTNAME}.${DOMAIN}
|
||||
mydomain = ${DOMAIN}
|
||||
myorigin = \$mydomain
|
||||
inet_interfaces = all
|
||||
inet_protocols = ipv4
|
||||
mydestination = localhost
|
||||
mynetworks = 127.0.0.0/8
|
||||
|
||||
# Virtual mailboxes
|
||||
virtual_mailbox_domains = ${DOMAIN}
|
||||
virtual_mailbox_base = /var/mail/vhosts
|
||||
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
|
||||
virtual_minimum_uid = 100
|
||||
virtual_uid_maps = static:5000
|
||||
virtual_gid_maps = static:5000
|
||||
|
||||
smtpd_banner = \$myhostname ESMTP
|
||||
biff = no
|
||||
append_dot_mydomain = no
|
||||
readme_directory = no
|
||||
|
||||
# Taille max message: 50 Mo
|
||||
message_size_limit = 52428800
|
||||
POSTFIX
|
||||
|
||||
# --- Postfix master.cf (ports) ---
|
||||
cat > /etc/postfix/master.cf << MASTER
|
||||
smtp inet n - y - - smtpd
|
||||
${SUBM_PORT} inet n - y - - smtpd
|
||||
-o syslog_name=postfix/submission
|
||||
-o smtpd_tls_security_level=encrypt
|
||||
-o smtpd_sasl_auth_enable=yes
|
||||
pickup unix n - y 60 1 pickup
|
||||
cleanup unix n - y - 0 cleanup
|
||||
qmgr unix n - n 300 1 qmgr
|
||||
tlsmgr unix - - y 1000? 1 tlsmgr
|
||||
rewrite unix - - y - - trivial-rewrite
|
||||
bounce unix - - y - 0 bounce
|
||||
defer unix - - y - 0 bounce
|
||||
trace unix - - y - 0 bounce
|
||||
verify unix - - y - 1 verify
|
||||
flush unix n - y 1000? 0 flush
|
||||
proxymap unix - - n - - proxymap
|
||||
proxywrite unix - - n - 1 proxymap
|
||||
smtp unix - - y - - smtp
|
||||
relay unix - - y - - smtp
|
||||
showq unix n - y - - showq
|
||||
error unix - - y - - error
|
||||
retry unix - - y - - error
|
||||
discard unix - - y - - discard
|
||||
local unix - n n - - local
|
||||
virtual unix - n n - - virtual
|
||||
lmtp unix - - y - - lmtp
|
||||
anvil unix - - y - 1 anvil
|
||||
scache unix - - y - 1 scache
|
||||
MASTER
|
||||
|
||||
# --- Dovecot ---
|
||||
cat > /etc/dovecot/conf.d/10-mail.conf << DOVECOT
|
||||
mail_location = maildir:/var/mail/vhosts/%d/%n/Maildir
|
||||
mail_privileged_group = vmail
|
||||
DOVECOT
|
||||
|
||||
cat > /etc/dovecot/conf.d/10-auth.conf << DOVECOTAUTH
|
||||
auth_mechanisms = plain login
|
||||
!include auth-passwdfile.conf.ext
|
||||
DOVECOTAUTH
|
||||
|
||||
cat > /etc/dovecot/conf.d/auth-passwdfile.conf.ext << PASSFILE
|
||||
passdb {
|
||||
driver = passwd-file
|
||||
args = scheme=SHA512-CRYPT /etc/dovecot/users
|
||||
}
|
||||
userdb {
|
||||
driver = static
|
||||
args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
|
||||
}
|
||||
PASSFILE
|
||||
|
||||
cat > /etc/dovecot/conf.d/10-master.conf << DOVMASTER
|
||||
service imap-login {
|
||||
inet_listener imap {
|
||||
port = ${IMAP_PORT}
|
||||
}
|
||||
inet_listener imaps {
|
||||
port = ${IMAPS_PORT}
|
||||
ssl = yes
|
||||
}
|
||||
}
|
||||
service auth {
|
||||
unix_listener auth-userdb {
|
||||
mode = 0600
|
||||
user = vmail
|
||||
}
|
||||
}
|
||||
DOVMASTER
|
||||
|
||||
# --- Samba workgroup ---
|
||||
sed -i "s/^\s*workgroup\s*=.*/ workgroup = ${WORKGROUP}/" /etc/samba/smb.conf
|
||||
|
||||
# --- Rechargement ---
|
||||
systemctl reload postfix || systemctl restart postfix
|
||||
systemctl reload dovecot || systemctl restart dovecot
|
||||
systemctl reload smbd || systemctl restart smbd
|
||||
|
||||
echo "OK: configuration appliquée pour ${DOMAIN}"
|
||||
70
scripts/create_account.sh
Normal file
70
scripts/create_account.sh
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
# create_account.sh <username> <password> <domain>
|
||||
# Appelé par l'interface web (via sudo) quand on crée un compte
|
||||
|
||||
set -e
|
||||
|
||||
USERNAME="$1"
|
||||
PASSWORD="$2"
|
||||
DOMAIN="$3"
|
||||
|
||||
if [[ -z "$USERNAME" || -z "$PASSWORD" || -z "$DOMAIN" ]]; then
|
||||
echo "Usage: $0 <username> <password> <domain>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MAILDIR="/var/mail/vhosts/${DOMAIN}/${USERNAME}/Maildir"
|
||||
SMBDIR="/srv/copymail/${USERNAME}"
|
||||
DOVECOT_PASSWD="/etc/dovecot/users"
|
||||
|
||||
# --- Maildir ---
|
||||
mkdir -p "${MAILDIR}/new" "${MAILDIR}/cur" "${MAILDIR}/tmp"
|
||||
chown -R vmail:vmail "/var/mail/vhosts/${DOMAIN}/${USERNAME}"
|
||||
chmod -R 770 "/var/mail/vhosts/${DOMAIN}/${USERNAME}"
|
||||
|
||||
# --- Postfix virtual mailboxes ---
|
||||
VMAILBOX="/etc/postfix/vmailbox"
|
||||
if ! grep -qF "${USERNAME}@${DOMAIN}" "${VMAILBOX}" 2>/dev/null; then
|
||||
echo "${USERNAME}@${DOMAIN} ${DOMAIN}/${USERNAME}/Maildir/" >> "${VMAILBOX}"
|
||||
fi
|
||||
postmap "${VMAILBOX}"
|
||||
|
||||
# --- Dovecot passwd-file ---
|
||||
# Format: username@domain:{SHA512-CRYPT}hash::::::
|
||||
PASS_HASH=$(doveadm pw -s SHA512-CRYPT -p "${PASSWORD}")
|
||||
if ! grep -qF "${USERNAME}@${DOMAIN}" "${DOVECOT_PASSWD}" 2>/dev/null; then
|
||||
echo "${USERNAME}@${DOMAIN}:${PASS_HASH}:::" >> "${DOVECOT_PASSWD}"
|
||||
else
|
||||
# Met à jour le mot de passe si le compte existe déjà
|
||||
sed -i "s|^${USERNAME}@${DOMAIN}:.*|${USERNAME}@${DOMAIN}:${PASS_HASH}:::|" "${DOVECOT_PASSWD}"
|
||||
fi
|
||||
|
||||
# --- Dossier SMB ---
|
||||
mkdir -p "${SMBDIR}"
|
||||
chown -R vmail:vmail "${SMBDIR}"
|
||||
chmod -R 775 "${SMBDIR}"
|
||||
|
||||
# --- Section Samba ---
|
||||
SMB_CONF="/etc/samba/smb.conf"
|
||||
if ! grep -qF "[${USERNAME}]" "${SMB_CONF}"; then
|
||||
cat >> "${SMB_CONF}" << SAMBA
|
||||
|
||||
[${USERNAME}]
|
||||
path = ${SMBDIR}
|
||||
browseable = yes
|
||||
writable = yes
|
||||
valid users = ${USERNAME}
|
||||
create mask = 0664
|
||||
directory mask = 0775
|
||||
SAMBA
|
||||
fi
|
||||
|
||||
# Ajoute l'utilisateur Samba (sans login système)
|
||||
(echo "${PASSWORD}"; echo "${PASSWORD}") | smbpasswd -a -s "${USERNAME}" 2>/dev/null || true
|
||||
|
||||
# --- Rechargement services ---
|
||||
systemctl reload postfix
|
||||
systemctl reload dovecot
|
||||
systemctl reload smbd
|
||||
|
||||
echo "OK: compte ${USERNAME}@${DOMAIN} créé."
|
||||
63
scripts/delete_account.sh
Normal file
63
scripts/delete_account.sh
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
# delete_account.sh <username>
|
||||
|
||||
set -e
|
||||
|
||||
USERNAME="$1"
|
||||
if [[ -z "$USERNAME" ]]; then
|
||||
echo "Usage: $0 <username>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DOMAIN=$(grep "^domain=" /opt/copymail/config.sh 2>/dev/null | cut -d= -f2)
|
||||
[[ -z "$DOMAIN" ]] && DOMAIN=$(php -r "require '/opt/copymail/web/includes/db.php'; echo cfg('domain');")
|
||||
|
||||
MAILDIR="/var/mail/vhosts/${DOMAIN}/${USERNAME}"
|
||||
SMBDIR="/srv/copymail/${USERNAME}"
|
||||
DOVECOT_PASSWD="/etc/dovecot/users"
|
||||
VMAILBOX="/etc/postfix/vmailbox"
|
||||
|
||||
# --- Supprime le Maildir ---
|
||||
[[ -d "${MAILDIR}" ]] && rm -rf "${MAILDIR}"
|
||||
|
||||
# --- Retire de vmailbox ---
|
||||
if [[ -f "${VMAILBOX}" ]]; then
|
||||
sed -i "/^${USERNAME}@${DOMAIN}/d" "${VMAILBOX}"
|
||||
postmap "${VMAILBOX}"
|
||||
fi
|
||||
|
||||
# --- Retire de Dovecot passwd ---
|
||||
if [[ -f "${DOVECOT_PASSWD}" ]]; then
|
||||
sed -i "/^${USERNAME}@${DOMAIN}:/d" "${DOVECOT_PASSWD}"
|
||||
fi
|
||||
|
||||
# --- Retire la section Samba ---
|
||||
SMB_CONF="/etc/samba/smb.conf"
|
||||
if grep -qF "[${USERNAME}]" "${SMB_CONF}"; then
|
||||
# Supprime la section du compte dans smb.conf
|
||||
python3 - <<PYEOF
|
||||
import re, sys
|
||||
|
||||
with open('${SMB_CONF}', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
pattern = r'\n\[${USERNAME}\][^\[]*'
|
||||
content = re.sub(pattern, '', content)
|
||||
|
||||
with open('${SMB_CONF}', 'w') as f:
|
||||
f.write(content)
|
||||
PYEOF
|
||||
fi
|
||||
|
||||
# Supprime utilisateur Samba
|
||||
smbpasswd -x "${USERNAME}" 2>/dev/null || true
|
||||
|
||||
# --- Supprime le dossier SMB (ATTENTION: supprime les fichiers) ---
|
||||
[[ -d "${SMBDIR}" ]] && rm -rf "${SMBDIR}"
|
||||
|
||||
# --- Rechargement ---
|
||||
systemctl reload postfix
|
||||
systemctl reload dovecot
|
||||
systemctl reload smbd
|
||||
|
||||
echo "OK: compte ${USERNAME} supprimé."
|
||||
Reference in New Issue
Block a user