Jelajahi Sumber

Merge branch 'mail-stack' into mail-file-fixes

Kristan Kenney 7 tahun lalu
induk
melakukan
63d7bb7b5d

+ 47 - 19
bin/v-add-cron-hestia-autoupdate

@@ -1,6 +1,6 @@
 #!/bin/bash
 # info: check letsencrypt domain
-# options: USER DOMAIN [ALIASES]
+# options: USER DOMAIN [ALIASES] [MAIL]
 #
 # The function check and validates domain with Let's Encrypt
 
@@ -13,6 +13,7 @@
 user=$1
 domain=$2
 aliases=$3
+mail=$3
 
 # LE API
 LE_API='https://acme-v02.api.letsencrypt.org'
@@ -54,26 +55,41 @@ query_le_v2() {
 #                    Verifications                         #
 #----------------------------------------------------------#
 
-check_args '2' "$#" 'USER DOMAIN [ALIASES]'
+check_args '2' "$#" 'USER DOMAIN [ALIASES] [MAIL]'
 is_format_valid 'user' 'domain' 'aliases'
-is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
 is_object_valid 'user' 'USER' "$user"
 is_object_unsuspended 'user' 'USER' "$user"
-is_object_valid 'web' 'DOMAIN' "$domain"
-is_object_unsuspended 'web' 'DOMAIN' "$domain"
-get_domain_values 'web'
-for alias in $(echo "$aliases" |tr ',' '\n' |sort -u); do
-    check_alias="$(echo $ALIAS |tr ',' '\n' |grep ^$alias$)"
-    if [ -z "$check_alias" ]; then
-        check_result $E_NOTEXIST "domain alias $alias doesn't exist"
-    fi
-done
+if [ -z "$mail" ]; then
+    is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
+    is_object_valid 'web' 'DOMAIN' "$domain"
+    is_object_unsuspended 'web' 'DOMAIN' "$domain"
+    get_domain_values 'web'
+    for alias in $(echo "$aliases" |tr ',' '\n' |sort -u); do
+        check_alias="$(echo $ALIAS |tr ',' '\n' |grep ^$alias$)"
+        if [ -z "$check_alias" ]; then
+            check_result $E_NOTEXIST "domain alias $alias doesn't exist"
+        fi
+    done
+else
+    is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
+    is_object_valid 'mail' 'DOMAIN' "$domain"
+    is_object_unsuspended 'mail' 'DOMAIN' "$domain"
+    is_object_value_empty 'mail' 'DOMAIN' "$domain" '$SSL'
+fi
+
 
 
 #----------------------------------------------------------#
 #                       Action                             #
 #----------------------------------------------------------#
 
+# Rework domain and alieses for mail.
+if [ ! -z "$mail" ]; then
+    original_domain=$domain
+    aliases="webmail.$domain,autodiscover.$domain"
+    domain="mail.$domain"
+fi
+
 # Registering LetsEncrypt user account
 $BIN/v-add-letsencrypt-user $user
 if [ "$?" -ne 0  ]; then
@@ -237,9 +253,15 @@ if [[ $(head -n 1 $ssl_dir/$domain.ca) = "-----END CERTIFICATE-----" ]]; then
 fi
 
 # Adding SSL
-ssl_home=$(search_objects 'web' 'LETSENCRYPT' 'yes' 'SSL_HOME')
-$BIN/v-delete-web-domain-ssl $user $domain > /dev/null 2>&1
-$BIN/v-add-web-domain-ssl $user $domain $ssl_dir $ssl_home
+if [ -z "$mail" ]; then
+    ssl_home=$(search_objects 'web' 'LETSENCRYPT' 'yes' 'SSL_HOME')
+    $BIN/v-delete-web-domain-ssl $user $domain > /dev/null 2>&1
+    $BIN/v-add-web-domain-ssl $user $domain $ssl_dir $ssl_home
+else
+    $BIN/v-delete-mail-domain-ssl $user $domain >/dev/null 2>&1
+    $BIN/v-add-mail-domain-ssl $user $domain $ssl_dir
+fi
+
 if [ "$?" -ne '0' ]; then
     touch $HESTIA/data/queue/letsencrypt.pipe
     sed -i "/ $domain /d" $HESTIA/data/queue/letsencrypt.pipe
@@ -256,11 +278,17 @@ if [ -z "$(grep v-update-lets $HESTIA/data/users/admin/cron.conf)" ]; then
 fi
 
 # Updating letsencrypt key
-if [ -z "$LETSENCRYPT" ]; then
-    add_object_key "web" 'DOMAIN' "$domain" 'LETSENCRYPT' 'FTP_USER'
+if [ -z "$mail" ]; then
+    if [ -z "$LETSENCRYPT" ]; then
+        add_object_key "web" 'DOMAIN' "$domain" 'LETSENCRYPT' 'FTP_USER'
+    fi
+    update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT' 'yes'
+else
+    if [ -z "$LETSENCRYPT" ]; then
+        add_object_key "mail" 'DOMAIN' "$original_domain" 'LETSENCRYPT'
+    fi
+    update_object_value 'mail' 'DOMAIN' "$original_domain" '$LETSENCRYPT' 'yes'
 fi
-update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT' 'yes'
-
 
 #----------------------------------------------------------#
 #                        Hestia                            #

+ 6 - 7
bin/v-add-mail-domain

@@ -21,6 +21,7 @@ dkim_size=${6-1024}
 source $HESTIA/func/main.sh
 source $HESTIA/func/domain.sh
 source $HESTIA/conf/hestia.conf
+source $HESTIA/func/ip.sh
 
 # Define mail user
 if [ "$MAIL_SYSTEM" = 'exim4' ]; then
@@ -32,7 +33,7 @@ fi
 # Additional argument formatting
 format_domain
 format_domain_idn
-
+get_user_ip
 
 #----------------------------------------------------------#
 #                    Verifications                         #
@@ -53,13 +54,11 @@ is_dir_symlink $HOMEDIR/$user/mail
 #----------------------------------------------------------#
 
 # Generating timestamp
-time_n_date=$(date +'%T %F')
-time=$(echo "$time_n_date" |cut -f 1 -d \ )
-date=$(echo "$time_n_date" |cut -f 2 -d \ )
+new_timestamp
 
 # Adding domain to mail.conf
 s="DOMAIN='$domain' ANTIVIRUS='$antivirus' ANTISPAM='$antispam' DKIM='$dkim'"
-s="$s CATCHALL='' ACCOUNTS='0' U_DISK='0' SUSPENDED='no' TIME='$time'"
+s="$s SSL='no' LETSENCRYPT='no' CATCHALL='' ACCOUNTS='0' WEBMAIL='yes' U_DISK='0' SUSPENDED='no' TIME='$time'"
 s="$s DATE='$date'"
 echo $s >> $USER_DATA/mail.conf
 touch $USER_DATA/mail/$domain.conf
@@ -128,15 +127,15 @@ if [ ! -z "$DNS_SYSTEM" ] && [ "$dkim" = 'yes' ]; then
     fi
 fi
 
-
 #----------------------------------------------------------#
 #                       Hestia                             #
 #----------------------------------------------------------#
 
 # Increasing domain value
 increase_user_value "$user" '$U_MAIL_DOMAINS'
+
 if [ "$dkim" = 'yes' ]; then
-    increase_user_value "$user" '$U_MAIL_DKMI'
+    increase_user_value "$user" '$U_MAIL_DKIM'
 fi
 
 # Logging

+ 97 - 0
bin/v-add-mail-domain-ssl

@@ -0,0 +1,97 @@
+#!/bin/bash
+# info: add mail SSL for $domain
+# options: USER DOMAIN SSL_DIR [RESTART]
+#
+# The function turns on SSL support for a mail domain. Parameter ssl_dir
+# is a path to a directory where 2 or 3 ssl files can be found. Certificate file 
+# mail.domain.tld.crt and its key mail.domain.tld.key are mandatory. Certificate
+# authority mail.domain.tld.ca file is optional.
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Argument definition
+user=$1
+domain=$2
+ssl_dir=$3
+restart="$3"
+
+# Additional argument formatting
+if [[ "$domain" =~ [[:upper:]] ]]; then
+    domain=$(echo "$domain" |tr '[:upper:]' '[:lower:]')
+fi
+if [[ "$domain" =~ ^www\..* ]]; then
+    domain=$(echo "$domain" |sed -e "s/^www.//")
+fi
+if [[ "$domain" =~ .*\.$ ]]; then
+    domain=$(echo "$domain" |sed -e "s/\.$//")
+fi
+
+domain=$(idn -t --quiet -u "$domain" )
+domain_idn=$(idn -t --quiet -a "$domain")
+
+# Includes
+source $HESTIA/func/main.sh
+source $HESTIA/func/domain.sh
+source $HESTIA/func/ip.sh
+source $HESTIA/conf/hestia.conf
+
+# Additional argument formatting
+format_domain
+format_domain_idn
+get_user_ip
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+check_args '3' "$#" 'USER DOMAIN SSL_DIR [RESTART]'
+is_format_valid 'user' 'domain' 'ssl_dir'
+is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
+is_object_valid 'user' 'USER' "$user"
+is_object_unsuspended 'user' 'USER' "$user"
+is_object_valid 'mail' 'DOMAIN' "$domain"
+is_object_unsuspended 'mail' 'DOMAIN' "$domain"
+is_object_value_empty 'mail' 'DOMAIN' "$domain" '$SSL'
+is_object_valid 'web' 'DOMAIN' "$domain"
+is_object_unsuspended 'web' 'DOMAIN' "$domain"
+is_web_domain_cert_valid
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+# Call routine to add SSL configuration to mail domain
+add_mail_ssl_config
+
+# Increase value for domain
+increase_user_value "$user" '$U_MAIL_SSL'
+
+# Set SSL as enabled in configuration
+update_object_value 'mail' 'DOMAIN' "$domain" '$SSL' "yes"
+
+# Refresh webmail configuration
+if [ ! -z "$WEB_SYSTEM" ]; then
+    add_ssl_webmail_config
+
+    # Restart web services for webmail changes to take effect
+    $BIN/v-restart-web $restart
+    $BIN/v-restart-proxy $restart
+fi
+
+#----------------------------------------------------------#
+#                       Hestia                             #
+#----------------------------------------------------------#
+
+# Restarting mail server
+$BIN/v-restart-mail $restart
+$BIN/v-restart-service $IMAP_SYSTEM $restart
+
+check_result $? "Mail restart failed" >/dev/null
+
+# Logging
+log_history "enabled mail ssl support for $domain"
+log_event "$OK" "$ARGUMENTS"
+
+exit

+ 1 - 0
bin/v-add-user

@@ -179,6 +179,7 @@ U_DNS_RECORDS='0'
 U_MAIL_DOMAINS='0'
 U_MAIL_DKIM='0'
 U_MAIL_ACCOUNTS='0'
+U_MAIL_SSL='0'
 U_DATABASES='0'
 U_CRON_JOBS='0'
 U_BACKUPS='0'

+ 68 - 0
bin/v-add-web-domain-ssl-force

@@ -0,0 +1,68 @@
+#!/bin/bash
+# info: change domain ssl certificate
+# options: USER DOMAIN SSL_DIR [RESTART]
+#
+# The function changes SSL domain certificate and the key. If ca file present
+# it will be replaced as well.
+
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Argument definition
+user=$1
+domain=$2
+domain_idn=$2
+restart=$3
+
+# Includes
+source $HESTIA/func/main.sh
+source $HESTIA/func/domain.sh
+source $HESTIA/conf/hestia.conf
+
+# Additional argument formatting
+format_domain
+format_domain_idn
+
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+check_args '3' "$#" 'USER DOMAIN SSL_DIR [RESTART]'
+is_format_valid 'user' 'domain' 'ssl_dir'
+is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
+is_object_valid 'user' 'USER' "$user"
+is_object_unsuspended 'user' 'USER' "$user"
+is_object_valid 'mail' 'DOMAIN' "$domain_idn"
+is_object_unsuspended 'mail' 'DOMAIN' "$domain_idn"
+is_object_value_empty 'mail' 'DOMAIN' "$domain_idn" '$SSL'
+is_web_domain_cert_valid
+
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+# Remove old configuration
+del_mail_ssl_config
+
+# Create new configuration
+add_mail_ssl_config
+
+#----------------------------------------------------------#
+#                       Hestia                             #
+#----------------------------------------------------------#
+
+# Restarting mail server
+$BIN/v-restart-mail $restart
+service dovecot restart
+service exim4 restart
+check_result $? "Mail restart failed" >/dev/null
+
+# Logging
+log_history "changed ssl certificate for $domain"
+log_event "$OK" "$ARGUMENTS"
+
+exit

+ 33 - 11
bin/v-change-sys-pma

@@ -1,6 +1,6 @@
 #!/bin/bash
 # info: deleting letsencrypt ssl cetificate for domain
-# options: USER DOMAIN [RESTART]
+# options: USER DOMAIN [RESTART] [MAIL]
 #
 # The function turns off letsencrypt SSL support for a domain.
 
@@ -13,6 +13,7 @@
 user=$1
 domain=$2
 restart=$3
+mail=$4
 
 # Includes
 source $HESTIA/func/main.sh
@@ -24,22 +25,33 @@ source $HESTIA/conf/hestia.conf
 #                    Verifications                         #
 #----------------------------------------------------------#
 
-check_args '2' "$#" 'USER DOMAIN [RESTART]'
+check_args '2' "$#" 'USER DOMAIN [RESTART] [MAIL]'
 is_format_valid 'user' 'domain'
 is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
 is_system_enabled "$WEB_SSL" 'SSL_SUPPORT'
 is_object_valid 'user' 'USER' "$user"
 is_object_unsuspended 'user' 'USER' "$user"
-is_object_valid 'web' 'DOMAIN' "$domain"
-is_object_unsuspended 'web' 'DOMAIN' "$domain"
-is_object_value_exist 'web' 'DOMAIN' "$domain" '$LETSENCRYPT'
+if [ -z "$mail"]; then
+    is_object_valid 'web' 'DOMAIN' "$domain"
+    is_object_unsuspended 'web' 'DOMAIN' "$domain"
+    is_object_value_exist 'web' 'DOMAIN' "$domain" '$LETSENCRYPT'
+else
+    is_object_valid 'mail' 'DOMAIN' "$domain"
+    is_object_unsuspended 'mail' 'DOMAIN' "$domain"
+    is_object_value_exist 'mail' 'DOMAIN' "$domain" '$LETSENCRYPT'
+fi
+
 
 #----------------------------------------------------------#
 #                       Action                             #
 #----------------------------------------------------------#
 
 # Delete SSL
-$BIN/v-delete-web-domain-ssl $user $domain $restart >/dev/null 2>&1
+if [ -z "$mail"]; then
+    $BIN/v-delete-web-domain-ssl $user $domain $restart >/dev/null 2>&1
+else
+    $BIN/v-delete-mail-domain-ssl $user $domain $restart >/dev/null 2>&1
+fi
 check_result $? "SSL delete" >/dev/null
 
 
@@ -48,16 +60,26 @@ check_result $? "SSL delete" >/dev/null
 #----------------------------------------------------------#
 
 # Updating letsencrypt flag
-update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT' 'no'
+if [ -z "$mail"]; then
+    update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT' 'no'
+else
+    update_object_value 'mail' 'DOMAIN' "$domain" '$LETSENCRYPT' 'no'
+fi
 
 # Restarting web
 $BIN/v-restart-web $restart
 check_result $? "Web restart failed" >/dev/null
 
-# Restarting proxy
-if [ ! -z "$PROXY_SYSTEM" ]; then
-    $BIN/v-restart-web $restart >/dev/null
-    check_result $? "Proxy restart failed" >/dev/null
+if [ -z "$mail"]; then
+    # Restarting proxy
+    if [ ! -z "$PROXY_SYSTEM" ]; then
+        $BIN/v-restart-web $restart >/dev/null
+        check_result $? "Proxy restart failed" >/dev/null
+    fi
+else
+    # Restarting mail
+    $BIN/v-restart-mail $restart
+    check_result $? "Mail restart failed" >/dev/null
 fi
 
 # Logging

+ 9 - 1
bin/v-delete-mail-domain

@@ -62,6 +62,10 @@ if [ "$DKIM" = 'yes' ] && [ -e "$USER_DATA/dns/$domain.conf" ]; then
     done
 fi
 
+# Delete SSL certificates and configuration
+if [ "$SSL" = 'yes' ]; then
+    del_mail_ssl_config
+fi
 
 #----------------------------------------------------------#
 #                       Hestia                             #
@@ -77,10 +81,14 @@ rm -f $USER_DATA/mail/*@$domain.msg
 # Decreasing domain value
 decrease_user_value "$user" '$U_MAIL_DOMAINS'
 if [ "$DKIM" = 'yes' ]; then
-    decrease_user_value "$user" '$U_MAIL_DKMI'
+    decrease_user_value "$user" '$U_MAIL_DKIM'
 fi
 decrease_user_value "$user" '$U_MAIL_ACCOUNTS' "$accounts"
 
+# Restart servers
+$BIN/v-restart-web $restart
+$BIN/v-restart-proxy $restart
+
 # Logging
 log_history "deleted mail domain $domain"
 log_event "$OK" "$ARGUMENTS"

+ 68 - 0
bin/v-delete-mail-domain-ssl

@@ -0,0 +1,68 @@
+#!/bin/bash
+# info: delete mail domain ssl support
+# options: USER DOMAIN
+#
+# The function delete ssl certificates.
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Includes
+source $HESTIA/func/main.sh
+source $HESTIA/func/domain.sh
+source $HESTIA/conf/hestia.conf
+
+# Argument definition
+user=$1
+domain=$2
+
+# Additional argument formatting
+format_domain
+format_domain_idn
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+check_args '2' "$#" 'USER DOMAIN'
+is_format_valid 'user' 'domain'
+is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
+is_object_valid 'user' 'USER' "$user"
+is_object_unsuspended 'user' 'USER' "$user"
+is_object_valid 'mail' 'DOMAIN' "$domain"
+is_object_unsuspended 'mail' 'DOMAIN' "$domain"
+is_object_value_exist 'mail' 'DOMAIN' "$domain" '$SSL'
+
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+# Delete mail domain SSL configuration
+del_mail_ssl_config
+
+# Delete SSL webmail configuration
+if [ ! -z "$WEB_SYSTEM" ]; then
+    del_webmail_ssl_config
+fi
+
+#----------------------------------------------------------#
+#                       Hestia                              #
+#----------------------------------------------------------#
+
+# Updating config
+update_object_value 'mail' 'DOMAIN' "$domain" '$SSL' 'no'
+decrease_user_value "$user" '$U_MAIL_SSL'
+
+# Restarting mail server
+$BIN/v-restart-mail $restart
+service dovecot restart
+service exim4 restart
+check_result $? "Mail restart failed" >/dev/null
+
+# Logging
+log_history "disabled mail SSL support on $domain"
+log_event "$OK" "$ARGUMENTS"
+
+exit

+ 7 - 3
bin/v-delete-web-domain-ssl-force

@@ -28,6 +28,8 @@ json_list() {
         "CATCHALL": "'$CATCHALL'",
         "ACCOUNTS": "'$ACCOUNTS'",
         "U_DISK": "'$U_DISK'",
+        "SSL": "'$SSL'",
+        "LETSENCRYPT": "'$LETSENCRYPT'",
         "SUSPENDED": "'$SUSPENDED'",
         "TIME": "'$TIME'",
         "DATE": "'$DATE'"
@@ -44,6 +46,8 @@ shell_list() {
     echo "CATCHALL:       $CATCHALL"
     echo "ACCOUNTS:       $ACCOUNTS"
     echo "DISK:           $U_DISK"
+    echo "SSL:            $SSL"
+    echo "LETSENCRYPT:    $LETSENCRYPT"
     echo "SUSPENDED:      $SUSPENDED"
     echo "TIME:           $TIME"
     echo "DATE:           $DATE"
@@ -52,15 +56,15 @@ shell_list() {
 # PLAIN list function
 plain_list() {
     echo -ne "$DOMAIN\t$ANTIVIRUS\t$ANTISPAM\t$DKIM\t$CATCHALL\t"
-    echo -e "$ACCOUNTS\t$U_DISK\t$SUSPENDED\t$TIME\t$DATE"
+    echo -e "$ACCOUNTS\t$U_DISK\t$SSL\t$LETSENCRYPT\t$SUSPENDED\t$TIME\t$DATE"
 }
 
 # CSV list function
 csv_list() {
     echo -n "DOMAIN,ANTIVIRUS,ANTISPAM,DKIM,CATCHALL,ACCOUNTS,U_DISK,"
-    echo "SUSPENDED,TIME,DATE"
+    echo "SSL,LETSENCRYPT,SUSPENDED,TIME,DATE"
     echo -n "$DOMAIN,$ANTIVIRUS,$ANTISPAM,$DKIM,$CATCHALL,$ACCOUNTS,$U_DISK"
-    echo "$SUSPENDED,$TIME,$DATE"
+    echo "$SSL,$LETSENCRYPT,$SUSPENDED,$TIME,$DATE"
 }
 
 

+ 150 - 0
bin/v-list-mail-domain-ssl

@@ -0,0 +1,150 @@
+#!/bin/bash
+# info: list mail domain ssl certificate
+# options: USER DOMAIN [FORMAT]
+#
+# The function of obtaining domain ssl files.
+
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Argument definition
+user=$1
+domain=$2
+format=${3-shell}
+
+# Includes
+source $HESTIA/func/main.sh
+
+# Additional argument formatting
+format_domain
+format_domain_idn
+
+# JSON list function
+json_list() {
+    echo '{'
+    echo -e "\t\"$domain_idn\": {"
+    echo "        \"CRT\": \"$crt\","
+    echo "        \"KEY\": \"$key\","
+    echo "        \"CA\": \"$ca\","
+    echo "        \"SUBJECT\": \"$subj\","
+    echo "        \"ALIASES\": \"$alt_dns\","
+    echo "        \"NOT_BEFORE\": \"$before\","
+    echo "        \"NOT_AFTER\": \"$after\","
+    echo "        \"SIGNATURE\": \"$signature\","
+    echo "        \"PUB_KEY\": \"$pub_key\","
+    echo "        \"ISSUER\": \"$issuer\""
+    echo -e "\t}\n}"
+}
+
+# SHELL list function
+shell_list() {
+    if [ ! -z "$crt" ]; then
+        echo -e "$crt"
+    fi
+    if [ ! -z "$key" ]; then
+        echo -e "\n$key"
+    fi
+    if [ ! -z "$ca" ]; then
+        echo -e "\n$ca"
+    fi
+    if [ ! -z "$crt" ]; then
+        echo
+        echo
+        echo "SUBJECT:        $subj"
+        if [ ! -z "$alt_dns" ]; then
+            echo "ALIASES:        ${alt_dns//,/ }"
+        fi
+        echo "VALID FROM:     $before"
+        echo "VALID TIL:      $after"
+        echo "SIGNATURE:      $signature"
+        echo "PUB_KEY:        $pub_key"
+        echo "ISSUER:         $issuer"
+    fi
+}
+
+# PLAIN list function
+plain_list() {
+    if [ ! -z "$crt" ]; then
+        echo -e "$crt"
+    fi
+    if [ ! -z "$key" ]; then
+        echo -e "\n$key"
+    fi
+    if [ ! -z "$ca" ]; then
+        echo -e "\n$ca"
+    fi
+    if [ ! -z "$crt" ]; then
+        echo "$subj"
+        echo "${alt_dns//,/ }"
+        echo "$before"
+        echo "$after"
+        echo "$signature"
+        echo "$pub_key"
+        echo "$issuer"
+    fi
+
+}
+
+# CSV list function
+csv_list() {
+    echo -n "CRT,KEY,CA,SUBJECT,ALIASES,NOT_BEFORE,NOT_AFTER,SIGNATURE,"
+    echo "PUB_KEY,ISSUER"
+    echo -n "\"$crt\",\"$key\",\"$ca\",\"$subj\",\"${alt_dns//,/ }\","
+    echo "\"$before\",\"$after\",\"$signature\",\"$pub_key\",\"$issuer\""
+}
+
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+check_args '2' "$#" 'USER DOMAIN [FORMAT]'
+is_object_valid 'user' 'USER' "$user"
+is_object_valid 'mail' 'DOMAIN' "$domain_idn"
+
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+# Parsing domain SSL certificate
+if [ -e "$USER_DATA/ssl/mail.$domain.crt" ]; then
+    crt=$(cat $USER_DATA/ssl/mail.$domain.crt |sed ':a;N;$!ba;s/\n/\\n/g')
+
+    info=$(openssl x509 -text -in $USER_DATA/ssl/mail.$domain.crt)
+    subj=$(echo "$info" |grep Subject: |cut -f 2 -d =)
+    before=$(echo "$info" |grep Before: |sed -e "s/.*Before: //")
+    after=$(echo "$info" |grep "After :" |sed -e "s/.*After : //")
+    signature=$(echo "$info" |grep "Algorithm:" |head -n1 )
+    signature=$(echo "$signature"| sed -e "s/.*Algorithm: //")
+    pub_key=$(echo "$info" |grep Public-Key: |cut -f2 -d \( | tr -d \))
+    issuer=$(echo "$info" |grep Issuer: |sed -e "s/.*Issuer: //")
+    alt_dns=$(echo "$info" |grep DNS |sed -e 's/DNS:/\n/g' |tr -d ',')
+    alt_dns=$(echo "$alt_dns" |tr -d ' ' |sed -e "/^$/d")
+    alt_dns=$(echo "$alt_dns" |sed -e ':a;N;$!ba;s/\n/,/g')
+fi
+
+if [ -e "$USER_DATA/ssl/mail.$domain.key" ]; then
+    key=$(cat $USER_DATA/ssl/mail.$domain.key |sed ':a;N;$!ba;s/\n/\\n/g')
+fi
+
+if [ -e "$USER_DATA/ssl/mail.$domain.ca" ]; then
+    ca=$(cat $USER_DATA/ssl/mail.$domain.ca |sed ':a;N;$!ba;s/\n/\\n/g')
+fi
+
+# Listing data
+case $format in
+    json)   json_list ;;
+    plain)  plain_list ;;
+    csv)    csv_list ;;
+    shell)  shell_list ;;
+esac
+
+
+#----------------------------------------------------------#
+#                       Hestia                              #
+#----------------------------------------------------------#
+
+exit

+ 7 - 6
bin/v-list-mail-domains

@@ -31,6 +31,7 @@ json_list() {
         "CATCHALL": "'$CATCHALL'",
         "ACCOUNTS": "'$ACCOUNTS'",
         "U_DISK": "'$U_DISK'",
+        "SSL": "'$SSL'",
         "SUSPENDED": "'$SUSPENDED'",
         "TIME": "'$TIME'",
         "DATE": "'$DATE'"
@@ -48,11 +49,11 @@ json_list() {
 # SHELL list function
 shell_list() {
     IFS=$'\n'
-    echo "DOMAIN   ANTIVIRUS   ANTISPAM   DKIM  ACC   DISK   SPND   DATE"
-    echo "------   ---------   --------   ----  ---   ----   ---   ----"
+    echo "DOMAIN   ANTIVIRUS   ANTISPAM   DKIM  SSL   ACC   DISK   SPND   DATE"
+    echo "------   ---------   --------   ----  ---   ---   ----   ---   ----"
     while read str; do
         eval $str
-        echo -n "$DOMAIN $ANTIVIRUS $ANTISPAM $DKIM $ACCOUNTS $U_DISK "
+        echo -n "$DOMAIN $ANTIVIRUS $ANTISPAM $DKIM $SSL $ACCOUNTS $U_DISK "
         echo "$SUSPENDED $DATE"
     done < <(cat $USER_DATA/mail.conf)
 }
@@ -62,7 +63,7 @@ plain_list() {
     IFS=$'\n'
     while read str; do
         eval $str
-        echo -ne "$DOMAIN\t$ANTIVIRUS\t$ANTISPAM\t$DKIM\t$CATCHALL\t"
+        echo -ne "$DOMAIN\t$ANTIVIRUS\t$ANTISPAM\t$DKIM\t$SSL\$CATCHALL\t"
         echo -e "$ACCOUNTS\t$U_DISK\t$SUSPENDED\t$TIME\t$DATE"
     done < <(cat $USER_DATA/mail.conf)
 }
@@ -70,11 +71,11 @@ plain_list() {
 # CSV list function
 csv_list() {
     IFS=$'\n'
-    echo -n "DOMAIN,ANTIVIRUS,ANTISPAM,DKIM,CATCHALL,ACCOUNTS,U_DISK,"
+    echo -n "DOMAIN,ANTIVIRUS,ANTISPAM,DKIM,SSL,CATCHALL,ACCOUNTS,U_DISK,"
     echo "SUSPENDED,TIME,DATE"
     while read str; do
         eval $str
-        echo -n "$DOMAIN,$ANTIVIRUS,$ANTISPAM,$DKIM,$CATCHALL,$ACCOUNTS,"
+        echo -n "$DOMAIN,$ANTIVIRUS,$ANTISPAM,$DKIM,$SSL,$CATCHALL,$ACCOUNTS,"
         echo "'$U_DISK,$SUSPENDED,$TIME,$DATE"
         echo
     done < <(cat $USER_DATA/mail.conf)

+ 2 - 2
bin/v-list-sys-hestia-autoupdate

@@ -39,7 +39,7 @@ fi
 
 # Reset counters
 U_MAIL_DOMAINS=0
-U_MAIL_DKMI=0
+U_MAIL_DKIM=0
 U_MAIL_ACCOUNTS=0
 SUSPENDED_MAIL=0
 U_DISK_MAIL=0
@@ -62,7 +62,7 @@ done
 
 # Updating counters
 update_user_value "$user" '$U_MAIL_DOMAINS' "$U_MAIL_DOMAINS"
-update_user_value "$user" '$U_MAIL_DKMI' "$U_MAIL_DKMI"
+update_user_value "$user" '$U_MAIL_DKIM' "$U_MAIL_DKIM"
 update_user_value "$user" '$U_MAIL_ACCOUNTS' "$U_MAIL_ACCOUNTS"
 update_user_value "$user" '$SUSPENDED_MAIL' "$SUSPENDED_MAIL"
 update_user_value "$user" '$U_DISK_MAIL' "$U_DISK_MAIL"

+ 20 - 0
bin/v-update-letsencrypt-ssl

@@ -52,6 +52,26 @@ for user in $($BIN/v-list-users plain |cut -f 1); do
             fi
         fi
     done
+
+    for domain in $(search_objects 'mail' 'LETSENCRYPT' 'yes' 'DOMAIN'); do
+        crt_data=$(openssl x509 -text -in $USER_DATA/ssl/$domain.crt)
+        not_after=$(echo "$crt_data" |grep "Not After" |cut -f 2,3,4 -d :)
+        expiration=$(date -d "$not_after" +%s)
+        now=$(date +%s)
+        seconds_valid=$((expiration - now))
+        days_valid=$((seconds_valid / 86400))
+        if [[ "$days_valid" -lt 31 ]]; then
+            if [ $lecounter -gt 0 ]; then
+                sleep 10
+            fi
+            ((lecounter++))
+            msg=$($BIN/v-add-letsencrypt-domain $user $domain '' yes)
+            if [ $? -ne 0 ]; then
+                echo "$domain $msg"
+            fi
+        fi
+    done
+
 done
 
 #----------------------------------------------------------#

+ 73 - 0
bin/v-update-sys-hestia

@@ -570,6 +570,79 @@ is_mail_new() {
 }
 
 
+# Add mail server SSL configuration
+add_mail_ssl_config() {
+     # Ensure that SSL certificate directories exists
+    if [ ! -d $HOMEDIR/$user/conf/mail/$domain/ssl/ ]; then
+        mkdir -p $HOMEDIR/$user/conf/mail/$domain/ssl/
+    fi
+
+    if [ ! -d /usr/local/hestia/ssl/mail ]; then
+        mkdir -p /usr/local/hestia/ssl/mail
+    fi
+
+    if [ ! -d /etc/dovecot/conf.d/domains ]; then
+        mkdir -p /etc/dovecot/conf.d/domains
+    fi
+
+    # Add certificate to Hestia user configuration data directory
+    cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/mail.$domain.crt
+    cp -f $ssl_dir/$domain.key $USER_DATA/ssl/mail.$domain.key
+    cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/mail.$domain.pem
+    if [ -e "$ssl_dir/$domain.ca" ]; then
+        cp -f $ssl_dir/$domain.ca $USER_DATA/ssl/mail.$domain.ca
+        echo >> $USER_DATA/ssl/mail.$domain.pem
+        cat $USER_DATA/ssl/mail.$domain.ca >> $USER_DATA/ssl/mail.$domain.pem
+    fi
+
+    chmod 660 $USER_DATA/ssl/mail.$domain.*
+
+    # Add certificate to user home directory
+    cp -f $USER_DATA/ssl/mail.$domain.crt $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt
+    cp -f $USER_DATA/ssl/mail.$domain.key $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key
+    cp -f $USER_DATA/ssl/mail.$domain.pem $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem
+    if [ -e "$USER_DATA/ssl/mail.$domain.ca" ]; then
+        cp -f $USER_DATA/ssl/mail.$domain.ca $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.ca
+    fi
+
+    # Add domain SSL configuration to dovecot
+    if [ -f /etc/dovecot/conf.d/domains/$domain.conf ]; then
+        rm -f /etc/dovecot/conf.d/domains/$domain.conf
+    fi
+    
+    echo "" >> /etc/dovecot/conf.d/domains/$domain.conf
+    echo "local_name mail.$domain {" >> /etc/dovecot/conf.d/domains/$domain.conf
+    echo "  ssl_cert = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem" >> /etc/dovecot/conf.d/domains/$domain.conf
+    echo "  ssl_key = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key" >> /etc/dovecot/conf.d/domains/$domain.conf
+    echo "}" >> /etc/dovecot/conf.d/domains/$domain.conf
+
+    # Add domain SSL configuration to exim4
+    ln -s $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem /usr/local/hestia/ssl/mail/mail.$domain.crt
+    ln -s $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key /usr/local/hestia/ssl/mail/mail.$domain.key
+
+    # Set correct permissions on certificates
+    chmod 0644 $HOMEDIR/$user/conf/mail/$domain/ssl/*
+    chown -h $user:mail $HOMEDIR/$user/conf/mail/$domain/ssl/*
+    chmod -R 0644 /usr/local/hestia/ssl/mail/*
+    chown -h $user:mail /usr/local/hestia/ssl/mail/*
+}
+
+# Delete SSL support for mail domain
+del_mail_ssl_config() {
+    # Remove dovecot configuration
+    rm -f /etc/dovecot/conf.d/domains/mail.$domain.conf
+
+    # Remove SSL vhost configuration
+    rm -f $HOMEDIR/$user/conf/mail/$domain/*.ssl.conf
+    rm -f /etc/$WEB_SYSTEM/conf.d/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
+    rm -f /etc/$PROXY_SYSTEM/conf.d/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
+
+    # Remove SSL certificates
+    rm -f $HOMEDIR/$user/conf/mail/$domain/ssl/*
+    rm -f $USER_DATA/ssl/mail.$domain.*
+    rm -f /usr/local/hestia/ssl/mail/mail.$domain.*
+}
+
 #----------------------------------------------------------#
 #                        CMN                               #
 #----------------------------------------------------------#

+ 6 - 0
func/rebuild.sh

@@ -545,6 +545,12 @@ rebuild_mail_domain_conf() {
             chown -R dovecot:mail $HOMEDIR/$user/conf/mail/$domain/passwd
         fi
         chown $user:mail $HOMEDIR/$user/mail/$domain_idn
+        # Remove and recreate SSL configuration
+            if [ "$SSL" = 'yes' ]; then
+                mkdir -p $HOMEDIR/$user/conf/mail/$domain/ssl/
+                del_mail_ssl_config
+                add_mail_ssl_config
+            fi
     fi
 
     # Update counters

+ 4 - 0
install/deb/dovecot/conf.d/10-mail.conf

@@ -2,3 +2,7 @@ mail_privileged_group = mail
 mail_access_groups = mail
 mail_location = maildir:%h/mail/%d/%n
 pop3_uidl_format = %08Xu%08Xv
+
+mailbox_list_index = yes
+mailbox_idle_check_interval = 30 secs
+maildir_copy_with_hardlinks = yes

+ 3 - 3
install/deb/dovecot/dovecot.conf

@@ -37,8 +37,8 @@ namespace {
     }
 
     mailbox Junk {
-        special_use = \Junk
         auto = no
+        special_use = \Junk
     }
 
     mailbox Sent {
@@ -47,12 +47,12 @@ namespace {
     }
 
     mailbox "Sent Mail" {
-        special_use = \Sent
         auto = no
+        special_use = \Sent
     }
     
     mailbox "Sent Messages" {
-        special_use = \Sent
         auto = no
+        special_use = \Sent
     }
 }

+ 27 - 5
install/deb/exim/exim4.conf.template

@@ -8,7 +8,7 @@
 #SPAM_SCORE = 50
 #CLAMD = yes
 
-smtp_banner = $smtp_active_hostname \
+smtp_banner = $smtp_active_hostname
 add_environment = <; PATH=/bin:/usr/bin
 keep_environment =
 disable_ipv6 = true
@@ -34,9 +34,31 @@ spamd_address = 127.0.0.1 783
 av_scanner = clamd: /var/run/clamav/clamd.ctl
 .endif
 
+log_selector = +tls_sni
+
 tls_advertise_hosts = *
-tls_certificate = /usr/local/hestia/ssl/certificate.crt
-tls_privatekey = /usr/local/hestia/ssl/certificate.key
+
+# here we test that $tls_in_sni really is a domain, but constructing an arbitrary email address foo@...
+# and then extracting the domain with a function that should fails if the email address is not valid
+# then we looks to see that the cert exists, and use it
+# otherwise we use the default cert in /etc/ssl
+tls_certificate = \
+        ${if and {\
+                     { eq {${domain:foo@$tls_in_sni}} {$tls_in_sni}}\
+                     { exists{/usr/local/hestia/ssl/mail/$tls_in_sni.crt} }\
+                 }\
+                 {/usr/local/hestia/ssl/mail/$tls_in_sni.crt}\
+                 {/usr/local/hestia/ssl/certificate.crt}\
+         }
+
+tls_privatekey = \
+        ${if and {\
+                     { eq {${domain:foo@$tls_in_sni}} {$tls_in_sni}}\
+                     { exists{/usr/local/hestia/ssl/mail/$tls_in_sni.key} }\
+                 }\
+                 {/usr/local/hestia/ssl/mail/$tls_in_sni.key}\
+                 {/usr/local/hestia/ssl/certificate.key}\
+         }
 
 daemon_smtp_ports = 25 : 465 : 587
 tls_on_connect_ports = 465
@@ -86,7 +108,7 @@ acl_check_mail:
   deny    condition     = ${if eq{$sender_helo_name}{}}
           message       = HELO required before MAIL
 
-  drop    message       = Helo name contains a ip address (HELO was $sender_helo_name) and not is valid
+  drop    message       = Helo name contains an IP address (HELO was $sender_helo_name) and not is valid
           condition     = ${if match{$sender_helo_name}{\N((\d{1,3}[.-]\d{1,3}[.-]\d{1,3}[.-]\d{1,3})|([0-9a-f]{8})|([0-9A-F]{8}))\N}{yes}{no}}
           condition     = ${if match {${lookup dnsdb{>: defer_never,ptr=$sender_host_address}}\}{$sender_helo_name}{no}{yes}}
           delay         = 45s
@@ -303,7 +325,7 @@ begin transports
 
 remote_smtp:
   driver = smtp
-  #helo_data = $sender_address_domain
+  helo_data = mail.$sender_address_domain
   dkim_domain = DKIM_DOMAIN
   dkim_selector = mail
   dkim_private_key = DKIM_PRIVATE_KEY

+ 179 - 0
web/edit/mail/index.php

@@ -39,6 +39,25 @@ if ((!empty($_GET['domain'])) && (empty($_GET['account'])))  {
     } else {
         $v_status =  'active';
     }
+    
+    $v_ssl = $data[$v_domain]['SSL'];
+    if (!empty($v_ssl)) {
+        exec (HESTIA_CMD."v-list-mail-domain-ssl ".$user." '".$v_domain."' json", $output, $return_var);
+        $ssl_str = json_decode(implode('', $output), true);
+        unset($output);
+        $v_ssl_crt = $ssl_str[$v_domain]['CRT'];
+        $v_ssl_key = $ssl_str[$v_domain]['KEY'];
+        $v_ssl_ca = $ssl_str[$v_domain]['CA'];
+        $v_ssl_subject = $ssl_str[$v_domain]['SUBJECT'];
+        $v_ssl_aliases = $ssl_str[$v_domain]['ALIASES'];
+        $v_ssl_not_before = $ssl_str[$v_domain]['NOT_BEFORE'];
+        $v_ssl_not_after = $ssl_str[$v_domain]['NOT_AFTER'];
+        $v_ssl_signature = $ssl_str[$v_domain]['SIGNATURE'];
+        $v_ssl_pub_key = $ssl_str[$v_domain]['PUB_KEY'];
+        $v_ssl_issuer = $ssl_str[$v_domain]['ISSUER'];
+    }
+    $v_letsencrypt = $data[$v_domain]['LETSENCRYPT'];
+    if (empty($v_letsencrypt)) $v_letsencrypt = 'no';
 }
 
 // List mail account
@@ -164,6 +183,166 @@ if ((!empty($_POST['save'])) && (!empty($_GET['domain'])) && (empty($_GET['accou
         check_return_code($return_var,$output);
         unset($output);
     }
+    
+    // Change SSL certificate
+    if (( $v_letsencrypt == 'no' ) && (empty($_POST['v_letsencrypt'])) && ( $v_ssl == 'yes' ) && (!empty($_POST['v_ssl'])) && (empty($_SESSION['error_msg']))) {
+        if (( $v_ssl_crt != str_replace("\r\n", "\n",  $_POST['v_ssl_crt'])) || ( $v_ssl_key != str_replace("\r\n", "\n",  $_POST['v_ssl_key'])) || ( $v_ssl_ca != str_replace("\r\n", "\n",  $_POST['v_ssl_ca']))) {
+            exec ('mktemp -d', $mktemp_output, $return_var);
+            $tmpdir = $mktemp_output[0];
+
+            // Certificate
+            if (!empty($_POST['v_ssl_crt'])) {
+                $fp = fopen($tmpdir."/".$_POST['v_domain'].".crt", 'w');
+                fwrite($fp, str_replace("\r\n", "\n",  $_POST['v_ssl_crt']));
+                fwrite($fp, "\n");
+                fclose($fp);
+            }
+
+            // Key
+            if (!empty($_POST['v_ssl_key'])) {
+                $fp = fopen($tmpdir."/".$_POST['v_domain'].".key", 'w');
+                fwrite($fp, str_replace("\r\n", "\n", $_POST['v_ssl_key']));
+                fwrite($fp, "\n");
+                fclose($fp);
+            }
+
+            // CA
+            if (!empty($_POST['v_ssl_ca'])) {
+                $fp = fopen($tmpdir."/".$_POST['v_domain'].".ca", 'w');
+                fwrite($fp, str_replace("\r\n", "\n", $_POST['v_ssl_ca']));
+                fwrite($fp, "\n");
+                fclose($fp);
+            }
+
+            exec (HESTIA_CMD."v-change-mail-domain-sslcert ".$user." ".$v_domain." ".$tmpdir." 'no'", $output, $return_var);
+            check_return_code($return_var,$output);
+            unset($output);
+            $restart_web = 'yes';
+            $restart_proxy = 'yes';
+
+            exec (HESTIA_CMD."v-list-mail-domain-ssl ".$user." '".$v_domain."' json", $output, $return_var);
+            $ssl_str = json_decode(implode('', $output), true);
+            unset($output);
+            $v_ssl_crt = $ssl_str[$v_domain]['CRT'];
+            $v_ssl_key = $ssl_str[$v_domain]['KEY'];
+            $v_ssl_ca = $ssl_str[$v_domain]['CA'];
+            $v_ssl_subject = $ssl_str[$v_domain]['SUBJECT'];
+            $v_ssl_aliases = $ssl_str[$v_domain]['ALIASES'];
+            $v_ssl_not_before = $ssl_str[$v_domain]['NOT_BEFORE'];
+            $v_ssl_not_after = $ssl_str[$v_domain]['NOT_AFTER'];
+            $v_ssl_signature = $ssl_str[$v_domain]['SIGNATURE'];
+            $v_ssl_pub_key = $ssl_str[$v_domain]['PUB_KEY'];
+            $v_ssl_issuer = $ssl_str[$v_domain]['ISSUER'];
+
+            // Cleanup certificate tempfiles
+            if (!empty($_POST['v_ssl_crt'])) unlink($tmpdir."/".$_POST['v_domain'].".crt");
+            if (!empty($_POST['v_ssl_key'])) unlink($tmpdir."/".$_POST['v_domain'].".key");
+            if (!empty($_POST['v_ssl_ca']))  unlink($tmpdir."/".$_POST['v_domain'].".ca");
+            rmdir($tmpdir);
+        }
+    }
+
+    // Delete Lets Encrypt support
+    if (( $v_letsencrypt == 'yes' ) && (empty($_POST['v_letsencrypt'])) && (empty($_SESSION['error_msg']))) {
+        exec (HESTIA_CMD."v-delete-letsencrypt-domain ".$user." ".$v_domain." 'no' 'yes'", $output, $return_var);
+        check_return_code($return_var,$output);
+        unset($output);
+        $v_ssl_crt = '';
+        $v_ssl_key = '';
+        $v_ssl_ca = '';
+        $v_letsencrypt = 'no';
+        $v_letsencrypt_deleted = 'yes';
+        $v_ssl = 'no';
+        $restart_mail = 'yes';
+    }
+
+    // Delete SSL certificate
+    if (( $v_ssl == 'yes' ) && (empty($_POST['v_ssl'])) && (empty($_SESSION['error_msg']))) {
+        exec (HESTIA_CMD."v-delete-mail-domain-ssl ".$v_username." ".$v_domain, $output, $return_var);
+        check_return_code($return_var,$output);
+        unset($output);
+        $v_ssl_crt = '';
+        $v_ssl_key = '';
+        $v_ssl_ca = '';
+        $v_ssl = 'no';
+        $restart_mail = 'yes';
+    }
+
+    // Add Lets Encrypt support
+    if ((!empty($_POST['v_ssl'])) && ( $v_letsencrypt == 'no' ) && (!empty($_POST['v_letsencrypt'])) && empty($_SESSION['error_msg'])) {
+        exec (HESTIA_CMD."v-add-letsencrypt-domain ".$user." ".$v_domain." ' ' 'yes'", $output, $return_var);
+        check_return_code($return_var,$output);
+        unset($output);
+        $v_letsencrypt = 'yes';
+        $v_ssl = 'yes';
+        $restart_mail = 'yes';
+     }
+
+     // Add SSL certificate
+     if (( $v_ssl == 'no' ) && (!empty($_POST['v_ssl']))  && (empty($v_letsencrypt_deleted)) && (empty($_SESSION['error_msg']))) {
+        if (empty($_POST['v_ssl_crt'])) $errors[] = 'ssl certificate';
+        if (empty($_POST['v_ssl_key'])) $errors[] = 'ssl key';
+        if (!empty($errors[0])) {
+            foreach ($errors as $i => $error) {
+                if ( $i == 0 ) {
+                    $error_msg = $error;
+                } else {
+                    $error_msg = $error_msg.", ".$error;
+                }
+            }
+            $_SESSION['error_msg'] = __('Field "%s" can not be blank.',$error_msg);
+        } else {
+            exec ('mktemp -d', $mktemp_output, $return_var);
+            $tmpdir = $mktemp_output[0];
+
+            // Certificate
+            if (!empty($_POST['v_ssl_crt'])) {
+                $fp = fopen($tmpdir."/".$_POST['v_domain'].".crt", 'w');
+                fwrite($fp, str_replace("\r\n", "\n", $_POST['v_ssl_crt']));
+                fclose($fp);
+            }
+
+            // Key
+            if (!empty($_POST['v_ssl_key'])) {
+                $fp = fopen($tmpdir."/".$_POST['v_domain'].".key", 'w');
+                fwrite($fp, str_replace("\r\n", "\n", $_POST['v_ssl_key']));
+                fclose($fp);
+            }
+
+            // CA
+            if (!empty($_POST['v_ssl_ca'])) {
+                $fp = fopen($tmpdir."/".$_POST['v_domain'].".ca", 'w');
+                fwrite($fp, str_replace("\r\n", "\n", $_POST['v_ssl_ca']));
+                fclose($fp);
+            }
+            exec (HESTIA_CMD."v-add-mail-domain-ssl ".$user." ".$v_domain." ".$tmpdir." 'no'", $output, $return_var);
+            check_return_code($return_var,$output);
+            unset($output);
+            $v_ssl = 'yes';
+            $restart_web = 'yes';
+            $restart_proxy = 'yes';
+
+            exec (HESTIA_CMD."v-list-mail-domain-ssl ".$user." '".$v_domain."' json", $output, $return_var);
+            $ssl_str = json_decode(implode('', $output), true);
+            unset($output);
+            $v_ssl_crt = $ssl_str[$_POST['v_domain']]['CRT'];
+            $v_ssl_key = $ssl_str[$_POST['v_domain']]['KEY'];
+            $v_ssl_ca = $ssl_str[$_POST['v_domain']]['CA'];
+            $v_ssl_subject = $ssl_str[$_POST['v_domain']]['SUBJECT'];
+            $v_ssl_aliases = $ssl_str[$_POST['v_domain']]['ALIASES'];
+            $v_ssl_not_before = $ssl_str[$_POST['v_domain']]['NOT_BEFORE'];
+            $v_ssl_not_after = $ssl_str[$_POST['v_domain']]['NOT_AFTER'];
+            $v_ssl_signature = $ssl_str[$_POST['v_domain']]['SIGNATURE'];
+            $v_ssl_pub_key = $ssl_str[$_POST['v_domain']]['PUB_KEY'];
+            $v_ssl_issuer = $ssl_str[$_POST['v_domain']]['ISSUER'];
+
+            // Cleanup certificate tempfiles
+            if (!empty($_POST['v_ssl_crt'])) unlink($tmpdir."/".$_POST['v_domain'].".crt");
+            if (!empty($_POST['v_ssl_key'])) unlink($tmpdir."/".$_POST['v_domain'].".key");
+            if (!empty($_POST['v_ssl_ca'])) unlink($tmpdir."/".$_POST['v_domain'].".ca");
+            rmdir($tmpdir);
+        }
+    }
 
     // Set success message
     if (empty($_SESSION['error_msg'])) {

+ 115 - 0
web/templates/admin/edit_mail.html

@@ -81,6 +81,121 @@
                                     <label><input type="checkbox" size="20" class="vst-checkbox" name="v_dkim" <?php if ($v_dkim == 'yes') echo "checked=yes"; ?>> <?php print __('DKIM Support');?></label>
                                 </td>
                             </tr>
+                            <tr>
+                                <td class="vst-text step-top">
+                                    <label><input type="checkbox" size="20" class="vst-checkbox" name="v_ssl" <?php if ($v_ssl == 'yes') echo "checked=yes" ?> onclick="javascript:elementHideShow('ssltable');"> <?php print __('SSL Support');?></label>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class="step-left">
+                                    <table style="display:<?php if ($v_ssl == 'no' ) { echo 'none';} else {echo 'block';}?> ;" id="ssltable">
+                                        <tr>
+                                            <td class="input-label vst-text">
+                                                <label><input type="checkbox" size="20" class="vst-checkbox" name="v_letsencrypt" <?php if($v_letsencrypt == 'yes' || $v_letencrypt == 'on') echo "checked=yes" ?> onclick="App.Actions.WEB.toggle_letsencrypt(this)"> <?php print __('Lets Encrypt Support');?></label>
+                                            </td>
+                                        </tr>
+                                      
+                                        <tr>
+                                            <td class="vst-text input-label">
+                                                <?php print __('SSL Certificate');?>
+                                                <span id="generate-csr"> / <a class="generate" target="_blank" href="/generate/ssl/?domain=<?=$v_domain?>"><?=__('Generate CSR')?></a></span>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td>
+                                                <textarea size="20" class="vst-textinput" name="v_ssl_crt"><?=htmlentities(trim($v_ssl_crt, "'"))?></textarea>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="vst-text input-label">
+                                                <?php print __('SSL Key');?>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td>
+                                                <textarea size="20" class="vst-textinput" name="v_ssl_key"><?=htmlentities(trim($v_ssl_key, "'"))?></textarea>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="vst-text input-label">
+                                                <?php print __('SSL Certificate Authority / Intermediate');?> <span class="optional">(<?php print __('optional');?>)</span>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td>
+                                                <textarea size="20" class="vst-textinput" name="v_ssl_ca"><?=htmlentities(trim($v_ssl_ca, "'"))?></textarea>
+                                            </td>
+                                        </tr>
+                                        <?
+                                        if ($v_ssl != 'no' ) { ?>
+                                            <tr>
+                                                <td>
+                                                    <table class="additional-info">
+                                                        <tr>
+                                                            <td>
+                                                                <?=__('SUBJECT')?>:
+                                                            </td>
+                                                            <td class="details">
+                                                                <?=$v_ssl_subject?>
+                                                            </td>
+                                                        </tr>
+                                                        <? if($v_ssl_aliases){?>
+                                                            <tr>
+                                                                <td>
+                                                                    <?=__('ALIASES')?>:
+                                                                </td>
+                                                                <td class="details">
+                                                                    <?=$v_ssl_aliases?>
+                                                                </td>
+                                                            </tr>
+                                                        <? } ?>
+                                                        <tr>
+                                                            <td>
+                                                                <?=__('NOT_BEFORE')?>:
+                                                            </td>
+                                                            <td class="details">
+                                                                <?=$v_ssl_not_before?>
+                                                            </td>
+                                                        </tr>
+                                                        <tr>
+                                                            <td>
+                                                                <?=__('NOT_AFTER')?>:
+                                                            </td>
+                                                            <td class="details">
+                                                                <?=$v_ssl_not_after?>
+                                                            </td>
+                                                        </tr>
+                                                        <tr>
+                                                            <td>
+                                                                <?=__('SIGNATURE')?>:
+                                                            </td>
+                                                            <td class="details">
+                                                                <?=$v_ssl_signature?>
+                                                            </td>
+                                                        </tr>
+                                                        <tr>
+                                                            <td>
+                                                                <?=__('PUB_KEY')?>:
+                                                            </td>
+                                                            <td class="details">
+                                                                <?=$v_ssl_pub_key?>
+                                                            </td>
+                                                        </tr>
+                                                        <tr>
+                                                            <td>
+                                                                <?=__('ISSUER')?>
+                                                            </td>
+                                                            <td class="details">
+                                                                <?=$v_ssl_issuer?>
+                                                            </td>
+                                                        </tr>
+                                                    </table>
+                                                </td>
+                                            </tr>
+                                        <? } // if ssl is enabled ?>
+                                    </table>
+                                </td>
+                            </tr>
                         </table>
                         <table class="data-col2">
                             <tr>

+ 1 - 1
web/templates/admin/edit_mail_acc.html

@@ -205,7 +205,7 @@
                         </tr>
                         <?
                             list($http_host, $port) = explode(':', $_SERVER["HTTP_HOST"].":");
-                            $webmail = "http://".$http_host."/webmail/";
+                            $webmail = "http://mail.".$http_host."/";
                             if (!empty($_SESSION['MAIL_URL'])) $webmail = $_SESSION['MAIL_URL'];
                         ?>
                         <tr>

+ 26 - 8
web/templates/admin/list_mail.html

@@ -14,7 +14,7 @@
               <td class="step-right">
                 <?
                   list($http_host, $port) = explode(':', $_SERVER["HTTP_HOST"].":");
-                  $webmail = "http://".$http_host."/webmail/";
+                  $webmail = "http://mail.".$http_host."/";
                   if (!empty($_SESSION['MAIL_URL'])) $webmail = $_SESSION['MAIL_URL'];
                 ?>
                 <a class="vst" href="<?=$webmail?>" target="_blank"><?=__('open webmail')?> <i></i></a>
@@ -67,19 +67,21 @@
           
                 <div class="l-unit__col l-unit__col--right step-top table-header">
                   <div style="margin-bottom: 40px;">
-                      <div class="clearfix l-unit__stat-col--left wide-3"><b><?php print __('Domain');?></b></div>
-                      <div class="clearfix l-unit__stat-col--left text-center"><b><?php print __('Accounts');?></b></div>
-                      <div class="clearfix l-unit__stat-col--left text-center"><b><?php print __('Disk');?></b></div>
+                      <div class="clearfix l-unit__stat-col--left wide-2"><b><?php print __('Domain');?></b></div>
+                      <div class="clearfix l-unit__stat-col--left text-center compact"><b><?php print __('Accounts');?></b></div>
+                      <div class="clearfix l-unit__stat-col--left text-center compact"><b><?php print __('Disk');?></b></div>
+                      <div class="clearfix l-unit__stat-col--left text-center compact-3"><b><?php print __('Webmail');?></b></div>
                       <div class="clearfix l-unit__stat-col--left text-center compact-3"><b><?php print __('Antivirus');?></b></div>
                       <div class="clearfix l-unit__stat-col--left text-center compact-3"><b><?php print __('AntiSpam');?></b></div>
                       <div class="clearfix l-unit__stat-col--left text-center compact-3"><b><?php print __('DKIM');?></b></div>
+                      <div class="clearfix l-unit__stat-col--left text-center compact-3"><b><?php print __('SSL');?></b></div>
                   </div>
                 </div>
               </div>
 
       <?
         list($http_host, $port) = explode(':', $_SERVER["HTTP_HOST"].":");
-        $webmail = "http://".$http_host."/webmail/";
+        $webmail = "http://mail.".$http_host."/";
         if (!empty($_SESSION['MAIL_URL'])) $webmail = $_SESSION['MAIL_URL'];
 
         foreach ($data as $key => $value) {
@@ -144,17 +146,25 @@ sort-accounts="<?=$data[$key]['ACCOUNTS']?>" sort-star="<? if($_SESSION['favouri
                       <input id="check<?php echo $i ?>" class="ch-toggle" type="checkbox" name="domain[]" value="<?php echo $key ?>">
                       <label for="check<?php echo $i ?>" class="check-label"></label>
                     </div>
-                  <div class="clearfix l-unit__stat-col--left wide-3"><b><?=$key?></b></div>
-                  <div class="clearfix l-unit__stat-col--left text-center"><b>
+                  <div class="clearfix l-unit__stat-col--left wide-2"><b><?=$key?></b></div>
+                  <div class="clearfix l-unit__stat-col--left text-center compact"><b>
                     <? if($data[$key]['ACCOUNTS']) { echo '<span>'.$data[$key]['ACCOUNTS'].'</span>'; ?>
                     <? } else {?>
                       <span>0</span>
                     <? } ?>
                     </b>
                   </div>
-                  <div class="clearfix l-unit__stat-col--left text-center"><b>
+                  <div class="clearfix l-unit__stat-col--left text-center compact"><b>
                     <?=humanize_usage_size($data[$key]['U_DISK'])?></b> <span class="text-small"><?=humanize_usage_measure($data[$key]['U_DISK'])?></span>
                   </div>
+                  <div class="clearfix l-unit__stat-col--left text-center compact-3"><b>
+                    <? if($data[$key]['WEBMAIL'] == 'no'){ ?>
+                      <i class="fas fa-minus-circle"></i>
+                    <? } else {?>
+                      <i class="fas fa-check-circle status-icon-green"></i>
+                    <? } ?>
+                  </b>
+                 </div>
                   <div class="clearfix l-unit__stat-col--left text-center compact-3"><b>
                       <? if($data[$key]['ANTIVIRUS'] == 'no'){ ?>
                         <i class="fas fa-times-circle" style="color: red;"></i>
@@ -179,6 +189,14 @@ sort-accounts="<?=$data[$key]['ACCOUNTS']?>" sort-star="<? if($_SESSION['favouri
                       <? } ?>
                     </b>
                   </div>
+                  <div class="clearfix l-unit__stat-col--left text-center compact-3"><b>
+                      <? if($data[$key]['SSL'] == 'no'){ ?>
+                        <i class="fas fa-times-circle" style="color: red;"></i>
+                      <? } else {?>
+                        <i class="fas fa-check-circle status-icon-green"></i>
+                      <? } ?>
+                    </b>
+                  </div>
               </div>
             </div>
         <!-- /.l-unit__col -->

+ 3 - 0
web/templates/admin/list_mail_acc.html

@@ -56,6 +56,9 @@
     <div class="l-separator"></div>
     <!-- /.l-separator -->
     <div class="l-center units animated fadeIn">
+        <div class="l-unit header">
+            <div class="subtitle"><?=__('Listing')?>  <?=htmlentities($_GET['domain'])?></div>
+        </div>
         <div class="l-unit header">
             <div class="l-unit__col l-unit__col--left clearfix">
               <div class="text-center jump-small-top"></div>