稳定后,再合并。
This commit is contained in:
midoks
2022-09-19 20:05:05 +08:00
parent 3722f57347
commit 4c05747942
10 changed files with 0 additions and 2570 deletions
-42
View File
@@ -1,42 +0,0 @@
CREATE TABLE IF NOT EXISTS `domain` (
`domain` varchar(255) NOT NULL,
`a_record` TEXT DEFAULT "",
`created` datetime NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`domain`)
);
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`)
);
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`)
);
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`)
);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

File diff suppressed because it is too large Load Diff
-489
View File
@@ -1,489 +0,0 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import socket
from datetime import datetime
try:
import dns.resolver
except:
if os.path.exists(os.getcwd() + '/bin'):
mw.mw(os.getcwd() + '/bin/pip install dnspython')
else:
mw.execShell('pip install dnspython')
import dns.resolver
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
import mail_init as mi
class App:
__setupPath = '/www/server/mail'
__session_conf = __setupPath + '/session.json'
_check_time = 86400
def __init__(self):
self.__setupPath = self.getServerDir()
self._session = self.__get_session()
def getArgs(self):
args = sys.argv[3:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':')
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def check_mail_sys(self):
args = self.getArgs()
if os.path.exists('/etc/postfix/sqlite_virtual_domains_maps.cf'):
mw.execShell(
'/sbin/postconf -e "message_size_limit = 102400000"')
# 修改postfix mydestination配置项
result = mw.readFile(self.postfix_main_cf)
if not result:
return mw.returnJson(False, "找不到postfix配置文件")
result = re.search(r"\n*mydestination\s*=(.+)", result)
if not result:
return mw.returnJson(False, "postfix配置文件中找不到mydestination配置项")
result = result.group(1)
if 'localhost' in result or '$myhostname' in result or '$mydomain' in result:
mw.execShell(
'/sbin/postconf -e "mydestination =" && systemctl restart postfix')
# 修改dovecot配置
dovecot_conf = public.readFile("/etc/dovecot/dovecot.conf")
if not dovecot_conf or not re.search(r"\n*protocol\s*imap", dovecot_conf):
return mw.returnJson(False, '配置dovecot失败')
# 修复之前版本未安装opendkim的问题
# if not (os.path.exists("/usr/sbin/opendkim") and os.path.exists("/etc/opendkim.conf") and os.path.exists("/etc/opendkim")):
# if not self.setup_opendkim():
# return public.returnMsg(False, 'Failed to configure opendkim 1')
return mw.returnJson(True, '邮局系统已经存在,重装之前请先卸载!')
else:
return mw.returnJson(False, '之前没有安装过邮局系统,请放心安装!')
def __get_session(self):
session = mw.readFile(self.__session_conf)
if session:
session = json.loads(session)
else:
session = {}
return session
def __get_dkim_value(self, domain):
'''
解析/etc/opendkim/keys/domain/default.txt得到域名要设置的dkim记录值
:param domain:
:return:
'''
if not os.path.exists("/www/server/dkim/{}".format(domain)):
os.makedirs("/www/server/dkim/{}".format(domain))
rspamd_pub_file = '/www/server/dkim/{}/default.pub'.format(domain)
opendkim_pub_file = '/etc/opendkim/keys/{0}/default.txt'.format(domain)
if os.path.exists(opendkim_pub_file) and not os.path.exists(rspamd_pub_file):
opendkim_pub = mw.readFile(opendkim_pub_file)
mw.writeFile(rspamd_pub_file, opendkim_pub)
rspamd_pri_file = '/www/server/dkim/{}/default.private'.format(
domain)
opendkim_pri_file = '/etc/opendkim/keys/{}/default.private'.format(
domain)
opendkim_pri = mw.readFile(opendkim_pri_file)
mw.writeFile(rspamd_pri_file, opendkim_pri)
if not os.path.exists(rspamd_pub_file):
return ''
file_body = mw.readFile(rspamd_pub_file).replace(
' ', '').replace('\n', '').split('"')
value = file_body[1] + file_body[3]
return value
def __check_mx(self, domain):
'''
检测域名是否有mx记录
:param domain:
:return:
'''
a_record = self.M('domain').where(
'domain=?', (domain,)).field('a_record').find()['a_record']
key = '{0}:{1}'.format(domain, 'MX')
now = int(time.time())
try:
value = ""
if key in self._session and self._session[key]["status"] != 0:
v_time = now - int(self._session[key]["v_time"])
if v_time < self._check_time:
value = self._session[key]["value"]
if '' == value:
resolver = dns.resolver.Resolver()
resolver.timeout = 1
try:
result = resolver.resolve(domain, 'MX')
except:
result = resolver.query(domain, 'MX')
value = str(result[0].exchange).strip('.')
if not a_record:
a_record = value
self.M('domain').where('domain=?', (domain,)).save(
'a_record', (a_record,))
if value == a_record:
self._session[key] = {"status": 1,
"v_time": now, "value": value}
return True
self._session[key] = {"status": 0, "v_time": now, "value": value}
return False
except:
# print(public.get_error_info())
self._session[key] = {"status": 0, "v_time": now,
"value": "None of DNS query names exist:{}".format(domain)}
return False
def __check_spf(self, domain):
'''
检测域名是否有spf记录
:param domain:
:return:
'''
key = '{0}:{1}'.format(domain, 'TXT')
now = int(time.time())
try:
value = ""
if key in self._session and self._session[key]["status"] != 0:
v_time = now - int(self._session[key]["v_time"])
if v_time < self._check_time:
value = self._session[key]["value"]
if '' == value:
resolver = dns.resolver.Resolver()
resolver.timeout = 1
# try:
result = resolver.resolve(domain, 'TXT')
# except:
# result = resolver.query(domain, 'TXT')
for i in result.response.answer:
for j in i.items:
value += str(j).strip()
if 'v=spf1' in value.lower():
self._session[key] = {"status": 1,
"v_time": now, "value": value}
return True
self._session[key] = {"status": 0, "v_time": now, "value": value}
return False
except:
# print(public.get_error_info())
self._session[key] = {"status": 0, "v_time": now,
"value": "None of DNS query spf exist:{}".format(domain)}
return False
def __check_dkim(self, domain):
'''
检测域名是否有dkim记录
:param domain:
:return:
'''
origin_domain = domain
domain = 'default._domainkey.{0}'.format(domain)
key = '{0}:{1}'.format(domain, 'TXT')
now = int(time.time())
try:
value = ""
if key in self._session and self._session[key]["status"] != 0:
v_time = now - int(self._session[key]["v_time"])
if v_time < self._check_time:
value = self._session[key]["value"]
if '' == value:
resolver = dns.resolver.Resolver()
resolver.timeout = 1
result = resolver.resolve(domain, 'TXT')
for i in result.response.answer:
for j in i.items:
value += str(j).strip()
new_v = self._get_dkim_value(origin_domain)
if new_v and new_v in value:
self._session[key] = {"status": 1,
"v_time": now, "value": value}
return True
self._session[key] = {"status": 0, "v_time": now, "value": value}
return False
except:
# print(public.get_error_info())
self._session[key] = {"status": 0, "v_time": now,
"value": "None of DNS query names exist:{}".format(domain)}
return False
def __check_dmarc(self, domain):
'''
检测域名是否有dmarc记录
:param domain:
:return:
'''
domain = '_dmarc.{0}'.format(domain)
key = '{0}:{1}'.format(domain, 'TXT')
now = int(time.time())
try:
value = ""
if key in self._session and self._session[key]["status"] != 0:
v_time = now - int(self._session[key]["v_time"])
if v_time < self._check_time:
value = self._session[key]["value"]
if '' == value:
resolver = dns.resolver.Resolver()
resolver.timeout = 1
result = resolver.resolve(domain, 'TXT')
for i in result.response.answer:
for j in i.items:
value += str(j).strip()
if 'v=dmarc1' in value.lower():
self._session[key] = {"status": 1,
"v_time": now, "value": value}
return True
self._session[key] = {"status": 0, "v_time": now, "value": value}
return False
except:
# print(public.get_error_info())
self._session[key] = {"status": 0, "v_time": now,
"value": "None of DNS query names exist:{}".format(domain)}
return False
def __gevent_jobs(self, domain, a_record):
from gevent import monkey
# monkey.patch_all()
import gevent
gevent.joinall([
gevent.spawn(self.__check_mx, domain),
gevent.spawn(self.__check_spf, domain),
gevent.spawn(self.__check_dkim, domain),
gevent.spawn(self.__check_dmarc, domain),
gevent.spawn(self.__check_a, a_record),
])
return True
def getInitDFile(self):
if app_debug:
return '/tmp/' + getPluginName()
return '/etc/init.d/' + getPluginName()
def getPluginName(self):
return 'mail'
def getPluginDir(self):
return mw.getPluginDir() + '/' + self.getPluginName()
def getServerDir(self):
return mw.getServerDir() + '/' + self.getPluginName()
def M(self, dbname='domain'):
file = self.getServerDir() + '/postfixadmin.db'
name = 'mail'
if not os.path.exists(file):
conn = mw.M(dbname).dbPos(self.getServerDir(), name)
csql = mw.readFile(self.getPluginDir() + '/conf/postfixadmin.sql')
csql_list = csql.split(';')
for index in range(len(csql_list)):
conn.execute(csql_list[index], ())
else:
# 现有run
# conn = mw.M(dbname).dbPos(getServerDir(), name)
# csql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
# csql_list = csql.split(';')
# for index in range(len(csql_list)):
# conn.execute(csql_list[index], ())
conn = mw.M(dbname).dbPos(self.getServerDir(), name)
return conn
def status(self):
return 'start'
def get_domains(self):
args = self.getArgs()
p = int(args['p']) if 'p' in args else 1
rows = int(args['size']) if 'size' in args else 10
callback = args['callback'] if 'callback' in args else ''
count = self.M('domain').count()
data = {}
# 获取分页数据
_page = {}
_page['count'] = count
_page['p'] = p
_page['row'] = rows
_page['tojs'] = callback
data['page'] = mw.getPage(_page)
start_pos = (_page['p'] - 1) * _page['row']
data_list = self.M('domain').order('created desc').limit(
str(start_pos) + ',' + str(_page['row'])).field('domain,a_record,created,active').select()
# print(data)
# print(data_list)
return mw.returnJson(True, 'ok', {'data': data_list, 'page': data['page']})
def runLog(self):
path = '/var/log/maillog'
# if "ubuntu" in:
# path = '/var/log/mail.log'
return path
def add_domain(self):
args = self.getArgs()
if 'domain' not in args:
return mw.returnJson(False, '请传入域名')
domain = args['domain']
a_record = args['a_record']
if not a_record.endswith(domain):
return mw.returnJson(False, 'A记录 [{}] 不属于该域名'.format(a_record))
if not mw.isDebugMode():
check = self.__check_a(a_record)
if not check[0]:
return mw.returnJson(False, 'A记录解析失败<br>域名:{}<br>IP:{}'.format(a_record, check[1]['value']))
if self.M('domain').where("domain=?", (domain,)).count() > 0:
return mw.returnJson(False, '该域名已存在')
cur_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
try:
self.M('domain').add('domain,a_record,created',
(domain, a_record, cur_time))
except:
return mw.returnJson(False, '邮局没有初始化成功!<br>'
'请尝试重新初始化,<br>'
'如果以下端口没访问将无法初始化 <br>port 25 [outbound direction]<br> '
'你可以尝试执行以下命令测试端口是否开启:<br><br> [ telnet gmail-smtp-in.l.google.com 25 ] <br> ')
# 在虚拟用户家目录创建对应域名的目录
if os.path.exists('/www/vmail'):
if not os.path.exists('/www/vmail/{0}'.format(domain)):
os.makedirs('/www/vmail/{0}'.format(domain))
mw.execShell('chown -R vmail:mail /www/vmail/{0}'.format(domain))
return mw.returnJson(False, 'OK')
def __check_a(self, hostname):
key = '{0}:{1}'.format(hostname, 'A')
now = int(time.time())
value = ""
error_ip = ""
ipaddress = mw.getLocalIp()
if not ipaddress:
return False, {"status": 0, "v_time": now, "value": error_ip}
try:
resolver = dns.resolver.Resolver()
resolver.timeout = 1
try:
result = resolver.resolve(hostname, 'A')
except:
result = resolver.query(hostname, 'A')
for i in result.response.answer:
for j in i.items:
error_ip = j
if str(j).strip() in ipaddress:
value = str(j).strip()
if value:
return True, {"status": 1, "v_time": now, "value": value}
return False, {"status": 0, "v_time": now, "value": error_ip}
except Exception as e:
raise e
return False, {"status": 0, "v_time": now, "value": error_ip}
def flush_domain_record(self):
'''
手动刷新域名记录
domain all/specify.com
:param args:
:return:
'''
args = self.getArgs()
if args['domain'] == 'all':
data_list = self.M('domain').order('created desc').field(
'domain,a_record,created,active').select()
for item in data_list:
# try:
# if os.path.exists("/usr/bin/rspamd"):
# self.set_rspamd_dkim_key(item['domain'])
# if os.path.exists("/usr/sbin/opendkim"):
# self._gen_dkim_key(item['domain'])
# except:
# return mw.returnJson(False, '请检查Rspamd服务器是否已经启动!')
self.__gevent_jobs(item['domain'], item['a_record'])
# else:
# try:
# if os.path.exists("/usr/bin/rspamd"):
# self.set_rspamd_dkim_key(args.domain)
# if os.path.exists("/usr/sbin/opendkim"):
# self._gen_dkim_key(args.domain)
# except:
# return mw.returnJson(False, '请检查Rspamd服务器是否已经启动!')
# self._gevent_jobs(args['domain'], None) # 不需要验证A记录
# mw.writeFile(self._session_conf, json.dumps(self._session))
return mw.returnJson(True, '刷新成功!')
def check_mail_env(self):
data = mi.mail_init().check_env()
return mw.returnJson(True, 'ok', data)
def change_hostname(self):
'''
mac
sudo scutil --set HostName mac_hostname.vm
'''
args = self.getArgs()
hostname = args['hostname']
rep_domain = "^(?=^.{3,255}$)[a-zA-Z0-9\_\-][a-zA-Z0-9\_\-]{0,62}(\.[a-zA-Z0-9\_\-][a-zA-Z0-9\_\-]{0,62})+$"
if not re.search(rep_domain, hostname):
return mw.returnJson(False, "请输入完整域名,例如 mail.bt.com),")
mw.execShell('hostnamectl set-hostname --static {}'.format(hostname))
h = socket.gethostname()
if h == hostname:
return mw.returnJson(True, "设置成功!")
return mw.returnJson(False, "设置失败!")
if __name__ == "__main__":
func = sys.argv[1]
classApp = App()
try:
data = eval("classApp." + func + "()")
print(data)
except Exception as e:
print('error:' + str(e))
-18
View File
@@ -1,18 +0,0 @@
{
"sort": 7,
"ps": "简单邮件服务[DEV]",
"name": "mail",
"title": "邮件服务",
"shell": "install.sh",
"versions":["1.0"],
"updates":["1.0"],
"tip": "soft",
"checks": "server/mail",
"path": "server/mail",
"display": 1,
"author": "midoks",
"date": "2022-09-13",
"home": "https://github.com/midoks/mdserver-web",
"type": 0,
"pid": "5"
}
-33
View File
@@ -1,33 +0,0 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
pip install dnspython
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
pip install dnspython
fi
action=$1
type=$2
if [ "${2}" == "" ];then
echo '缺少安装脚本...' > $install_tmp
exit 0
fi
if [ ! -d $curPath/versions/$2 ];then
echo '缺少安装脚本2...' > $install_tmp
exit 0
fi
sh -x $curPath/versions/$2/install.sh $1
-626
View File
@@ -1,626 +0,0 @@
var mail = {
plugin_name: 'mail',
post_env_list:['HostName','Postfix-Version','Postfix-install','Sqlite-support','Dovecot-install','Redis-install','Redis-Passwd','Rspamd-install','SElinux'],
post_env_text:['主机名','Postfix版本','Postfix安装','Sqlite支持','Dovecot安装','Redis安装','Redis密码','Rspamd','SElinux'],
init: function () {
var _this = this;
this.event();
$('.layui-layer-page').hide();
setTimeout(function () {
var win = $(window),
layer = $('.layui-layer-page');
layer.show();
layer.css({
'width':'1080px',
'top':((win.height()-layer.height())/2)+'px',
'left':((win.width()-1000)/2)+'px',
'zIndex':'999'
});
$('.layui-layer-shade').css('zIndex', '998');
}, 200);
_this.check_mail_sys({
tips: '正在检查邮局服务是否正常,请稍后....',
hostname: ''
}, function (res) {
console.log("aaaa",res);
if (res.status == false && res.msg == '之前没有安装过邮局系统,请放心安装!') {
layer.confirm('当前未设置邮局服务,是否现在设置?', {
icon: 0,
title: '邮局初始化',
btn: ['设置', '取消'], //按钮
cancel: function () {
layer.closeAll();
}
}, function (index) {
_this.check_post_env('setup_mail_sys');
}, function () {
layer.closeAll();
});
} else {
// _this.create_domain_list();
$('.tasklist .tab-nav span:first').click(); // 初始化
_this.loadScript('/static/ckeditor/ckeditor.js', function () {
CKEDITOR.replace('editor1', {
customConfig: '/static/ckeditor/config.js?v1.0'
})
});
}
});
// _this.create_domain_list();
},
event: function () {
var _this = this;
$('.bt-w-main .bt-w-menu p').click(function () {
var index = $(this).index();
$(this).addClass('on').siblings().removeClass('on');
$('.soft-man-con .task_block').eq(index).show().siblings().hide();
console.log(index);
switch (index) {
case 0:
_this.create_domain_list();
// _this.get_mailSSL_status(function (res) {
// $('#certificateSSL').prop("checked", res);
// });
break;
}
});
console.log(_this);
},
// 编辑添加邮箱用户视图-方法
edit_domain_view: function (type, obj) {
var _this = this;
if (obj == undefined) {
obj = {
domain: '',
company_name: '',
admin_name: '',
admin_phone: ''
}
}
layer.open({
type: 1,
title: type ? '添加邮箱域名' : '编辑邮箱域名',
area: '500px',
closeBtn: 1,
btn: [type ? '提交' : '保存', '取消'],
content: "<div class='bt-form pd20'>\
<div class='line'>\
<span class='tname'>邮箱域名</span>\
<div class='info-r c4'>\
<input class='bt-input-text mr5' type='text' name='domain' " + (!type ? "readonly='readonly'" : "") +
" value='" + obj.domain + "' placeholder='请输入域名,例如btmail.cn' style='width:320px;' />\
</div>\
</div>\
<div class='line'>\
<span class='tname'>A记录</span>\
<div class='info-r c4'>\
<input class='bt-input-text mr5' type='text' name='a_record' " + (!type ? "readonly='readonly'" : "") +
" value='" + obj.domain + "' placeholder='请输入A记录,例如:btmail.btmail.cn' style='width:320px;' />\
</div>\
</div>\
<div class='line'>\
<ul class='help-info-text c7 mlr20' style='margin-top: 0px'>\
<li style='color: red;'>当前邮箱域名仅支持一级域名</li>\
<li>A记录解析参数[主机记录:mail或其他字符]、[记录值:当前服务器IP]</li>\
<li>A记录需要解析当前域名A记录,A记录=主机记录值+当前域名</li>\
</ul>\
</div>\
</div>",
yes: function (index, layers) {
var array = [
['domain', '邮箱域名不能为空!', 'a_record', 'A记录值不能为空!']
],
_form = {},
tel_reg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/;
for (var i = 0; i < array.length; i++) {
if ($('[name="' + array[i][0] + '"]').val() == '') {
layer.msg(array[i][1], {
icon: 2
});
return false;
} else if (array[i][0] == 'admin_phone' && !tel_reg.test($('[name="' + array[i]
[0] + '"]').val())) {
layer.msg('管理手机号码格式错误,请重试!', {
icon: 2
});
return false;
}
_form[array[i][0]] = $('[name="' + array[i][0] + '"]').val();
_form[array[i][2]] = $('[name="' + array[i][2] + '"]').val();
}
if (type) {
_this.add_domain(_form, function (res) {
console.log(res);
_this.create_domain_list({
page: 1,
size: 10
}, function (res) {
var rdata = res.msg.data,
hostname = rdata;
for (var i = 0; i < rdata.length; i++) {
if (rdata[i].domain == _form['domain']) hostname =
rdata[i]['domain']
}
layer.close(index);
});
});
} else {
_form['active'] = obj.active;
_this.update_domain(_form, function (res) {
_this.create_domain_list({
page: 1,
size: 10
}, function (res) {
layer.msg(res.msg, {
icon: 1
});
layer.close(index);
});
});
}
}
})
},
// 添加域名_请求
add_domain: function (obj, callback) {
this.send({
tips: '正在添加域名,请稍候...',
method: 'add_domain',
data: {
domain: obj.domain,
a_record: obj.a_record,
company_name: obj.company_name,
admin_name: obj.admin_name,
admin_phone: obj.admin_phone
},
success: function (res) {
if (callback) callback(res);
}
});
},
// 获取域名列表_请求
get_domain_list: function (obj, callback) {
this.send({
tips: '正在获取域名列表,请稍候....',
method: 'get_domains',
data: {
p: obj.page,
size: obj.size
},
success: function (res) {
if (callback) callback(res);
}
})
},
flush_domain_record: function(obj,callback){
var _this = this;
this.send({
tips: obj == 'all'?'正在刷新所有域名记录,刷新时间视域名数量而定,请稍后...':'Refresh domain record, please wait...',
method: 'flush_domain_record',
data: {
domain: obj
},
success: function (res) {
console.log(res);
if(res.status) _this.create_domain_list();
if (callback) callback(res);
}
});
},
// 创建域名列表-方法
create_domain_list: function (obj, callback) {
if (obj == undefined) obj = {
page: 1,
size: 10
}
var _this = this;
this.get_domain_list(obj, function (res) {
console.log(res);
var _tbody = '',
rdata = res.data.data;
_this.domain_list = rdata
if (rdata.length > 0) {
for (var i = 0; i < rdata.length; i++) {
_tbody += '<tr>\
<td>' + rdata[i].domain + '</td>\
<td>' + (rdata[i].mx_status ?
'<div style="color:#20a53a;"><span class="glyphicon glyphicon-ok" style="margin-right: 7px;"></span>已设置</div>' :
'<div style="color:red;display: inline-block;"><span class="glyphicon glyphicon-remove" style="margin-right: 7px;"></span><a href="javascript:;" style="color:red" onclick="mail.set_analysis_mail(\'' +
rdata[i].dkim_value + '\',\'' + rdata[i].dmarc_value + '\',\'' + rdata[i]
.domain + '\',\'' + rdata[i].mx_record + '\')">未设置记录值</a></div>') + '</td>\
<td>' + (rdata[i].a_status ?
'<div style="color:#20a53a;"><span class="glyphicon glyphicon-ok" style="margin-right: 7px;"></span>已设置</div>' :
'<div style="color:red;display: inline-block;"><span class="glyphicon glyphicon-remove" style="margin-right: 7px;"></span><a href="javascript:;" style="color:red" onclick="mail.set_analysis_mail(\'' +
rdata[i].dkim_value + '\',\'' + rdata[i].dmarc_value + '\',\'' + rdata[i]
.domain + '\',\'' + rdata[i].mx_record + '\')">未设置记录值</a></div>') + '</td>\
<td>' + (rdata[i].spf_status ?
'<div style="color:#20a53a;"><span class="glyphicon glyphicon-ok" style="margin-right: 7px;"></span>已设置</span></div>' :
'<div style="color:red;display: inline-block;"><span class="glyphicon glyphicon-remove" style="margin-right: 7px;"></span><a href="javascript:;" style="color:red" onclick="mail.set_analysis_mail(\'' +
rdata[i].dkim_value + '\',\'' + rdata[i].dmarc_value + '\',\'' + rdata[i]
.domain + '\',\'' + rdata[i].mx_record + '\')">未设置记录值</a></div>') + '</td>\
<td>' + (rdata[i].dkim_status ?
'<div style="color:#20a53a;"><span class="glyphicon glyphicon-ok" style="margin-right: 7px;"></span>已设置</span></div>' :
'<div style="color:red;display: inline-block;"><span class="glyphicon glyphicon-remove" style="margin-right: 7px;"></span><a href="javascript:;" style="color:red" onclick="mail.set_analysis_mail(\'' +
rdata[i].dkim_value + '\',\'' + rdata[i].dmarc_value + '\',\'' + rdata[i]
.domain + '\',\'' + rdata[i].mx_record + '\')">未设置记录值</a></div>') + '</td>\
<td>' + (rdata[i].dmarc_status ?
'<div style="color:#20a53a;"><span class="glyphicon glyphicon-ok" style="margin-right: 7px;"></span>已设置</span></div>' :
'<div style="color:red;display: inline-block;"><span class="glyphicon glyphicon-remove" style="margin-right: 7px;"></span><a href="javascript:;" style="color:red" onclick="mail.set_analysis_mail(\'' +
rdata[i].dkim_value + '\',\'' + rdata[i].dmarc_value + '\',\'' + rdata[i]
.domain + '\',\'' + rdata[i].mx_record + '\')">未设置记录值</a></div>') + '</td>\
<td><div><input type="checkbox" id="'+ rdata[i].domain +'" '+(rdata[i].catch_all ? 'checked':'')+' class="btswitch btswitch-ios catch_all"><label for="'+ rdata[i].domain +'" class="btswitch-btn"></label></div></td>\
<td><a href="javascript:;" class="btlink add_certificate" data-index='+i+'>'+(rdata[i].ssl_status?('到期时间: '+rdata[i].ssl_info.notAfter):'添加证书')+'</a></td>\
<td style="text-align: right;">' + (rdata[i].mx_status ? (
'<a href="javascript:;" class="btlink edit_ground_domain" data-hostname="' +
rdata[i].mx_record + '" data-domain="' + rdata[i].domain +
'" data-index="' + i + '">用户管理</a>') : (
'<a href="javascript:;" class="btlink" onclick="mail.set_analysis_mail(\'' +
rdata[i].dkim_value + '\',\'' + rdata[i].dmarc_value + '\',\'' + rdata[
i].domain + '\',\'' + rdata[i].mx_record + '\')">添加记录值</a>')) + '&nbsp;|&nbsp;\
<a href="javascript:;" class="btlink red del_domain" data-domain="' + rdata[i].domain + '">删除</a>\
</td>\
</tr>';
};
}
$('#domain_list').html(_tbody);
$('#domain_page').html(res.page);
$('#domain_page a').click(function (e) {
_this.create_domain_list({
page: $(this).attr('href').split('p=')[1],
size: 10
})
e.stopPropagation();
e.preventDefault();
})
$('#flush_domain_record').unbind().on('click',function(e){
_this.flush_domain_record('all',function(res){
layer.msg(res.msg, { icon: res.status ? 1 : 2 });
});
})
$('.add_certificate').unbind().on('click',function(){
var index = $(this).attr('data-index')
_this.open_certificate_view(rdata[index].ssl_status, rdata[index].domain, rdata[index].ssl_info.dns, index)
})
$('.catch_all').click(function (e) {
e.preventDefault();
var _catch = $(this),
_status = $(this).prop('checked'),
_html = _status ? '<div style="font-size: 12px;"><span>邮件转寄</span><input class="bt-input-text mr5 catchall" type="text" name="catchall" placeholder="捕获不存在的邮箱,转发到此邮箱" style="width:275px;margin-left: 10px;"></div>' : '确认关闭此功能?',
loadT = layer.confirm(_html, {title:'CatchAll设置', closeBtn: 2, area: '500'},function(){
var _email = _status ? $(".catchall").val() : '',
loadS = bt.load();
_this.enable_catchall({domain:_catch.attr('id'), email: _email},function(res){
loadS.close();
if(res.status) _catch.prop('checked', _status);
layer.msg(res.msg, { icon: res.status ? 1 : 2 });
loadT.close();
})
});
});
if (callback) callback(res);
});
},
// 获取邮箱服务是否正常_请求
check_mail_sys: function (obj, callback) {
this.send({
tips: obj.tips,
method: 'check_mail_sys',
data: {
hostname: obj.hostname
},
check: true,
success: function (res) {
if (callback) callback(res);
}
})
},
// 检查邮箱环境
check_mail_env:function(callback){
this.send({
tips: '正在检查邮局环境,请稍候...',
method: 'check_mail_env',
success: function (res) {
if (callback) callback(res);
}
})
},
//检查邮局环境
check_post_env:function (name) {
var _this = this;
var layerE = layer.open({
skin:"",
type: 1,
closeBtn:1,
title:'检查邮局环境',
area: ['600px','520px'], //宽高
btn: ['提交','取消','刷新列表'],
content:'\
<div class="pd20 mlr20 bt-mail-index" accept-charset="utf-8">\
<div id="checkPostEnv">\
<div class="divtable" style="max-height:auto;">\
<table class="table table-hover">\
<thead style="position:relative;z-index:1;">\
<tr>\
<th><span>环境</span></th>\
<th><span>详情</span></th>\
<th><span>操作</span></th>\
</tr>\
</thead>\
<tbody>\
</tbody>\
</table>\
</div>\
</div>\
<ul class="help-info-text c7 mlr20">\
<li>如果邮局环境异常,请先排除故障。 请在所有异常修复完成后执行下一步操作</li>\
</ul>\
</div>',
success:function(index){
_this.create_post_env_table();
},
cancel:function(){
layer.closeAll();
},
yes:function(){
if($('#checkPostEnv').find('.set_mail_key').length > 0){
layer.msg('请修复好所有的异常再提交');
}else{
switch (name){
case 'setup_mail_sys':
_this.setup_mail_sys({tips:'正在初始化邮局...'},function(res){
layer.close(layerE)
layer.msg(res.msg,{icon:res.status?1:2});
_this.create_domain_list();
});
break;
case 'change_to_rspamd':
_this.change_to_rspamd(function(res){
layer.close(layerE)
layer.msg(res.msg,{icon:res.status?1:2});
_this.create_server_status_table()
})
break;
}
}
},
btn3: function(index, layero){
_this.create_post_env_table();
return false;
},
btn2: function(index, layero){
name == 'change_to_rspamd'?layer.close(layerE):layer.closeAll();
},
})
},
//创建邮局环境列表
create_post_env_table:function (callback){
var _this = this;
_this.check_mail_env(function(rdata){
var res = rdata.data;
$('#checkPostEnv tbody').empty();
$.each(_this.post_env_list,function(index,item){
var list = [];
var noOperList = ['Redis-install', 'Redis-Passwd', 'SElinux'];
if(res[item].msg && noOperList.includes(item)){
$('#checkPostEnv tbody').append($('<tr><td>'+_this.post_env_text[index] +'</td><td title="'+res[item].msg.toString()+'" class="'+(res[item].status?'green':'set_mail_key red')+'">'+(res[item].status?"就绪":(res[item].msg.toString().length>30?res[item].msg.toString().substring(0,30)+'...':res[item].msg.toString()))+'</td><td>无操作</td></tr>'))
}else{
$('#checkPostEnv tbody').append($(`<tr><td>`+_this.post_env_text[index] +`</td><td title="`+res[item].msg+`" class="${(res[item].status?"green":"red")}">${(res[item].status?"就绪":(res[item].msg !=''?(res[item].msg.toString().length>30?res[item].msg.toString().substring(0,30)+'...':res[item].msg.toString()):"异常"))}</td><td>${(res[item].status?"无操作":"<a href='javascript:;' class='btlink set_mail_key' data-keys= "+ item+" >修复</a>")}</td></tr>`))
}
$('#checkPostEnv .divtable').removeClass('mtb10');
});
});
$('#checkPostEnv').unbind().on('click','a',function(){
var key = $(this).attr('data-keys');
var confirmA = layer.confirm('是否修复邮局环境?', {
title: '修复邮局环境',
icon: 3,
closeBtn:2,
btn: ['确定', '取消'],
},function(index, layero){
_this.repair_mail_env(key);
});
})
if(callback) callback()
},
//修复邮局环境
repair_mail_env: function (key) {
var _this = this,_key;
switch(key) {
case 'Postfix-Version':
case 'Postfix-install':
case 'Sqlite-support':
_key = 'repair_postfix';
break;
case 'Rspamd-install':
_key = 'install_rspamd';
break;
case 'Dovecot-install':
_key = 'repair_dovecot';
break;
case 'HostName':
_key = 'repair_host_name';
break;
}
if (key == 'HostName'){
this.repair_host_name();
return;
}
this.send({
tips: '正在修复' + key + ',请稍候...',
method: _key,
success: function (res) {
layer.msg(res.msg, { icon: res.status?1:2 });
_this.create_post_env_table();
}
})
},
// 修复hostname
repair_host_name: function () {
var _this = this;
layer.open({
type: 1,
shift: 5,
closeBtn: 1,
shadeClose: false,
title: '修复【主机名】',
btn: ['确定', '取消'],
area: "400px",
content: '\
<div class="bt-form pd20">\
<div class="line">\
<span class="tname">域名</span>\
<div class="info-r" style="margin-left: 102px;">\
<input class="bt-input-text" type="text" name="hostname" style="width: 190px" />\
</div>\
</div>\
<ul class="help-info-text c7">\
<li>请输入你的完整域名,如:mail.mw.cn</li>\
</ul>\
</div>',
success: function ($layer, index) {
},
yes: function(index){
var hostname = $('input[name="hostname"]').val().trim();
if (hostname === '') {
layer.msg('请输入你的完整域名', { icon: 2, closeBtn: true });
return
}
_this.change_hostname({
hostname: hostname,
}, function (res) {
layer.close(index);
_this.create_post_env_table();
layer.msg(res.msg, { icon: res.status ? 1 : 5 });
});
}
});
},
// 一键修复主机名
change_hostname: function(data, callback){
this.send({
tips: '正在获取修复主机名, 请稍候...',
method: 'change_hostname',
data: data,
success: function (res) {
if (callback) callback(res);
}
});
},
str2Obj:function(str){
var data = {};
kv = str.split('&');
for(i in kv){
v = kv[i].split('=');
data[v[0]] = v[1];
}
return data;
},
send:function(info){
var tips = info['tips'];
var method = info['method'];
var args = info['data'];
var callback = info['success'];
var loadT = layer.msg(tips, { icon: 16, time: 0, shade: 0.3 });
var data = {};
data['name'] = 'mail';
data['func'] = method;
data['version'] = $('.plugin_version').attr('version');
if (typeof(args) == 'string'){
data['args'] = JSON.stringify(this.str2Obj(args));
} else {
data['args'] = JSON.stringify(args);
}
$.post('/plugins/run', data, function(res) {
layer.close(loadT);
if (!res.status){
layer.msg(res.msg,{icon:2,time:10000});
return;
}
var ret_data = $.parseJSON(res.data);
console.log("send:",ret_data);
// if (!ret_data.status){
// layer.msg(ret_data.msg,{icon:2,time:2000});
// return;
// }
// console.log("send2:",ret_data);
if(typeof(callback) == 'function'){
callback(ret_data);
}
},'json');
},
postCallback:function(info){
var tips = info['tips'];
var method = info['method'];
var args = info['data'];
var callback = info['success'];
var loadT = layer.msg(tips, { icon: 16, time: 0, shade: 0.3 });
var data = {};
data['name'] = 'mail';
data['func'] = method;
data['version'] = $('.plugin_version').attr('version');
if (typeof(args) == 'string'){
data['args'] = JSON.stringify(this.str2Obj(args));
} else {
data['args'] = JSON.stringify(args);
}
$.post('/plugins/callback', data, function(res) {
layer.close(loadT);
if (!res.status){
layer.msg(res.msg,{icon:2,time:10000});
return;
}
var ret_data = $.parseJSON(res.data);
if (!ret_data.status){
layer.msg(ret_data.msg,{icon:2,time:2000});
return;
}
if(typeof(callback) == 'function'){
callback(res);
}
},'json');
}
}
-69
View File
@@ -1,69 +0,0 @@
# coding:utf-8
import sys
import io
import os
import time
import re
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
class mail_init:
def __init__(self):
self.logfile = '/tmp/mail_init.log'
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(
mw.getServerDir() + '/redis/bin/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 mw.execShell(
'getenforce')[0].lower() else {"status": False, "msg": "请先禁用SElinux"}
return data
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 mw.returnData(True, 'success')
return mw.returnData(False, '你的主机名 ({}) 不合规定, 需要是完整域名'
'你可以通过以下命令修复你的主机名 '
'在ssh终端执行 \'hostnamectl set-hostname --static mail.example.com\''.format(hostname))
def check_postfix_ver(self):
postfix_version = mw.execShell(
r"postconf mail_version|sed -r 's/.* ([0-9\.]+)$/\1/'")[0].strip()
if postfix_version.startswith('3'):
return mw.returnData(True, postfix_version)
else:
return mw.returnData(False, "当前版本不支持或Postfix没有安装成功:{}".format(postfix_version))
def check_redis_passwd(self, redis_install):
redis_conf = mw.readFile(mw.getServerDir() + '/redis/redis.conf')
if redis_install['status']:
if re.search('\n\s*requirepass', redis_conf):
return mw.returnData(True, "Redis已经设置密码")
return mw.returnData(False, "请到Redis管理器设置密码!")
def check_sqlite(self):
if not mw.execShell('postconf -m | grep sqlite')[0].strip():
return mw.returnData(False, "Postfix不支持Sqlite")
return mw.returnData(True, "Postfix已支持Sqlite")
-148
View File
@@ -1,148 +0,0 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
cpu_arch=`arch`
if [[ $cpu_arch != "x86_64" ]];then
echo 'Does not support non-x86 system installation'
exit 0
fi
# if [ -f "/usr/bin/apt-get" ];then
# systemver='ubuntu'
# elif [ -f "/etc/redhat-release" ];then
# systemver=`cat /etc/redhat-release|sed -r 's/.* ([0-9]+)\..*/\1/'`
# postfixver=`postconf mail_version|sed -r 's/.* ([0-9\.]+)$/\1/'`
# else
# echo 'Unsupported system version'
# exit 0
# fi
## curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update_dev.sh | bash
## debug:
## cd /www/server/mdserver-web/plugins/mail && bash install.sh install 1.0
bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl`
OSNAME_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
Install_debain(){
hostname=`hostname`
# 安装postfix和postfix-sqlite
debconf-set-selections <<< "postfix postfix/mailname string ${hostname}"
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'"
apt install postfix -y
apt install postfix-sqlite -y
apt install sqlite -y
# 安装dovecot和dovecot-sieve
apt install dovecot-core dovecot-pop3d dovecot-imapd dovecot-lmtpd dovecot-sqlite dovecot-sieve -y
apt install rspamd -y
apt install cyrus-sasl-plain -y
}
Uninstall_debain(){
apt remove postfix postfix-sqlite -y && rm -rf /etc/postfix
dpkg -P postfix postfix-sqlite
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
apt remove opendkim opendkim-tools -y
dpkg -P opendkim opendkim-tools
apt remove rspamd -y
dpkg -P rspamd
}
Install_ubuntu(){
Install_debain
}
Uninstall_ubuntu(){
Uninstall_debain
}
Install_App()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
runScript=$curPath/install_$OSNAME.sh
if [[ -f $runScript ]]; then
sh -x $runScript install
elif [[ $OSNAME = "debian" ]]; then
Install_debain
else
Install_ubuntu
fi
if [ ! -f /etc/dovecot/conf.d/90-sieve.conf ];then
if [ -f "/usr/bin/apt-get" ];then
apt install dovecot-sieve -y
else
rm -rf /etc/dovecot_back
cp -a /etc/dovecot /etc/dovecot_back
yum remove dovecot -y
yum install dovecot-pigeonhole -y
if [ ! -f /usr/sbin/dovecot ]; then
yum install dovecot -y
fi
\cp -a /etc/dovecot_back/* /etc/dovecot
chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot
systemctl enable dovecot
systemctl restart dovecot
fi
fi
filesize=`ls -l /etc/dovecot/dh.pem | awk '{print $5}'`
echo $filesize
if [ ! -f "/etc/dovecot/dh.pem" ] || [ $filesize -lt 300 ]; then
openssl dhparam 2048 > /etc/dovecot/dh.pem
fi
mkdir -p $serverPath/mail
echo '1.0' > $serverPath/mail/version.pl
echo '安装完成' > $install_tmp
}
Uninstall_App()
{
runScript=$curPath/install_$OSNAME.sh
if [[ -f $runScript ]]; then
sh -x $runScript uninstall
elif [[ $OSNAME = "debian" ]]; then
Uninstall_debain
else
Uninstall_ubuntu
fi
if [ -f $serverPath/mail/initd/mail ];then
$serverPath/mail/initd/mail stop
fi
rm -rf /etc/postfix
rm -rf /etc/dovecot
rm -rf /etc/opendkim
rm -rf /usr/share/rspamd/www/rspamd
echo "Uninstall_Mail" > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
-118
View File
@@ -1,118 +0,0 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
cpu_arch=`arch`
if [[ $cpu_arch != "x86_64" ]];then
echo 'Does not support non-x86 system installation'
exit 0
fi
OSNAME_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
Install_centos8()
{
yum install epel-release -y
# 卸载系统自带的postfix
if [[ $cpu_arch = "x86_64" && $postfixver != "3.4.9" ]];then
yum remove postfix -y
rm -rf /etc/postfix
fi
# 安装postfix和postfix-sqlite
yum localinstall $pluginPath/rpm/postfix3-3.4.9-1.gf.el8.x86_64.rpm -y
yum localinstall $pluginPath/rpm/postfix3-sqlite-3.4.9-1.gf.el8.x86_64.rpm -y
if [[ ! -f "/usr/sbin/postfix" ]]; then
yum install postfix -y
yum install postfix-sqlite -y
fi
# 安装dovecot和dovecot-sieve
yum install dovecot-pigeonhole -y
if [[ ! -f "/usr/sbin/dovecot" ]]; then
yum install dovecot -y
fi
# 安装opendkim
# 安装rspamd
install_rspamd
yum install cyrus-sasl-plain -y
}
Install_centos7() {
yum install epel-release -y
# 卸载系统自带的postfix
if [[ $cpu_arch = "x86_64" && $postfixver != "3.4.7" ]];then
yum remove postfix -y
rm -rf /etc/postfix
fi
# 安装postfix和postfix-sqlite
yum localinstall $pluginPath/rpm/postfix3-3.4.7-1.gf.el7.x86_64.rpm -y
yum localinstall $pluginPath/rpm/postfix3-sqlite-3.4.7-1.gf.el7.x86_64.rpm -y
if [[ ! -f "/usr/sbin/postfix" ]]; then
yum install postfix -y
yum install postfix-sqlite -y
fi
# 安装dovecot和dovecot-sieve
yum install dovecot-pigeonhole -y
if [[ ! -f "/usr/sbin/dovecot" ]]; then
yum install dovecot -y
fi
#安装rspamd
install_rspamd
yum install cyrus-sasl-plain -y
}
install_rspamd() {
if [[ $OSNAME_ID = "7" ]];then
wget -O /etc/yum.repos.d/rspamd.repo https://rspamd.com/rpm-stable/centos-7/rspamd.repo
rpm --import https://rspamd.com/rpm-stable/gpg.key
yum makecache
yum install rspamd -y
elif [ $OSNAME_ID = "8" ]; then
wget -O /etc/yum.repos.d/rspamd.repo https://rspamd.com/rpm-stable/centos-8/rspamd.repo
rpm --import https://rspamd.com/rpm-stable/gpg.key
yum makecache
yum install rspamd -y
else
CODENAME=`lsb_release -c -s`
mkdir -p /etc/apt/keyrings
wget -O- https://rspamd.com/apt-stable/gpg.key | gpg --dearmor | tee /etc/apt/keyrings/rspamd.gpg > /dev/null
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/rspamd.gpg] http://rspamd.com/apt-stable/ $CODENAME main" | tee /etc/apt/sources.list.d/rspamd.list
echo "deb-src [arch=amd64 signed-by=/etc/apt/keyrings/rspamd.gpg] http://rspamd.com/apt-stable/ $CODENAME main" | tee -a /etc/apt/sources.list.d/rspamd.list
apt-get update
export DEBIAN_FRONTEND=noninteractive
apt-get --no-install-recommends install rspamd -y
fi
}
Install_App() {
if [ "$OSNAME_ID" == "7" ];then
Install_centos7
elif [ "$OSNAME_ID" == "8" ];then
Install_centos8
fi
}
Uninstall_App()
{
yum remove postfix -y
yum remove dovecot -y
yum remove opendkim -y
yum remove rspamd -y
yum remove dovecot-pigeonhole -y
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi