Files
2026-08-18 09:40:08 +02:00

9.2 KiB

KUBE  /  Mail server

Mail server

Template of zone

$TTL 300
@           IN  SOA ns1.mydns.example. dnsadmin.mydomain.com. (
                2025091001 ; serial
                3600       ; refresh
                900        ; retry
                1209600    ; expire
                300        ; minimum
)
            IN  NS  ns1.mydns.example.
            IN  NS  ns2.mydns.example.

; ===== A/AAAA =====
mta         IN  A      {{PUBLIC_IPV4}}
; mta       IN  AAAA   {{PUBLIC_IPV6}}   ; if available

; if desired, client sites can resolve to the same IP
{{US1}}     IN  A      {{PUBLIC_IPV4}}
{{US2}}     IN  A      {{PUBLIC_IPV4}}
{{US3}}     IN  A      {{PUBLIC_IPV4}}

; ===== MX =====
; @           IN  MX 10  mta.{{ROOT_DOMAIN}}. ; the root domain also accepts mail, if needed
{{US1}}     IN  MX 10  mta.{{ROOT_DOMAIN}}.
{{US2}}     IN  MX 10  mta.{{ROOT_DOMAIN}}.
{{US3}}     IN  MX 10  mta.{{ROOT_DOMAIN}}.

; ===== SPF =====
; @           IN  TXT    "v=spf1 mx ~all" ; if available
mta         IN  TXT    "v=spf1 a -all"
{{US1}}     IN  TXT    "v=spf1 mx ~all"
{{US2}}     IN  TXT    "v=spf1 mx ~all"
{{US3}}     IN  TXT    "v=spf1 mx ~all"

; ===== DKIM =====
; For each customer domain, publish its own public key.
; The selector can be shared (e.g., selector1); keys are different.
selector1._domainkey.{{US1}} IN TXT "v=DKIM1; k=rsa; p={{PUBKEY_US1}}"
selector1._domainkey.{{US2}} IN TXT "v=DKIM1; k=rsa; p={{PUBKEY_US2}}"
selector1._domainkey.{{US3}} IN TXT "v=DKIM1; k=rsa; p={{PUBKEY_US3}}"

; ===== DMARC =====
; Initially p=none to collect reports without impacting delivery.
_dmarc.{{US1}} IN TXT "v=DMARC1; p=none; adkim=r; aspf=r; rua=mailto:{{DMARC_AGG}}; ruf=mailto:{{DMARC_FOR}}"
_dmarc.{{US2}} IN TXT "v=DMARC1; p=none; adkim=r; aspf=r; rua=mailto:{{DMARC_AGG}}; ruf=mailto:{{DMARC_FOR}}"
_dmarc.{{US3}} IN TXT "v=DMARC1; p=none; adkim=r; aspf=r; rua=mailto:{{DMARC_AGG}}; ruf=mailto:{{DMARC_FOR}}"
; It is recommended to set DMARC on the root domain to cover ALL subdomains with a single policy.
; _dmarc         IN TXT "v=DMARC1; p=quarantine; sp=quarantine; adkim=r; aspf=r; rua=mailto:{{DMARC_AGG}}; ruf=mailto:{{DMARC_FOR}}"
; (if test mode first — replace p=none, sp=none)

; ===== Additionally (optional but useful) =====
; MTA-STS (if to implement)
;_mta-sts      IN TXT "v=STSv1; id=2025-09-10"
;_smtp._tls    IN TXT "v=TLSRPTv1; rua=mailto:tlsrpt@{{ROOT_DOMAIN}}"
;autoconfig    IN CNAME autoconfig.mailhost.example.   ; for client autoconfiguration
;autodiscover  IN CNAME autodiscover.mailhost.example.
; ===== PTR =====
{{PUBLIC_IPV4}} → mta.{{ROOT_DOMAIN}}

Check: Postfix HELO/EHLO = mta.{{ROOT_DOMAIN}}

Example

{{ROOT_DOMAIN}} → krumax.cz
{{PUBLIC_IPV4}} → 31.31.73.67
{{US1}}/{{US2}}/{{US3}} → us1 / us2 / us3
{{PUBKEY_US1}}/{{PUBKEY_US2}}/{{PUBKEY_US3}} → DKIM public keys (only the content after p=, in a single line)
{{DMARC_AGG}}/{{DMARC_FOR}} → Addresses for DMARC reports (for example, dmarc@krumax.cz)

$TTL 300

; ===== A =====
mta         IN  A      31.31.73.67
us1         IN  A      31.31.73.67
us2         IN  A      31.31.73.67
us3         IN  A      31.31.73.67

; ===== MX =====
us1         IN  MX 10  mta.krumax.cz.
us2         IN  MX 10  mta.krumax.cz.
us3         IN  MX 10  mta.krumax.cz.

; ===== SPF =====
mta         IN  TXT    "v=spf1 a -all"
us1         IN  TXT    "v=spf1 mx ~all"
us2         IN  TXT    "v=spf1 mx ~all"
us3         IN  TXT    "v=spf1 mx ~all"

; ===== DKIM =====
selector1._domainkey.us1 IN TXT "v=DKIM1; k=rsa; p=MIIBI...(us1)"
selector1._domainkey.us2 IN TXT "v=DKIM1; k=rsa; p=MIIBI...(us2)"
selector1._domainkey.us3 IN TXT "v=DKIM1; k=rsa; p=MIIBI...(us3)"

; ===== DMARC =====
_dmarc.us1  IN TXT "v=DMARC1; p=none; adkim=r; aspf=r; rua=mailto:dmarc@krumax.cz; ruf=mailto:dmarc@krumax.cz"
_dmarc.us2  IN TXT "v=DMARC1; p=none; adkim=r; aspf=r; rua=mailto:dmarc@krumax.cz; ruf=mailto:dmarc@krumax.cz"
_dmarc.us3  IN TXT "v=DMARC1; p=none; adkim=r; aspf=r; rua=mailto:dmarc@krumax.cz; ruf=mailto:dmarc@krumax.cz"
; ===== PTR =====
31.31.73.67 → mta.krumax.cz

Example of adding a new domain in Postfix

  1. Adding the domain and generating DKIM
sudo kube.sh postfix add us2.krumax.cz
  1. Retrieving DKIM
sudo kube.sh postfix dkim us2.krumax.cz
  1. Adding DNS records:
us2         IN  A      31.31.73.67
us2         IN  MX 10  mta.krumax.cz.
selector1._domainkey.us2 IN TXT "v=DKIM1; k=rsa; p=MIIBI...(from step 2)"
_dmarc.us2  IN TXT "v=DMARC1; p=none; adkim=r; aspf=r; rua=mailto:dmarc@krumax.cz; ruf=mailto:dmarc@krumax.cz"

Send mail in PHP.

Create file for test send mail send-mail.php

<?
mb_internal_encoding('UTF-8');
$to        = 'maksym.krugol@wedos.org';
$toName    = 'Maksym Krugol';
$from      = 'no-reply@us1.krumax.cz';
$fromName  = 'Support team US1';
$return    = 'bounce@us1.krumax.cz';
$subject   = mb_encode_mimeheader('Test delivery (PHP)', 'UTF-8', 'B', "\r\n");
$bodyText  = "Hi! Test with PHP.";
$bodyQP    = quoted_printable_encode($bodyText);
$headers = [
  "From: $fromName <$from>",
  "Reply-To: $from",
  "Return-Path: $return",
  "Date: " . date('r'),
  "Message-ID: <" . time() . "." . bin2hex(random_bytes(6)) . "@" . $hostname . ">",
  "MIME-Version: 1.0",
  "Content-Type: text/plain; charset=UTF-8",
  "Content-Transfer-Encoding: quoted-printable",
  "List-Unsubscribe: <mailto:unsubscribe@us1.krumax.cz?subject=unsubscribe>, <https://us1.krumax.cz/unsubscribe/".rawurlencode('maksym.krugol@wedos.org').">",
];
$headersStr = implode("\r\n", $headers);

$status = mail("$toName <$to>", $subject, $bodyQP, $headersStr, "-f$return");
echo $status ? "Success\n" : "Failed\n";

Send mail in Wordpress.

  1. Add Wordpress plugin /wp-content/mu-plugins/smtp.php
<?php
// For 25 port (without TLS/login)
add_action('phpmailer_init', function ($phpmailer) {
    $phpmailer->isSMTP();
    $phpmailer->XMailer     = 'krumaxMailer 1.0';
    $phpmailer->Host        = 'mta.krumax.cz';
    $phpmailer->Port        = 25;
    $phpmailer->SMTPAuth    = false;
    $phpmailer->SMTPSecure  = '';
    $phpmailer->SMTPAutoTLS = false;
    $phpmailer->From        = 'no-reply@us1.krumax.cz';
    // $phpmailer->FromName    = 'Support team US1';
    // $phpmailer->Hostname    = 'us1.krumax.cz';
    // $phpmailer->Encoding    = 'quoted-printable';
    // $phpmailer->Sender      = 'bounce@us1.krumax.cz';
    // $phpmailer->Timeout     = 15;
});
<?php
// For 587 port (with TLS/login)
add_action('phpmailer_init', function ($phpmailer) {
    $phpmailer->isSMTP();
    $phpmailer->XMailer     = 'krumaxMailer 1.0';
    $phpmailer->Host        = 'mta.krumax.cz';
    $phpmailer->Port        = 587;
    $phpmailer->Username    = 'postmaster@us1.krumax.cz';
    $phpmailer->Password    = 'qwerty';
    $phpmailer->SMTPAuth    = true;
    $phpmailer->SMTPSecure  = 'tls';
    $phpmailer->SMTPAutoTLS = true;
    $phpmailer->SMTPOptions = [
      'ssl' => [
        'allow_self_signed' => true,
      ],
    ];
    $phpmailer->From        = 'no-reply@us1.krumax.cz';
    // $phpmailer->FromName    = 'Support team US1';
    // $phpmailer->Hostname    = 'us1.krumax.cz';
    // $phpmailer->Encoding    = 'quoted-printable';
    // $phpmailer->Sender      = 'bounce@us1.krumax.cz';
    // $phpmailer->Timeout     = 15;
});
  1. Create file for test send mail /send-mail.php
<?php
require_once 'wp-load.php';

$domain = "us1.krumax.cz";
$to = "maksym.krugol@wedos.org";
$toName = "Maksym Krugol";
$subject = "Test delivery (Wordpress)";
$message = "Hi! Test with Wordpress.";
$headers = [
    "List-Unsubscribe: <mailto:unsubscribe@{$domain}?subject=unsubscribe>, <https://{$domain}/unsubscribe/{$to}>"
];

if (wp_mail("$toName <{$to}>", $subject, $message, $headers)) {
    echo "Success";
} else {
    echo "Failed";
}
  1. Open URL http://us1.krumax.cz/send-mail.php

Send mail from pod in k3s (use Postfix).

  1. Install postfix: apt-get install -y postfix
  2. Set config:
postconf -e 'myhostname = mta.krumax.cz'
postconf -e 'mydomain = us1.krumax.cz'
postconf -e 'myorigin = $mydomain'
  1. Create file test.mail:
From: Support team US1 <no-reply@us1.krumax.cz>
To: Maksym Krugol <maksym.krugol@wedos.org>
Subject: Test delivery (postfix)
Date: Wed, 17 Sep 2025 10:53:13 +0200
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Hi! Test with /usr/sbin/sendmail.
  1. Send mail: sendmail -v -oi -t -f 'no-reply@us1.krumax.cz' < test.mail

Send mail from pod in k3s (use msmtp).

  1. Install msmtp: apt-get install -y msmtp msmtp-mta ca-certificates
  2. Set config /etc/msmtprc:
defaults
auth           on
tls            on
tls_starttls   on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        /var/log/msmtp.log

account default
host     mta.krumax.cz
port     587
from     no-reply@us1.krumax.cz
user     postmaster@us1.krumax.cz
password qwerty
  1. Create file test.mail:
From: Support team US1 <no-reply@us1.krumax.cz>
To: Maksym Krugol <maksym.krugol@wedos.org>
Subject: Test delivery (msmtp)
Date: Wed, 17 Sep 2025 10:53:13 +0200
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Hi! Test with msmtp/sendmail.
  1. Send mail: sendmail -v -oi -t -f 'no-reply@us1.krumax.cz' < test.mail