#!/bin/bash # Email Server Setup Script # Components: Postfix, Dovecot, Amavis, SpamAssassin, OpenDKIM, PostgreSQL, PostfixAdmin # SSL: Let's Encrypt (DNS-01 Challenge) # Author: Email Server Setup Script # Date: $(date) set -euo pipefail # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration variables DOMAIN="" HOSTNAME="" ADMIN_EMAIL="" DB_NAME="postfix" DB_USER="postfix" DB_PASSWORD="" POSTFIXADMIN_PASSWORD="" WEBROOT="/var/www/postfixadmin" # Logging LOG_FILE="/var/log/email-server-setup.log" log() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" } error() { echo -e "${RED}ERROR: $1${NC}" >&2 log "ERROR: $1" exit 1 } info() { echo -e "${BLUE}INFO: $1${NC}" log "INFO: $1" } success() { echo -e "${GREEN}SUCCESS: $1${NC}" log "SUCCESS: $1" } warning() { echo -e "${YELLOW}WARNING: $1${NC}" log "WARNING: $1" } # Check if running as root check_root() { if [[ $EUID -ne 0 ]]; then error "This script must be run as root" fi } # Get user input get_configuration() { echo -e "${BLUE}Email Server Configuration${NC}" echo "=================================" while [[ -z "$DOMAIN" ]]; do read -p "Enter your domain name (e.g., example.com): " DOMAIN done while [[ -z "$HOSTNAME" ]]; do read -p "Enter your hostname (e.g., mail.example.com): " HOSTNAME done while [[ -z "$ADMIN_EMAIL" ]]; do read -p "Enter admin email address: " ADMIN_EMAIL done while [[ -z "$DB_PASSWORD" ]]; do read -s -p "Enter PostgreSQL password for postfix user: " DB_PASSWORD echo done while [[ -z "$POSTFIXADMIN_PASSWORD" ]]; do read -s -p "Enter PostfixAdmin setup password: " POSTFIXADMIN_PASSWORD echo done info "Configuration completed" } # Update system update_system() { info "Updating system packages..." apt update && apt upgrade -y success "System updated" } # Install required packages install_packages() { info "Installing required packages..." # Install basic packages apt install -y \ curl \ wget \ gnupg \ lsb-release \ software-properties-common \ certbot \ nginx \ ufw # Install PostgreSQL apt install -y postgresql postgresql-contrib # Install Postfix and related packages debconf-set-selections <<< "postfix postfix/mailname string $HOSTNAME" debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'" apt install -y \ postfix \ postfix-pgsql \ postfix-policyd-spf-python # Install Dovecot apt install -y \ dovecot-core \ dovecot-imapd \ dovecot-pop3d \ dovecot-lmtpd \ dovecot-pgsql # Install Amavis and SpamAssassin apt install -y \ amavisd-new \ spamassassin \ clamav \ clamav-daemon \ clamav-freshclam # Try to install clamav-unofficial-sigs if available if apt-cache show clamav-unofficial-sigs >/dev/null 2>&1; then apt install -y clamav-unofficial-sigs info "Installed clamav-unofficial-sigs" else warning "clamav-unofficial-sigs package not available, skipping (this is normal on newer systems)" fi # Install OpenDKIM apt install -y opendkim opendkim-tools # Install PHP and Apache for PostfixAdmin apt install -y \ apache2 \ php \ php-fpm \ php-cli \ php-pgsql \ php-mbstring \ php-xml \ php-curl \ php-zip \ php-gd success "All packages installed" } # Configure PostgreSQL configure_postgresql() { info "Configuring PostgreSQL..." # Start PostgreSQL systemctl start postgresql systemctl enable postgresql # Create database and user sudo -u postgres psql -c "CREATE DATABASE $DB_NAME;" sudo -u postgres psql -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';" sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;" # Create tables for Postfix sudo -u postgres psql -d "$DB_NAME" << 'EOF' CREATE TABLE domains ( domain varchar(50) NOT NULL, description varchar(255), aliases int NOT NULL default '0', mailboxes int NOT NULL default '0', maxquota bigint NOT NULL default '0', quota bigint NOT NULL default '0', transport varchar(255) default NULL, backupmx boolean NOT NULL default '0', created timestamp NOT NULL default now(), modified timestamp NOT NULL default now(), active boolean NOT NULL default '1', PRIMARY KEY (domain) ); CREATE TABLE aliases ( address varchar(255) NOT NULL, goto text NOT NULL, domain varchar(255) NOT NULL, created timestamp NOT NULL default now(), modified timestamp NOT NULL default now(), active boolean NOT NULL default '1', PRIMARY KEY (address) ); CREATE TABLE mailbox ( username varchar(255) NOT NULL, password varchar(255) NOT NULL, name varchar(255) NOT NULL default '', maildir varchar(255) NOT NULL default '', quota bigint NOT NULL default '0', local_part varchar(255) NOT NULL, domain varchar(255) NOT NULL, created timestamp NOT NULL default now(), modified timestamp NOT NULL default now(), active boolean NOT NULL default '1', PRIMARY KEY (username) ); CREATE TABLE domain_admins ( username varchar(255) NOT NULL, domain varchar(255) NOT NULL, created timestamp NOT NULL default now(), active boolean NOT NULL default '1', PRIMARY KEY (username, domain) ); CREATE TABLE admin ( username varchar(255) NOT NULL, password varchar(255) NOT NULL, created timestamp NOT NULL default now(), modified timestamp NOT NULL default now(), active boolean NOT NULL default '1', PRIMARY KEY (username) ); CREATE TABLE log ( timestamp timestamp NOT NULL default now(), username varchar(255) NOT NULL default '', domain varchar(255) NOT NULL default '', action varchar(255) NOT NULL default '', data text NOT NULL default '' ); CREATE TABLE vacation ( email varchar(255) NOT NULL, subject varchar(255) NOT NULL, body text NOT NULL, cache text NOT NULL default '', domain varchar(255) NOT NULL, created timestamp NOT NULL default now(), active boolean NOT NULL default '1', PRIMARY KEY (email) ); CREATE TABLE quota ( username varchar(255) NOT NULL, path varchar(100) NOT NULL, current bigint NOT NULL default 0, PRIMARY KEY (username, path) ); CREATE TABLE quota2 ( username varchar(100) NOT NULL, bytes bigint NOT NULL default 0, messages int NOT NULL default 0, PRIMARY KEY (username) ); EOF # Grant permissions sudo -u postgres psql -d "$DB_NAME" -c "GRANT SELECT ON ALL TABLES IN SCHEMA public TO $DB_USER;" sudo -u postgres psql -d "$DB_NAME" -c "GRANT INSERT, UPDATE, DELETE ON aliases, mailbox, domain_admins, domains TO $DB_USER;" sudo -u postgres psql -d "$DB_NAME" -c "GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO $DB_USER;" # Insert the primary domain sudo -u postgres psql -d "$DB_NAME" -c "INSERT INTO domains (domain, description, active) VALUES ('$DOMAIN', 'Primary domain configured during setup', '1') ON CONFLICT (domain) DO NOTHING;" success "PostgreSQL configured" } # Configure Postfix configure_postfix() { info "Configuring Postfix..." # Backup original configuration cp /etc/postfix/main.cf /etc/postfix/main.cf.backup # Create main.cf cat > /etc/postfix/main.cf << EOF # Basic configuration myhostname = $HOSTNAME mydomain = $DOMAIN myorigin = \$mydomain inet_interfaces = all inet_protocols = ipv4 mydestination = localhost # Virtual domains virtual_mailbox_domains = pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf virtual_mailbox_maps = pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf virtual_alias_maps = pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf virtual_mailbox_base = /var/mail/vhosts virtual_minimum_uid = 100 virtual_uid_maps = static:5000 virtual_gid_maps = static:5000 # SSL/TLS configuration smtpd_tls_cert_file = /etc/letsencrypt/live/$HOSTNAME/fullchain.pem smtpd_tls_key_file = /etc/letsencrypt/live/$HOSTNAME/privkey.pem smtpd_tls_security_level = may smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtp_tls_security_level = may smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 # SASL authentication smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_auth_enable = yes # Restrictions smtpd_helo_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_pipelining, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname smtpd_sender_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_sender, reject_unknown_sender_domain smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_unknown_recipient_domain, reject_non_fqdn_recipient smtpd_data_restrictions = reject_unauth_pipelining # Content filter (Amavis) content_filter = smtp-amavis:[127.0.0.1]:10024 # Milters (OpenDKIM) milter_protocol = 2 milter_default_action = accept smtpd_milters = inet:localhost:8891 non_smtpd_milters = inet:localhost:8891 # Miscellaneous message_size_limit = 52428800 mailbox_size_limit = 0 biff = no append_dot_mydomain = no readme_directory = no compatibility_level = 2 EOF # Create PostgreSQL lookup files cat > /etc/postfix/pgsql-virtual-mailbox-domains.cf << EOF user = $DB_USER password = $DB_PASSWORD hosts = localhost dbname = $DB_NAME query = SELECT 1 FROM domains WHERE domain='%s' AND active='1' EOF cat > /etc/postfix/pgsql-virtual-mailbox-maps.cf << EOF user = $DB_USER password = $DB_PASSWORD hosts = localhost dbname = $DB_NAME query = SELECT 1 FROM mailbox WHERE username='%s' AND active='1' EOF cat > /etc/postfix/pgsql-virtual-alias-maps.cf << EOF user = $DB_USER password = $DB_PASSWORD hosts = localhost dbname = $DB_NAME query = SELECT goto FROM aliases WHERE address='%s' AND active='1' EOF # Set permissions chmod 640 /etc/postfix/pgsql-*.cf chown root:postfix /etc/postfix/pgsql-*.cf # Configure master.cf for submission and smtps cat >> /etc/postfix/master.cf << EOF # Submission port 587 submission inet n - y - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=private/auth -o smtpd_reject_unlisted_recipient=no -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING # SMTPS port 465 smtps inet n - y - - smtpd -o syslog_name=postfix/smtps -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=private/auth -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING # Amavis smtp-amavis unix - - - - 2 smtp -o smtp_data_done_timeout=1200 -o smtp_send_xforward_command=yes -o disable_dns_lookups=yes -o max_use=20 127.0.0.1:10025 inet n - - - - smtpd -o content_filter= -o local_recipient_maps= -o relay_recipient_maps= -o smtpd_restriction_classes= -o smtpd_delay_reject=no -o smtpd_client_restrictions=permit_mynetworks,reject -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o smtpd_data_restrictions=reject_unauth_pipelining -o smtpd_end_of_data_restrictions= -o mynetworks=127.0.0.0/8 -o smtpd_error_sleep_time=0 -o smtpd_soft_error_limit=1001 -o smtpd_hard_error_limit=1000 -o smtpd_client_connection_count_limit=0 -o smtpd_client_connection_rate_limit=0 -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks EOF # Create virtual mailbox directory mkdir -p /var/mail/vhosts groupadd -g 5000 vmail 2>/dev/null || true useradd -g vmail -u 5000 vmail -d /var/mail/vhosts -m 2>/dev/null || true chown -R vmail:vmail /var/mail/vhosts success "Postfix configured" } # Configure Dovecot configure_dovecot() { info "Configuring Dovecot..." # Backup configuration cp -r /etc/dovecot /etc/dovecot.backup # Main configuration cat > /etc/dovecot/dovecot.conf << EOF !include_try /usr/share/dovecot/protocols.d/*.protocol protocols = imap pop3 lmtp !include conf.d/*.conf !include_try local.conf EOF # 10-mail.conf cat > /etc/dovecot/conf.d/10-mail.conf << EOF mail_location = maildir:/var/mail/vhosts/%d/%n namespace inbox { inbox = yes } mail_privileged_group = mail mail_uid = vmail mail_gid = vmail first_valid_uid = 5000 last_valid_uid = 5000 first_valid_gid = 5000 last_valid_gid = 5000 EOF # 10-auth.conf cat > /etc/dovecot/conf.d/10-auth.conf << EOF disable_plaintext_auth = yes auth_mechanisms = plain login !include auth-sql.conf.ext EOF # auth-sql.conf.ext cat > /etc/dovecot/conf.d/auth-sql.conf.ext << EOF passdb { driver = sql args = /etc/dovecot/dovecot-sql.conf.ext } userdb { driver = static args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n } EOF # dovecot-sql.conf.ext cat > /etc/dovecot/dovecot-sql.conf.ext << EOF driver = pgsql connect = host=localhost dbname=$DB_NAME user=$DB_USER password=$DB_PASSWORD default_pass_scheme = SHA512-CRYPT password_query = SELECT username as user, password FROM mailbox WHERE username='%u' AND active='1' EOF # 10-master.conf cat > /etc/dovecot/conf.d/10-master.conf << EOF service imap-login { inet_listener imap { port = 143 } inet_listener imaps { port = 993 ssl = yes } } service pop3-login { inet_listener pop3 { port = 110 } inet_listener pop3s { port = 995 ssl = yes } } service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { mode = 0600 user = postfix group = postfix } } service auth { unix_listener /var/spool/postfix/private/auth { mode = 0666 user = postfix group = postfix } unix_listener auth-userdb { mode = 0600 user = vmail group = vmail } user = dovecot } service auth-worker { user = vmail } EOF # 10-ssl.conf cat > /etc/dovecot/conf.d/10-ssl.conf << EOF ssl = required ssl_cert = /etc/opendkim.conf << EOF Syslog yes UMask 007 Socket inet:8891@localhost PidFile /var/run/opendkim/opendkim.pid OversignHeaders From TrustAnchorFile /usr/share/dns/root.key UserID opendkim KeyTable /etc/opendkim/key.table SigningTable /etc/opendkim/signing.table ExternalIgnoreList /etc/opendkim/trusted.hosts InternalHosts /etc/opendkim/trusted.hosts EOF # Key table echo "mail._domainkey.$DOMAIN $DOMAIN:mail:/etc/opendkim/keys/$DOMAIN/mail.private" > /etc/opendkim/key.table # Signing table echo "*@$DOMAIN mail._domainkey.$DOMAIN" > /etc/opendkim/signing.table # Trusted hosts cat > /etc/opendkim/trusted.hosts << EOF 127.0.0.1 localhost $HOSTNAME $DOMAIN EOF success "OpenDKIM configured" # Display DNS record info "Add this TXT record to your DNS:" echo "mail._domainkey.$DOMAIN" cat /etc/opendkim/keys/$DOMAIN/mail.txt } # Configure Amavis and SpamAssassin configure_amavis() { info "Configuring Amavis and SpamAssassin..." # Update ClamAV signatures freshclam # Configure Amavis cat > /etc/amavis/conf.d/15-content_filter_mode << 'EOF' use strict; @bypass_virus_checks_maps = ( \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re); @bypass_spam_checks_maps = ( \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re); 1; # ensure a defined return EOF cat > /etc/amavis/conf.d/20-debian_defaults << EOF use strict; \$MYHOME = '/var/lib/amavis'; \$mydomain = '$DOMAIN'; \$myhostname = '$HOSTNAME'; \$max_servers = 3; \$daemon_user = 'amavis'; \$daemon_group = 'amavis'; \$inet_socket_port = 10024; \$policy_bank{'MYNETS'} = { originating => 1, os_fingerprint_method => undef, }; \$interface_policy{'10024'} = 'ORIGINATING'; \$policy_bank{'ORIGINATING'} = { originating => 1, allow_disclaimers => 1, virus_admin_maps => ["virusalert\\\@\$mydomain"], spam_admin_maps => ["virusalert\\\@\$mydomain"], warnbadhsender => 1, forward_method => 'smtp:[127.0.0.1]:10025', smtpd_discard_ehlo_keywords => ['8BITMIME'], bypass_banned_checks_maps => [1], terminate_dsn_on_notify_success => 0, }; \$sa_tag_level_deflt = 2.0; \$sa_tag2_level_deflt = 6.0; \$sa_kill_level_deflt = 6.9; \$sa_dsn_cutoff_level = 10; \$penpals_bonus_score = 8; \$penpals_threshold_high = \$sa_kill_level_deflt; \$bounce_killer_score = 100; \$virus_admin = "postmaster\\\@\$mydomain"; \$mailfrom_notify_admin = "postmaster\\\@\$mydomain"; \$mailfrom_notify_recip = "postmaster\\\@\$mydomain"; \$mailfrom_notify_spamadmin = "postmaster\\\@\$mydomain"; \$mailfrom_to_quarantine = ''; \@lookup_sql_dsn = ( ['DBI:Pg:database=$DB_NAME;host=127.0.0.1;port=5432', '$DB_USER', '$DB_PASSWORD'] ); \$enable_db = 1; \$enable_global_cache = 1; \$inet_socket_bind = '127.0.0.1'; @inet_acl = qw(127.0.0.1); 1; EOF # Configure SpamAssassin cat > /etc/spamassassin/local.cf << EOF rewrite_header Subject *****SPAM***** report_safe 0 required_score 5.0 use_bayes 1 use_bayes_rules 1 bayes_auto_learn 1 skip_rbl_checks 0 use_razor2 1 use_dcc 1 use_pyzor 1 EOF # Add amavis user to clamav group usermod -a -G clamav amavis success "Amavis and SpamAssassin configured" } # Get Let's Encrypt certificates using the DNS challenge get_ssl_certificates() { info "Obtaining Let's Encrypt certificates..." if [[ ! -f "/etc/letsencrypt/live/$HOSTNAME/fullchain.pem" ]]; then warning "SSL certificates for $HOSTNAME were not found." echo -e "${YELLOW}This script will use the DNS challenge method with Certbot, which does not require opening port 80.${NC}" echo -e "${YELLOW}You will need to manually update your DNS records during this process.${NC}" echo echo -e "${BLUE}1. Install the appropriate Certbot DNS plugin for your DNS provider (e.g., 'certbot-dns-cloudflare' for Cloudflare).${NC}" echo -e "${BLUE}2. Create the necessary API credentials file for Certbot to access your DNS provider's API.${NC}" echo -e "${BLUE}3. Run the following command (with your plugin and credentials) to obtain your certificate:${NC}" echo -e "${GREEN} certbot certonly --dns-PLUGIN --dns-PLUGIN-credentials /path/to/credentials.ini -d \"$HOSTNAME\" -d \"www.$HOSTNAME\" --agree-tos --email \"$ADMIN_EMAIL\"${NC}" echo -e "${YELLOW}After running the command and successfully obtaining the certificates, press ENTER to continue this script.${NC}" read -p "" fi if [[ ! -f "/etc/letsencrypt/live/$HOSTNAME/fullchain.pem" ]]; then error "Failed to find SSL certificate. Please obtain it manually and re-run this script." fi # Set up auto-renewal (crontab -l 2>/dev/null; echo "0 12 * * * /usr/bin/certbot renew --quiet") | crontab - success "SSL certificates obtained" } # Install PostfixAdmin install_postfixadmin() { info "Installing PostfixAdmin..." # Download PostfixAdmin cd /tmp wget https://github.com/postfixadmin/postfixadmin/archive/postfixadmin-3.3.11.tar.gz tar -xzf postfixadmin-3.3.11.tar.gz mv postfixadmin-postfixadmin-3.3.11 $WEBROOT # Set permissions chown -R www-data:www-data $WEBROOT chmod -R 755 $WEBROOT # Create PostfixAdmin configuration cat > $WEBROOT/config.local.php << EOF 'abuse@change-this-to-your.domain.tld', 'hostmaster' => 'hostmaster@change-this-to-your.domain.tld', 'postmaster' => 'postmaster@change-this-to-your.domain.tld', 'webmaster' => 'webmaster@change-this-to-your.domain.tld' ); \$CONF['domain_path'] = 'YES'; \$CONF['domain_in_mailbox'] = 'YES'; \$CONF['maildir_name_hook'] = 'maildir_name_hook'; function maildir_name_hook(\$domain, \$user) { return \$domain . '/' . \$user . '/'; } ?> EOF # Configure Apache virtual host cat > /etc/apache2/sites-available/postfixadmin.conf << EOF ServerName $HOSTNAME Redirect permanent / https://$HOSTNAME/ ServerName $HOSTNAME DocumentRoot $WEBROOT/public SSLEngine on SSLCertificateFile /etc/letsencrypt/live/$HOSTNAME/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/$HOSTNAME/privkey.pem Options -Indexes AllowOverride All Require all granted ErrorLog \${APACHE_LOG_DIR}/postfixadmin_error.log CustomLog \${APACHE_LOG_DIR}/postfixadmin_access.log combined EOF # Enable Apache modules and site a2enmod ssl a2enmod rewrite a2ensite postfixadmin a2dissite 000-default success "PostfixAdmin installed" } # Configure firewall configure_firewall() { info "Configuring firewall..." # Reset UFW ufw --force reset # Default policies ufw default deny incoming ufw default allow outgoing # Allow SSH ufw allow ssh # Allow email ports ufw allow 25/tcp # SMTP ufw allow 587/tcp # Submission ufw allow 465/tcp # SMTPS ufw allow 110/tcp # POP3 ufw allow 995/tcp # POP3S ufw allow 143/tcp # IMAP ufw allow 993/tcp # IMAPS # Allow web ports ufw allow 80/tcp # HTTP ufw allow 443/tcp # HTTPS # Enable UFW ufw --force enable success "Firewall configured" } # Start and enable services start_services() { info "Starting and enabling services..." # Reload systemd systemctl daemon-reload # Start and enable services systemctl enable --now postgresql systemctl enable --now postfix systemctl enable --now dovecot systemctl enable --now amavis systemctl enable --now spamassassin systemctl enable --now clamav-daemon systemctl enable --now clamav-freshclam systemctl enable --now opendkim systemctl enable --now apache2 success "All services started and enabled" } # Display final information display_final_info() { success "Email server setup completed!" echo echo -e "${BLUE}=== Setup Summary ===${NC}" echo "Primary Domain: $DOMAIN" echo "Hostname: $HOSTNAME" echo "Admin Email: $ADMIN_EMAIL" echo "PostfixAdmin URL: https://$HOSTNAME/postfixadmin/" echo echo -e "${YELLOW}=== DNS Records to Add for $DOMAIN ===${NC}" echo "A $HOSTNAME [Your server IP]" echo "MX $DOMAIN $HOSTNAME" echo "TXT $DOMAIN \"v=spf1 mx ~all\"" echo "TXT _dmarc.$DOMAIN \"v=DMARC1; p=none; rua=mailto:dmarc@$DOMAIN\"" echo echo -e "${YELLOW}=== DKIM DNS Record for $DOMAIN ===${NC}" cat /etc/opendkim/keys/$DOMAIN/mail.txt echo echo -e "${YELLOW}=== Next Steps ===${NC}" echo "1. Add the DNS records shown above" echo "2. Visit https://$HOSTNAME/postfixadmin/setup.php to complete PostfixAdmin setup" echo "3. Create your first domain and mailbox in PostfixAdmin" echo "4. Test email sending and receiving" echo echo -e "${BLUE}=== Multiple Domain Support ===${NC}" echo "This server supports unlimited virtual domains!" echo echo "To add additional domains:" echo "1. Run: ./add-domain.sh newdomain.com" echo "2. Add the provided DNS records" echo "3. Configure the domain in PostfixAdmin" echo "4. Create mailboxes for the new domain" echo echo -e "${BLUE}=== Application SMTP Configuration ===${NC}" echo "Your applications can send email using these settings:" echo " Host: $HOSTNAME" echo " Port: 587 (STARTTLS) or 465 (SSL/TLS)" echo " Username: mailbox@yourdomain.com (full email address)" echo " Password: [mailbox password from PostfixAdmin]" echo " Security: STARTTLS or SSL/TLS" echo echo -e "${GREEN}Setup completed successfully!${NC}" } # Main execution main() { echo -e "${BLUE}Email Server Setup Script${NC}" echo "=========================" echo check_root get_configuration update_system install_packages configure_postgresql get_ssl_certificates configure_postfix configure_dovecot configure_opendkim configure_amavis install_postfixadmin configure_firewall start_services display_final_info } # Run main function main "$@"