mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2025-07-26 00:01:53 -04:00
Compare commits
24 Commits
5cb7c0f768
...
a8dfa95126
Author | SHA1 | Date | |
---|---|---|---|
|
a8dfa95126 | ||
|
3b3c2b7141 | ||
|
f55c3c0887 | ||
|
f423ad77f3 | ||
|
8ba1e1ba9e | ||
|
55576084fc | ||
|
03311b06c9 | ||
|
b5c3d01834 | ||
|
f398ecbe39 | ||
|
8f1ae0f099 | ||
|
c8bee57732 | ||
|
85641794c3 | ||
|
849decaa59 | ||
|
6e88550f92 | ||
|
7c52483887 | ||
|
0aa520c030 | ||
|
548999f163 | ||
|
63df547306 | ||
|
547d2ca308 | ||
|
46b995f9e3 | ||
|
afed94cc0e | ||
|
cfa47eb873 | ||
|
7079000ee0 | ||
|
03ed81dc3f |
2
.github/renovate.json
vendored
2
.github/renovate.json
vendored
@ -12,7 +12,7 @@
|
|||||||
"baseBranches": ["staging"],
|
"baseBranches": ["staging"],
|
||||||
"enabledManagers": ["github-actions", "regex", "docker-compose"],
|
"enabledManagers": ["github-actions", "regex", "docker-compose"],
|
||||||
"ignorePaths": [
|
"ignorePaths": [
|
||||||
"data\/web\/inc\/lib\/vendor\/matthiasmullie\/minify\/**"
|
"data\/web\/inc\/lib\/vendor\/**"
|
||||||
],
|
],
|
||||||
"regexManagers": [
|
"regexManagers": [
|
||||||
{
|
{
|
||||||
|
@ -75,7 +75,8 @@ my $sth = $dbh->prepare("SELECT id,
|
|||||||
custom_params,
|
custom_params,
|
||||||
subscribeall,
|
subscribeall,
|
||||||
timeout1,
|
timeout1,
|
||||||
timeout2
|
timeout2,
|
||||||
|
dry
|
||||||
FROM imapsync
|
FROM imapsync
|
||||||
WHERE active = 1
|
WHERE active = 1
|
||||||
AND is_running = 0
|
AND is_running = 0
|
||||||
@ -111,13 +112,16 @@ while ($row = $sth->fetchrow_arrayref()) {
|
|||||||
$subscribeall = @$row[18];
|
$subscribeall = @$row[18];
|
||||||
$timeout1 = @$row[19];
|
$timeout1 = @$row[19];
|
||||||
$timeout2 = @$row[20];
|
$timeout2 = @$row[20];
|
||||||
|
$dry = @$row[21];
|
||||||
|
|
||||||
if ($enc1 eq "TLS") { $enc1 = "--tls1"; } elsif ($enc1 eq "SSL") { $enc1 = "--ssl1"; } else { undef $enc1; }
|
if ($enc1 eq "TLS") { $enc1 = "--tls1"; } elsif ($enc1 eq "SSL") { $enc1 = "--ssl1"; } else { undef $enc1; }
|
||||||
|
|
||||||
my $template = $run_dir . '/imapsync.XXXXXXX';
|
my $template = $run_dir . '/imapsync.XXXXXXX';
|
||||||
my $passfile1 = File::Temp->new(TEMPLATE => $template);
|
my $passfile1 = File::Temp->new(TEMPLATE => $template);
|
||||||
my $passfile2 = File::Temp->new(TEMPLATE => $template);
|
my $passfile2 = File::Temp->new(TEMPLATE => $template);
|
||||||
|
|
||||||
|
binmode( $passfile1, ":utf8" );
|
||||||
|
|
||||||
print $passfile1 "$password1\n";
|
print $passfile1 "$password1\n";
|
||||||
print $passfile2 trim($master_pass) . "\n";
|
print $passfile2 trim($master_pass) . "\n";
|
||||||
|
|
||||||
@ -148,6 +152,7 @@ while ($row = $sth->fetchrow_arrayref()) {
|
|||||||
"--host2", "localhost",
|
"--host2", "localhost",
|
||||||
"--user2", $user2 . '*' . trim($master_user),
|
"--user2", $user2 . '*' . trim($master_user),
|
||||||
"--passfile2", $passfile2->filename,
|
"--passfile2", $passfile2->filename,
|
||||||
|
($dry eq "1" ? ('--dry') : ()),
|
||||||
'--no-modulesversion',
|
'--no-modulesversion',
|
||||||
'--noreleasecheck'];
|
'--noreleasecheck'];
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ ARG MAILPARSE_PECL_VERSION=3.1.6
|
|||||||
# renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?<version>.*)$
|
# renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?<version>.*)$
|
||||||
ARG MEMCACHED_PECL_VERSION=3.2.0
|
ARG MEMCACHED_PECL_VERSION=3.2.0
|
||||||
# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=(?<version>.*)$
|
# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=(?<version>.*)$
|
||||||
ARG REDIS_PECL_VERSION=6.0.1
|
ARG REDIS_PECL_VERSION=6.0.2
|
||||||
# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=(?<version>.*)$
|
# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=(?<version>.*)$
|
||||||
ARG COMPOSER_VERSION=2.6.5
|
ARG COMPOSER_VERSION=2.6.5
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ server {
|
|||||||
deny all;
|
deny all;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
|
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+)\.php(?:$|\/) {
|
||||||
fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
|
fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
|
||||||
set $path_info $fastcgi_path_info;
|
set $path_info $fastcgi_path_info;
|
||||||
try_files $fastcgi_script_name =404;
|
try_files $fastcgi_script_name =404;
|
||||||
@ -105,7 +105,7 @@ server {
|
|||||||
fastcgi_read_timeout 1200;
|
fastcgi_read_timeout 1200;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
|
location ~ ^\/(?:updater|ocs-provider)(?:$|\/) {
|
||||||
try_files $uri/ =404;
|
try_files $uri/ =404;
|
||||||
index index.php;
|
index index.php;
|
||||||
}
|
}
|
||||||
|
@ -631,15 +631,19 @@ rspamd_config:register_symbol({
|
|||||||
end
|
end
|
||||||
local out_parts = {}
|
local out_parts = {}
|
||||||
for _,o in ipairs(out) do
|
for _,o in ipairs(out) do
|
||||||
if type(o) ~= 'table' then
|
if type(o) ~= 'table' then
|
||||||
out_parts[#out_parts + 1] = o
|
out_parts[#out_parts + 1] = o
|
||||||
out_parts[#out_parts + 1] = newline_s
|
out_parts[#out_parts + 1] = newline_s
|
||||||
else
|
else
|
||||||
out_parts[#out_parts + 1] = o[1]
|
local removePrefix = "--\x0D\x0AContent-Type"
|
||||||
if o[2] then
|
if string.lower(string.sub(tostring(o[1]), 1, string.len(removePrefix))) == string.lower(removePrefix) then
|
||||||
out_parts[#out_parts + 1] = newline_s
|
o[1] = string.sub(tostring(o[1]), string.len("--\x0D\x0A") + 1)
|
||||||
end
|
end
|
||||||
end
|
out_parts[#out_parts + 1] = o[1]
|
||||||
|
if o[2] then
|
||||||
|
out_parts[#out_parts + 1] = newline_s
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
task:set_message(out_parts)
|
task:set_message(out_parts)
|
||||||
else
|
else
|
||||||
|
@ -325,6 +325,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$timeout2 = intval($_data['timeout2']);
|
$timeout2 = intval($_data['timeout2']);
|
||||||
$skipcrossduplicates = intval($_data['skipcrossduplicates']);
|
$skipcrossduplicates = intval($_data['skipcrossduplicates']);
|
||||||
$automap = intval($_data['automap']);
|
$automap = intval($_data['automap']);
|
||||||
|
$dry = intval($_data['dry']);
|
||||||
$port1 = $_data['port1'];
|
$port1 = $_data['port1'];
|
||||||
$host1 = strtolower($_data['host1']);
|
$host1 = strtolower($_data['host1']);
|
||||||
$password1 = $_data['password1'];
|
$password1 = $_data['password1'];
|
||||||
@ -435,8 +436,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `delete1`, `delete2`, `timeout1`, `timeout2`, `automap`, `skipcrossduplicates`, `maxbytespersecond`, `subscribeall`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `custom_params`, `active`)
|
$stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `delete1`, `delete2`, `timeout1`, `timeout2`, `automap`, `skipcrossduplicates`, `maxbytespersecond`, `subscribeall`, `dry`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `custom_params`, `active`)
|
||||||
VALUES (:user2, :exclude, :delete1, :delete2, :timeout1, :timeout2, :automap, :skipcrossduplicates, :maxbytespersecond, :subscribeall, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :custom_params, :active)");
|
VALUES (:user2, :exclude, :delete1, :delete2, :timeout1, :timeout2, :automap, :skipcrossduplicates, :maxbytespersecond, :subscribeall, :dry, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :custom_params, :active)");
|
||||||
$stmt->execute(array(
|
$stmt->execute(array(
|
||||||
':user2' => $username,
|
':user2' => $username,
|
||||||
':custom_params' => $custom_params,
|
':custom_params' => $custom_params,
|
||||||
@ -450,6 +451,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
':skipcrossduplicates' => $skipcrossduplicates,
|
':skipcrossduplicates' => $skipcrossduplicates,
|
||||||
':maxbytespersecond' => $maxbytespersecond,
|
':maxbytespersecond' => $maxbytespersecond,
|
||||||
':subscribeall' => $subscribeall,
|
':subscribeall' => $subscribeall,
|
||||||
|
':dry' => $dry,
|
||||||
':subfolder2' => $subfolder2,
|
':subfolder2' => $subfolder2,
|
||||||
':host1' => $host1,
|
':host1' => $host1,
|
||||||
':authmech1' => 'PLAIN',
|
':authmech1' => 'PLAIN',
|
||||||
@ -2031,6 +2033,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$success = (isset($_data['success'])) ? NULL : $is_now['success'];
|
$success = (isset($_data['success'])) ? NULL : $is_now['success'];
|
||||||
$delete2duplicates = (isset($_data['delete2duplicates'])) ? intval($_data['delete2duplicates']) : $is_now['delete2duplicates'];
|
$delete2duplicates = (isset($_data['delete2duplicates'])) ? intval($_data['delete2duplicates']) : $is_now['delete2duplicates'];
|
||||||
$subscribeall = (isset($_data['subscribeall'])) ? intval($_data['subscribeall']) : $is_now['subscribeall'];
|
$subscribeall = (isset($_data['subscribeall'])) ? intval($_data['subscribeall']) : $is_now['subscribeall'];
|
||||||
|
$dry = (isset($_data['dry'])) ? intval($_data['dry']) : $is_now['dry'];
|
||||||
$delete1 = (isset($_data['delete1'])) ? intval($_data['delete1']) : $is_now['delete1'];
|
$delete1 = (isset($_data['delete1'])) ? intval($_data['delete1']) : $is_now['delete1'];
|
||||||
$delete2 = (isset($_data['delete2'])) ? intval($_data['delete2']) : $is_now['delete2'];
|
$delete2 = (isset($_data['delete2'])) ? intval($_data['delete2']) : $is_now['delete2'];
|
||||||
$automap = (isset($_data['automap'])) ? intval($_data['automap']) : $is_now['automap'];
|
$automap = (isset($_data['automap'])) ? intval($_data['automap']) : $is_now['automap'];
|
||||||
@ -2164,6 +2167,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
`timeout1` = :timeout1,
|
`timeout1` = :timeout1,
|
||||||
`timeout2` = :timeout2,
|
`timeout2` = :timeout2,
|
||||||
`subscribeall` = :subscribeall,
|
`subscribeall` = :subscribeall,
|
||||||
|
`dry` = :dry,
|
||||||
`active` = :active
|
`active` = :active
|
||||||
WHERE `id` = :id");
|
WHERE `id` = :id");
|
||||||
$stmt->execute(array(
|
$stmt->execute(array(
|
||||||
@ -2189,6 +2193,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
':timeout1' => $timeout1,
|
':timeout1' => $timeout1,
|
||||||
':timeout2' => $timeout2,
|
':timeout2' => $timeout2,
|
||||||
':subscribeall' => $subscribeall,
|
':subscribeall' => $subscribeall,
|
||||||
|
':dry' => $dry,
|
||||||
':active' => $active,
|
':active' => $active,
|
||||||
));
|
));
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
|
@ -3,7 +3,7 @@ function init_db_schema() {
|
|||||||
try {
|
try {
|
||||||
global $pdo;
|
global $pdo;
|
||||||
|
|
||||||
$db_version = "14022023_1000";
|
$db_version = "15112023_1536";
|
||||||
|
|
||||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||||
@ -704,6 +704,7 @@ function init_db_schema() {
|
|||||||
"timeout1" => "SMALLINT NOT NULL DEFAULT '600'",
|
"timeout1" => "SMALLINT NOT NULL DEFAULT '600'",
|
||||||
"timeout2" => "SMALLINT NOT NULL DEFAULT '600'",
|
"timeout2" => "SMALLINT NOT NULL DEFAULT '600'",
|
||||||
"subscribeall" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"subscribeall" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
|
"dry" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||||
"is_running" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
"is_running" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||||
"returned_text" => "LONGTEXT",
|
"returned_text" => "LONGTEXT",
|
||||||
"last_run" => "TIMESTAMP NULL DEFAULT NULL",
|
"last_run" => "TIMESTAMP NULL DEFAULT NULL",
|
||||||
|
@ -19,10 +19,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Cache dependencies
|
- name: Cache dependencies
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.composer/cache/files
|
path: ~/.composer/cache/files
|
||||||
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
|
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
|
||||||
@ -52,10 +52,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Cache dependencies
|
- name: Cache dependencies
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.composer/cache/files
|
path: ~/.composer/cache/files
|
||||||
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
|
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
|
||||||
|
@ -12,7 +12,7 @@ jobs:
|
|||||||
dependency-version: [prefer-lowest, prefer-stable]
|
dependency-version: [prefer-lowest, prefer-stable]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
@ -31,7 +31,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: composer update --no-progress --ignore-platform-reqs
|
run: composer update --no-progress --ignore-platform-reqs
|
||||||
@ -43,7 +43,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
|
@ -13,7 +13,7 @@ jobs:
|
|||||||
php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0']
|
php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0']
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: shivammathur/setup-php@v2
|
- uses: shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
|
@ -25,7 +25,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
|
@ -32,7 +32,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout code"
|
- name: "Checkout code"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: "Install PHP with extensions"
|
- name: "Install PHP with extensions"
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
@ -86,7 +86,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout code"
|
- name: "Checkout code"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: "Install PHP with extensions"
|
- name: "Install PHP with extensions"
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
|
@ -18,7 +18,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout code"
|
- name: "Checkout code"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: "Set-up PHP"
|
- name: "Set-up PHP"
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
@ -33,7 +33,7 @@ jobs:
|
|||||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||||
|
|
||||||
- name: Cache dependencies
|
- name: Cache dependencies
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.composercache.outputs.dir }}
|
path: ${{ steps.composercache.outputs.dir }}
|
||||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||||
@ -54,7 +54,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout code"
|
- name: "Checkout code"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: "Run DOCtor-RST"
|
- name: "Run DOCtor-RST"
|
||||||
uses: docker://oskarstark/doctor-rst
|
uses: docker://oskarstark/doctor-rst
|
||||||
|
@ -236,118 +236,120 @@ $RSPAMD_MAPS = array(
|
|||||||
|
|
||||||
$IMAPSYNC_OPTIONS = array(
|
$IMAPSYNC_OPTIONS = array(
|
||||||
'whitelist' => array(
|
'whitelist' => array(
|
||||||
|
'abort',
|
||||||
|
'authmd51',
|
||||||
|
'authmd52',
|
||||||
'authmech1',
|
'authmech1',
|
||||||
'authmech2',
|
'authmech2',
|
||||||
'authuser1',
|
'authuser1',
|
||||||
'authuser2',
|
'authuser2',
|
||||||
'debugcontent',
|
|
||||||
'disarmreadreceipts',
|
|
||||||
'logdir',
|
|
||||||
'debugcrossduplicates',
|
|
||||||
'maxsize',
|
|
||||||
'minsize',
|
|
||||||
'minage',
|
|
||||||
'search',
|
|
||||||
'noabletosearch',
|
|
||||||
'pidfile',
|
|
||||||
'pidfilelocking',
|
|
||||||
'search1',
|
|
||||||
'search2',
|
|
||||||
'sslargs1',
|
|
||||||
'sslargs2',
|
|
||||||
'syncduplicates',
|
|
||||||
'usecache',
|
|
||||||
'synclabels',
|
|
||||||
'truncmess',
|
|
||||||
'domino2',
|
|
||||||
'expunge1',
|
|
||||||
'filterbuggyflags',
|
|
||||||
'justconnect',
|
|
||||||
'justfolders',
|
|
||||||
'maxlinelength',
|
|
||||||
'useheader',
|
|
||||||
'noabletosearch1',
|
|
||||||
'nolog',
|
|
||||||
'prefix1',
|
|
||||||
'prefix2',
|
|
||||||
'sep1',
|
|
||||||
'sep2',
|
|
||||||
'nofoldersizesatend',
|
|
||||||
'justfoldersizes',
|
|
||||||
'proxyauth1',
|
|
||||||
'skipemptyfolders',
|
|
||||||
'include',
|
|
||||||
'subfolder1',
|
|
||||||
'subscribed',
|
|
||||||
'subscribe',
|
|
||||||
'debug',
|
'debug',
|
||||||
|
'debugcontent',
|
||||||
|
'debugcrossduplicates',
|
||||||
|
'debugflags',
|
||||||
|
'debugfolders',
|
||||||
|
'debugimap',
|
||||||
|
'debugimap1',
|
||||||
'debugimap2',
|
'debugimap2',
|
||||||
|
'debugmemory',
|
||||||
|
'debugssl',
|
||||||
|
'delete1emptyfolders',
|
||||||
|
'delete2folders',
|
||||||
|
'disarmreadreceipts',
|
||||||
|
'domain1',
|
||||||
|
'domain2',
|
||||||
'domino1',
|
'domino1',
|
||||||
|
'domino2',
|
||||||
|
'dry',
|
||||||
|
'errorsmax',
|
||||||
'exchange1',
|
'exchange1',
|
||||||
'exchange2',
|
'exchange2',
|
||||||
|
'exitwhenover',
|
||||||
|
'expunge1',
|
||||||
|
'f1f2',
|
||||||
|
'filterbuggyflags',
|
||||||
|
'folder',
|
||||||
|
'folderfirst',
|
||||||
|
'folderlast',
|
||||||
|
'folderrec',
|
||||||
|
'gmail1',
|
||||||
|
'gmail2',
|
||||||
|
'idatefromheader',
|
||||||
|
'include',
|
||||||
|
'inet4',
|
||||||
|
'inet6',
|
||||||
|
'justconnect',
|
||||||
|
'justfolders',
|
||||||
|
'justfoldersizes',
|
||||||
'justlogin',
|
'justlogin',
|
||||||
'keepalive1',
|
'keepalive1',
|
||||||
'keepalive2',
|
'keepalive2',
|
||||||
|
'log',
|
||||||
|
'logdir',
|
||||||
|
'logfile',
|
||||||
|
'maxbytesafter',
|
||||||
|
'maxlinelength',
|
||||||
|
'maxmessagespersecond',
|
||||||
|
'maxsize',
|
||||||
|
'maxsleep',
|
||||||
|
'minage',
|
||||||
|
'minsize',
|
||||||
|
'noabletosearch',
|
||||||
|
'noabletosearch1',
|
||||||
'noabletosearch2',
|
'noabletosearch2',
|
||||||
|
'noexpunge1',
|
||||||
'noexpunge2',
|
'noexpunge2',
|
||||||
|
'nofoldersizesatend',
|
||||||
|
'noid',
|
||||||
|
'nolog',
|
||||||
|
'nomixfolders',
|
||||||
'noresyncflags',
|
'noresyncflags',
|
||||||
'nossl1',
|
'nossl1',
|
||||||
'nouidexpunge2',
|
'nossl2',
|
||||||
'syncinternaldates',
|
|
||||||
'idatefromheader',
|
|
||||||
'useuid',
|
|
||||||
'debugflags',
|
|
||||||
'debugimap',
|
|
||||||
'delete1emptyfolders',
|
|
||||||
'delete2folders',
|
|
||||||
'gmail2',
|
|
||||||
'office1',
|
|
||||||
'testslive6',
|
|
||||||
'debugimap1',
|
|
||||||
'errorsmax',
|
|
||||||
'tests',
|
|
||||||
'gmail1',
|
|
||||||
'maxmessagespersecond',
|
|
||||||
'maxbytesafter',
|
|
||||||
'maxsleep',
|
|
||||||
'abort',
|
|
||||||
'resyncflags',
|
|
||||||
'resynclabels',
|
|
||||||
'syncacls',
|
|
||||||
'nosyncacls',
|
'nosyncacls',
|
||||||
|
'notls1',
|
||||||
|
'notls2',
|
||||||
|
'nouidexpunge2',
|
||||||
'nousecache',
|
'nousecache',
|
||||||
'office2',
|
|
||||||
'testslive',
|
|
||||||
'debugmemory',
|
|
||||||
'exitwhenover',
|
|
||||||
'noid',
|
|
||||||
'noexpunge1',
|
|
||||||
'authmd51',
|
|
||||||
'logfile',
|
|
||||||
'proxyauth2',
|
|
||||||
'domain1',
|
|
||||||
'domain2',
|
|
||||||
'oauthaccesstoken1',
|
'oauthaccesstoken1',
|
||||||
'oauthaccesstoken2',
|
'oauthaccesstoken2',
|
||||||
'oauthdirect1',
|
'oauthdirect1',
|
||||||
'oauthdirect2',
|
'oauthdirect2',
|
||||||
'folder',
|
'office1',
|
||||||
'folderrec',
|
'office2',
|
||||||
'folderfirst',
|
'pidfile',
|
||||||
'folderlast',
|
'pidfilelocking',
|
||||||
'nomixfolders',
|
'prefix1',
|
||||||
'authmd52',
|
'prefix2',
|
||||||
'debugfolders',
|
'proxyauth1',
|
||||||
'nossl2',
|
'proxyauth2',
|
||||||
|
'resyncflags',
|
||||||
|
'resynclabels',
|
||||||
|
'search',
|
||||||
|
'search1',
|
||||||
|
'search2',
|
||||||
|
'sep1',
|
||||||
|
'sep2',
|
||||||
|
'showpasswords',
|
||||||
|
'skipemptyfolders',
|
||||||
'ssl2',
|
'ssl2',
|
||||||
|
'sslargs1',
|
||||||
|
'sslargs2',
|
||||||
|
'subfolder1',
|
||||||
|
'subscribe',
|
||||||
|
'subscribed',
|
||||||
|
'syncacls',
|
||||||
|
'syncduplicates',
|
||||||
|
'syncinternaldates',
|
||||||
|
'synclabels',
|
||||||
|
'tests',
|
||||||
|
'testslive',
|
||||||
|
'testslive6',
|
||||||
'tls2',
|
'tls2',
|
||||||
'notls2',
|
'truncmess',
|
||||||
'debugssl',
|
'usecache',
|
||||||
'notls1',
|
'useheader',
|
||||||
'inet4',
|
'useuid'
|
||||||
'inet6',
|
|
||||||
'log',
|
|
||||||
'showpasswords'
|
|
||||||
),
|
),
|
||||||
'blacklist' => array(
|
'blacklist' => array(
|
||||||
'skipmess',
|
'skipmess',
|
||||||
|
@ -220,7 +220,7 @@ jQuery(function($){
|
|||||||
if (value.score > 0) highlightClass = 'negative';
|
if (value.score > 0) highlightClass = 'negative';
|
||||||
else if (value.score < 0) highlightClass = 'positive';
|
else if (value.score < 0) highlightClass = 'positive';
|
||||||
else highlightClass = 'neutral';
|
else highlightClass = 'neutral';
|
||||||
$('#qid_detail_symbols').append('<span data-bs-toggle="tooltip" class="rspamd-symbol ' + highlightClass + '" title="' + (value.options ? value.options.join(', ') : '') + '">' + value.name + ' (<span class="score">' + value.score + '</span>)</span>');
|
$('#qid_detail_symbols').append('<span data-bs-toggle="tooltip" class="rspamd-symbol ' + highlightClass + '" title="' + (value.options ? escapeHtml(value.options.join(', ')) : '') + '">' + value.name + ' (<span class="score">' + value.score + '</span>)</span>');
|
||||||
});
|
});
|
||||||
$('[data-bs-toggle="tooltip"]').tooltip();
|
$('[data-bs-toggle="tooltip"]').tooltip();
|
||||||
}
|
}
|
||||||
@ -295,3 +295,7 @@ jQuery(function($){
|
|||||||
$(".table_collapse_option").hide();
|
$(".table_collapse_option").hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@
|
|||||||
"include_exclude_info": "Ve výchozím nastavení (bez výběru), jsou adresovány <b>všechny mailové schránky</b>",
|
"include_exclude_info": "Ve výchozím nastavení (bez výběru), jsou adresovány <b>všechny mailové schránky</b>",
|
||||||
"includes": "Zahrnout tyto přijemce",
|
"includes": "Zahrnout tyto přijemce",
|
||||||
"ip_check": "Kontrola IP",
|
"ip_check": "Kontrola IP",
|
||||||
"ip_check_disabled": "Kontrola IP je zakázána. Můžete ji povolit v nabídce<br> <strong>Systém > Nastavení > Možnosti > Přizpůsobení</strong>.",
|
"ip_check_disabled": "Kontrola IP je vypnuta. Můžete ji zapnout v <br> <strong>System > Nastavení > Options > Přizpůsobení</strong>",
|
||||||
"ip_check_opt_in": "Přihlásit se k používání služby třetí strany <strong>ipv4.mailcow.email</strong> a <strong>ipv6.mailcow.email</strong> pro zjištění externích IP adres.",
|
"ip_check_opt_in": "Přihlásit se k používání služby třetí strany <strong>ipv4.mailcow.email</strong> a <strong>ipv6.mailcow.email</strong> pro zjištění externích IP adres.",
|
||||||
"is_mx_based": "Na základě MX",
|
"is_mx_based": "Na základě MX",
|
||||||
"last_applied": "Naposledy použité",
|
"last_applied": "Naposledy použité",
|
||||||
@ -343,9 +343,7 @@
|
|||||||
"verify": "Ověřit",
|
"verify": "Ověřit",
|
||||||
"yes": "✓",
|
"yes": "✓",
|
||||||
"f2b_ban_time_increment": "Délka banu je prodlužována s každým dalším banem",
|
"f2b_ban_time_increment": "Délka banu je prodlužována s každým dalším banem",
|
||||||
"f2b_max_ban_time": "Maximální délka banu (s)",
|
"f2b_max_ban_time": "Maximální délka banu (s)"
|
||||||
"ip_check": "Kontrola IP",
|
|
||||||
"ip_check_disabled": "Kontrola IP je vypnuta. Můžete ji zapnout v <br> <strong>System > Nastavení > Options > Přizpůsobení</strong>"
|
|
||||||
},
|
},
|
||||||
"danger": {
|
"danger": {
|
||||||
"access_denied": "Přístup odepřen nebo jsou neplatná data ve formuláři",
|
"access_denied": "Přístup odepřen nebo jsou neplatná data ve formuláři",
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
"domain": "Domain",
|
"domain": "Domain",
|
||||||
"domain_matches_hostname": "Domain %s darf nicht dem Hostnamen entsprechen",
|
"domain_matches_hostname": "Domain %s darf nicht dem Hostnamen entsprechen",
|
||||||
"domain_quota_m": "Domain-Speicherplatz gesamt (MiB)",
|
"domain_quota_m": "Domain-Speicherplatz gesamt (MiB)",
|
||||||
|
"dry": "Synchronisation simulieren",
|
||||||
"enc_method": "Verschlüsselung",
|
"enc_method": "Verschlüsselung",
|
||||||
"exclude": "Elemente ausschließen (Regex)",
|
"exclude": "Elemente ausschließen (Regex)",
|
||||||
"full_name": "Vor- und Nachname",
|
"full_name": "Vor- und Nachname",
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
"domain": "Domain",
|
"domain": "Domain",
|
||||||
"domain_matches_hostname": "Domain %s matches hostname",
|
"domain_matches_hostname": "Domain %s matches hostname",
|
||||||
"domain_quota_m": "Total domain quota (MiB)",
|
"domain_quota_m": "Total domain quota (MiB)",
|
||||||
|
"dry": "Simulate synchronization",
|
||||||
"enc_method": "Encryption method",
|
"enc_method": "Encryption method",
|
||||||
"exclude": "Exclude objects (regex)",
|
"exclude": "Exclude objects (regex)",
|
||||||
"full_name": "Full name",
|
"full_name": "Full name",
|
||||||
|
@ -326,7 +326,11 @@
|
|||||||
"password_policy_lowerupper": "Doit contenir des caractères minuscules et majuscules",
|
"password_policy_lowerupper": "Doit contenir des caractères minuscules et majuscules",
|
||||||
"password_policy_numbers": "Doit contenir au moins un chiffre",
|
"password_policy_numbers": "Doit contenir au moins un chiffre",
|
||||||
"ip_check": "Vérification IP",
|
"ip_check": "Vérification IP",
|
||||||
"ip_check_disabled": "La vérification IP est désactivée. Vous pouvez l'activer sous<br> <strong>Système > Configuration > Options > Personnaliser</strong>"
|
"ip_check_disabled": "La vérification IP est désactivée. Vous pouvez l'activer sous<br> <strong>Système > Configuration > Options > Personnaliser</strong>",
|
||||||
|
"logo_normal_label": "Normal",
|
||||||
|
"logo_dark_label": "Inversé pour le mode sombre",
|
||||||
|
"allowed_methods": "Access-Control-Allow-Methods",
|
||||||
|
"allowed_origins": "Access-Control-Allow-Origin"
|
||||||
},
|
},
|
||||||
"danger": {
|
"danger": {
|
||||||
"access_denied": "Accès refusé ou données de formulaire non valides",
|
"access_denied": "Accès refusé ou données de formulaire non valides",
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
<input type="hidden" value="0" name="skipcrossduplicates">
|
<input type="hidden" value="0" name="skipcrossduplicates">
|
||||||
<input type="hidden" value="0" name="active">
|
<input type="hidden" value="0" name="active">
|
||||||
<input type="hidden" value="0" name="subscribeall">
|
<input type="hidden" value="0" name="subscribeall">
|
||||||
|
<input type="hidden" value="0" name="dry">
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
<label class="control-label col-sm-2" for="host1">{{ lang.edit.hostname }}</label>
|
<label class="control-label col-sm-2" for="host1">{{ lang.edit.hostname }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
@ -95,7 +96,7 @@
|
|||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<label class="control-label col-sm-2" for="custom_params">{{ lang.add.custom_params }}</label>
|
<label class="control-label col-sm-2" for="custom_params">{{ lang.add.custom_params }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input type="text" class="form-control" name="custom_params" id="custom_params" value="{{ result.custom_params }}" placeholder="--dry --some-param=xy --other-param=yx">
|
<input type="text" class="form-control" name="custom_params" id="custom_params" value="{{ result.custom_params }}" placeholder="--some-param=xy --other-param=yx">
|
||||||
<small class="text-muted">{{ lang.add.custom_params_hint }}</small>
|
<small class="text-muted">{{ lang.add.custom_params_hint }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -141,6 +142,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<div class="offset-sm-2 col-sm-10">
|
||||||
|
<div class="form-check">
|
||||||
|
<label><input type="checkbox" class="form-check-input" value="1" name="dry"{% if result.dry == '1' %} checked{% endif %}> {{ lang.add.dry }} (--dry)</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="offset-sm-2 col-sm-10">
|
<div class="offset-sm-2 col-sm-10">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
|
@ -955,7 +955,7 @@
|
|||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<label class="control-label col-sm-2 text-sm-end" for="custom_params">{{ lang.add.custom_params }}</label>
|
<label class="control-label col-sm-2 text-sm-end" for="custom_params">{{ lang.add.custom_params }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input type="text" class="form-control" name="custom_params" placeholder="--dry --some-param=xy --other-param=yx">
|
<input type="text" class="form-control" name="custom_params" placeholder="--some-param=xy --other-param=yx">
|
||||||
<small class="text-muted">{{ lang.add.custom_params_hint }}</small>
|
<small class="text-muted">{{ lang.add.custom_params_hint }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -994,13 +994,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-4">
|
<div class="row mb-2">
|
||||||
<div class="offset-sm-2 col-sm-10">
|
<div class="offset-sm-2 col-sm-10">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<label><input type="checkbox" class="form-check-input" value="1" name="subscribeall" checked> {{ lang.add.subscribeall }} (--subscribeall)</label>
|
<label><input type="checkbox" class="form-check-input" value="1" name="subscribeall" checked> {{ lang.add.subscribeall }} (--subscribeall)</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-4">
|
||||||
|
<div class="offset-sm-2 col-sm-10">
|
||||||
|
<div class="form-check">
|
||||||
|
<label><input type="checkbox" class="form-check-input" value="1" name="dry"> {{ lang.add.dry }} (--dry)</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
<div class="offset-sm-2 col-sm-10">
|
<div class="offset-sm-2 col-sm-10">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
|
@ -167,6 +167,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<div class="offset-sm-2 col-sm-10">
|
||||||
|
<div class="form-check">
|
||||||
|
<label><input type="checkbox" class="form-check-input" value="1" name="dry" checked> {{ lang.add.dry }} (--dry)</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="offset-sm-2 col-sm-10">
|
<div class="offset-sm-2 col-sm-10">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
|
@ -218,7 +218,7 @@ services:
|
|||||||
- sogo
|
- sogo
|
||||||
|
|
||||||
dovecot-mailcow:
|
dovecot-mailcow:
|
||||||
image: mailcow/dovecot:1.25
|
image: mailcow/dovecot:1.26
|
||||||
depends_on:
|
depends_on:
|
||||||
- mysql-mailcow
|
- mysql-mailcow
|
||||||
dns:
|
dns:
|
||||||
|
122
helper-scripts/generate_caa_record.py
Executable file
122
helper-scripts/generate_caa_record.py
Executable file
@ -0,0 +1,122 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Based on github.com/diafygi/acme-tiny, original copyright:
|
||||||
|
# Copyright Daniel Roesler, under MIT license, see LICENSE at github.com/diafygi/acme-tiny
|
||||||
|
import argparse, subprocess, json, os, sys, base64, binascii, time, hashlib, re, copy, textwrap, logging
|
||||||
|
try:
|
||||||
|
from urllib.request import urlopen, Request # Python 3
|
||||||
|
except ImportError: # pragma: no cover
|
||||||
|
from urllib2 import urlopen, Request # Python 2
|
||||||
|
|
||||||
|
DEFAULT_DIRECTORY_URL = "https://acme-v02.api.letsencrypt.org/directory"
|
||||||
|
|
||||||
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
LOGGER.addHandler(logging.StreamHandler())
|
||||||
|
LOGGER.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
def get_id(account_key, log=LOGGER, directory_url=DEFAULT_DIRECTORY_URL, contact=None):
|
||||||
|
directory, acct_headers, alg, jwk = None, None, None, None # global variables
|
||||||
|
|
||||||
|
# helper functions - base64 encode for jose spec
|
||||||
|
def _b64(b):
|
||||||
|
return base64.urlsafe_b64encode(b).decode('utf8').replace("=", "")
|
||||||
|
|
||||||
|
# helper function - run external commands
|
||||||
|
def _cmd(cmd_list, stdin=None, cmd_input=None, err_msg="Command Line Error"):
|
||||||
|
proc = subprocess.Popen(cmd_list, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
out, err = proc.communicate(cmd_input)
|
||||||
|
if proc.returncode != 0:
|
||||||
|
raise IOError("{0}\n{1}".format(err_msg, err))
|
||||||
|
return out
|
||||||
|
|
||||||
|
# helper function - make request and automatically parse json response
|
||||||
|
def _do_request(url, data=None, err_msg="Error", depth=0):
|
||||||
|
try:
|
||||||
|
resp = urlopen(Request(url, data=data, headers={"Content-Type": "application/jose+json", "User-Agent": "acme-tiny"}))
|
||||||
|
resp_data, code, headers = resp.read().decode("utf8"), resp.getcode(), resp.headers
|
||||||
|
except IOError as e:
|
||||||
|
resp_data = e.read().decode("utf8") if hasattr(e, "read") else str(e)
|
||||||
|
code, headers = getattr(e, "code", None), {}
|
||||||
|
try:
|
||||||
|
resp_data = json.loads(resp_data) # try to parse json results
|
||||||
|
except ValueError:
|
||||||
|
pass # ignore json parsing errors
|
||||||
|
if depth < 100 and code == 400 and resp_data['type'] == "urn:ietf:params:acme:error:badNonce":
|
||||||
|
raise IndexError(resp_data) # allow 100 retrys for bad nonces
|
||||||
|
if code not in [200, 201, 204]:
|
||||||
|
raise ValueError("{0}:\nUrl: {1}\nData: {2}\nResponse Code: {3}\nResponse: {4}".format(err_msg, url, data, code, resp_data))
|
||||||
|
return resp_data, code, headers
|
||||||
|
|
||||||
|
# helper function - make signed requests
|
||||||
|
def _send_signed_request(url, payload, err_msg, depth=0):
|
||||||
|
payload64 = "" if payload is None else _b64(json.dumps(payload).encode('utf8'))
|
||||||
|
new_nonce = _do_request(directory['newNonce'])[2]['Replay-Nonce']
|
||||||
|
protected = {"url": url, "alg": alg, "nonce": new_nonce}
|
||||||
|
protected.update({"jwk": jwk} if acct_headers is None else {"kid": acct_headers['Location']})
|
||||||
|
protected64 = _b64(json.dumps(protected).encode('utf8'))
|
||||||
|
protected_input = "{0}.{1}".format(protected64, payload64).encode('utf8')
|
||||||
|
out = _cmd(["openssl", "dgst", "-sha256", "-sign", account_key], stdin=subprocess.PIPE, cmd_input=protected_input, err_msg="OpenSSL Error")
|
||||||
|
data = json.dumps({"protected": protected64, "payload": payload64, "signature": _b64(out)})
|
||||||
|
try:
|
||||||
|
return _do_request(url, data=data.encode('utf8'), err_msg=err_msg, depth=depth)
|
||||||
|
except IndexError: # retry bad nonces (they raise IndexError)
|
||||||
|
return _send_signed_request(url, payload, err_msg, depth=(depth + 1))
|
||||||
|
|
||||||
|
# helper function - poll until complete
|
||||||
|
def _poll_until_not(url, pending_statuses, err_msg):
|
||||||
|
result, t0 = None, time.time()
|
||||||
|
while result is None or result['status'] in pending_statuses:
|
||||||
|
assert (time.time() - t0 < 3600), "Polling timeout" # 1 hour timeout
|
||||||
|
time.sleep(0 if result is None else 2)
|
||||||
|
result, _, _ = _send_signed_request(url, None, err_msg)
|
||||||
|
return result
|
||||||
|
|
||||||
|
# parse account key to get public key
|
||||||
|
log.info("Parsing account key...")
|
||||||
|
out = _cmd(["openssl", "rsa", "-in", account_key, "-noout", "-text"], err_msg="OpenSSL Error")
|
||||||
|
pub_pattern = r"modulus:[\s]+?00:([a-f0-9\:\s]+?)\npublicExponent: ([0-9]+)"
|
||||||
|
pub_hex, pub_exp = re.search(pub_pattern, out.decode('utf8'), re.MULTILINE|re.DOTALL).groups()
|
||||||
|
pub_exp = "{0:x}".format(int(pub_exp))
|
||||||
|
pub_exp = "0{0}".format(pub_exp) if len(pub_exp) % 2 else pub_exp
|
||||||
|
alg, jwk = "RS256", {
|
||||||
|
"e": _b64(binascii.unhexlify(pub_exp.encode("utf-8"))),
|
||||||
|
"kty": "RSA",
|
||||||
|
"n": _b64(binascii.unhexlify(re.sub(r"(\s|:)", "", pub_hex).encode("utf-8"))),
|
||||||
|
}
|
||||||
|
accountkey_json = json.dumps(jwk, sort_keys=True, separators=(',', ':'))
|
||||||
|
thumbprint = _b64(hashlib.sha256(accountkey_json.encode('utf8')).digest())
|
||||||
|
|
||||||
|
# get the ACME directory of urls
|
||||||
|
log.info("Getting directory...")
|
||||||
|
directory, _, _ = _do_request(directory_url, err_msg="Error getting directory")
|
||||||
|
log.info("Directory found!")
|
||||||
|
|
||||||
|
# create account and get the global key identifier
|
||||||
|
log.info("Registering account...")
|
||||||
|
reg_payload = {"termsOfServiceAgreed": True} if contact is None else {"termsOfServiceAgreed": True, "contact": contact}
|
||||||
|
account, code, acct_headers = _send_signed_request(directory['newAccount'], reg_payload, "Error registering")
|
||||||
|
log.info("Registered!" if code == 201 else "Already registered!")
|
||||||
|
|
||||||
|
return acct_headers['Location']
|
||||||
|
|
||||||
|
def main(argv=None):
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
description=textwrap.dedent("""\
|
||||||
|
Generate a CAA record for Mailcow.
|
||||||
|
|
||||||
|
Example Usage: python mailcow_gencaa.py --account-key data/assets/ssl/acme/account.pem
|
||||||
|
""")
|
||||||
|
)
|
||||||
|
parser.add_argument("--account-key", required=True, help="path to your Let's Encrypt account private key")
|
||||||
|
parser.add_argument("--quiet", action="store_const", const=logging.ERROR, help="suppress output except for errors")
|
||||||
|
parser.add_argument("--directory-url", default=DEFAULT_DIRECTORY_URL, help="certificate authority directory url, default is Let's Encrypt")
|
||||||
|
parser.add_argument("--contact", metavar="CONTACT", default=None, nargs="*", help="Contact details (e.g. mailto:aaa@bbb.com) for your account-key")
|
||||||
|
|
||||||
|
args = parser.parse_args(argv)
|
||||||
|
LOGGER.setLevel(args.quiet or LOGGER.level)
|
||||||
|
id = get_id(args.account_key, log=LOGGER, directory_url=args.directory_url, contact=args.contact)
|
||||||
|
print("Use this as your CAA record:")
|
||||||
|
print('issue 128 "letsencrypt.org;accounturi={}"'.format(id))
|
||||||
|
|
||||||
|
if __name__ == "__main__": # pragma: no cover
|
||||||
|
main(sys.argv[1:])
|
@ -106,6 +106,10 @@ elif [[ ${NC_UPDATE} == "y" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "php /web/nextcloud/updater/updater.phar"
|
docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "php /web/nextcloud/updater/updater.phar"
|
||||||
|
NC_SUBD=$(docker exec -i -u www-data $(docker ps -f name=php-fpm-mailcow -q) /web/nextcloud/occ config:system:get overwritehost)
|
||||||
|
mv ./data/conf/nginx/nextcloud.conf ./data/conf/nginx/nextcloud.conf-$(date +%s).bak
|
||||||
|
cp ./data/assets/nextcloud/nextcloud.conf ./data/conf/nginx/
|
||||||
|
sed -i "s/NC_SUBD/${NC_SUBD}/g" ./data/conf/nginx/nextcloud.conf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
elif [[ ${NC_INSTALL} == "y" ]]; then
|
elif [[ ${NC_INSTALL} == "y" ]]; then
|
||||||
|
Loading…
x
Reference in New Issue
Block a user