17 Commits

Author SHA1 Message Date
58298abe3a * Wed Jan 08 2025 Brian Read <brianr@koozali.org> 1.0-11.sme
- reload-or-restart postfix after pseudonym change [SME: 12863]
2025-01-08 10:20:49 +00:00
72362ffc32 * Sun Dec 29 2024 Brian Read <brianr@koozali.org> 1.0-10.sme
- Quotes round smtp-auth-proxy in templates for main.cf and sasl-passwd [SME: 12836]
2024-12-29 06:42:00 +00:00
8dff3cd3fc * Mon Dec 23 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-9.sme
- fix virtual  expected format: key whitespace value for empty group [SME: 12834]
2024-12-23 00:33:21 -05:00
23c9a3a595 * Fri Dec 20 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-8.sme
- fix catch-all behaviour [SME: 12382]
  myorigin now is hostname
  in case email sent outside by deamon generic rewrite occurs
2024-12-20 07:24:15 -05:00
abba39ab3c * Fri Dec 20 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-7.sme
- fix catch-all behaviour [SME: 12382]
  myorigin now is hostname
  in case email sent outside by deamon generic rewrite occurs
2024-12-20 00:36:26 -05:00
de44e4000a readme 2024-12-17 10:56:39 -05:00
fddc92eb16 * Sun Dec 15 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-6.sme
- add mini-qmail as Message delivery agent  [SME: 12737]
  few other fixes; +x on needed executable files
  migrate old qmail properties used in postfix
  catch all non existing recipient / check BCC working
2024-12-17 07:05:35 -05:00
77135e244f readme 2024-12-17 01:04:17 -05:00
df66a327cc * Sun Dec 15 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-5.sme
- add mini-qmail as Message delivery agent  [SME: 12737]
  few other fixes; +x on needed executable files
  migrate old qmail properties used in postfix
  catch all non existing recipient / check BCC working
2024-12-17 00:30:48 -05:00
0e6e82c9a1 * Sun Dec 15 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-5.sme
- add mini-qmail as Message delivery agent  [SME: 12737]
  few other fixes; +x on needed executable files
  migrate old qmail properties used in postfix
  catch all non existing recipient / check BCC working
2024-12-16 17:14:34 -05:00
0cec86dcb7 * Sun Dec 15 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-4.sme
- add mini-qmail as Message delivery agent  [SME: 12737]
  few other fixes
  TODO  migrate old qmail properties and change in template
  TODO catch all non existing recipient / check BCC working
2024-12-15 16:10:49 -05:00
f2b33f4260 install procedure 2024-11-19 16:06:13 -05:00
e037fa4736 * Tue Nov 19 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-3.sme
- add requirements [SME: 12737]
- add conf-postfix
2024-11-19 11:28:57 -05:00
77e9c3660c fix typo in command line 2024-11-19 10:45:45 +01:00
26a8c58271 * Sun Nov 17 2024 <jpp@koozali.org> 1.0-2.sme
- listen only via sockets
- use both unix user and virtual users
- groups and pseudonyms implemented in virtual maps
- support smarthost with and without auth
- support global and per domain delegated mail server
- support ssl
- uses qmail - recipient delimiter in left part of email.
- all domains set as local domains in mydestination
- message_size_limit
- local and remote concurency limit
2024-11-17 22:28:50 -05:00
51be51501f * Sun Nov 17 2024 <jpp@koozali.org> 1.0-2.sme
- listen only via sockets
- use both unix user and virtual users
- groups and pseudonyms implemented in virtual maps
- support smarthost with and without auth
- support global and per domain delegated mail server
- support ssl
- uses qmail - recipient delimiter in left part of email.
- all domains set as local domains in mydestination
- message_size_limit
- local and remote concurency limit
2024-11-17 22:28:07 -05:00
aa8479eaa9 * Sun Nov 17 2024 <jpp@koozali.org> 1.0-2.sme
- listen only via sockets
- use both unix user and virtual users
- groups and pseudonyms implemented in virtual maps
- support smarthost with and without auth
- support global and per domain delegated mail server
- support ssl
- uses qmail - recipient delimiter in left part of email.
- all domains set as local domains in mydestination
- message_size_limit
- local and remote concurency limit
2024-11-17 22:25:49 -05:00
51 changed files with 707 additions and 116 deletions

3
.gitignore vendored
View File

@@ -1,3 +1,4 @@
*.rpm
*.tar.gz
*.log
*spec-20**.bak
*.spec-20**.bak

View File

@@ -20,27 +20,80 @@ Show list of outstanding bugs:
Koozali SME Server wrapper to configure postfix
## Development and testing
```
mkdir /etc/e-smith/templates-custom/var/service/qpsmtpd/config/plugins/
echo 'return "queue/postfix-queue";' > /etc/e-smith/templates-custom/var/service/qpsmtpd/config/plugins/90queue-qmail-queue
config setprop qmail status disabled
systemctl stop qmail
signal-event email-update
dnf install smerserver-postfix
```
then test
```
echo "This email confirms that Postfix is working" | mail -s "Testing Posfix" emailuser@example.com
```
or using roundcube
or using roundcube/ mail client
DONE
* main domain
* listen only socket
* virtual alias for system, pseudonyms, groups, shared
* forward email support via .qmail
* spam filtering to .junk
* .qmail support using mini-qmail + wrapper and seakablepipe
* maildrop/procmail support directly via .qmail
* check /usr/sbin/sendmail -> /etc/alternatives/mta -> /usr/sbin/sendmail.postfix
* EmailUnknownUser support in virtual
* migrate and remove qmail properties to postfix
* make a copy of /var/qmail/control/smtproutes to (su)qpsmtpd/config/smtproutes
TODO
* remote SMTP
* smart SMTP
* SSL
* logging
* .qmail support or alternative
* maildrop/procmail support ?
* switch smeserver-qpsmtpd support to postfix
* check /usr/sbin/sendmail -> /etc/alternatives/mta -> /usr/sbin/sendmail.postfix upon removal/update of qmail
* remove from smeserver-mail /usr/local/sbin/smtp-auth-proxy.pl
* migrate and rewrite code for smtp-auth-proxy properties
* panel to list / manage queue
FUTURE
* .foward support, when/if .qmail support is dropped
* ldap / AD user support
* throttle for some destination
TO CHECK
$prop->{Blacklist} = $smtp_proxy_rec->prop('Blacklist') || " ";
$prop->{Debug} = $smtp_proxy_rec->prop('Debug');
VARIABLES
domain
* domain -> EmailTo to send all emails for a domain to an email
* domain -> MailServer
* domain -> VirtualMail as default disabled, will only accepte mails to a defined pseudonym for this domain
config
* DelegateMailServer
* SMTPSmartHost
* postfix->MaxMessageSize defined as 15Mb
* postfix->FilterType (empty)
* postfix->ConcurrencyRemote default to 20
* postfix->ConcurrencyLocal default to 20
* postfix->DoubleBounceTo default to postmaster
* postfix->tls_security_level default to may
* postfix->tls_enforce_peername default to yes
* $qpsmtpd{HeloHost} default to $myhostname
* smtp-auth-proxy SMTPSmartHost
* smtp-auth-proxy Userid
* smtp-auth-proxy Passwd
* smtp-auth-proxy PeerPort
* EmailUnknownUser (default to returntosender)
REFERENCES
* https://serverfault.com/questions/638152/how-to-remove-postfix-queue-messages-sent-to-a-specific-domain
* https://unix.stackexchange.com/questions/93197/postfix-configuration-to-verify-all-recipients
* https://phoenixnap.com/kb/postfix-smtp
* https://www.gentei.org/~yuuji/software/dotqmail/
* https://www.gentei.org/~yuuji/software/dotqmail/dotqmail
* https://sixohthree.com/424/smtp-2
* https://mailing.postfix.users.narkive.com/AhepT4TC/qmail-local-transport
* https://skarnet.org/software/s6-portable-utils/
* https://johnleach.co.uk/documents/qmail-to-postfix/
* https://www.mail-archive.com/search?l=tmda-users@tmda.net&q=subject:%22Slightly+OT%5C%3A+Opinions+Wanted+%5C-+Implementing+dot%5C-qmail+in+postfix%5C%3F%22&o=newest&f=1
* https://luke.skr.jp/hsj/?cmd=backup&action=nowdiff&page=OpenBlockS%2FMailServer&age=3
* https://www.postfix.org/ADDRESS_CLASS_README.html#virtual_mailbox_class
* https://www.postfix.org/VIRTUAL_README.html#virtual_mailbox
* https://www.postfix.org/ADDRESS_CLASS_README.html#virtual_alias_class
* https://www.postfix.org/master.5.html
* https://hostadvice.com/how-to/web-hosting/vps/how-to-setup-postfix-as-send-only-mail-server-on-an-ubuntu-18-04-dedicated-server-or-vps/
* https://sscnet.ch/content/update-3-installing-qpsmtpd-bionic-beaver-ubuntu
* https://www.postfix.org/postconf.5.html#luser_relay
* https://serverfault.com/questions/960074/luser-relay-does-not-forward-the-emails
* https://serverfault.com/questions/885483/postfix-catchall-user-not-found-in-virtual-alias-table

View File

@@ -13,35 +13,47 @@ foreach (qw(
master.cf
transport
virtual
))
sasl_passwd
generic
))
{
templates2events("/var/qmail/control/$_", qw(
templates2events("/etc/postfix/$_", qw(
console-save
bootstrap-console-save
domain-create
domain-delete
ip-change
email-update
group-create
group-modify
group-delete
host-create
host-delete
host-modify
post-upgrade
smeserver-postfix-update
user-create
user-modify
user-delete
user-modify-admin
));
}
#--------------------------------------------------
# actions for ssl-update event:
# write config files and create startup link
#--------------------------------------------------
$event = "ssl-update";
templates2events("/etc/postfix/ssl/postfix.pem", $event);
#--------------------------------------------------
# actions for console-save event:
# write config files and create startup link
#--------------------------------------------------
$event = "console-save";
# If qmail-send is running, it will receive the SIGHUP and ignore the
# start command. If it is not running then the signal will be ignored
# and qmail-send will read its new configuration files anyway.
safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix");
templates2events("/etc/postfix/ssl/postfix.pem", $event);
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
#--------------------------------------------------
# actions for bootstrap-console-save event:
@@ -49,11 +61,9 @@ safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix")
#--------------------------------------------------
$event = "bootstrap-console-save";
# TODO alternative ? event_link("pseudonym-cleanup", $event, "03");
# TODO alternative ? event_link("qmail-update-group", $event, "20");
# TODO alternative ? event_link("qmail-update-user", $event, "55");
# TODO alternative ? templates2events("/var/qmail/users/assign", $event);
# TODO alternative ? safe_symlink("/var/qmail/bin/qmail-newu", "root/etc/e-smith/events/$event/S55email-assign");
event_link('conf-postfix', $event, '04');
templates2events("/etc/postfix/ssl/postfix.pem", $event);
#--------------------------------------------------
# actions for domain-create event:
@@ -61,7 +71,17 @@ $event = "bootstrap-console-save";
#--------------------------------------------------
$event = "domain-create";
safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix");
templates2events("/etc/postfix/ssl/postfix.pem", $event);
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
#--------------------------------------------------
# actions for domain-modify event:
# rewrite config files and restart server
#--------------------------------------------------
$event = "domain-modify";
templates2events("/etc/postfix/ssl/postfix.pem", $event);
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
#--------------------------------------------------
# actions for domain-delete event:
@@ -69,7 +89,8 @@ safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix")
#--------------------------------------------------
$event = "domain-delete";
safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix");
templates2events("/etc/postfix/ssl/postfix.pem", $event);
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
#--------------------------------------------------
# actions for email-update event:
@@ -80,10 +101,9 @@ safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix")
#--------------------------------------------------
$event = "email-update";
templates2events("/etc/postfix/ssl/postfix.pem", $event);
# TODO alternative ? event_link("qmail-update-user", $event, "03");
# TODO alternative ? event_link("pseudonym-cleanup", $event, "30");
safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix");
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
safe_symlink("adjust", "root/etc/e-smith/events/$event/services2adjust/masq");
safe_symlink("restart", "root/etc/e-smith/events/$event/services2adjust/smtp-auth-proxy");
@@ -92,33 +112,27 @@ safe_symlink("restart", "root/etc/e-smith/events/$event/services2adjust/smtp-aut
#--------------------------------------------------
$event = "group-create";
# TODO alternative ? event_link("pseudonym-cleanup", $event, "03");
# TODO alternative ? event_link("qmail-update-group", $event, "20");
# TODO alternative ? templates2events("/var/qmail/users/assign", $event);
# TODO alternative ? safe_symlink("/var/qmail/bin/qmail-newu", "root/etc/e-smith/events/$event/S55email-assign");
safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix");
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
# TODO need to reload postfix and expand /etc/postfix/virtual
#--------------------------------------------------
# actions for group-delete event:
#--------------------------------------------------
$event = "group-delete";
# TODO alternative ? event_link("pseudonym-cleanup", $event, "03");
# TODO alternative ? event_link("qmail-delete-group", $event, "20");
# TODO alternative ? templates2events("/var/qmail/users/assign", $event);
# TODO alternative ? safe_symlink("/var/qmail/bin/qmail-newu", "root/etc/e-smith/events/$event/S55email-assign");
safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix");
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
# TODO need to reload postfix and expand /etc/postfix/virtual
#--------------------------------------------------
# actions for group-modify event:
#--------------------------------------------------
$event = "group-modify";
# TODO alternative ? event_link("pseudonym-cleanup", $event, "03");
# TODO alternative ? event_link("qmail-update-group", $event, "20");
# TODO alternative ? templates2events("/var/qmail/users/assign", $event);
# TODO alternative ? safe_symlink("/var/qmail/bin/qmail-newu", "root/etc/e-smith/events/$event/S55email-assign");
safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix");
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
#--------------------------------------------------
# actions for user-create event:
@@ -126,7 +140,7 @@ safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix")
$event = "user-create";
# TODO alternative ? event_link("qmail-update-user", $event, "20");
# TODO alternative ? event_link("qmail-update-group", $event, "20");
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
#--------------------------------------------------
# actions for user-modify event
@@ -134,7 +148,7 @@ $event = "user-create";
$event = "user-modify";
# TODO alternative ? event_link("qmail-update-user", $event, "20");
# TODO alternative ? event_link("qmail-update-group", $event, "20");
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
#--------------------------------------------------
# actions for user-modify-admin event
@@ -142,13 +156,14 @@ $event = "user-modify";
$event = "user-modify-admin";
# TODO alternative ? event_link("qmail-update-user", $event, "20");
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
#--------------------------------------------------
# actions for user-delete event
#--------------------------------------------------
$event = "user-delete";
# TODO alternative ? event_link("qmail-update-group", $event, "25");
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
#--------------------------------------------------
# actions for ip-up event:
@@ -162,7 +177,8 @@ $event = "ip-up";
#--------------------------------------------------
$event = "ip-change";
safe_symlink("sighup", "root/etc/e-smith/events/$event/services2adjust/postfix");
templates2events("/etc/postfix/ssl/postfix.pem", $event);
safe_symlink("reload", "root/etc/e-smith/events/$event/services2adjust/postfix");
@@ -181,19 +197,30 @@ foreach my $file (qw(
{
templates2events( $file, $event );
};
templates2events("/etc/postfix/ssl/postfix.pem", $event);
#action needed in case we have a systemd unit
event_link('conf-postfix', $event, '04');
event_link('systemd-default', $event, '10');
event_link('systemd-reload', $event, '50');
safe_symlink("restart", "root/etc/e-smith/events/$event/services2adjust/postfix");
#services we might need to restart
#event_services($event, 'xxxx' => 'restart', 'yyyy' => 'restart');
safe_symlink("restart", "root/etc/e-smith/events/$event/services2adjust/qpsmtpd");
safe_symlink("restart", "root/etc/e-smith/events/$event/services2adjust/sqpsmtpd");
safe_symlink("restart", "root/etc/e-smith/events/$event/services2adjust/uqpsmtpd");
#Backup files
# backup_includes("smeserver-postfix", qw(
# files(s) to be backed up
#));
#--------------------------------------------------
# actions for pseudonym-{create,delete,modify}
#--------------------------------------------------
foreach $event ( qw(pseudonym-create pseudonym-modify pseudonym-delete) )
{
safe_symlink("reload-or-restart", "root/etc/e-smith/events/$event/services2adjust/postfix");
}

View File

@@ -0,0 +1 @@
15000000

View File

@@ -0,0 +1,14 @@
{
# migrate qmail -> postfix MaxMessageSize FilterType ConcurrencyRemote ConcurrencyLocal DoubleBounceTo
# we keep qmail as MDA so we can leave DeliveryType DeliveryInstruction
for ( qw( MaxMessageSize FilterType ConcurrencyRemote ConcurrencyLocal DoubleBounceTo) ) {
my $sa = $DB->get('qmail') or next;
my $value=$DB->get_prop_and_delete('qmail',$_) or next;
next if (exists $postfix{$_});
$DB->set_prop('postfix', $_ , $value);
}
# TODO we migrate smtp-auth-proxy ; SMTPSmartHost Userid Passwd PeerPort
}

View File

@@ -0,0 +1,8 @@
#!/bin/bash
#first we set postfix sendmail as default one
/usr/sbin/alternatives --set mta /usr/sbin/sendmail.postfix
# we add qpsmtpd to the group to allow to send email to postfix sockets
/usr/sbin/usermod -a -G postdrop qpsmtpd

View File

@@ -0,0 +1,3 @@
UID="root"
GID="root"
PERMS=0600

View File

@@ -0,0 +1,5 @@
TEMPLATE_PATH="/home/e-smith/ssl.pem"
OUTPUT_FILENAME="/etc/postfix/ssl/postfix.pem"
UID="root"
GID="root"
PERMS=0640

View File

@@ -0,0 +1,2 @@
#change myorigin to local domain for outgoing emails
@{$SystemName} @{$DomainName}

View File

@@ -0,0 +1 @@
compatibility_level=2

View File

@@ -1 +1,7 @@
myorigin = $mydomain
{
# do not put a domain that will be used to recieve emails there
# if you do so you will lose email with the virtual rewriting process.
# this will complete local sent email and virtual right hands
}# do not put real domain there to avoid loop, or catch-all issues
myorigin = $myhostname
append_at_myorigin = yes

View File

@@ -1,2 +1,2 @@
inet_interfaces = loopback-only
inet_interfaces = all
inet_protocols = all

View File

@@ -0,0 +1,5 @@
{
# qmail compatibility - instead of +
# default empty
}recipient_delimiter = -
expand_owner_alias = yes

View File

@@ -1,2 +1,16 @@
# TODO add all domains and hosts related here
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
# SME Primary domain and host: looks up all recipients in /etc/passwd and /etc/aliases
mydestination = $myorigin $myhostname $mydomain $myhostname.$mydomain localhost.$mydomain localhost {
$OUT = " ";
my $i = 0;
use esmith::DomainsDB;
my $ddb = esmith::DomainsDB->open_ro;
my @domains = map { $_->key } $ddb->get_all_by_prop('type' => 'domain');
foreach my $domain ( @domains )
{
my $d = $ddb->get($domain);
next if (($d->prop('VirtualMail') || "disabled") eq "enabled");
next unless (($d->prop('MailServer') || '') eq '');
next if $domain eq $DomainName;
$OUT .= "$domain ";
}
}

View File

@@ -1,30 +0,0 @@
{
$OUT = '';
my $virtual = 'virtual_alias_domains = ';
use esmith::DomainsDB;
my $domainsdb = esmith::DomainsDB->open_ro();
my $tempstr = '';
for my $domain ($domainsdb->domains)
{
my $primary = $domain->prop('SystemPrimaryDomain');
next if ( $primary eq 'yes' );
my $mail_server = $domain->prop('MailServer')
|| $DelegateMailServer
|| 'localhost';
next if ( $mail_server ne 'localhost' );
$emaildomain = $domain->key;
$tempstr .= "$emaildomain ";
}
if ( $tempstr ne '' )
{
$OUT .= "$virtual";
$OUT .= "$tempstr\n";
$OUT .= "virtual_alias_maps = hash:/etc/postfix/virtual";
}
}

View File

@@ -0,0 +1,21 @@
{
# SME Server Virtual domains
# to configure emails for those domains use pseudonyms to point to a unix account.
# sales@virtualdomain.com -> admin
$OUT = "virtual_alias_domains = ";
my $i = 0;
use esmith::DomainsDB;
my $ddb = esmith::DomainsDB->open_ro;
my @domains = map { $_->key } $ddb->get_all_by_prop('type' => 'domain');
foreach my $domain ( @domains )
{
my $d = $ddb->get($domain);
next unless (($d->prop('VirtualMail') || "disabled") eq "enabled");
next unless (($d->prop('MailServer') || '') eq '');
$OUT .= "$domain " unless $domain eq $DomainName;
$i ++ unless $domain eq $DomainName;;
}
$OUT = "# no SME Server Virtual domains configured" unless $i>0;
}

View File

@@ -0,0 +1,2 @@
# list of all virtual aliases : groups, pseudonyms ...
virtual_alias_maps = hash:/etc/postfix/virtual

View File

@@ -0,0 +1,7 @@
{
#message_size_limit = 10240000 (default)
# our previous default with qmail was 15000000
my $MaxMessageSize = $postfix{'MaxMessageSize'} || "15000000";
$OUT = "message_size_limit = $MaxMessageSize\n";
}

View File

@@ -1,13 +1,10 @@
{
$OUT = '';
my $transport = 'transport_maps = hash:/etc/postfix/transport ';
my $display = 0;
use esmith::DomainsDB;
my $domainsdb = esmith::DomainsDB->open_ro();
for my $domain ($domainsdb->domains)
for my $domain ($domainsdb->get_all)
{
my $mail_server = $domain->prop('MailServer')
|| $DelegateMailServer
@@ -15,10 +12,16 @@
if ( $mail_server ne 'localhost' )
{
$OUT = "$transport\n";
$display = 1;
}
}
$display = 1 if (
$SMTPSmartHost
&&
($SMTPSmartHost ne 'off')
&&
($SMTPSmartHost !~ /^\s*$/)
);
$OUT = "$transport\n" if $display eq 1;
}

View File

@@ -0,0 +1,3 @@
default_destination_concurrency_limit = { $postfix{'ConcurrencyRemote'} || "20"; }
local_destination_concurrency_limit = { $postfix{'ConcurrencyLocal'} || "20"; }

View File

@@ -0,0 +1,5 @@
{
# we use the value of EmailUnknownUser (default to returntosender)
return "# we bounce all unknown address $EmailUnknownUser not set or equal to returntosender " unless (defined $EmailUnknownUser and $EmailUnknownUser ne 'returntosender');
$OUT ="luser_relay = $EmailUnknownUser";
}

View File

@@ -0,0 +1 @@
2bounce_notice_recipient = { $postfix{'DoubleBounceTo'} || "postmaster"; }

View File

@@ -0,0 +1 @@
smtp_helo_name = { $qpsmtpd{HeloHost} || '$mydomain' }

View File

@@ -0,0 +1,27 @@
smtp_tls_cert_file = /etc/postfix/ssl/postfix.pem
smtpd_tls_cert_file = /etc/postfix/ssl/postfix.pem
smtp_tls_note_starttls_offer = yes
{
# see http://www.postfix.org/postconf.5.html#smtp_tls_security_level
# *smtp_use_tls = yes (default no) this is oportunistic deprecated option
# equivalent of smtp_tls_security_level = may
# *smtp_enforce_tls = yes (default no) also deprecated
# would require it and require remote SMTP server hostname matches
# the information in the remote server certificate, and that the remote SMTP server certificate
# was issued by a CA that is trusted by the Postfix SMTP client
}smtp_tls_security_level = {
my $smarthost = $SMTPSmartHost || "off";
my $userid = ${'smtp-auth-proxy'}{'Userid'} || "";
my $tls_security_level = $postfix{'tls_security_level'} || "may";
$tls_security_level = "encrypt" if ($smarthost ne "off" && $userid ne "");
$OUT = $tls_security_level;
}
smtp_tls_enforce_peername = { (($postfix{'tls_enforce_peername'}||'yes') eq "yes")? 'yes' : 'no'; }
{
# keeping default for this one
# smtp_tls_ciphers = medium
}{
# keeping default for this one
# smtp_tls_protocols = !SSLv2, !SSLv3
# smtp_tls_protocols = >=TLSv1
}smtp_tls_loglevel = 1

View File

@@ -0,0 +1,15 @@
## SME relay outgoing mails to smarthost
{
my $smarthost = $SMTPSmartHost || "off";
my $userid = ${'smtp-auth-proxy'}{'Userid'} || "";
my $password = ${'smtp-auth-proxy'}{'Passwd'} || "";
my $port = ${'smtp-auth-proxy'}{'PeerPort'} || "25";
return "#Smarthost disabled" unless $smarthost ne "off";
$OUT = "relayhost = [$smarthost]:$port\n";
if ($userid ne "")
{
$OUT .= "smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd\n";
$OUT .= "smtp_sasl_security_options = noanonymous\n";
$OUT .= "smtp_sasl_auth_enable = yes\n";
}
}

View File

@@ -0,0 +1,22 @@
# qmail local delivery{
## alternatively we could set a db with per user delivery
# mailbox_command_maps = hash:/etc/postfix/mailbox_commands
## in /etc/postfix/mailbox_commands
# # These users need qmail-local delivery.
# johndoe /usr/local/libexec/postqmail-local
# janedoe /usr/local/libexec/postqmail-local
###########################################
# alternatively we could ask dovecot to handle the delivery
#mailbox_command = /usr/libexec/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT" -d "$USER"
# then sieve rules are needed
# maildrop or procmail could do to ....
}
prepend_delivered_header = file, forward
mailbox_command = /usr/bin/postqmail-local
# qmail needs to forward to qmqpd
qmqpd_authorized_clients = 127.0.0.1

View File

@@ -0,0 +1,2 @@
# rewrite addresse of outgoing emails
smtp_generic_maps = hash:/etc/postfix/generic

View File

@@ -1,4 +1,3 @@
2525 inet n - n - - smtpd
#smtp inet n - n - - smtpd
#smtp inet n - n - 1 postscreen
#smtpd pass - - n - - smtpd

View File

@@ -0,0 +1 @@
628 inet n - n - - qmqpd

View File

@@ -1,4 +1,3 @@
#628 inet n - n - - qmqpd
pickup unix n - n 60 1 pickup
cleanup unix n - n - 0 cleanup
qmgr unix n - n 300 1 qmgr

View File

@@ -0,0 +1,4 @@
# qmail need to test for virtual boxes
qmail-local unix - n n - - pipe
user=$USER argv=/usr/bin/sudo -u $user -H /usr/bin/postqmail-local ${mailbox} ${extension} ${nexthop} ${sender}

View File

@@ -0,0 +1,15 @@
## SME relay outgoing mails to smarthost
{
my $smarthost = $SMTPSmartHost || "off";
my $userid = ${'smtp-auth-proxy'}{'Userid'} || "";
my $password = ${'smtp-auth-proxy'}{'Passwd'} || "";
my $port = ${'smtp-auth-proxy'}{'PeerPort'} || "25";
return "#Smarthost disabled" unless $smarthost ne "off";
$OUT = "";
if ($userid ne "")
{
$OUT .= "[$smarthost]:$port $userid:$password\n";
}
}

View File

@@ -6,19 +6,26 @@
for my $domain ($domainsdb->domains)
for my $domain ($domainsdb->get_all)
{
my $mail_server = $domain->prop('MailServer')
|| $DelegateMailServer
|| 'localhost';
if ( $mail_server ne 'localhost' )
{
my ($dest,$port) = split(':',$mail_server);
$port = ( $port =~ /^\d+$/)? $port : "25";
$emaildomain = $domain->key;
$OUT .= "\@$emaildomain\t$mail_server\n";
$OUT .= "$emaildomain\t smtp:[$dest]:$port\n";
}
else
{
$emaildomain = $domain->key;
$OUT .= "$emaildomain\t local:\$myhostname\n";
}
}
}

View File

@@ -0,0 +1,5 @@
{
my $smarthost = $SMTPSmartHost || "off";
$OUT = "";
$OUT = "# SME relay smarthost is defined in main.cf relayhost variable" if $SMTPSmartHost ne "off";
}

View File

@@ -0,0 +1,8 @@
{
return "# no DelegateMailServer, we are using our own smtp" unless (defined $DelegateMailServer and $DelegateMailServer);
my ($dest,$port) = split(':',$DelegateMailServer);
my $port = ( $port =~ /^\d+$/)? $port : "25";
$OUT = "* smtp:[$dest]:$port";
}

View File

@@ -0,0 +1,24 @@
{
# mailer-daemon -> postmaster -> root (via /etc/aliases) and also defined as pseudonyms
# abuse -> root (via /etc/aliases) and also defined as pseudonyms
# postmaster -> root via etc/aliases, and admin via pseudonyms
# TODO handle qmail user alias
}
# SME system users
root admin
{
$OUT = "";
use esmith::AccountsDB;
my $adb = esmith::AccountsDB->open_ro or die "Couldn't open AccountsDB";
for my $acct ($adb->get_all_by_prop(type=>"system"))
{
next if ($acct->key eq "alias");
next if ($acct->key eq "shared");
next if ($acct->key eq "root");
$OUT .= $acct->key . "\t\t\tadmin\n";
}
}

View File

@@ -0,0 +1,19 @@
# SME users
{
my $dms = $DelegateMailServer;
return "# DelegateMailServer is set" if ($dms && ($dms !~ /^\s*$/));
$OUT = "";
use esmith::AccountsDB;
my $adb = esmith::AccountsDB->open_ro or die "Couldn't open AccountsDB";
for my $user ($adb->users)
{
#next unless ($pseudo->key =~ /@/); <== aliase to emails or catch-all @domain.com are ok
$OUT .= $user->key . "\t\t\t".$user->key."\n";
}
}

View File

@@ -1,3 +1,4 @@
# SME pseudonyms
{
my $dms = $DelegateMailServer;
@@ -11,16 +12,16 @@
for my $pseudo ($adb->pseudonyms)
{
#next unless ($pseudo->key =~ /@/);
#next unless ($pseudo->key =~ /@/);
my $account = $pseudo->prop("Account");
$account = "admin" and warn $pseudo->prop("Account") . " is not a valid account, default to admin " unless $adb->get($account);
my $acct = $adb->get($account);
if ($acct->prop('type') eq "group")
{
$account =~ s/\./:/g;
}
my $account = $pseudo->prop("Account");
$account = "admin" and warn $pseudo->prop("Account") . " is not a valid account, default to admin " unless $adb->get($account);
my $acct = $adb->get($account);
if ($acct->prop('type') eq "group")
{
$account =~ s/\./:/g;
}
$OUT .= $pseudo->key . "\t$account\n";
$OUT .= $pseudo->key . "\t\t\t$account\n";
}
}

View File

@@ -0,0 +1,30 @@
# SME groups
{
# inspired from former /etc/e-smith/events/actions/qmail-update-group
my $adb = esmith::AccountsDB->open_ro or die "Couldn't open AccountsDB";
for my $group ($adb->groups)
{
#next unless ($pseudo->key =~ /@/);
my %properties = $group->props;
my $acct = $group->key;
my @group_members = split(/,/, $properties{Members});
# Check if we should exclude members from this group email address
my @exclude_users = split(/,/, ($properties{EmailExcludeUsers} || ''));
my @exclude_groups = split(/,/, ($properties{EmailExcludeGroups} || ''));
foreach my $exclude_group (@exclude_groups){
my $g = $a->get($exclude_group);
next unless $g;
push @exclude_users, split(/,/, ($g->prop('Members') || ''));
}
my %exclude = map { $_, 1 } @exclude_users;
@exclude_users = keys %exclude;
my @members = ();
foreach my $user (@group_members){
next if grep { $_ eq $user } @exclude_users;
push @members, $user;
}
my $members = join(' ', @members);
$OUT .= "$acct\t\t\t$members\n" if $members;
}
}

View File

@@ -0,0 +1,14 @@
# Shared group
{
use esmith::AccountsDB;
my $a = esmith::AccountsDB->open_ro;
$OUT = "shared\t\t\t";
for my $user ( $a->get('admin'), $a->users )
{
next if ( ($user->prop('EveryoneEmail') || 'yes') eq 'no');
$OUT .= $user->key . " ";
}
}

View File

@@ -0,0 +1,17 @@
{
return "" ; #not used
# as we might have virtualdomains we prefer this over luser_relay
return "# we bounce all unknown address $EmailUnknownUser not set or equal to returntosender " unless (defined $EmailUnknownUser and $EmailUnknownUser ne 'returntosender');
$OUT = "catch-all";
my $i = 0;
use esmith::DomainsDB;
my $ddb = esmith::DomainsDB->open_ro;
my @domains = map { $_->key } $ddb->get_all_by_prop('type' => 'domain');
foreach my $domain ( @domains )
{
my $d = $ddb->get($domain);
next if (($d->prop('VirtualMail') || "disabled") eq "enabled");
next unless (($d->prop('MailServer') || '') eq '');
$OUT .= "\@$domain $EmailUnknownUser\n";
}
}

0
root/etc/postfix/ssl/.gitignore vendored Normal file
View File

View File

@@ -0,0 +1,15 @@
#!/bin/bash
/usr/sbin/e-smith/expand-template /etc/postfix/virtual
/usr/sbin/e-smith/expand-template /etc/postfix/sasl_passwd
/usr/sbin/e-smith/expand-template /etc/postfix/transport
/usr/sbin/e-smith/expand-template /etc/postfix/generic
/usr/sbin/e-smith/expand-template /etc/postfix/main.cf
/usr/sbin/e-smith/expand-template /etc/postfix/master.cf
# sensitive file, we want to be sure.
touch /etc/postfix/sasl_passwd.db
chmod 0600 /etc/postfix/sasl_passwd.db
chown root:root /etc/postfix/sasl_passwd.db
/usr/sbin/postmap /etc/postfix/virtual
/usr/sbin/postmap /etc/postfix/sasl_passwd
/usr/sbin/postmap /etc/postfix/transport
/usr/sbin/postmap /etc/postfix/generic

View File

@@ -0,0 +1,17 @@
#!/bin/bash
/usr/sbin/e-smith/expand-template /etc/postfix/virtual
/usr/sbin/e-smith/expand-template /etc/postfix/sasl_passwd
/usr/sbin/e-smith/expand-template /etc/postfix/transport
/usr/sbin/e-smith/expand-template /etc/postfix/generic
#TODO /usr/sbin/e-smith/expand-template /etc/postfix/main.cf
#TODO /usr/sbin/e-smith/expand-template /etc/postfix/master.cf
# sensitive file, we want to be sure.
touch /etc/postfix/sasl_passwd.db
chmod 0600 /etc/postfix/sasl_passwd.db
chown root:root /etc/postfix/sasl_passwd.db
/usr/libexec/postfix/aliasesdb
/usr/sbin/postmap /etc/postfix/virtual
/usr/sbin/postmap /etc/postfix/sasl_passwd
/usr/sbin/postmap /etc/postfix/transport
/usr/sbin/postmap /etc/postfix/generic
/usr/sbin/postfix reload

125
root/usr/bin/dotqmail Normal file
View File

@@ -0,0 +1,125 @@
#!/usr//bin/zsh -f
# credit https://www.gentei.org/~yuuji/software/dotqmail/
# original work of HIROSE Yuuji yuuji@example.org
# license none
setopt multios
dotqm=${DOTQMAIL:-.qmail}
DQHOME=${DQHOME:-$HOME}
cd $DQHOME
DEFAULTSPOOL=./Maildir/
PATH=${PATH}:/usr/sbin:/usr/lib:/var/qmail/bin; export PATH
if [ -s $DQHOME/.dotqmailexts ]; then
while IFS=: read ext home; do
home=${home/\~\//$HOME/}
home=${(e)home}
case $EXTENSION in
$ext|${ext}-*)
if [ -d $home ]; then
DQHOME=`(cd $home; pwd)`; break
fi ;;
esac
done < $DQHOME/.dotqmailexts
fi
DQBASE=$DQHOME/${dotqm}-
cd $DQHOME
export EXT=${EXTENSION//+/-}
export EXT2=${${(M)EXT%%-*}/-/}
export EXT3=${${(M)EXT2%%-*}/-/}
export EXT4=${${(M)EXT3%%-*}/-/}
# $HOST manipulation is not symmetrical with $EXT
# If $HOSTn has no dots, $HOST(n+1) has same name as $HOSTn
export HOST=$DOMAIN
export HOST2=${HOST%.*}
export HOST3=${HOST2%.*}
export HOST4=${HOST3%.*}
fdq=''
x=${(L)EXT//./:}
dq=${DQBASE}$x
function maildirmake() {
mkdir -m 700 $1 && mkdir -m 700 $1/{new,cur,tmp}
}
[[ -n "$DEBUG" ]] && echo PPP:dq=$dq >> $HOME/ddebug
if [[ $USER == $LOCAL ]]; then
fdq=$DQHOME/${1:-${dotqm}}
[[ -s $fdq ]] || echo "$DEFAULTSPOOL" > $fdq
elif [[ -s $dq ]]; then
fdq=$dq
else
while [[ x"$x" != x"" ]]; do
x=${${(M)x##*-}%-}
dq=${DQBASE}$x${x:+-}default
if [[ -s $dq ]]; then
fdq=$dq; break
fi
done
dq=${DQBASE}$x${x:+-}default
if [[ -s $dq ]]; then
fdq=$dq
fi
fi
function maildir() {
[[ -d $1 ]] || maildirmake $1
dir=$1/new
host=`hostname`
zmodload zsh/datetime || exit 111
(echo -n "$RPLINE"; cat) > $dir/$EPOCHSECONDS.$$.$host
}
function mbox() {
# no locking! do not use poor mbox!
(echo -n $UFLINE
echo -n $RPLINE
cat
echo) >> $1
}
flush() {
[[ -n "$DEBUG" ]] && echo out=$out >> $HOME/ddebug
###echo found: $fdq, default: $DEFAULT, out=$out
[[ -n "$DEBUG" ]] && env > $DQHOME/ENV
#eval "cat ${out:->/dev/null}"
eval "echo '$body' | sed 1,2d ${out:->/dev/null}"
out=""
}
[[ -n "$DEBUG" ]] && echo fdq=$fdq >> $HOME/ddebug
if [[ -n "$fdq" && -s $fdq ]]; then
default=${EXT/$x/}
[[ x"$default" != x"" ]] && export DEFAULT=${default#-}
IFS= body=`cat`
export UFLINE="${${(@f)body}[1]}"$'\n'
export RPLINE="${${(@f)body}[2]}"$'\n'
if [[ -e ${fdq}-owner ]]; then
# If .qmail-ext-owner exists, use local-owner@domain. (dot-qmail(5))
newsender="-f ${LOCAL}-owner@$DOMAIN "
echo newsender=$newsender >> $HOME/ddebug
fi
cat $fdq | while read -r line; do
case "$line" in
\#*) ;;
\|*)
# A program line should executed sequentially and should be
# ceased further instructions when program exits at 99.
[ "$out" ] && flush
echo "$body" | eval "${line#\|}"
[ $? = 99 ] && exit 0
;;
# Other instructions should be processed simultaneously.
.*/|/*/)
out="$out > >(maildir $line)" ;;
.*|/*)
out="$out > >(mbox $line)" ;;
*)
out="$out > >(sendmail ${newsender}-- ${line#\&})" ;;
esac
ec=$?
[[ -n "$DEBUG" ]] && echo "$ec by [$line]" >> $HOME/ddebug
done
flush
exit 0
else
# not found
exit 111
fi

View File

@@ -0,0 +1,13 @@
#!/bin/sh
#credit Ron Bickers <rbickers@logicetc.com>
# $1 = $LOCAL
# $2 = $EXTENSION
# $3 = $DOMAIN
# $4 = $SENDER
export PATH=$PATH:/usr/local/bin:/var/qmail/bin
tail -n +2 | /usr/local/bin/seekablepipe qmail-local -- \
"$USER" "$HOME" "$LOCAL" "${EXTENSION:+-}" "$EXTENSION" "$DOMAIN" "$SENDER" ./Maildir/
e=$?
(($e == 111)) && exit 75
(($e == 100)) && exit 77
exit $e

View File

@@ -0,0 +1,9 @@
[Service]
ExecStartPre=/sbin/e-smith/service-status postfix
ExecStartPre=/sbin/e-smith/systemd/postfix-pre
ExecReload=
ExecReload=/sbin/e-smith/systemd/postfix-reload
SyslogIdentifier=postfix
[Install]
WantedBy=sme-server.target

View File

@@ -0,0 +1,7 @@
#!/bin/sh
set -e
tmp=/var/tmp/seekable.$$
exec 3<&0 4<&1 >$tmp <$tmp
rm $tmp
cat <&3
exec ${1+"$@"} 1<&4 3>&- 4>&-

View File

@@ -1,6 +1,6 @@
%define name smeserver-postfix
%define version 1.0
%define release 1
%define release 11
Summary: This is what smeserver-postfix does.
Name: %{name}
Version: %{version}
@@ -13,12 +13,53 @@ Prefix: %{_prefix}
BuildArchitectures: noarch
BuildRequires: e-smith-devtools
Requires: e-smith-release >= 10.0
Requires: postfix
Requires: postfix-perl-scripts
Requires: postfix-pcre
Requires: zsh
Requires: smeserver-mini-qmail
AutoReqProv: no
%description
Koozali SME Server wrapper to configure postfix
%changelog
* Wed Jan 08 2025 Brian Read <brianr@koozali.org> 1.0-11.sme
- reload-or-restart postfix after pseudonym change [SME: 12863]
* Sun Dec 29 2024 Brian Read <brianr@koozali.org> 1.0-10.sme
- Quotes round smtp-auth-proxy in templates for main.cf and sasl-passwd [SME: 12836]
* Mon Dec 23 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-9.sme
- fix virtual expected format: key whitespace value for empty group [SME: 12834]
* Fri Dec 20 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-8.sme
- fix catch-all behaviour [SME: 12382]
myorigin now is hostname
in case email sent outside by deamon generic rewrite occurs
* Sun Dec 15 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-6.sme
- add mini-qmail as Message delivery agent [SME: 12737]
few other fixes; +x on needed executable files
migrate old qmail properties used in postfix
catch all non existing recipient / check BCC working
* Tue Nov 19 2024 Jean-Philippe Pialasse <jpp@koozali.org> 1.0-3.sme
- add requirements [SME: 12737]
- add conf-postfix
* Sun Nov 17 2024 <jpp@koozali.org> 1.0-2.sme
- listen only via sockets
- use both unix user and virtual users
- groups and pseudonyms implemented in virtual maps
- support smarthost with and without auth
- support global and per domain delegated mail server
- support ssl
- uses qmail - recipient delimiter in left part of email.
- all domains set as local domains in mydestination
- message_size_limit
- local and remote concurency limit
* Tue Oct 15 2024 <jpp@koozali.org> 1.0-1.sme
- Initial code - create RPM [SME: 12737]
templates from Stefano Zamboni
@@ -35,10 +76,12 @@ rm -rf $RPM_BUILD_ROOT
(cd root ; find . -depth -print | cpio -dump $RPM_BUILD_ROOT)
rm -f %{name}-%{version}-filelist
/sbin/e-smith/genfilelist $RPM_BUILD_ROOT \
--file /sbin/e-smith/systemd/postfix-reload 'attr(750,root,root)' \
--file /sbin/e-smith/systemd/postfix-pre 'attr(750,root,root)' \
--file /usr/bin/dotqmail 'attr(0555,root,root)' \
--file /usr/bin/postqmail-local 'attr(0555,root,root)' \
--file /usr/local/bin/seekablepipe 'attr(0555,root,root)' \
> %{name}-%{version}-filelist
#echo "%doc COPYING" >> %{name}-%{version}-filelist
#--dir <dir> 'attr(755,user,grp)' \
#--file <file> 'attr(755,root,root)' \
%clean
cd ..