├── .gitignore ├── resources └── easymail-logo.png ├── nginx └── install.sh ├── autostart ├── install.sh └── run.sh ├── tests ├── config.php ├── install.sh ├── imap_integration_test.php ├── pop3_integration_test.php └── smtp_integration_test.php ├── roundcube ├── password_plugin_config ├── nginx_config ├── config └── install.sh ├── exportDb.sh ├── autoconfig ├── install.sh ├── autoconfig.php ├── nginx_config └── autodiscover.php ├── importDb.sh ├── LICENSE ├── mysql └── install.sh ├── dkim └── install.sh ├── README.md ├── spamassassin └── install.sh ├── install.sh ├── dovecot ├── 10-master.conf └── install.sh ├── postfix └── install.sh ├── .travis.yml └── post_install.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /.* 2 | !.gitignore -------------------------------------------------------------------------------- /resources/easymail-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runeasymail/easymail/HEAD/resources/easymail-logo.png -------------------------------------------------------------------------------- /nginx/install.sh: -------------------------------------------------------------------------------- 1 | # Install Nginx 2 | set -e 3 | 4 | apt-get update -y 5 | apt-get install nginx -y 6 | 7 | rm -r /etc/nginx/sites-enabled/* 8 | -------------------------------------------------------------------------------- /autostart/install.sh: -------------------------------------------------------------------------------- 1 | # Set up the bash script for autostarting the services in case of reboot 2 | set -e 3 | 4 | AUTOSTART_DIR="$CURRENT_DIR/autostart" 5 | 6 | cp $AUTOSTART_DIR/run.sh /run.sh 7 | chmod +x /run.sh 8 | -------------------------------------------------------------------------------- /autostart/run.sh: -------------------------------------------------------------------------------- 1 | service mysql start 2 | service nginx start 3 | service php7.0-fpm start 4 | service postfix start 5 | service dovecot start 6 | service spamassassin start 7 | service opendkim start 8 | service cron start 9 | service syslog-ng start & 10 | -------------------------------------------------------------------------------- /tests/config.php: -------------------------------------------------------------------------------- 1 | /opt/easymail/data/mysql/db.sql 10 | -------------------------------------------------------------------------------- /autoconfig/install.sh: -------------------------------------------------------------------------------- 1 | # Install autoconfig and autodiscover 2 | set -e 3 | 4 | AUTOCONFIG_DIR="$CURRENT_DIR/autoconfig" 5 | 6 | mkdir /usr/share/nginx/autoconfig_and_autodiscover 7 | 8 | cp $AUTOCONFIG_DIR/autoconfig.php /usr/share/nginx/autoconfig_and_autodiscover/ 9 | cp $AUTOCONFIG_DIR/autodiscover.php /usr/share/nginx/autoconfig_and_autodiscover/ 10 | cp $AUTOCONFIG_DIR/nginx_config /etc/nginx/sites-enabled/autoconfig_and_autodiscover 11 | 12 | sed -i "s#__EASYMAIL_SSL_CA_BUNDLE_FILE__#$SSL_CA_BUNDLE_FILE#g" /etc/nginx/sites-enabled/autoconfig_and_autodiscover 13 | sed -i "s#__EASYMAIL_SSL_PRIVATE_KEY_FILE__#$SSL_PRIVATE_KEY_FILE#g" /etc/nginx/sites-enabled/autoconfig_and_autodiscover 14 | 15 | service nginx reload 16 | -------------------------------------------------------------------------------- /importDb.sh: -------------------------------------------------------------------------------- 1 | export EASYMAIL_CONFIG="/opt/easymail/config.ini" 2 | 3 | export DATABASE=$(cat "$EASYMAIL_CONFIG" | grep mysql_easymail_database: | awk -F':' '{ print $2;}') 4 | export DATABASE2=$(cat "$EASYMAIL_CONFIG" | grep mysql_roundcube_database: | awk -F':' '{ print $2;}') 5 | 6 | export USERNAME=$(cat "$EASYMAIL_CONFIG" | grep mysql_root_username: | awk -F':' '{ print $2;}') 7 | export PASSWORD=$(cat "$EASYMAIL_CONFIG" | grep mysql_root_password: | awk -F':' '{ print $2;}') 8 | 9 | mysql -u$USERNAME -p$PASSWORD -e "DROP DATABASE IF EXISTS $DATABASE; CREATE DATABASE $DATABASE;" 10 | mysql -u$USERNAME -p$PASSWORD -e "DROP DATABASE IF EXISTS $DATABASE2; CREATE DATABASE $DATABASE2;" 11 | mysql -u$USERNAME -p$PASSWORD < /opt/easymail/data/mysql/db.sql 12 | -------------------------------------------------------------------------------- /autoconfig/autoconfig.php: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | {$domain} 14 | {$mail} 15 | {$mail} 16 | 17 | {$host} 18 | 143 19 | STARTTLS 20 | {$mail} 21 | password-cleartext 22 | 23 | 24 | {$host} 25 | 587 26 | STARTTLS 27 | password-cleartext 28 | {$mail} 29 | 30 | 31 | 32 | EOP; 33 | 34 | 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Gyuner Zeki and Pavel Tashev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /roundcube/nginx_config: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name __EASYMAIL_HOSTNAME__; 4 | 5 | location /.well-known/acme-challenge/ { 6 | alias /var/www/challenges/; 7 | try_files $uri =404; 8 | } 9 | 10 | location / { 11 | rewrite ^ https://$host$request_uri; 12 | } 13 | } 14 | 15 | server { 16 | listen 443; 17 | server_name __EASYMAIL_HOSTNAME__; 18 | 19 | ssl on; 20 | ssl_certificate __EASYMAIL_SSL_CA_BUNDLE_FILE__; 21 | ssl_certificate_key __EASYMAIL_SSL_PRIVATE_KEY_FILE__; 22 | ssl_session_timeout 5m; 23 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # don't use SSLv3 ref: POODLE 24 | ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES"; 25 | ssl_prefer_server_ciphers on; 26 | 27 | client_max_body_size 16M; 28 | 29 | # __EASY_MAIL_INCLUDE__ 30 | 31 | root /usr/share/nginx/roundcubemail; 32 | index index.php index.html index.htm; 33 | error_log /var/log/nginx/error.log; 34 | 35 | location / { 36 | try_files $uri $uri/ =404; 37 | } 38 | 39 | location ~ \.php$ { 40 | try_files $uri =404; 41 | fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; 42 | fastcgi_index index.php; 43 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 44 | include fastcgi_params; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /mysql/install.sh: -------------------------------------------------------------------------------- 1 | # Install MySQL 2 | set -e 3 | 4 | export DEBIAN_FRONTEND=noninteractive 5 | 6 | debconf-set-selections <<< "mysql-community-server mysql-community-server/data-dir select ''" 7 | #debconf-set-selections <<< "mysql-community-server mysql-community-server/root-pass password ${ROOT_MYSQL_PASSWORD}" 8 | #debconf-set-selections <<< "mysql-community-server mysql-community-server/re-root-pass password ${ROOT_MYSQL_PASSWORD}" 9 | 10 | apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys 5072E1F5 11 | echo "deb http://repo.mysql.com/apt/ubuntu/ trusty mysql-5.7" | tee -a /etc/apt/sources.list.d/mysql.list 12 | apt-get update -y && apt-get install mysql-server expect -y 13 | update-alternatives --remove my.cnf /etc/mysql/my.cnf.migrated 14 | service mysql start 15 | 16 | expect -c " 17 | set timeout 10 18 | spawn mysql_secure_installation 19 | 20 | expect \"Press y|Y for Yes, any other key for No:\" 21 | send \"n\r\" 22 | 23 | expect \"New password:\" 24 | send \"$ROOT_MYSQL_PASSWORD\r\" 25 | 26 | expect \"Re-enter new password:\" 27 | send \"$ROOT_MYSQL_PASSWORD\r\" 28 | 29 | expect \"Remove anonymous users? (Press y|Y for Yes, any other key for No) :\" 30 | send \"y\r\" 31 | 32 | expect \"Disallow root login remotely? (Press y|Y for Yes, any other key for No) :\" 33 | send \"n\r\" 34 | 35 | expect \"Remove test database and access to it? (Press y|Y for Yes, any other key for No) :\" 36 | send \"y\r\" 37 | 38 | expect \"Reload privilege tables now? (Press y|Y for Yes, any other key for No) :\" 39 | send \"y\r\" 40 | 41 | expect eof" 42 | -------------------------------------------------------------------------------- /tests/imap_integration_test.php: -------------------------------------------------------------------------------- 1 | array( 17 | 'verify_peer' => false, 18 | 'verfify_peer_name' => false, 19 | ) 20 | ); 21 | 22 | // SMTP 23 | $config['smtp_server'] = 'tls://127.0.0.1'; 24 | $config['smtp_port'] = 587; 25 | $config['smtp_user'] = '%u'; 26 | $config['smtp_pass'] = '%p'; 27 | $config['smtp_auth_type'] = 'LOGIN'; 28 | $config['smtp_conn_options'] = array( 29 | 'ssl' => array( 30 | 'verify_peer' => false, 31 | 'verify_peer_name' => false, 32 | ) 33 | ); 34 | 35 | // SYSTEM 36 | $config['force_https'] = true; 37 | $config['login_autocomplete'] = 2; 38 | $config['ip_check'] = true; 39 | $config['des_key'] = 'YAk0uOQ99JjmDrSdAGrr6Xrs'; 40 | $config['useragent'] = 'Roundcube Webmail'; 41 | $config['identities_level'] = 3; 42 | $config['mime_types'] = '/etc/mime.types'; 43 | 44 | // USER INTERFACE 45 | $config['create_default_folders'] = true; 46 | $config['quota_zero_as_unlimited'] = true; 47 | 48 | // USER PREFERENCES 49 | $config['default_charset'] = 'UTF-8'; 50 | $config['draft_autosave'] = 60; 51 | $config['preview_pane'] = true; 52 | $config['autoexpand_threads'] = 2; 53 | $config['check_all_folders'] = true; 54 | 55 | // PLUGINS 56 | $config['plugins'] = array('password','jqueryui','managesieve'); 57 | -------------------------------------------------------------------------------- /autoconfig/nginx_config: -------------------------------------------------------------------------------- 1 | server { 2 | listen 443; 3 | server_name autoconfig.* autodiscover.*; 4 | 5 | root /usr/share/nginx/autoconfig_and_autodiscover; 6 | index index.php index.html index.htm; 7 | error_log /var/log/nginx/error.log; 8 | 9 | ssl on; 10 | ssl_certificate __EASYMAIL_SSL_CA_BUNDLE_FILE__; 11 | ssl_certificate_key __EASYMAIL_SSL_PRIVATE_KEY_FILE__; 12 | ssl_session_timeout 5m; 13 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # don't use SSLv3 ref: POODLE 14 | ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES"; 15 | ssl_prefer_server_ciphers on; 16 | 17 | location /mail/config-v1.1.xml { 18 | try_files $uri /autoconfig.php?$args; 19 | rewrite ^(.+)$ /autoconfig.php?$1 last; 20 | } 21 | 22 | location /autodiscover/autodiscover.xml { 23 | try_files $uri /autodiscover.php?$args; 24 | rewrite ^(.+)$ /autodiscover.php?$1 last; 25 | } 26 | 27 | location ~ \.php$ { 28 | try_files $uri =404; 29 | fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; 30 | fastcgi_index index.php; 31 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 32 | include fastcgi_params; 33 | } 34 | } 35 | 36 | server { 37 | listen 80; 38 | server_name autoconfig.* autodiscover.*; 39 | 40 | root /usr/share/nginx/autoconfig_and_autodiscover; 41 | index index.php index.html index.htm; 42 | error_log /var/log/nginx/error.log; 43 | 44 | location /mail/config-v1.1.xml { 45 | try_files $uri /autoconfig.php?$args; 46 | rewrite ^(.+)$ /autoconfig.php?$1 last; 47 | } 48 | 49 | location /autodiscover/autodiscover.xml { 50 | try_files $uri /autodiscover.php?$args; 51 | rewrite ^(.+)$ /autodiscover.php?$1 last; 52 | } 53 | 54 | location ~ \.php$ { 55 | try_files $uri =404; 56 | fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; 57 | fastcgi_index index.php; 58 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 59 | include fastcgi_params; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /dkim/install.sh: -------------------------------------------------------------------------------- 1 | # Install DKIM 2 | set -e 3 | 4 | apt-get install opendkim opendkim-tools -y 5 | 6 | echo " 7 | AutoRestart Yes 8 | AutoRestartRate 10/1h 9 | UMask 002 10 | Syslog yes 11 | SyslogSuccess Yes 12 | LogWhy Yes 13 | 14 | Canonicalization relaxed/simple 15 | 16 | ExternalIgnoreList refile:/etc/opendkim/TrustedHosts 17 | InternalHosts refile:/etc/opendkim/TrustedHosts 18 | KeyTable dsn:mysql://$MYSQL_USERNAME:$MYSQL_PASSWORD@$MYSQL_HOSTNAME/$MYSQL_DATABASE/table=dkim?keycol=id?datacol=domain_name,selector,private_key 19 | SigningTable dsn:mysql://$MYSQL_USERNAME:$MYSQL_PASSWORD@$MYSQL_HOSTNAME/$MYSQL_DATABASE/table=dkim?keycol=domain_name?datacol=id 20 | 21 | 22 | Mode sv 23 | PidFile /var/run/opendkim/opendkim.pid 24 | SignatureAlgorithm rsa-sha256 25 | 26 | UserID opendkim:opendkim 27 | 28 | Socket inet:12301@localhost 29 | 30 | RequireSafeKeys false 31 | 32 | Selector mail 33 | 34 | " > /etc/opendkim.conf 35 | 36 | echo 'SOCKET="inet:12301@localhost"' > /etc/default/opendkim 37 | 38 | echo " 39 | milter_protocol = 2 40 | milter_default_action = accept 41 | smtpd_milters = unix:/spamass/spamass.sock, inet:localhost:12301 42 | non_smtpd_milters = unix:/spamass/spamass.sock, inet:localhost:12301 43 | " >> /etc/postfix/main.cf 44 | 45 | mkdir /etc/opendkim -p 46 | touch /etc/opendkim/TrustedHosts 47 | 48 | wget http://mirrors.kernel.org/ubuntu/pool/universe/libo/libopendbx/libopendbx1-mysql_1.4.6-9build1_amd64.deb 49 | dpkg -i libopendbx1-mysql_1.4.6-9build1_amd64.deb 50 | 51 | mysql -u$ROOT_MYSQL_USERNAME -p$ROOT_MYSQL_PASSWORD << EOF 52 | USE $MYSQL_DATABASE; 53 | CREATE TABLE IF NOT EXISTS dkim ( 54 | id int(11) NOT NULL AUTO_INCREMENT, 55 | domain_name varchar(50) NOT NULL, 56 | selector varchar(50) NOT NULL, 57 | private_key text NOT NULL, 58 | public_key text NOT NULL, 59 | PRIMARY KEY (id) 60 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 61 | EOF 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | Build Status 5 | Last stable version 6 | License 7 |

8 | 9 | # Easy way to install 10 | ``` 11 | export E="yourdomain.com" && wget -qO- http://easy.supersecure.email/get | sh 12 | ``` 13 | 14 | ## About EasyMail 15 | EasyMail is an open-sourced software which will help you to build your own mail server. 16 | 17 | It is accessible and powerful tool which can be used for your personal projects and as a mail server in your company (SMTP server solution). 18 | 19 | ## Learn EasyMail 20 | More detail information can be found on the website [easy.supersecure.email](http://easy.supersecure.email/). 21 | 22 | For the installation instructions, please read [the documentation of EasyMail](http://easy.supersecure.email/master/installation). 23 | 24 | # Easy upgrade to the latest (still beta use with care) 25 | ``` 26 | wget -qO- http://easy.supersecure.email/upgrade | sh 27 | ``` 28 | 29 | ## Contributing 30 | Thank you for considering contributing to EasyMail! The contribution guide can be found in the [EasyMail documentation](http://easy.supersecure.email/master/contribution-guide). 31 | 32 | Every individual, company or organization who uses and likes EasyMail can support it by providing their names, logos and other initials in order to be used on the website, the Github repository and advertisement materials whose purpose is to popularize EasyMail. 33 | 34 | ## License 35 | EasyMail is open-sourced software licensed under the [MIT license](https://github.com/runeasymail/easymail/blob/master/LICENSE). 36 | -------------------------------------------------------------------------------- /autoconfig/autodiscover.php: -------------------------------------------------------------------------------- 1 | (.*?)\<\/EMailAddress\>/", $data, $matches); 5 | //set Content-Type 6 | header("Content-Type: application/xml"); 7 | $host = '__EASYMAIL_HOSTNAME__'; 8 | 9 | echo ''; ?> 10 | 11 | 12 | 13 | 14 | email 15 | settings 16 | 17 | IMAP 18 | 19 | 993 20 | off 21 | 22 | off 23 | on 24 | on 25 | 26 | 27 | POP3 28 | 29 | 995 30 | off 31 | 32 | off 33 | on 34 | on 35 | 36 | 37 | SMTP 38 | 39 | 587 40 | off 41 | 42 | off 43 | on 44 | off 45 | off 46 | TLS 47 | on 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /spamassassin/install.sh: -------------------------------------------------------------------------------- 1 | # Install SpamAssassin 2 | set -e 3 | 4 | apt-get install spamassassin spamc -y 5 | groupadd spamd 6 | useradd -g spamd -s /bin/false -d /var/log/spamassassin spamd 7 | mkdir /var/log/spamassassin 8 | chown spamd:spamd /var/log/spamassassin 9 | cp /etc/default/spamassassin /etc/default/spamassassin.orig 10 | sed -i "s/ENABLED=0/ENABLED=1/" /etc/default/spamassassin 11 | sed -i "s/CRON=0/CRON=1/" /etc/default/spamassassin 12 | 13 | # Clean version 14 | # SAHOME="/var/log/spamassassin/" 15 | # OPTIONS="--create-prefs --max-children 2 --username spamd -H ${SAHOME} -s ${SAHOME}spamd.log" 16 | sed -i "s/OPTIONS=.*/SAHOME=\"\/var\/log\/spamassassin\/\"\nOPTIONS=\"--create-prefs --max-children 2 --username spamd -H \${SAHOME} -s \${SAHOME}spamd.log\"/" /etc/default/spamassassin 17 | 18 | # ADD "-o content_filter=spamassassin\n-o receive_override_options=no_address_mappings" AFTER smtp inet n - - - - smtpd 19 | sed -i "s/smtp .* smtpd/smtp inet n - - - - smtpd\n -o content_filter=spamassassin\n -o receive_override_options=no_address_mappings/" /etc/postfix/master.cf 20 | 21 | echo " 22 | spamassassin unix - n n - - pipe 23 | user=spamd argv=/usr/bin/spamc -f -e 24 | /usr/sbin/sendmail -oi -f \${sender} \${recipient} 25 | " >> /etc/postfix/master.cf 26 | 27 | chown -R postfix:postdrop /var/spool/postfix/public 28 | chown -R postfix:postdrop /var/spool/postfix/maildrop/ 29 | chmod -R 0770 /var/spool/postfix/maildrop/ 30 | postfix reload 31 | service spamassassin restart 32 | 33 | #Move spam message to spam folder 34 | apt-get install dovecot-sieve dovecot-managesieved -y 35 | 36 | echo " 37 | protocol lmtp { 38 | postmaster_address = admin@__EASYMAIL_HOSTNAME__ 39 | mail_plugins = \$mail_plugins sieve 40 | } 41 | " >> /etc/dovecot/conf.d/20-lmtp.conf 42 | 43 | echo " 44 | plugin { 45 | sieve = ~/.dovecot.sieve 46 | sieve_global_path = /var/lib/dovecot/sieve/default.sieve 47 | sieve_dir = ~/sieve 48 | sieve_global_dir = /var/lib/dovecot/sieve/ 49 | } 50 | " > /etc/dovecot/conf.d/90-sieve.conf 51 | 52 | 53 | mkdir /var/lib/dovecot/sieve/ 54 | echo " 55 | require \"fileinto\"; 56 | if header :contains \"X-Spam-Flag\" \"YES\" { 57 | fileinto \"Junk\"; 58 | } 59 | " > /var/lib/dovecot/sieve/default.sieve 60 | chown -R vmail:vmail /var/lib/dovecot 61 | sievec /var/lib/dovecot/sieve/default.sieve 62 | 63 | service dovecot restart 64 | -------------------------------------------------------------------------------- /tests/pop3_integration_test.php: -------------------------------------------------------------------------------- 1 | authorise($hostname, 110, 30, $email, $password); 19 | $mail = new PHPMailer; 20 | $mail->SMTPDebug = 0; 21 | $mail->SMTPSecure = 'tls'; 22 | $mail->SMTPOptions = array( 23 | 'ssl' => array( 24 | 'verify_peer' => false, 25 | 'verify_peer_name' => false, 26 | 'allow_self_signed' => true 27 | ) 28 | ); 29 | $mail->Host = $hostname; 30 | $mail->From = $email; 31 | $mail->setFrom($email, $from); 32 | $mail->addAddress($email, $from); 33 | $mail->Subject = $subject; 34 | $mail->isHTML(false); 35 | $mail->Body = $body; 36 | 37 | if (!$mail->send()) { 38 | die2("Can't send email over POP3, STARTTLS on port 110: ".$mail->ErrorInfo); 39 | } 40 | 41 | sleep(1); 42 | $inbox = (array) imap_check($imap_stream); 43 | 44 | if ($messages_in_inbox == $inbox['Nmsgs']) { 45 | die2("Message not received over POP3, STARTTLS on port 110: ".imap_last_error()); 46 | } 47 | 48 | $messages_in_inbox = $inbox['Nmsgs']; 49 | 50 | // SSL on port 995 51 | $imap_stream = imap_open("{".$hostname.":993/imap/ssl/novalidate-cert}INBOX", $email, $password) or die2("Can't connect over IMAP, SSL on port 993: ".imap_last_error()); 52 | $pop = new POP3; 53 | $pop->authorise($hostname, 995, 30, $email, $password); 54 | $mail = new PHPMailer; 55 | $mail->SMTPDebug = 0; 56 | $mail->SMTPSecure = 'ssl'; 57 | $mail->SMTPOptions = array( 58 | 'ssl' => array( 59 | 'verify_peer' => false, 60 | 'verify_peer_name' => false, 61 | 'allow_self_signed' => true 62 | ) 63 | ); 64 | $mail->Host = $hostname; 65 | $mail->From = $email; 66 | $mail->setFrom($email, $from); 67 | $mail->addAddress($email, $from); 68 | $mail->Subject = $subject; 69 | $mail->isHTML(false); 70 | $mail->Body = $body; 71 | 72 | if (!$mail->send()) { 73 | die2("Can't send email over POP3, SSL on port 995: ".$mail->ErrorInfo); 74 | } 75 | 76 | sleep(1); 77 | $inbox = (array) imap_check($imap_stream); 78 | 79 | if ($messages_in_inbox == $inbox['Nmsgs']) { 80 | die2("Message not received over POP3, SSL on port 995: ".imap_last_error()); 81 | } 82 | -------------------------------------------------------------------------------- /tests/smtp_integration_test.php: -------------------------------------------------------------------------------- 1 | Host = $hostname; 19 | $mail->Port = 587; 20 | $mail->isSMTP(); 21 | $mail->SMTPDebug = 0; 22 | $mail->SMTPSecure = 'tls'; 23 | $mail->SMTPOptions = array( 24 | 'ssl' => array( 25 | 'verify_peer' => false, 26 | 'verify_peer_name' => false, 27 | 'allow_self_signed' => true 28 | ) 29 | ); 30 | $mail->SMTPAuth = true; 31 | $mail->Username = $email; 32 | $mail->Password = $password; 33 | $mail->setFrom($email, $from); 34 | $mail->addAddress($email, $from); 35 | $mail->Subject = $subject; 36 | $mail->isHTML(false); 37 | $mail->Body = $body; 38 | 39 | if (!$mail->send()) { 40 | die2("Can't send email over SMTP, STARTTLS on port 587: ".$mail->ErrorInfo); 41 | } 42 | 43 | sleep(1); 44 | $inbox = (array) imap_check($imap_stream); 45 | 46 | if ($messages_in_inbox == $inbox['Nmsgs']) { 47 | die2("Message not received over SMTP, STARTTLS on port 587: ".imap_last_error()); 48 | } 49 | 50 | $messages_in_inbox = $inbox['Nmsgs']; 51 | 52 | // SSL on port 465 53 | $imap_stream = imap_open("{".$hostname.":993/imap/ssl/novalidate-cert}INBOX", $email, $password) or die2("Can't connect over IMAP, SSL on port 993: ".imap_last_error()); 54 | $mail = new PHPMailer; 55 | $mail->Host = $hostname; 56 | $mail->Port = 465; 57 | $mail->isSMTP(); 58 | $mail->SMTPDebug = 0; 59 | $mail->SMTPSecure = 'ssl'; 60 | $mail->SMTPOptions = array( 61 | 'ssl' => array( 62 | 'verify_peer' => false, 63 | 'verify_peer_name' => false, 64 | 'allow_self_signed' => true 65 | ) 66 | ); 67 | $mail->SMTPAuth = true; 68 | $mail->Username = $email; 69 | $mail->Password = $password; 70 | $mail->setFrom($email, $from); 71 | $mail->addAddress($email, $from); 72 | $mail->Subject = $subject; 73 | $mail->isHTML(false); 74 | $mail->Body = $body; 75 | 76 | if (!$mail->send()) { 77 | die2("Can't send email over SMTP, SSL on port 465: ".$mail->ErrorInfo); 78 | } 79 | 80 | sleep(1); 81 | $inbox = (array) imap_check($imap_stream); 82 | 83 | if ($messages_in_inbox == $inbox['Nmsgs']) { 84 | die2("Message not received over SMTP, SSL on port 465: ".imap_last_error()); 85 | } 86 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | # Update and install initially required services 4 | apt update -y 5 | apt upgrade -y 6 | apt install openssl python dialog cron -y 7 | 8 | export CURRENT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 9 | 10 | export HOSTNAME="__EASYMAIL_HOSTNAME__" 11 | export SSL_CA_BUNDLE_FILE="/etc/dovecot/dovecot.pem" 12 | export SSL_PRIVATE_KEY_FILE="/etc/dovecot/private/dovecot.pem" 13 | 14 | export ADMIN_EMAIL="admin@$HOSTNAME" 15 | export ADMIN_PASSWORD_UNENCRYPTED='__EASYMAIL_ADMIN_PASSWORD_UNENCRYPTED__' 16 | export ADMIN_PASSWORD=$(openssl passwd -1 $ADMIN_PASSWORD_UNENCRYPTED) 17 | 18 | export ROOT_MYSQL_USERNAME='root' 19 | export ROOT_MYSQL_PASSWORD='__EASYMAIL_ROOT_MYSQL_PASSWORD__' 20 | 21 | export MYSQL_DATABASE='mailserver' 22 | export MYSQL_HOSTNAME='127.0.0.1' 23 | export MYSQL_USERNAME='mailuser' 24 | export MYSQL_PASSWORD='__EASYMAIL_MYSQL_PASSWORD__' 25 | 26 | export ROUNDCUBE_MYSQL_DATABASE='roundcube_dbname' 27 | export ROUNDCUBE_MYSQL_USERNAME='roundcube_user' 28 | export ROUNDCUBE_MYSQL_PASSWORD='__EASYMAIL_ROUNDCUBE_MYSQL_PASSWORD__' 29 | export ROUNDCUBE_VERSION=1.2.5 30 | 31 | export EASY_MAIL_DIR="/opt/easymail" && mkdir $EASY_MAIL_DIR 32 | 33 | function set_hostname { 34 | sed -i "s/__EASYMAIL_HOSTNAME__/$HOSTNAME/g" $1 35 | } 36 | 37 | export -f set_hostname 38 | 39 | # Install 40 | bash $CURRENT_DIR/mysql/install.sh 41 | bash $CURRENT_DIR/postfix/install.sh 42 | bash $CURRENT_DIR/dovecot/install.sh 43 | bash $CURRENT_DIR/nginx/install.sh 44 | bash $CURRENT_DIR/roundcube/install.sh 45 | bash $CURRENT_DIR/autoconfig/install.sh 46 | bash $CURRENT_DIR/spamassassin/install.sh 47 | bash $CURRENT_DIR/autostart/install.sh 48 | bash $CURRENT_DIR/dkim/install.sh 49 | 50 | # Save the system configurations 51 | echo " 52 | [general] 53 | general_hostname:__EASYMAIL_HOSTNAME__ 54 | 55 | [ssl] 56 | public_dovecot_key:$SSL_CA_BUNDLE_FILE 57 | private_dovecot_key:$SSL_PRIVATE_KEY_FILE 58 | 59 | [mysql_root] 60 | mysql_root_username:$ROOT_MYSQL_USERNAME 61 | mysql_root_password:$ROOT_MYSQL_PASSWORD 62 | 63 | [mysql_easymail] 64 | mysql_easymail_database:$MYSQL_DATABASE 65 | mysql_easymail_hostname:$MYSQL_HOSTNAME 66 | mysql_easymail_username:$MYSQL_USERNAME 67 | mysql_easymail_password:$MYSQL_PASSWORD 68 | 69 | [mysql_roundcube] 70 | mysql_roundcube_database:$ROUNDCUBE_MYSQL_DATABASE 71 | mysql_roundcube_username:$ROUNDCUBE_MYSQL_USERNAME 72 | mysql_roundcube_password:$ROUNDCUBE_MYSQL_PASSWORD 73 | 74 | [roundcube_web] 75 | roundcube_web_url:https://__EASYMAIL_HOSTNAME__ 76 | roundcube_web_username:admin@__EASYMAIL_HOSTNAME__ 77 | roundcube_web_password:$ADMIN_PASSWORD_UNENCRYPTED 78 | 79 | " >> $EASY_MAIL_DIR/config.ini 80 | 81 | cp $CURRENT_DIR/exportDb.sh $EASY_MAIL_DIR/exportDb.sh 82 | cp $CURRENT_DIR/importDb.sh $EASY_MAIL_DIR/importDb.sh 83 | 84 | cp $CURRENT_DIR/post_install.sh $EASY_MAIL_DIR/post_install.sh 85 | 86 | -------------------------------------------------------------------------------- /dovecot/10-master.conf: -------------------------------------------------------------------------------- 1 | #default_process_limit = 100 2 | #default_client_limit = 1000 3 | 4 | # Default VSZ (virtual memory size) limit for service processes. This is mainly 5 | # intended to catch and kill processes that leak memory before they eat up 6 | # everything. 7 | #default_vsz_limit = 256M 8 | 9 | # Login user is internally used by login processes. This is the most untrusted 10 | # user in Dovecot system. It shouldn't have access to anything at all. 11 | #default_login_user = dovenull 12 | 13 | # Internal user is used by unprivileged processes. It should be separate from 14 | # login user, so that login processes can't disturb other processes. 15 | #default_internal_user = dovecot 16 | 17 | service imap-login { 18 | inet_listener imap { 19 | #port = 143 20 | } 21 | inet_listener imaps { 22 | #port = 993 23 | #ssl = yes 24 | } 25 | 26 | # Number of connections to handle before starting a new process. Typically 27 | # the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0 28 | # is faster. 29 | #service_count = 1 30 | 31 | # Number of processes to always keep waiting for more connections. 32 | #process_min_avail = 0 33 | 34 | # If you set service_count=0, you probably need to grow this. 35 | #vsz_limit = $default_vsz_limit 36 | } 37 | 38 | service pop3-login { 39 | inet_listener pop3 { 40 | #port = 110 41 | } 42 | inet_listener pop3s { 43 | #port = 995 44 | #ssl = yes 45 | } 46 | } 47 | 48 | service lmtp { 49 | unix_listener /var/spool/postfix/private/dovecot-lmtp { 50 | mode = 0600 51 | user = postfix 52 | group = postfix 53 | } 54 | } 55 | 56 | service imap { 57 | # Most of the memory goes to mmap()ing files. You may need to increase this 58 | # limit if you have huge mailboxes. 59 | #vsz_limit = $default_vsz_limit 60 | 61 | # Max. number of IMAP processes (connections) 62 | #process_limit = 1024 63 | } 64 | 65 | service pop3 { 66 | # Max. number of POP3 processes (connections) 67 | #process_limit = 1024 68 | } 69 | 70 | service auth { 71 | # auth_socket_path points to this userdb socket by default. It's typically 72 | # used by dovecot-lda, doveadm, possibly imap process, etc. Its default 73 | # permissions make it readable only by root, but you may need to relax these 74 | # permissions. Users that have access to this socket are able to get a list 75 | # of all usernames and get results of everyone's userdb lookups. 76 | unix_listener /var/spool/postfix/private/auth { 77 | mode = 0666 78 | user = postfix 79 | group = postfix 80 | } 81 | 82 | unix_listener auth-userdb { 83 | mode = 0600 84 | user = vmail 85 | #group = 86 | } 87 | 88 | # Postfix smtp-auth 89 | #unix_listener /var/spool/postfix/private/auth { 90 | # mode = 0666 91 | #} 92 | 93 | # Auth process is run as this user. 94 | user = dovecot 95 | } 96 | 97 | service auth-worker { 98 | # Auth worker process is run as root by default, so that it can access 99 | # /etc/shadow. If this isn't necessary, the user should be changed to 100 | # $default_internal_user. 101 | user = vmail 102 | } 103 | 104 | service dict { 105 | # If dict proxy is used, mail processes should have access to its socket. 106 | # For example: mode=0660, group=vmail and global mail_access_groups=vmail 107 | unix_listener dict { 108 | #mode = 0600 109 | #user = 110 | #group = 111 | } 112 | } -------------------------------------------------------------------------------- /roundcube/install.sh: -------------------------------------------------------------------------------- 1 | # Install Roundcube and its dependencies 2 | set -e 3 | 4 | ROUNDCUBE_DIR="$CURRENT_DIR/roundcube" 5 | 6 | apt-get install language-pack-en-base software-properties-common -y 7 | LC_ALL=en_US.UTF-8 add-apt-repository ppa:ondrej/php -y 8 | apt-get install php7.0-fpm mcrypt php7.0-mcrypt php7.0-intl php7.0-mysql php7.0-mbstring php7.0-curl php7.0-zip php-xml php-xml-parser php7.0-cli php7.0-gd php-apcu php7.0-imap php-mail php-mail-mimedecode php-mime-type php-mail-mime -y 9 | 10 | phpenmod intl zip 11 | 12 | apt-get install wget -y 13 | 14 | cp $ROUNDCUBE_DIR/nginx_config /etc/nginx/sites-enabled/roundcube 15 | 16 | sed -i "s#__EASYMAIL_SSL_CA_BUNDLE_FILE__#$SSL_CA_BUNDLE_FILE#g" /etc/nginx/sites-enabled/roundcube 17 | sed -i "s#__EASYMAIL_SSL_PRIVATE_KEY_FILE__#$SSL_PRIVATE_KEY_FILE#g" /etc/nginx/sites-enabled/roundcube 18 | 19 | cd /tmp && wget -O roundcubemail.tar.gz https://github.com/roundcube/roundcubemail/releases/download/$ROUNDCUBE_VERSION/roundcubemail-$ROUNDCUBE_VERSION-complete.tar.gz 20 | tar -xvzf roundcubemail.tar.gz 21 | mkdir /usr/share/roundcubemail 22 | cp -r roundcubemail-$ROUNDCUBE_VERSION/ /usr/share/nginx/roundcubemail 23 | 24 | cd /usr/share/nginx/roundcubemail/ 25 | cp /etc/php/7.0/fpm/php.ini /etc/php/7.0/fpm/php.ini.orig 26 | sed -i "s/;cgi.fix_pathinfo=.*/cgi.fix_pathinfo=0/" /etc/php/7.0/fpm/php.ini 27 | sed -i "s/post_max_size =.*/post_max_size = 16M/" /etc/php/7.0/fpm/php.ini 28 | sed -i "s/upload_max_filesize =.*/upload_max_filesize = 15M/" /etc/php/7.0/fpm/php.ini 29 | 30 | mysqladmin -u$ROOT_MYSQL_USERNAME -p$ROOT_MYSQL_PASSWORD create $ROUNDCUBE_MYSQL_DATABASE 31 | mysql -u$ROOT_MYSQL_USERNAME -p$ROOT_MYSQL_PASSWORD << EOF 32 | GRANT SELECT, EXECUTE, SHOW VIEW, ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EVENT, INDEX, INSERT, REFERENCES, TRIGGER, UPDATE, LOCK TABLES ON $ROUNDCUBE_MYSQL_DATABASE.* TO '$ROUNDCUBE_MYSQL_USERNAME'@'$MYSQL_HOSTNAME' IDENTIFIED BY '$ROUNDCUBE_MYSQL_PASSWORD'; 33 | GRANT SELECT, UPDATE ON $MYSQL_DATABASE.* TO '$ROUNDCUBE_MYSQL_USERNAME'@'$MYSQL_HOSTNAME'; 34 | FLUSH PRIVILEGES; 35 | USE $ROUNDCUBE_MYSQL_DATABASE; 36 | EOF 37 | 38 | chmod -R 644 /usr/share/nginx/roundcubemail/temp /usr/share/nginx/roundcubemail/logs 39 | export NGINX_ROUNDCUBEMAIL_FILE=/usr/share/nginx/roundcubemail/config/config.inc.php 40 | cp $ROUNDCUBE_DIR/config $NGINX_ROUNDCUBEMAIL_FILE 41 | 42 | sed -i "s/__EASYMAIL_MYSQL_HOSTNAME__/$MYSQL_HOSTNAME/g" $NGINX_ROUNDCUBEMAIL_FILE 43 | sed -i "s/__EASYMAIL_ROUNDCUBE_MYSQL_DATABASE__/$ROUNDCUBE_MYSQL_DATABASE/g" $NGINX_ROUNDCUBEMAIL_FILE 44 | sed -i "s/__EASYMAIL_ROUNDCUBE_MYSQL_USERNAME__/$ROUNDCUBE_MYSQL_USERNAME/g" $NGINX_ROUNDCUBEMAIL_FILE 45 | sed -i "s/__EASYMAIL_ROUNDCUBE_MYSQL_PASSWORD__/$ROUNDCUBE_MYSQL_PASSWORD/g" $NGINX_ROUNDCUBEMAIL_FILE 46 | 47 | mysql -h $MYSQL_HOSTNAME -u$ROUNDCUBE_MYSQL_USERNAME -p$ROUNDCUBE_MYSQL_PASSWORD $ROUNDCUBE_MYSQL_DATABASE < /usr/share/nginx/roundcubemail/SQL/mysql.initial.sql 48 | rm -r /usr/share/nginx/roundcubemail/installer 49 | cd /usr/share/nginx/roundcubemail/plugins/password/ 50 | cp config.inc.php.dist config.inc.php 51 | 52 | cat $ROUNDCUBE_DIR/password_plugin_config >> /usr/share/nginx/roundcubemail/plugins/password/config.inc.php 53 | sed -i "s/ $2 82 | } 83 | 84 | cd /etc/postfix/ 85 | postfix_mysql_file "query = SELECT 1 FROM virtual_domains WHERE name='%s'" mysql-virtual-mailbox-domains.cf 86 | postfix_mysql_file "query = SELECT 1 FROM virtual_users WHERE email='%s'" mysql-virtual-mailbox-maps.cf 87 | postfix_mysql_file "query = SELECT destination FROM virtual_aliases WHERE source='%s'" mysql-virtual-alias-maps.cf 88 | postfix_mysql_file "query = SELECT to_address FROM recipient_bcc WHERE from_address='%s'" mysql-recipient-bcc-maps.cf 89 | 90 | sed -i -E 's/^(\s*)system\(\);/\1unix-stream("\/dev\/log");/' /etc/syslog-ng/syslog-ng.conf 91 | service syslog-ng start 92 | service postfix start 93 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: bash 2 | 3 | services: 4 | - docker 5 | 6 | script: 7 | - mkdir -p /opt/easymail/data/{mysql,dovecot,opendkim,ssl} 8 | - docker run -it -v /home/travis/build/runeasymail/easymail/:/easymail -p=110:110 -p=25:25 -p=995:995 -p=80:80 -p=443:443 -p=587:587 -p=993:993 -p=143:143 -p=465:465 --name="easymail" ubuntu:16.04 /bin/sh -c "bash /easymail/install.sh" 9 | - docker commit easymail easymail-img 10 | 11 | # Smoke tests START 12 | - docker rm easymail 13 | - docker run -itd -v /home/travis/build/runeasymail/easymail/:/easymail -v /opt/easymail/data/ssl/:/opt/easymail/data/ssl/ -v /opt/easymail/data/dovecot/:/var/mail/vhosts/ -v /opt/easymail/data/mysql/:/opt/easymail/data/mysql/ -p=110:110 -p=25:25 -p=995:995 -p=80:80 -p=443:443 -p=587:587 -p=993:993 -p=143:143 -p=465:465 -h "test.example.com" --name="easymail" easymail-img /bin/sh -c "bash /opt/easymail/post_install.sh; exec /bin/bash" 14 | - sleep 20 15 | - docker exec easymail wget --no-check-certificate https://test.example.com 16 | # Smoke tests END 17 | 18 | # Integration tests START 19 | - docker exec easymail bash /easymail/tests/install.sh 20 | - docker exec easymail php /easymail/tests/imap_integration_test.php 21 | - docker exec easymail php /easymail/tests/pop3_integration_test.php 22 | - docker exec easymail php /easymail/tests/smtp_integration_test.php 23 | # Integration tests END 24 | 25 | env: 26 | global: 27 | - secure: "Z6z/fFxVZWBjUSH/6Thg9WOg1r9yqXekS1COYxQ+mZeeakPOOnC7N1zy/DR7/8eWdQvXMDcgpqBXN68wtUdxi6VtuRuwqSRz0o3eytrpbP/kTg+fx7wRHzhEOonlZM/Gd1rJioPQQGgp2TBWEUi4jAduYSGswMeLIqLC6jMu1OfXGzolvctI+DNhNAvvIvuAiyv3uQTt9fHtgKi3ZeprM6Z0OVRRphW4IE07d3kP4pQ3P6MznN4054xR1zypacen7xMPWzOzFjELucYJmOkgVbHbHf6s9M5ElyOrfUcV7L4rvyZX4ze7H8OVGh2NVYC8LwCwkhSNtjeI6onCJBogj6VQ53xW/XRmD4QF5xN6g57gUzGluonuv/kPisMXETUizYFEjaUyH3djJcsErPegvmwhldjrH11AGlDl+fTKcb5sdE8XHLPPRwB97sPhlSZmDnG3zGCBPoV8DJkxO22Z0yity63ijAdH5Yi2UqccpR+n7An+YgZTiTnwOxsQVtgiEcRvUJ680X5WR0EjA4Z2DLjmztxxoa5GyE/LipZ6b1ZorvMfLeff1BwHXnB7Xq8CLoP+NOONgaFxfOyFxB1oMrjlQ8FlgXwe/xJu5whoyCc1hs/HL0rrprcZ8pKgkDq37ge97gMmYsKCP2ZaJOrqeKU8VCxFVTml6js+/9Wwkqk=" # DOCKER_EMAIL 28 | - secure: "nqCxdcWfn6qPXzxAwPjNjaqRpDRqP1q1gwgG4R68JrPbFODQRHCVbvTwWoJIR+Png4B93NJ9lJF82gmwODGg9BC0GlBH0h6PeRXflIyVlC80h/RnSYQxXM2+zZQPjnnKHY673YdWiBw9URl0ztbhp8xiQQ8fYvhIUuxs2gsDcK3NoQtRhcHbDA1lt3Jmffm9k1MHwaAI2H7UmsnJo/runCJVwoyF3iF0vUG6lqvd0dEqLhAX9ayw+AMVrlFtx8IE3+eSuFcHQQlOfr6iw7suyuiEkMzbsCgO0YbLJC187gRXYzgIQ6sVQNLaC7z5pKSmGMQi22QG1iDwTBPpwtaUq9cyhakdGJ9qUxrFjsVwNdB4zmbGYlEiGOtpmXwYGf900GOPYtutq7ToI230yTpsyQfk/KF8tGQw0mAh4F79KteJVnvaPoffEpNUk2nNdFtNc7Ot8yFynaUF+LXTG4US+w4HUPis2HMV57WVYk0z4hgwoBnHjv/9dSfI5VfmywtR+ctMzv7cqBE/UqHUpH9A69XlLvLyMn32aEao1437QnZAKvdHTzGOlRBXrCIPMkE1W3uljKH9wECogxpKbUpTmVukaHJ7Y5cb7o696T6YTJJ7VfTNqrsfCIK3QMN39RN/uJdam27isiLfpDugN9YQ3nYi7wT4yVIIe7k3dX4pv/k=" # DOCKER_USER 29 | - secure: "ZMkxy/nq2cfjMqB7Geq965cbijd2ghgOIAgdteKtm8SYVtl2kL8zujE62elOR8QTLDgjbbTudn3vriGiOj2Mz200j7aLJekEEByVgAD9vzgfm8uu49fbuSkV6/ADKx0FFWBONXIa9Od/1AAoG0P2T6MM/7fWh3gUG5ZjmA5B6UNQpRHYQFMWe/Ikbm860wyOFA98fz2nk5APQowzmCiGe5MQSE3fysQ5Dy8Al8IbC2f4ORWnADYS1S7xdtgQHt9lUaKBYq0rpx1ImfbtwzOOQCn+VOujlURgqaPhKzPjC7eL2luTFe4oIeqb+ENnRqj5SRJoB3xxfVIy/0TdL5eTqUaq/5PJmGbC/xC5pGl+czD3PkszVFqD3IHszD31WqVDvtNURNx+5GBAEioE2AgeaYAcX27mBYDbpvGkfYos3pBVlBP8xcmfA9EeagvCvB1edqBe9jtcIw7Va8qX73zVIJgjxCAhtA3BH/Sr4KYxdDQ1T/sQ5Fcs6yDyXauE+Jo3xxWToQi7dP2jpwStWeLCYr6rJtFK89fExNkEzAkz2kQfSKb0g53o+n5DuKu2Fa311Lz/9QdnDQiNoDYPKeWkZgWDNvSGApTaDRzLaOhCL3nGzrrRcuUYPWfdYoRm8CNzrbUGRBOc+8AX5oECdjEnC75AIGlxhZW0chPQHwex0Qo=" # DOCKER_PASS 30 | 31 | after_success: 32 | - if [ "$TRAVIS_TAG" != "" ]; then 33 | docker login -u $DOCKER_USER -p $DOCKER_PASS && 34 | docker tag easymail-img easymail/easymail:$TRAVIS_TAG && 35 | docker push easymail/easymail:$TRAVIS_TAG; 36 | else 37 | docker login -u $DOCKER_USER -p $DOCKER_PASS && 38 | docker tag easymail-img easymail/only-for-testing-purposes:$TRAVIS_BUILD_NUMBER && 39 | docker push easymail/only-for-testing-purposes:$TRAVIS_BUILD_NUMBER; 40 | fi 41 | -------------------------------------------------------------------------------- /dovecot/install.sh: -------------------------------------------------------------------------------- 1 | # Install Dovecot 2 | set -e 3 | 4 | DOVECOT_DIR="$CURRENT_DIR/dovecot" 5 | 6 | debconf-set-selections <<< "dovecot-core dovecot-core/ssl-cert-exists string error" 7 | debconf-set-selections <<< "dovecot-core dovecot-core/ssl-cert-name string localhost" 8 | debconf-set-selections <<< "dovecot-core dovecot-core/create-ssl-cert boolean true" 9 | 10 | apt-get install dovecot-core dovecot-imapd dovecot-pop3d dovecot-lmtpd dovecot-mysql -y 11 | 12 | cp /etc/postfix/master.cf /etc/postfix/master.cf.orig 13 | cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig 14 | cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.orig 15 | cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.orig 16 | cp /etc/dovecot/conf.d/10-master.conf /etc/dovecot/conf.d/10-master.conf.orig 17 | cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.orig 18 | cp /etc/dovecot/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext.orig 19 | 20 | echo " 21 | #Automatic added by script for auto install mail server. 22 | 465 inet n - n - - smtpd 23 | -o syslog_name=postfix/smtps 24 | -o smtpd_tls_wrappermode=yes 25 | -o smtpd_sasl_auth_enable=yes 26 | -o smtpd_client_restrictions=permit_sasl_authenticated,reject 27 | 28 | submission inet n - - - - smtpd 29 | -o smtpd_tls_security_level=encrypt 30 | -o smtpd_sasl_auth_enable=yes 31 | -o smtpd_client_restrictions=permit_sasl_authenticated,reject 32 | " >> /etc/postfix/master.cf 33 | 34 | echo " 35 | #Automatic added by script for auto install mail server. 36 | protocols = imap pop3 lmtp sieve 37 | ssl = required 38 | ssl_cert = <$SSL_CA_BUNDLE_FILE 39 | ssl_key = <$SSL_PRIVATE_KEY_FILE 40 | " >> /etc/dovecot/dovecot.conf 41 | 42 | sed -i "s/mail_location = .*/mail_location = maildir:\/var\/mail\/vhosts\/%d\/\%n/g" /etc/dovecot/conf.d/10-mail.conf 43 | sed -i "s/#mail_privileged_group =/mail_privileged_group = mail/g" /etc/dovecot/conf.d/10-mail.conf 44 | 45 | mkdir -p /var/mail/vhosts/__EASYMAIL_HOSTNAME__ 46 | groupadd -g 5000 vmail 47 | useradd -g vmail -u 5000 vmail -d /var/mail 48 | chown -R vmail:vmail /var/mail 49 | 50 | sed -i "s/^#disable_plaintext_auth = .*/disable_plaintext_auth = yes/g" /etc/dovecot/conf.d/10-auth.conf 51 | sed -i "s/^auth_mechanisms = .*/auth_mechanisms = plain login/g" /etc/dovecot/conf.d/10-auth.conf 52 | sed -i "s/\!include auth-system.conf.ext/#\!include auth-system.conf.ext/g" /etc/dovecot/conf.d/10-auth.conf 53 | sed -i "s/#\!include auth-sql.conf.ext/\!include auth-sql.conf.ext/g" /etc/dovecot/conf.d/10-auth.conf 54 | 55 | echo ' 56 | passdb { 57 | driver = sql 58 | args = /etc/dovecot/dovecot-sql.conf.ext 59 | } 60 | userdb { 61 | driver = static 62 | args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n 63 | } 64 | ' > /etc/dovecot/conf.d/auth-sql.conf.ext 65 | 66 | echo " 67 | driver = mysql 68 | connect = host=$MYSQL_HOSTNAME dbname=$MYSQL_DATABASE user=$MYSQL_USERNAME password=$MYSQL_PASSWORD 69 | default_pass_scheme = CRYPT 70 | password_query = SELECT email as user, password FROM virtual_users WHERE email='%u'; 71 | " >> /etc/dovecot/dovecot-sql.conf.ext 72 | 73 | chown -R vmail:dovecot /etc/dovecot 74 | chmod -R o-rwx /etc/dovecot 75 | 76 | cp $DOVECOT_DIR/10-master.conf /etc/dovecot/conf.d/10-master.conf 77 | 78 | # Generate self-signed certificate 79 | openssl req -new -x509 -days 365000 -nodes -subj "/C=/ST=/L=/O=/CN=EasyMail" -out "$SSL_CA_BUNDLE_FILE" -keyout "$SSL_PRIVATE_KEY_FILE" 80 | 81 | # Configure Sieve 82 | apt-get install dovecot-sieve dovecot-managesieved php-net-sieve apache2- -y 83 | echo " 84 | plugin { 85 | sieve = ~/.dovecot.sieve 86 | sieve_global_path = /var/lib/dovecot/sieve/default.sieve 87 | sieve_dir = ~/sieve 88 | sieve_global_dir = /var/lib/dovecot/sieve/ 89 | } 90 | service managesieve-login { 91 | inet_listener sieve { 92 | port = 4190 93 | address = 127.0.0.1 94 | } 95 | 96 | service_count = 1 97 | process_min_avail = 1 98 | vsz_limit = 64M 99 | } 100 | service managesieve { 101 | process_limit = 10 102 | } 103 | protocol lda { 104 | mail_plugins = "sieve" 105 | postmaster_address = $ADMIN_EMAIL 106 | } 107 | " >> /etc/dovecot/dovecot.conf 108 | 109 | service dovecot reload 110 | service postfix reload 111 | -------------------------------------------------------------------------------- /post_install.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | # Check for min system requirements 4 | if (($(($(free -mt|awk '/^Total:/{print $2}')*1)) <= 700)); then 5 | echo -e "EasyMail has been stopped because of the following minimum requirements:\n"; 6 | echo -e "- RAM (or RAM + SWAP) >= 1GB\n\n"; 7 | exit; 8 | fi 9 | 10 | # run only once 11 | ALREADY_RUN_POST_INSTALL_FILE="/opt/easymail/already-run-post-install.txt" 12 | 13 | if [ ! -e "$ALREADY_RUN_POST_INSTALL_FILE" ]; then 14 | mkdir /etc/opendkim/keys -p 15 | echo "127.0.0.1 16 | localhost 17 | 192.168.0.1/24 18 | " >> /etc/opendkim/TrustedHosts 19 | chown opendkim:opendkim /etc/opendkim/ -R 20 | chown -R mysql:mysql /var/lib/mysql /var/run/mysqld 21 | fi 22 | 23 | bash /run.sh; 24 | 25 | if [ -e "$ALREADY_RUN_POST_INSTALL_FILE" ]; then 26 | exit; 27 | fi 28 | 29 | touch $ALREADY_RUN_POST_INSTALL_FILE 30 | 31 | # create payload directory 32 | mkdir -p /opt/easymail/data/{mysql,dovecot,ssl} 33 | 34 | # Get variables 35 | export EASYMAIL_CONFIG="/opt/easymail/config.ini" 36 | export ROUNDCUBE_MYSQL_USERNAME=$(cat "$EASYMAIL_CONFIG" | grep mysql_roundcube_username: | awk -F':' '{ print $2;}') 37 | 38 | export MYSQL_HOSTNAME=$(cat "$EASYMAIL_CONFIG" | grep mysql_easymail_hostname: | awk -F':' '{ print $2;}') 39 | export MYSQL_USERNAME=$(cat "$EASYMAIL_CONFIG" | grep mysql_easymail_username: | awk -F':' '{ print $2;}') 40 | 41 | export ROOT_MYSQL_USERNAME=$(cat "$EASYMAIL_CONFIG" | grep mysql_root_username: | awk -F':' '{ print $2;}') 42 | export OLD_ROOT_MYSQL_PASSWORD=$(cat "$EASYMAIL_CONFIG" | grep mysql_root_password: | awk -F':' '{ print $2;}') 43 | export MYSQL_DATABASE=$(cat "$EASYMAIL_CONFIG" | grep mysql_easymail_database: | awk -F':' '{ print $2;}') 44 | 45 | # Define some functions 46 | function set_hostname { 47 | sed -i "s/__EASYMAIL_HOSTNAME__/$HOSTNAME/g" $1 48 | } 49 | 50 | function get_rand_password() { 51 | < /dev/urandom tr -dc A-Za-z-0-9 | head -c${1:-60}; 52 | } 53 | 54 | function apply_easymail_configs { 55 | export FILEPATH=$1; 56 | 57 | sed -i "s/__EASYMAIL_MYSQL_PASSWORD__/$MYSQL_PASSWORD/g" $FILEPATH 58 | sed -i "s/__EASYMAIL_ROOT_MYSQL_PASSWORD__/$ROOT_MYSQL_PASSWORD/g" $FILEPATH 59 | sed -i "s/__EASYMAIL_ROUNDCUBE_MYSQL_PASSWORD__/$ROUNDCUBE_MYSQL_PASSWORD/g" $FILEPATH 60 | 61 | sed -i "s/__EASYMAIL_ADMIN_PASSWORD_UNENCRYPTED__/$ADMIN_PASSWORD_UNENCRYPTED/g" $FILEPATH 62 | 63 | sed -i "s/__EASYMAIL_HOSTNAME__/$HOSTNAME/g" $FILEPATH 64 | } 65 | 66 | export -f set_hostname 67 | 68 | # Re-generate the passwords 69 | export ADMIN_PASSWORD_UNENCRYPTED=$(get_rand_password) 70 | export ADMIN_PASSWORD=$(openssl passwd -1 $ADMIN_PASSWORD_UNENCRYPTED) 71 | export ROOT_MYSQL_PASSWORD=$(get_rand_password) 72 | export MYSQL_PASSWORD=$(get_rand_password) 73 | export ROUNDCUBE_MYSQL_PASSWORD=$(get_rand_password) 74 | 75 | export SSL_CA_BUNDLE_FILE="/opt/easymail/data/ssl/public.pem" 76 | export SSL_PRIVATE_KEY_FILE="/opt/easymail/data/ssl/private.pem" 77 | 78 | chmod 0777 -R /opt/easymail/data/ssl 79 | 80 | # if the sertificate files are there don't re-generate them. 81 | if [ ! -e "$SSL_CA_BUNDLE_FILE" ] || [ ! -e "$SSL_PRIVATE_KEY_FILE" ] ; then 82 | # Re-generate the self-signed certificate 83 | openssl req -new -x509 -days 365000 -nodes -subj "/C=/ST=/L=/O=/CN=EasyMail" -out "$SSL_CA_BUNDLE_FILE" -keyout "$SSL_PRIVATE_KEY_FILE" 84 | fi 85 | 86 | # new SSL location for Postfix 87 | postconf -e smtpd_tls_cert_file=$SSL_CA_BUNDLE_FILE 88 | postconf -e smtpd_tls_key_file=$SSL_PRIVATE_KEY_FILE 89 | 90 | # new SSL location for Nginx 91 | sed -i -e "s#ssl_certificate .*#ssl_certificate $SSL_CA_BUNDLE_FILE;#g" /etc/nginx/sites-enabled/roundcube 92 | sed -i -e "s#ssl_certificate_key .*#ssl_certificate_key $SSL_PRIVATE_KEY_FILE;#g" /etc/nginx/sites-enabled/roundcube 93 | 94 | # new SSL location for Dovecot 95 | sed -i -e "s#ssl_cert .*#ssl_cert = <$SSL_CA_BUNDLE_FILE#g" /etc/dovecot/dovecot.conf 96 | sed -i -e "s#ssl_key .*#ssl_key = <$SSL_PRIVATE_KEY_FILE#g" /etc/dovecot/dovecot.conf 97 | 98 | # Set HOSTNAME for auto configurations 99 | set_hostname /usr/share/nginx/autoconfig_and_autodiscover/autoconfig.php 100 | set_hostname /usr/share/nginx/autoconfig_and_autodiscover/autodiscover.php 101 | 102 | # Set HOSTNAME for Roundcube 103 | set_hostname /etc/nginx/sites-enabled/roundcube 104 | 105 | # Set HOSTNAME for Postfix 106 | debconf-set-selections <<< "postfix postfix/mailname string $HOSTNAME" 107 | 108 | # Set HOSTNAME for MySQL 109 | export ADMIN_EMAIL="admin@$HOSTNAME" 110 | mysql -u$ROOT_MYSQL_USERNAME -p$OLD_ROOT_MYSQL_PASSWORD << EOF 111 | 112 | USE $MYSQL_DATABASE; 113 | 114 | UPDATE \`virtual_domains\` 115 | SET \`name\`='$HOSTNAME' 116 | WHERE \`id\`='1'; 117 | 118 | UPDATE \`virtual_users\` 119 | SET \`email\`='$ADMIN_EMAIL', \`password\`='$ADMIN_PASSWORD' 120 | WHERE \`id\`='1'; 121 | 122 | ALTER USER 'roundcube_user'@'127.0.0.1' IDENTIFIED BY '$ROUNDCUBE_MYSQL_PASSWORD'; 123 | ALTER USER 'mailuser'@'%' IDENTIFIED BY '$MYSQL_PASSWORD'; 124 | GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '$ROOT_MYSQL_PASSWORD' WITH GRANT OPTION; 125 | DROP USER root@localhost; 126 | EOF 127 | 128 | # reset generate roundcubemail 129 | apply_easymail_configs /usr/share/nginx/roundcubemail/plugins/password/config.inc.php 130 | apply_easymail_configs /usr/share/nginx/roundcubemail/config/config.inc.php 131 | apply_easymail_configs /usr/share/nginx/roundcubemail/public_html/plugins/password/config.inc.php 132 | 133 | # Set HOSTNAME for Dovecot 134 | mkdir -p /var/mail/vhosts/$HOSTNAME 135 | chown vmail:vmail /var/mail/vhosts -R 136 | 137 | apply_easymail_configs /etc/dovecot/dovecot.conf 138 | apply_easymail_configs /etc/dovecot/dovecot-sql.conf.ext 139 | apply_easymail_configs /etc/dovecot/conf.d/20-lmtp.conf 140 | echo "log_path = /opt/easymail/logs/dovecot.log" >> /etc/dovecot/dovecot.conf 141 | 142 | postconf -e myhostname="$HOSTNAME" 143 | apply_easymail_configs /etc/postfix/mysql-virtual-mailbox-maps.cf 144 | apply_easymail_configs /etc/postfix/mysql-recipient-bcc-maps.cf 145 | apply_easymail_configs /etc/postfix/mysql-virtual-alias-maps.cf 146 | apply_easymail_configs /etc/postfix/mysql-virtual-mailbox-domains.cf 147 | apply_easymail_configs /etc/opendkim.conf 148 | 149 | # Reload services 150 | service nginx restart 151 | service dovecot reload 152 | service postfix reload 153 | 154 | echo "Create a log dir" 155 | mkdir /opt/easymail/logs/ 156 | 157 | echo "Add new configurations to easymail config file" 158 | apply_easymail_configs $EASYMAIL_CONFIG 159 | 160 | update-ca-certificates 161 | --------------------------------------------------------------------------------