| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| import sys,re,os,json |
| sys.path.append("class/") |
| sys.path.append("/www/server/panel/class/") |
| import public |
| main_cf = "/etc/postfix/main.cf" |
| download_url = public.get_url() |
|
|
|
|
| def get_postconf(): |
| if os.path.exists("/usr/sbin/postconf"): |
| return "/usr/sbin/postconf" |
| elif os.path.exists("/sbin/postconf"): |
| return "/sbin/postconf" |
| else: |
| return "postconf" |
|
|
| class change_to_rspamd: |
|
|
| def change_dkim_server(self): |
| |
| pass |
|
|
| def change_postfix_conf(self): |
| |
| shell = """ |
| {postconf} -e "myhostname = $(hostname)" |
| {postconf} -e "smtpd_milters = inet:127.0.0.1:11332" |
| {postconf} -e "non_smtpd_milters = inet:127.0.0.1:11332" |
| {postconf} -e "milter_mail_macros = i {{mail_addr}} {{client_addr}} {{client_name}} {{auth_authen}}" |
| {postconf} -e "milter_protocol = 6" |
| {postconf} -e "milter_default_action = accept" |
| """.format(postconf=get_postconf()) |
| public.ExecShell(shell) |
|
|
| def comment_old_spam(self): |
| conf = public.readFile(main_cf) |
| if not conf: |
| return |
| rep = "##BT-ANTISPAM-BEGIN(.|\n)+##BT-ANTISPAM-END" |
| conf = re.sub(rep, "", conf) |
| public.writeFile(main_cf, conf) |
|
|
| def change_dovecot_conf(self): |
| |
| shell = """ |
| wget "{download_conf_url}/mail_sys/dovecot/90-sieve_rspamd.conf" -O /etc/dovecot/conf.d/90-sieve.conf -T 10 |
| wget "{download_conf_url}/mail_sys/dovecot/20-lmtp.conf" -O /etc/dovecot/conf.d/20-lmtp.conf -T 10 |
| wget "{download_conf_url}/mail_sys/dovecot/20-imap.conf" -O /etc/dovecot/conf.d/20-imap.conf -T 10 |
| wget "{download_conf_url}/mail_sys/dovecot/15-mailboxes.conf" -O /etc/dovecot/conf.d/15-mailboxes.conf -T 10 |
| """.format(download_conf_url=download_url) |
| public.ExecShell(shell) |
|
|
| def main(self): |
| self.comment_old_spam() |
| self.change_postfix_conf() |
| self.change_dovecot_conf() |
| mail_server_init().setup_rspamd() |
|
|
| class mail_server_init: |
|
|
| def __init__(self): |
| self.sys_v = public.get_linux_distribution().lower() |
| self.logfile = '/tmp/mail_init.log' |
| self.db_files = { |
| 'postfixadmin': '/www/vmail/postfixadmin.db', |
| 'postfixmaillog': '/www/vmail/postfixmaillog.db', |
| 'mail_unsubscribe': '/www/vmail/mail_unsubscribe.db', |
| 'abnormal_recipient': '/www/vmail/abnormal_recipient.db' |
| } |
| def write_logs(self,content,emtpy=None): |
| if emtpy: |
| public.writeFile(self.logfile, '') |
| if '\n' not in content: |
| content += '\n' |
| public.writeFile(self.logfile,content,'a+') |
|
|
| def check_env(self): |
| data = {} |
| data['HostName'] = self.check_hostname() |
| data['Postfix-install'] = {"status":True,"msg":"Postfix已经安装"} if os.path.exists('/usr/sbin/postfix') else {"status":False,"msg":"Postfix未安装,请点击修复按钮"} |
| data['Dovecot-install'] = {"status":True,"msg":"Deovecot已经安装"} if os.path.exists('/usr/sbin/dovecot') else {"status":False,"msg":"Dovecot未安装,请点击修复按钮"} |
| data['Postfix-Version'] = self.check_postfix_ver() |
| data['Redis-install'] = {"status":True,"msg":"Redis已经安装"} if os.path.exists('/www/server/redis/src/redis-server') else {"status":False,"msg":"请到软件商店内安装Redis"} |
| data['Redis-Passwd'] = self.check_redis_passwd(data['Redis-install']) |
| data['Rspamd-install'] = {"status":True,"msg":"Rspamd已经安装"} if os.path.exists('/usr/bin/rspamd') else {"status":False,"msg":"Rspamd未安装,请点击修复按钮"} |
| data['Sqlite-support'] = self.check_sqlite() |
| data['SElinux'] ={"status":True,"msg":"SElinux已经禁用"} if not 'enforcing' in public.ExecShell('getenforce')[0].lower() else {"status":False,"msg":"请先禁用SElinux"} |
| return data |
|
|
| |
| def setup_mail_sys(self, args): |
| ''' |
| 安装邮局系统主函数 |
| :param args: |
| :return: |
| ''' |
| self.write_logs('|-Set up the postfix service to listen to all network cards...') |
| public.ExecShell('{postconf} -e "inet_interfaces = all"'.format(postconf=get_postconf())) |
| self.write_logs('|-Checking system key directory permissions...') |
| if self._check_syssafe(): |
| self.write_logs('|-Check system key directory permissions: failed') |
| return public.returnMsg(False, '请先关闭【系统加固】') |
| self.write_logs('|-Initializing...') |
| if not self.prepare_work(): |
| return public.returnMsg(False, '初始化失败') |
| if not self.conf_postfix()['status']: |
| return public.returnMsg(False, 'Postfix配置失败!') |
| if not self.conf_dovecot(): |
| return public.returnMsg(False, 'Dovecot配置失败!') |
| if not self.setup_rspamd(): |
| return public.returnMsg(False, 'Rspamd配置失败!') |
| |
| |
|
|
| |
| from sslModel import dataModel |
| dataModel.main().check_table() |
|
|
| self.write_logs('|{}'.format("-"*60)) |
| self.write_logs('|-Initialized successfully!') |
| return public.returnMsg(True, '初始化完成') |
|
|
| |
| def _check_syssafe(self, args=None): |
| if not os.path.exists('/www/server/panel/plugin/syssafe/'): |
| return False |
| data = json.loads(public.readFile('/www/server/panel/plugin/syssafe/config.json')) |
| return data['open'] |
|
|
| def check_hostname(self): |
| import socket |
| rep = '^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$' |
| hostname = socket.gethostname() |
| if re.search(rep,hostname): |
| return public.returnMsg(True,'success') |
| return public.returnMsg(False, '你的主机名 ({}) 不合规定, 需要是完整域名' |
| '你可以通过以下命令修复你的主机名 ' |
| '在ssh终端执行 \'hostnamectl set-hostname --static mail.example.com\''.format(hostname)) |
|
|
| def M(self, table_name): |
| import db |
| sql = db.Sql() |
| sql._Sql__DB_FILE = '/www/vmail/postfixadmin.db' |
| return sql.table(table_name) |
| def MD(self, table_name, db_key): |
| if db_key not in self.db_files: |
| raise ValueError(f"Unknown database key: {db_key}") |
| import db |
| sql = db.Sql() |
| sql._Sql__DB_FILE = self.db_files[db_key] |
| sql._Sql__encrypt_keys = [] |
| return sql.table(table_name) |
|
|
| |
| def _release_port(self, port): |
| from collections import namedtuple |
| try: |
| import firewalls |
| get = namedtuple("get", ["port", "ps", "type"]) |
| get.port = port |
| get.ps = 'Mail-Server' |
| get.type = "port" |
| firewalls.firewalls().AddAcceptPort(get) |
| |
| return port |
| except Exception as e: |
| return "Release failed {}".format(e) |
|
|
| def prepare_work(self): |
| ''' |
| 安装前的准备工作 |
| :return: |
| ''' |
| shell_str = ''' |
| useradd -r -u 150 -g mail -d /www/vmail -s /sbin/nologin -c "Virtual Mail User" vmail |
| mkdir -p /www/vmail |
| chmod -R 770 /www/vmail |
| chown -R vmail:mail /www/vmail |
| |
| if [ ! -f "/www/vmail/postfixadmin.db" ]; then |
| touch /www/vmail/postfixadmin.db |
| chown vmail:mail /www/vmail/postfixadmin.db |
| chmod 660 /www/vmail/postfixadmin.db |
| fi''' |
| self.write_logs('',emtpy=True) |
| self.write_logs('|-Adding user: vmail') |
| self.write_logs('|-Create mail storage directory: /www/vmail') |
| self.write_logs('|-Set directory permissions: 770') |
| self.write_logs('|-Set directory owner: vmail:mail') |
| if "centos" in self.sys_v: |
| public.ExecShell(shell_str) |
| elif "ubuntu" in self.sys_v: |
| public.ExecShell(shell_str) |
| |
| if not os.path.exists("/etc/pki/dovecot/certs/dovecot.pem"): |
| self.write_logs('|-Generate dovecot certificate: /etc/pki/dovecot/certs/dovecot.pem') |
| shell_str = """ |
| sudo mkdir -p /etc/pki/dovecot/certs/ |
| sudo mkdir -p /etc/pki/dovecot/private/ |
| sudo cp /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/pki/dovecot/certs/dovecot.pem |
| sudo mv /etc/ssl/private/ssl-cert-snakeoil.key /etc/pki/dovecot/private/dovecot.pem |
| """ |
| public.ExecShell(shell_str) |
| else: |
| return public.returnMsg(False, "目前仅支持Centos和Ubuntu") |
| |
| for i in ["25", "110", "143", "465", "995", "993", "587"]: |
| self.write_logs('|-Releasing port: {}'.format(i)) |
| self._release_port(i) |
| |
| from safeModel.firewallModel import main as firewall |
| firewall_obj = firewall() |
| |
| new_get = public.dict_obj() |
| new_get.protocol = "tcp" |
| new_get.ports = str(i) |
| new_get.choose = "all" |
| new_get.address = "" |
| new_get.domain = "" |
| new_get.types = "accept" |
| new_get.brief = "Mail-Server" |
| new_get.source = "" |
| firewall_obj.create_rules(new_get) |
| |
| |
| self.write_logs('|-Initializing database...') |
| sql = '''CREATE TABLE IF NOT EXISTS `domain` ( |
| `domain` varchar(255) NOT NULL, |
| `a_record` TEXT DEFAULT "", |
| `mailboxes` int DEFAULT 50, -- 创建邮箱数量 |
| `mailbox_quota` bigint(20) NOT NULL DEFAULT 5368709120, -- 邮箱默认空间大小 |
| `quota` bigint(20) NOT NULL DEFAULT 10737418240, -- 域名配额 |
| `rate_limit` int DEFAULT 12, -- 每秒几个邮件 |
| `created` datetime NOT NULL, |
| `active` tinyint(1) NOT NULL DEFAULT 1, |
| PRIMARY KEY (`domain`));''' |
|
|
| with self.M("") as obj: |
| obj.execute(sql, ()) |
|
|
| |
|
|
|
|
| |
| sql = '''CREATE TABLE IF NOT EXISTS `mailbox` ( |
| `username` varchar(255) NOT NULL, |
| `password` varchar(255) NOT NULL, |
| `password_encode` varchar(255) NOT NULL, |
| `full_name` varchar(255) NOT NULL, |
| `is_admin` tinyint(1) NOT NULL DEFAULT 0, |
| `maildir` varchar(255) NOT NULL, |
| `quota` bigint(20) NOT NULL DEFAULT 0, |
| `local_part` varchar(255) NOT NULL, |
| `domain` varchar(255) NOT NULL, |
| `created` datetime NOT NULL, |
| `modified` datetime NOT NULL, |
| `active` tinyint(1) NOT NULL DEFAULT 1, |
| PRIMARY KEY (`username`));''' |
| with self.M("") as obj: |
| obj.execute(sql, ()) |
| |
|
|
| |
| sql = '''CREATE TABLE IF NOT EXISTS `alias` ( |
| `address` varchar(255) NOT NULL, |
| `goto` text NOT NULL, |
| `domain` varchar(255) NOT NULL, |
| `created` datetime NOT NULL, |
| `modified` datetime NOT NULL, |
| `active` tinyint(1) NOT NULL DEFAULT 1, |
| PRIMARY KEY (`address`));''' |
| with self.M("") as obj: |
| obj.execute(sql, ()) |
| |
| |
| sql = '''CREATE TABLE IF NOT EXISTS `alias_domain` ( |
| `alias_domain` varchar(255) NOT NULL, |
| `target_domain` varchar(255) NOT NULL, |
| `created` datetime NOT NULL, |
| `modified` datetime NOT NULL, |
| `active` tinyint(1) NOT NULL DEFAULT 1, |
| PRIMARY KEY (`alias_domain`));''' |
| with self.M("") as obj: |
| obj.execute(sql, ()) |
| |
| |
| |
| sql = '''CREATE TABLE IF NOT EXISTS `temp_email` ( |
| `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| `name` varchar(255) NULL, -- 邮件名 有模版时为模版名 |
| `type` tinyint(1) NOT NULL DEFAULT 0, --上传html 0 拖拽html 1 |
| `content` text NOT NULL, -- 邮件正文 路径 |
| `render` text NOT NULL, -- html渲染数据 |
| `created` INTEGER NOT NULL, |
| `modified` INTEGER NOT NULL, |
| `is_temp` tinyint(1) NOT NULL DEFAULT 0 -- 是否是模版 |
| );''' |
| with self.M("") as obj: |
| obj.execute(sql, ()) |
| |
|
|
| |
| sql = '''CREATE TABLE IF NOT EXISTS `email_task` ( |
| `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| `task_name` varchar(255) NOT NULL, -- 任务名 |
| `addresser` varchar(320) NOT NULL, -- 发件人 |
| `recipient_count` int NOT NULL, -- 收件人数量 |
| `task_process` tinyint NOT NULL, -- 任务进程 0待执行 1执行中 2 已完成 |
| `pause` tinyint NOT NULL, -- 暂停状态 1 暂停中 0 未暂停 执行中的任务才能暂停 |
| `temp_id` INTEGER NOT NULL, -- 邮件对应id |
| `is_record` INTEGER NOT NULL DEFAULT 0, -- 是否记录到发件箱 |
| `unsubscribe` INTEGER NOT NULL DEFAULT 0, -- 是否增加退订按钮 0 没有 1 增加退订按钮 |
| `threads` INTEGER NOT NULL DEFAULT 0, -- 线程数量 控制发送线程数 0时自动控制线程 0~10 |
| `created` INTEGER NOT NULL, |
| `modified` INTEGER NOT NULL, |
| `remark` text, -- 备注 |
| `etypes` varchar(320) NOT NULL DEFAULT '1', -- 邮件类型id 默认为1 多类型 1,2,3 |
| `start_time` INTEGER NOT NULL DEFAULT 0, -- 任务开始时间 |
| `subject` text NULL, -- 邮件主题 改task存 可空 |
| `full_name` varchar(255), -- 新发件人名 改task存 可空 |
| `recipient` text NOT NULL, -- 收件人路径 改task存 |
| `track_open` INTEGER NOT NULL DEFAULT 0, -- 追踪邮件打开 |
| `track_click` INTEGER NOT NULL DEFAULT 0, -- 链接点击 |
| `active` tinyint(1) NOT NULL DEFAULT 0 -- 预留字段 |
| );''' |
| with self.M("") as obj: |
| obj.execute(sql, ()) |
| |
|
|
| |
|
|
| sql = '''CREATE TABLE IF NOT EXISTS `task_count` ( |
| `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| `task_id` INTEGER NOT NULL, -- 所属任务编号 |
| `recipient` varchar(320) NOT NULL, -- 收件人 |
| `delay` varchar(320) NOT NULL, -- 延时 |
| `delays` varchar(320) NOT NULL, -- 各阶段延时 |
| `dsn` varchar(320) NOT NULL, -- dsn |
| `relay` text NOT NULL, -- 中继服务器 |
| `domain` varchar(320) NOT NULL, -- 域名 |
| `status` varchar(255) NOT NULL, -- 错误状态 |
| `err_info` text NOT NULL, -- 错误详情 |
| `created` INTEGER NOT NULL DEFAULT 0, |
| UNIQUE (`task_id`, `recipient`) -- 联合唯一约束 |
| );''' |
| with self.M("") as obj: |
| obj.execute(sql, ()) |
|
|
| |
| sql = '''CREATE TABLE IF NOT EXISTS `mail_type` ( |
| `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| `mail_type` varchar(320) NOT NULL, -- 邮件类型 |
| `created` INTEGER NOT NULL, |
| `active` tinyint(1) NOT NULL DEFAULT 0 -- 预留字段 |
| );''' |
| with self.M("") as obj: |
| obj.execute(sql, ()) |
|
|
| |
| sql_insert = ''' INSERT INTO `mail_type`(`mail_type`, `created`) VALUES ('Default', strftime('%s', 'now'));''' |
| with self.M("") as obj: |
| obj.execute(sql_insert, ()) |
|
|
| |
| sql = '''CREATE TABLE IF NOT EXISTS `mail_unsubscribe` ( |
| `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| `created` INTEGER NOT NULL, |
| `recipient` varchar(320) NOT NULL, -- 收件人 |
| `etype` INTEGER NOT NULL DEFAULT 1, -- 邮件类型id |
| `active` tinyint(1) NOT NULL DEFAULT 0, -- 0 取消订阅 1订阅 |
| `task_id` INTEGER DEFAULT 0, -- 群发任务 id (退订有关联id 订阅没有) |
| UNIQUE(etype, recipient) |
| );''' |
|
|
| with self.MD("", "mail_unsubscribe") as obj3: |
| aa = obj3.execute(sql, ()) |
| |
|
|
|
|
| |
| sql = '''CREATE TABLE IF NOT EXISTS `mail_errlog` ( |
| `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| `created` INTEGER NOT NULL, |
| `recipient` varchar(320) NOT NULL, -- 收件人 |
| `delay` varchar(320) NOT NULL, -- 延时 |
| `delays` varchar(320) NOT NULL, -- 各阶段延时 |
| `dsn` varchar(320) NOT NULL, -- dsn |
| `relay` text NOT NULL, -- 中继服务器 |
| `domain` varchar(320) NOT NULL, -- 域名 |
| `status` varchar(255) NOT NULL, -- 错误状态 |
| `err_info` text NOT NULL, -- 错误详情 |
| UNIQUE(created, recipient) |
| );''' |
| with self.MD("", "postfixmaillog") as obj2: |
| obj2.execute(sql, ()) |
| |
|
|
|
|
|
|
| |
| sql = '''CREATE TABLE IF NOT EXISTS `log_analysis` ( |
| `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| `received` INTEGER NOT NULL DEFAULT 0, -- 接收 |
| `delivered` INTEGER NOT NULL DEFAULT 0, -- 发送 |
| `forwarded` INTEGER NOT NULL DEFAULT 0, -- 转发 |
| `deferred` INTEGER NOT NULL DEFAULT 0, -- 延迟 |
| `bounced` INTEGER NOT NULL DEFAULT 0, -- 退回 |
| `rejected` INTEGER NOT NULL DEFAULT 0, -- 拒绝 |
| `time` INTEGER NOT NULL, -- 时间 每小时时间戳 |
| UNIQUE(`created`) |
| );''' |
| with self.M("") as obj: |
| obj.execute(sql, ()) |
|
|
| |
| sql = '''CREATE TABLE IF NOT EXISTS `abnormal_recipient` ( |
| `id` INTEGER PRIMARY KEY AUTOINCREMENT, |
| `created` INTEGER NOT NULL, -- 邮件时间 时间戳 |
| `recipient` varchar(320) NOT NULL, -- 收件人 |
| `count` INTEGER NOT NULL, -- 次数 |
| `status` varchar(255) NOT NULL, -- 状态 |
| `task_name` varchar(255) NOT NULL, -- 任务名 |
| UNIQUE(recipient) |
| );''' |
|
|
| with self.MD("", "abnormal_recipient") as obj4: |
| obj4.execute(sql, ()) |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| if os.path.exists('/www/vmail/postfixadmin.db'): |
| self.write_logs('|-The database is initialized successfully...') |
| return True |
| else: |
| self.write_logs('|-Database initialization failed...') |
| return False |
|
|
| def _check_sendmail(self): |
| pid = '/run/sendmail/mta/sendmail.pid' |
| if os.path.exists(pid): |
| self.write_logs('|-Check that there is an additional mail service aaa, which is stopping') |
| public.ExecShell('systemctl stop sendmail && systemctl disable sendmail') |
|
|
| def conf_postfix(self): |
| ''' |
| 安装,配置postfix服务, postfix提供发信功能 |
| :return: |
| ''' |
| |
| self._check_sendmail() |
| |
| self.write_logs('|-Initializing postfix...') |
| edit_postfix_conf_shell = ''' |
| {postconf} -e "myhostname = $(hostname)" |
| {postconf} -e "inet_interfaces = all" |
| {postconf} -e "mydestination =" |
| |
| {postconf} -e "virtual_mailbox_domains = sqlite:/etc/postfix/sqlite_virtual_domains_maps.cf" |
| {postconf} -e "virtual_alias_maps = sqlite:/etc/postfix/sqlite_virtual_alias_new_maps.cf, sqlite:/etc/postfix/sqlite_virtual_alias_domain_new_maps.cf, sqlite:/etc/postfix/sqlite_virtual_alias_domain_catchall_new_maps.cf, sqlite:/etc/postfix/bt_catchnone_maps.cf" |
| {postconf} -e "virtual_mailbox_maps = sqlite:/etc/postfix/sqlite_virtual_mailbox_maps.cf, sqlite:/etc/postfix/sqlite_virtual_alias_domain_mailbox_maps.cf" |
| |
| {postconf} -e "smtpd_sasl_type = dovecot" |
| {postconf} -e "smtpd_sasl_path = private/auth" |
| {postconf} -e "smtpd_sasl_auth_enable = yes" |
| {postconf} -e "smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination" |
| |
| {postconf} -e "smtpd_use_tls = yes" |
| {postconf} -e "smtp_tls_security_level = may" |
| {postconf} -e "smtpd_tls_security_level = may" |
| |
| {postconf} -e "virtual_transport = lmtp:unix:private/dovecot-lmtp" |
| {postconf} -e "smtpd_milters = inet:127.0.0.1:11332" |
| {postconf} -e "non_smtpd_milters = inet:127.0.0.1:11332" |
| {postconf} -e "milter_mail_macros = i {{mail_addr}} {{client_addr}} {{client_name}} {{auth_authen}}" |
| {postconf} -e "milter_protocol = 6" |
| {postconf} -e "milter_default_action = accept" |
| {postconf} -e "message_size_limit = 102400000" |
| '''.format(postconf=get_postconf()) |
| public.ExecShell(edit_postfix_conf_shell) |
| self.write_logs('|-Downloading additional configuration files...') |
| download_sql_conf_shell = ''' |
| wget "{download_conf_url}/mail_sys/postfix/master.cf" -O /etc/postfix/master.cf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/postfix/sqlite_virtual_alias_domain_catchall_new_maps.cf" -O /etc/postfix/sqlite_virtual_alias_domain_catchall_new_maps.cf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/postfix/bt_catchnone_maps.cf" -O /etc/postfix/bt_catchnone_maps.cf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/postfix/sqlite_virtual_alias_domain_new_maps.cf" -O /etc/postfix/sqlite_virtual_alias_domain_new_maps.cf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/postfix/sqlite_virtual_alias_domain_mailbox_maps.cf" -O /etc/postfix/sqlite_virtual_alias_domain_mailbox_maps.cf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/postfix/sqlite_virtual_alias_domain_maps.cf" -O /etc/postfix/sqlite_virtual_alias_domain_maps.cf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/postfix/sqlite_virtual_domains_maps.cf" -O /etc/postfix/sqlite_virtual_domains_maps.cf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/postfix/sqlite_virtual_alias_new_maps.cf" -O /etc/postfix/sqlite_virtual_alias_new_maps.cf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/postfix/sqlite_virtual_domains_new_maps.cf" -O /etc/postfix/sqlite_virtual_domains_new_maps.cf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/postfix/sqlite_virtual_mailbox_maps.cf" -O /etc/postfix/sqlite_virtual_mailbox_maps.cf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/postfix/btrule.cf" -O /etc/postfix/btrule.cf -T 10 >> {logfile} 2>&1 |
| '''.format(download_conf_url=download_url,logfile=self.logfile) |
| aaa = public.ExecShell(download_sql_conf_shell) |
| |
|
|
| result = public.readFile("/etc/postfix/sqlite_virtual_mailbox_maps.cf") |
| if not result or not re.search(r"\n*query\s*=\s*", result): |
| self.write_logs('|- Read file content {}: Failed'.format("/etc/postfix/sqlite_virtual_mailbox_maps.cf")) |
| return public.returnMsg(False,"获取邮局配置失败!") |
|
|
| restart_service_shell = 'systemctl enable postfix && systemctl restart postfix' |
| self.write_logs('|-Restarting postfix service...') |
| public.ExecShell(restart_service_shell) |
| return public.returnMsg(True,"配置成功!") |
|
|
| def conf_dovecot(self): |
| ''' |
| 安装,配置dovecot服务, dovecot提供收信功能 |
| :return: |
| ''' |
| self.write_logs('|-Initializing dovecot...') |
| self.write_logs('|-Downloading additional configuration files...') |
| download_conf_shell = ''' |
| wget "{download_conf_url}/mail_sys/dovecot/dovecot-sql.conf.ext" -O /etc/dovecot/dovecot-sql.conf.ext -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/dovecot/dovecot.conf" -O /etc/dovecot/dovecot.conf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/dovecot/10-mail.conf" -O /etc/dovecot/conf.d/10-mail.conf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/dovecot/10-ssl.conf" -O /etc/dovecot/conf.d/10-ssl.conf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/dovecot/10-master.conf" -O /etc/dovecot/conf.d/10-master.conf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/dovecot/10-auth.conf" -O /etc/dovecot/conf.d/10-auth.conf -T 10 >> {logfile} 2>&1 |
| |
| wget "{download_conf_url}/mail_sys/dovecot/90-sieve_rspamd.conf" -O /etc/dovecot/conf.d/90-sieve.conf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/dovecot/20-lmtp.conf" -O /etc/dovecot/conf.d/20-lmtp.conf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/dovecot/20-imap.conf" -O /etc/dovecot/conf.d/20-imap.conf -T 10 >> {logfile} 2>&1 |
| wget "{download_conf_url}/mail_sys/dovecot/15-mailboxes.conf" -O /etc/dovecot/conf.d/15-mailboxes.conf -T 10 >> {logfile} 2>&1 |
| '''.format(download_conf_url=download_url,logfile=self.logfile) |
| public.ExecShell(download_conf_shell) |
| result = public.readFile("/etc/dovecot/dovecot.conf") |
| if not result or not re.search(r"\n*protocol\s+imap", result): |
| self.write_logs('|-Read file content {}: Failed'.format("/etc/dovecot/dovecot.conf")) |
| return False |
|
|
| |
| dovecot_conf = public.readFile("/etc/dovecot/dovecot.conf") |
| dovecot_conf = re.sub(r"#protocols\s*=\s*imap\s*pop3\s*lmtp", "protocols = imap pop3 lmtp", dovecot_conf) |
| public.writeFile("/etc/dovecot/dovecot.conf", dovecot_conf) |
|
|
| if 'centos8' in self.sys_v: |
| if not self.create_ssl(): |
| self.write_logs('|-Generate self-signed certificate: Failed') |
| return False |
| if not os.path.exists('/etc/pki/dovecot/private/dovecot.pem') or not os.path.exists( |
| '/etc/pki/dovecot/certs/dovecot.pem'): |
| self.create_ssl() |
| restart_service_shell = ''' |
| chown -R vmail:dovecot /etc/dovecot |
| chmod -R o-rwx /etc/dovecot |
| |
| systemctl enable dovecot |
| systemctl restart dovecot |
| ''' |
| self.write_logs('|-Restarting dovecot...') |
| public.ExecShell(restart_service_shell) |
| return True |
|
|
| |
| def create_ssl(self, get=None): |
| import OpenSSL |
| self.write_logs('|-生成自签证书...') |
| from mailModel import mainModel as mail_sys_main |
| mail_sys_main.main().back_file('/etc/pki/dovecot/certs/dovecot.pem') |
| mail_sys_main.main().back_file('/etc/pki/dovecot/private/dovecot.pem') |
| key = OpenSSL.crypto.PKey() |
| key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) |
| cert = OpenSSL.crypto.X509() |
| cert.set_serial_number(0) |
| cert.get_subject().CN = public.GetLocalIp() |
| cert.set_issuer(cert.get_subject()) |
| cert.gmtime_adj_notBefore(0) |
| cert.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60) |
| cert.set_pubkey(key) |
| cert.sign(key, 'md5') |
| cert_ca = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert) |
| private_key = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key) |
| if not isinstance(cert_ca, str): |
| cert_ca = cert_ca.decode() |
| if not isinstance(private_key, str): |
| private_key = private_key.decode() |
| if len(cert_ca) > 100 and len(private_key) > 100: |
| public.writeFile('/etc/pki/dovecot/certs/dovecot.pem', cert_ca) |
| public.writeFile('/etc/pki/dovecot/private/dovecot.pem', private_key) |
| return True |
| else: |
| mail_sys_main.main().restore_file('/etc/pki/dovecot/certs/dovecot.pem') |
| mail_sys_main.main().restore_file('/etc/pki/dovecot/private/dovecot.pem') |
| return False |
|
|
| def check_postfix_ver(self): |
| postfix_version = public.ExecShell(r"{postconf} mail_version|sed -r 's/.* ([0-9\.]+)$/\1/'".format( |
| postconf=get_postconf()))[0].strip() |
| if postfix_version.startswith('3'): |
| return public.returnMsg(True,postfix_version) |
| else: |
| return public.returnMsg(False,"当前版本不支持或Postfix没有安装成功:{}".format(postfix_version)) |
|
|
| def check_redis_passwd(self,redis_install): |
| redis_conf = public.readFile('/www/server/redis/redis.conf') |
| if redis_install['status']: |
| if re.search('\n\s*requirepass',redis_conf): |
| return public.returnMsg(True,"Redis已经设置密码") |
| return public.returnMsg(False,"请到Redis管理器设置密码!") |
|
|
| def check_sqlite(self): |
| if not public.ExecShell('{postconf} -m | grep sqlite'.format(postconf=get_postconf()))[0].strip(): |
| return public.returnMsg(False,"Postfix的Sqlite包异常,请检查") |
| return public.returnMsg(True,"Postfix已支持Sqlite") |
|
|
| def setup_rspamd(self): |
| |
| |
| self.write_logs('|-Initializing rspamd...') |
| edit_postfix_conf_shell = ''' |
| {postconf} -e "smtpd_milters = inet:127.0.0.1:11332" |
| {postconf} -e "non_smtpd_milters = inet:127.0.0.1:11332" |
| {postconf} -e "milter_mail_macros = i {{mail_addr}} {{client_addr}} {{client_name}} {{auth_authen}}" |
| {postconf} -e "milter_protocol = 6" |
| {postconf} -e "milter_default_action = accept" |
| '''.format(postconf=get_postconf()) |
| public.ExecShell(edit_postfix_conf_shell) |
| self.write_logs('|-Downloading additional configuration files...') |
| get_rspamd_conf_shell = """ |
| mkdir -p /usr/lib/dovecot/sieve |
| wget -O /etc/rspamd/worker-normal.inc {download_conf_url}/mail_sys/rspamd/worker-normal.inc -T 20 --no-check-certificate >> {logfile} 2>&1 |
| wget -O /etc/rspamd/worker-fuzzy.inc {download_conf_url}/mail_sys/rspamd/worker-fuzzy.inc -T 20 --no-check-certificate >> {logfile} 2>&1 |
| wget -O /etc/rspamd/statistic.conf {download_conf_url}/mail_sys/rspamd/statistic.conf -T 20 --no-check-certificate >> {logfile} 2>&1 |
| wget -O /etc/rspamd/local.d/worker-controller.inc {download_conf_url}/mail_sys/rspamd/worker-controller.inc -T 20 --no-check-certificate >> {logfile} 2>&1 |
| wget -O /etc/rspamd/worker-proxy.inc {download_conf_url}/mail_sys/rspamd/worker-proxy.inc -T 20 --no-check-certificate >> {logfile} 2>&1 |
| wget -O /etc/rspamd/local.d/dkim_signing.conf {download_conf_url}/mail_sys/rspamd/modules.d/dkim_signing_bt.conf -T 20 --no-check-certificate >> {logfile} 2>&1 |
| wget -O /etc/rspamd/local.d/milter_headers.conf {download_conf_url}/mail_sys/rspamd/modules.d/milter_headers_bt.conf -T 20 --no-check-certificate >> {logfile} 2>&1 |
| wget -O /etc/rspamd/local.d/redis.conf {download_conf_url}/mail_sys/rspamd/modules.d/redis_bt.conf -T 20 --no-check-certificate >> {logfile} 2>&1 |
| |
| wget -O /usr/lib/dovecot/sieve/report-ham.sieve {download_conf_url}/mail_sys/dovecot/lib/report-ham.sieve -T 20 --no-check-certificate >> {logfile} 2>&1 |
| wget -O /usr/lib/dovecot/sieve/report-spam.sieve {download_conf_url}/mail_sys/dovecot/lib/report-spam.sieve -T 20 --no-check-certificate >> {logfile} 2>&1 |
| wget -O /usr/lib/dovecot/sieve/spam-to-folder.sieve {download_conf_url}/mail_sys/dovecot/lib/spam-to-folder.sieve -T 20 --no-check-certificate >> {logfile} 2>&1 |
| wget -O /usr/lib/dovecot/sieve/sa-learn-spam.sh {download_conf_url}/mail_sys/dovecot/lib/sa-learn-spam.sh -T 20 --no-check-certificate >> {logfile} 2>&1 |
| wget -O /usr/lib/dovecot/sieve/sa-learn-ham.sh {download_conf_url}/mail_sys/dovecot/lib/sa-learn-ham.sh -T 20 --no-check-certificate >> {logfile} 2>&1 |
| sievec /usr/lib/dovecot/sieve/spam-to-folder.sieve |
| sievec /usr/lib/dovecot/sieve/report-spam.sieve |
| sievec /usr/lib/dovecot/sieve/report-ham.sieve |
| chmod +x /usr/lib/dovecot/sieve/sa-learn-spam.sh |
| chmod +x /usr/lib/dovecot/sieve/sa-learn-ham.sh |
| """.format(download_conf_url=download_url,logfile=self.logfile) |
| public.ExecShell(get_rspamd_conf_shell) |
| |
| self.write_logs('|-Generating rspamd management password...') |
| passwd = public.GetRandomString(8) |
| passwd_en = public.ExecShell('rspamadm pw -p "{}"'.format(passwd))[0].strip('\n') |
| public.writeFile('/etc/rspamd/passwd', passwd) |
| worker_controller_path = '/etc/rspamd/local.d/worker-controller.inc' |
| worker_controller = public.readFile(worker_controller_path) |
| if worker_controller: |
| if 'BT_PASSWORD' in worker_controller: |
| worker_controller = worker_controller.replace('password = "BT_PASSWORD";', |
| 'password = "{}";'.format(passwd_en)) |
| public.writeFile(worker_controller_path, worker_controller) |
| |
| rspamd_redis_path = '/etc/rspamd/local.d/redis.conf' |
| rspamd_redis = public.readFile(rspamd_redis_path) |
| if rspamd_redis: |
| if 'BT_REDIS_PASSWD' in rspamd_redis: |
| rspamd_redis = rspamd_redis.replace('password = "BT_REDIS_PASSWD";', |
| 'password = "{}";'.format(self.get_redis_passwd())) |
| public.writeFile(rspamd_redis_path, rspamd_redis) |
| self.write_logs('|-Restarting rspamd...') |
| public.ExecShell('systemctl restart rspamd postfix dovecot') |
| return True |
|
|
| def get_redis_passwd(self): |
| redis_path = '/www/server/redis/redis.conf' |
| redis_conf = public.readFile(redis_path) |
| passwd = re.search('\n\s*requirepass\s+(.*)',redis_conf) |
| if passwd: |
| return passwd.groups(0)[0] |
| return False |
|
|
| def install_dovecot_on_ubuntu(self): |
| install_shell = """ |
| sudo apt remove dovecot-core dovecot-imapd dovecot-lmtpd dovecot-pop3d dovecot-sqlite dovecot-sieve -y |
| dpkg -P dovecot-core dovecot-imapd dovecot-lmtpd dovecot-pop3d dovecot-sqlite dovecot-sieve |
| sudo apt install dovecot-core dovecot-pop3d dovecot-imapd dovecot-lmtpd dovecot-sqlite dovecot-sieve -y |
| """ |
| public.ExecShell(install_shell) |
| shell_str = """ |
| sudo rm -f /etc/pki/dovecot/certs/dovecot.pem |
| sudo rm -f /etc/pki/dovecot/private/dovecot.pem |
| sudo mkdir -p /etc/pki/dovecot/certs/ |
| sudo mkdir -p /etc/pki/dovecot/private/ |
| sudo cp /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/pki/dovecot/certs/dovecot.pem |
| sudo mv /etc/ssl/private/ssl-cert-snakeoil.key /etc/pki/dovecot/private/dovecot.pem |
| """ |
| public.ExecShell(shell_str) |
| return self.conf_dovecot() |
|
|
| def install_dovecot_on_centos7(self): |
| install_shell = """ |
| yum remove dovecot -y |
| yum install dovecot-pigeonhole -y |
| yum install dovecot -y |
| """ |
| public.ExecShell(install_shell) |
| return self.conf_dovecot() |
|
|
| def install_dovecot_on_centos8(self): |
| install_shell = """ |
| yum remove dovecot -y |
| yum install dovecot-pigeonhole -y |
| yum install dovecot -y |
| """ |
| public.ExecShell(install_shell) |
| return self.conf_dovecot() |
|
|
| def install_postfix_on_ubuntu(self): |
| back_shell = "" |
| restore_shell = "" |
| if os.path.exists("/etc/postfix/main.cf"): |
| back_shell = "mv /etc/postfix /etc/postfix_aap_bak" |
| restore_shell = """ |
| sudo rm -rf /etc/postfix |
| mv /etc/postfix_aap_bak /etc/postfix |
| """ |
| install_shell = """ |
| %s |
| sudo apt remove postfix postfix-sqlite -y |
| sudo dpkg -P postfix postfix-sqlite |
| sudo debconf-set-selections <<< "postfix postfix/mailname string ${hostname}" |
| sudo debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'" |
| sudo apt install postfix -y |
| sudo apt install postfix-sqlite -y |
| sudo apt install sqlite -y |
| %s |
| """ % (back_shell,restore_shell) |
| public.ExecShell(install_shell) |
|
|
| def install_postfix_on_centos7(self): |
| back_shell = "" |
| restore_shell = "" |
| if os.path.exists("/etc/postfix/main.cf"): |
| back_shell = "mv /etc/postfix /etc/postfix_aap_bak" |
| restore_shell = """ |
| sudo rm -rf /etc/postfix |
| mv /etc/postfix_aap_bak /etc/postfix |
| """ |
| install_shell = """ |
| {b} |
| yum remove postfix -y |
| wget -O /tmp/postfix3-3.4.7-1.gf.el7.x86_64.rpm {download_conf_url}/install/plugin/mail_sys/rpm/postfix3-3.4.7-1.gf.el7.x86_64.rpm |
| yum localinstall /tmp/postfix3-3.4.7-1.gf.el7.x86_64.rpm -y |
| rm -f /tmp/postfix3-3.4.7-1.gf.el7.x86_64.rpm |
| wget -O /tmp/postfix3-sqlite-3.4.7-1.gf.el7.x86_64.rpm {download_conf_url}/install/plugin/mail_sys/rpm/postfix3-sqlite-3.4.7-1.gf.el7.x86_64.rpm |
| yum localinstall /tmp/postfix3-sqlite-3.4.7-1.gf.el7.x86_64.rpm -y |
| /tmp/postfix3-sqlite-3.4.7-1.gf.el7.x86_64.rpm |
| {r} |
| """.format(download_conf_url=download_url,b=back_shell,r=restore_shell) |
| public.ExecShell(install_shell) |
|
|
| def install_postfix_on_centos8(self): |
| back_shell = "" |
| restore_shell = "" |
| if os.path.exists("/etc/postfix/main.cf"): |
| back_shell = "mv /etc/postfix /etc/postfix_aap_bak" |
| restore_shell = """ |
| sudo rm -rf /etc/postfix |
| mv /etc/postfix_aap_bak /etc/postfix |
| """ |
| install_shell = """ |
| {b} |
| yum remove postfix -y |
| wget -O /tmp/postfix3-3.4.9-1.gf.el8.x86_64.rpm {download_conf_url}/install/plugin/mail_sys/rpm/postfix3-3.4.9-1.gf.el8.x86_64.rpm |
| yum localinstall /tmp/postfix3-3.4.9-1.gf.el8.x86_64.rpm -y |
| rm -f /tmp/postfix3-3.4.9-1.gf.el8.x86_64.rpm |
| wget -O /tmp/postfix3-sqlite-3.4.9-1.gf.el8.x86_64.rpm {download_conf_url}/install/plugin/mail_sys/rpm/postfix3-sqlite-3.4.9-1.gf.el8.x86_64.rpm |
| yum localinstall /tmp/postfix3-sqlite-3.4.9-1.gf.el8.x86_64.rpm -y |
| rm -f /tmp/postfix3-sqlite-3.4.9-1.gf.el8.x86_64.rpm |
| {r} |
| """.format(download_conf_url=download_url,b=back_shell,r=restore_shell) |
| public.ExecShell(install_shell) |
|
|
| if __name__ == '__main__': |
| args = sys.argv |
| if len(args) > 1: |
| if args[1] == 'change_to_rspamd': |
| change_to_rspamd().main() |
| elif args[1] == 'setup_mail_sys': |
| print(mail_server_init().setup_mail_sys(args)) |
| elif args[1] == 'check_env': |
| print(mail_server_init().check_env()) |
| elif args[1] == 'install_dovecot_on_ubuntu': |
| print(mail_server_init().install_dovecot_on_ubuntu()) |
| elif args[1] == 'install_dovecot_on_centos7': |
| print(mail_server_init().install_dovecot_on_centos7()) |
| elif args[1] == 'install_dovecot_on_centos8': |
| print(mail_server_init().install_dovecot_on_centos8()) |
| elif args[1] == 'install_postfix_on_ubuntu': |
| print(mail_server_init().install_postfix_on_ubuntu()) |
| elif args[1] == 'install_postfix_on_centos7': |
| print(mail_server_init().install_postfix_on_centos7()) |
| elif args[1] == 'install_postfix_on_centos8': |
| print(mail_server_init().install_postfix_on_centos8()) |
| else: |
| print('args error') |
| else: |
| print('args error') |