diff --git a/.gitignore b/.gitignore index 968d967..49ce398 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.rpm +*.tar.gz *.log -*spec-20* \ No newline at end of file +*spec-20* diff --git a/README.md b/README.md index 5bc4ef1..be0d422 100644 --- a/README.md +++ b/README.md @@ -21,26 +21,95 @@ 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 + mkdir -p /etc/e-smith/templates-custom/var/service/{qpsmtpd,sqpsmtpd,uqpsmtpd}/config/peers/{0,local}/90queue-qmail-queue + echo 'return "queue/postfix-queue";' > /etc/e-smith/templates-custom/var/service/{qpsmtpd,sqpsmtpd,uqpsmtpd}/config/peers/{0,local}/90queue-qmail-queue config setprop qmail status disabled systemctl stop qmail signal-event email-update dnf install smerserver-postfix ``` -then test + +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 + + +to remove +``` + rm -rf /etc/e-smith/templates-custom/var/service/{qpsmtpd,sqpsmtpd,uqpsmtpd}/config/peers/{0,local}/ + config setprop qmail status enabled + systemctl start qmail + signal-event email-update + dnf remove smerserver-postfix +``` + + +DONE +* main domain +* listen only socket +* virtual alias for system, pseudonyms, groups, shared TODO -* remote SMTP -* smart SMTP -* SSL -* logging -* .qmail support or alternative -* maildrop/procmail support ? +* regression: forward email support via .qmail or .forward +* regression: spam filtering to .junk +* regression: .qmail support or alternative via .forward +* regression: maildrop/procmail support directly or via .forward or via .qmail support +* regression: EmailUnknownUser support ( we can not use luser_relay as we use virtual_alias (this might need to add all unix accoutns in this virtual map and also all needed content of /etc/aliases when not returntosender) * switch smeserver-qpsmtpd support to postfix * check /usr/sbin/sendmail -> /etc/alternatives/mta -> /usr/sbin/sendmail.postfix upon removal/update of qmail +* .foward support +* remove from smeserver-mail /usr/local/sbin/smtp-auth-proxy.pl +* migrate and rewrite code for smtp-auth-proxy properties +* migrate and remove qmail properties to postfix +* make a copy of qmail/config/smtproutes to (su)qpsmtpd/config/smtproutes + +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 +* qmail/postfix->MaxMessageSize defined as 15Mb +* qmail/postfix->FilterType (empty) +* qmail/postfix->ConcurrencyRemote default to 20 +* qmail/postfix->ConcurrencyLocal default to 20 +* qmail/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://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 diff --git a/createlinks b/createlinks index 90a7a04..83fd6f1 100644 --- a/createlinks +++ b/createlinks @@ -13,35 +13,46 @@ foreach (qw( master.cf transport virtual - )) + sasl_passwd +)) { - 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 +60,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 +70,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 +88,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 +100,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 +111,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 +139,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 +147,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 +155,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 +176,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,13 +196,17 @@ 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( diff --git a/root/etc/e-smith/db/configuration/defaults/postfix/MaxMessageSize b/root/etc/e-smith/db/configuration/defaults/postfix/MaxMessageSize new file mode 100644 index 0000000..1fa94b1 --- /dev/null +++ b/root/etc/e-smith/db/configuration/defaults/postfix/MaxMessageSize @@ -0,0 +1 @@ +15000000 diff --git a/root/etc/e-smith/db/configuration/default/postfix/status b/root/etc/e-smith/db/configuration/defaults/postfix/status similarity index 100% rename from root/etc/e-smith/db/configuration/default/postfix/status rename to root/etc/e-smith/db/configuration/defaults/postfix/status diff --git a/root/etc/e-smith/db/configuration/default/postfix/type b/root/etc/e-smith/db/configuration/defaults/postfix/type similarity index 100% rename from root/etc/e-smith/db/configuration/default/postfix/type rename to root/etc/e-smith/db/configuration/defaults/postfix/type diff --git a/root/etc/e-smith/templates.metadata/etc/postfix/sasl_passwd b/root/etc/e-smith/templates.metadata/etc/postfix/sasl_passwd new file mode 100644 index 0000000..0c7fc96 --- /dev/null +++ b/root/etc/e-smith/templates.metadata/etc/postfix/sasl_passwd @@ -0,0 +1,3 @@ +UID="root" +GID="root" +PERMS=0600 diff --git a/root/etc/e-smith/templates.metadata/etc/postfix/ssl/postfix.pem b/root/etc/e-smith/templates.metadata/etc/postfix/ssl/postfix.pem new file mode 100644 index 0000000..1a9f529 --- /dev/null +++ b/root/etc/e-smith/templates.metadata/etc/postfix/ssl/postfix.pem @@ -0,0 +1,5 @@ +TEMPLATE_PATH="/home/e-smith/ssl.pem" +OUTPUT_FILENAME="/etc/postfix/ssl/postfix.pem" +UID="root" +GID="root" +PERMS=0640 diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/40inet b/root/etc/e-smith/templates/etc/postfix/main.cf/40inet index bdea448..8f8e4d9 100644 --- a/root/etc/e-smith/templates/etc/postfix/main.cf/40inet +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/40inet @@ -1,2 +1,2 @@ -inet_interfaces = loopback-only +inet_interfaces = all inet_protocols = all diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/45recipients b/root/etc/e-smith/templates/etc/postfix/main.cf/45recipients new file mode 100644 index 0000000..95cefc5 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/45recipients @@ -0,0 +1,5 @@ +{ +# qmail compatibility - instead of + +# default empty +} +recipient_delimiter = - diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/50mydestination b/root/etc/e-smith/templates/etc/postfix/main.cf/50mydestination index d27077f..c69bae7 100644 --- a/root/etc/e-smith/templates/etc/postfix/main.cf/50mydestination +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/50mydestination @@ -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 = $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 "; + } +} diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/50virtual b/root/etc/e-smith/templates/etc/postfix/main.cf/50virtual deleted file mode 100644 index e03dcc5..0000000 --- a/root/etc/e-smith/templates/etc/postfix/main.cf/50virtual +++ /dev/null @@ -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"; - } -} - diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/50virtual_domains b/root/etc/e-smith/templates/etc/postfix/main.cf/50virtual_domains new file mode 100644 index 0000000..7b64e49 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/50virtual_domains @@ -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; +} diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/51virtual b/root/etc/e-smith/templates/etc/postfix/main.cf/51virtual new file mode 100644 index 0000000..f7d4fbc --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/51virtual @@ -0,0 +1,2 @@ +# list of all virtual aliases : groups, pseudonyms ... +virtual_alias_maps = hash:/etc/postfix/virtual diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/60msgsize b/root/etc/e-smith/templates/etc/postfix/main.cf/60msgsize new file mode 100644 index 0000000..aa88ab7 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/60msgsize @@ -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"; +} + diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/60transport b/root/etc/e-smith/templates/etc/postfix/main.cf/60transport index 420d59d..3c630c6 100644 --- a/root/etc/e-smith/templates/etc/postfix/main.cf/60transport +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/60transport @@ -1,12 +1,9 @@ { $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) { my $mail_server = $domain->prop('MailServer') @@ -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; } diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/61concurency b/root/etc/e-smith/templates/etc/postfix/main.cf/61concurency new file mode 100644 index 0000000..54a1eee --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/61concurency @@ -0,0 +1,3 @@ +default_destination_concurrency_limit = { $postfix{'ConcurrencyRemote'} || "20"; } +local_destination_concurrency_limit = { $postfix{'ConcurrencyLocal'} || "20"; } + diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/65doublebounce b/root/etc/e-smith/templates/etc/postfix/main.cf/65doublebounce new file mode 100644 index 0000000..83ae149 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/65doublebounce @@ -0,0 +1 @@ +2bounce_notice_recipient = { $postfix{'DoubleBounceTo'} || "postmaster"; } diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/65heloname b/root/etc/e-smith/templates/etc/postfix/main.cf/65heloname new file mode 100644 index 0000000..233ae61 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/65heloname @@ -0,0 +1 @@ +smtp_helo_name = { $qpsmtpd{HeloHost} || '$myhostname'} diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/70certificates b/root/etc/e-smith/templates/etc/postfix/main.cf/70certificates new file mode 100644 index 0000000..1291c16 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/70certificates @@ -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 diff --git a/root/etc/e-smith/templates/etc/postfix/main.cf/75smarthost b/root/etc/e-smith/templates/etc/postfix/main.cf/75smarthost new file mode 100644 index 0000000..d73ff18 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/main.cf/75smarthost @@ -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"; + } +} diff --git a/root/etc/e-smith/templates/etc/postfix/master.cf/20smtp b/root/etc/e-smith/templates/etc/postfix/master.cf/20smtp index b8ecf33..9e23cb6 100644 --- a/root/etc/e-smith/templates/etc/postfix/master.cf/20smtp +++ b/root/etc/e-smith/templates/etc/postfix/master.cf/20smtp @@ -1,4 +1,5 @@ -2525 inet n - n - - smtpd +#2525 inet n - n - - smtpd +# :25 is in use by qpsmtpd #smtp inet n - n - - smtpd #smtp inet n - n - 1 postscreen #smtpd pass - - n - - smtpd diff --git a/root/etc/e-smith/templates/etc/postfix/sasl_passwd/20smarthost b/root/etc/e-smith/templates/etc/postfix/sasl_passwd/20smarthost new file mode 100644 index 0000000..b8fda55 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/sasl_passwd/20smarthost @@ -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"; + } + +} + diff --git a/root/etc/e-smith/templates/etc/postfix/transport/10hosts b/root/etc/e-smith/templates/etc/postfix/transport/10hosts index 0f5004a..fd4ced7 100644 --- a/root/etc/e-smith/templates/etc/postfix/transport/10hosts +++ b/root/etc/e-smith/templates/etc/postfix/transport/10hosts @@ -10,15 +10,22 @@ { 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"; + } } } - diff --git a/root/etc/e-smith/templates/etc/postfix/transport/20smarthost b/root/etc/e-smith/templates/etc/postfix/transport/20smarthost new file mode 100644 index 0000000..55abc53 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/transport/20smarthost @@ -0,0 +1,5 @@ +{ + my $smarthost = $SMTPSmartHost || "off"; + $OUT = ""; + $OUT = "# SME relay smarthost is defined in main.cf relayhost variable" if $SMTPSmartHost ne "off"; +} diff --git a/root/etc/e-smith/templates/etc/postfix/transport/30delegateMailServer b/root/etc/e-smith/templates/etc/postfix/transport/30delegateMailServer new file mode 100644 index 0000000..703ade2 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/transport/30delegateMailServer @@ -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"; + +} diff --git a/root/etc/e-smith/templates/etc/postfix/virtual/05system b/root/etc/e-smith/templates/etc/postfix/virtual/05system new file mode 100644 index 0000000..f8194b7 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/virtual/05system @@ -0,0 +1,25 @@ +{ +# 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 "admin"); + 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"; + } + +} diff --git a/root/etc/e-smith/templates/etc/postfix/virtual/06user b/root/etc/e-smith/templates/etc/postfix/virtual/06user new file mode 100644 index 0000000..eeda8ca --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/virtual/06user @@ -0,0 +1,3 @@ +# SME users +# not needed postfix will map all system users directly + diff --git a/root/etc/e-smith/templates/etc/postfix/virtual/10pseudonyms b/root/etc/e-smith/templates/etc/postfix/virtual/10pseudonyms index 5df25ec..066c661 100644 --- a/root/etc/e-smith/templates/etc/postfix/virtual/10pseudonyms +++ b/root/etc/e-smith/templates/etc/postfix/virtual/10pseudonyms @@ -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"; } } diff --git a/root/etc/e-smith/templates/etc/postfix/virtual/15groups b/root/etc/e-smith/templates/etc/postfix/virtual/15groups new file mode 100644 index 0000000..d8c83f7 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/virtual/15groups @@ -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"; + } +} diff --git a/root/etc/e-smith/templates/etc/postfix/virtual/16shared b/root/etc/e-smith/templates/etc/postfix/virtual/16shared new file mode 100644 index 0000000..cc759b8 --- /dev/null +++ b/root/etc/e-smith/templates/etc/postfix/virtual/16shared @@ -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 . " "; + } +} diff --git a/root/etc/postfix/ssl/.gitignore b/root/etc/postfix/ssl/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/root/sbin/e-smith/systemd/postfix-pre b/root/sbin/e-smith/systemd/postfix-pre new file mode 100755 index 0000000..2eddf84 --- /dev/null +++ b/root/sbin/e-smith/systemd/postfix-pre @@ -0,0 +1,11 @@ +#!/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 +# 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 diff --git a/root/sbin/e-smith/systemd/postfix-reload b/root/sbin/e-smith/systemd/postfix-reload new file mode 100755 index 0000000..6363a06 --- /dev/null +++ b/root/sbin/e-smith/systemd/postfix-reload @@ -0,0 +1,12 @@ +#!/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 +# 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/postfix reload diff --git a/root/usr/bin/dotqmail b/root/usr/bin/dotqmail new file mode 100644 index 0000000..d7202f8 --- /dev/null +++ b/root/usr/bin/dotqmail @@ -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; 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 diff --git a/root/usr/bin/postqmail-local b/root/usr/bin/postqmail-local new file mode 100644 index 0000000..e5ece0a --- /dev/null +++ b/root/usr/bin/postqmail-local @@ -0,0 +1,14 @@ +#!/bin/sh +#credit Ron Bickers +# $1 = $LOCAL +# $2 = $EXTENSION +# $3 = $DOMAIN +# $4 = $SENDER +export PATH=$PATH:/usr/local/bin:/var/qmail/bin +tail +2 | seekablepipe qmail-local -- \ + "$USER" "$HOME" "$LOCAL" "${EXTENSION:+-}" "$EXTENSION" + "$DOMAIN""$SENDER" ./Maildir/ +e=$? +(($e == 111)) && exit 75 +(($e == 100)) && exit 77 +exit $e diff --git a/root/usr/lib/systemd/system/postfix.service.d/50koozali.conf b/root/usr/lib/systemd/system/postfix.service.d/50koozali.conf new file mode 100644 index 0000000..3b2b7bf --- /dev/null +++ b/root/usr/lib/systemd/system/postfix.service.d/50koozali.conf @@ -0,0 +1,6 @@ +[Service] +ExecStartPre=-/usr/sbin/postmap /etc/postfix/virtual +ExecStartPre=/sbin/e-smith/service-status postfix + +[Install] +WantedBy=sme-server.target diff --git a/smeserver-postfix.spec b/smeserver-postfix.spec index 00ce9a9..5f4a148 100644 --- a/smeserver-postfix.spec +++ b/smeserver-postfix.spec @@ -13,12 +13,25 @@ Prefix: %{_prefix} BuildArchitectures: noarch BuildRequires: e-smith-devtools Requires: e-smith-release >= 10.0 +Requires: zsh AutoReqProv: no %description Koozali SME Server wrapper to configure postfix %changelog +* Sun Nov 17 2024 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 1.0-1.sme - Initial code - create RPM [SME: 12737] templates from Stefano Zamboni @@ -35,6 +48,8 @@ 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)' \ > %{name}-%{version}-filelist #echo "%doc COPYING" >> %{name}-%{version}-filelist #--dir 'attr(755,user,grp)' \