Actions
Milestone #78
openinstall mailserver
Milestone #78:
install mailserver
Status:
new
Priority:
wishlist
Assignee:
-
Start date:
Due date:
% Done:
0%
Estimated time:
Sprint:
Description
Setting up a mail server on Kubernetes that uses Gmail as a relay while maintaining good deliverability requires careful configuration. Here's a step-by-step guide:
1. Prerequisites ¶
First, enable "Less Secure Apps" or better, create an App Password:
- Enable 2FA on your Google account
- Generate an App Password:
Security > App passwords > Generate - Note down the generated 16-character password
2. Kubernetes Deployment ¶
Mail Server Configuration (Postfix)¶
# postfix-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postfix
spec:
replicas: 1
selector:
matchLabels:
app: postfix
template:
metadata:
labels:
app: postfix
spec:
containers:
- name: postfix
image: catatnight/postfix:latest
env:
- name: maildomain
value: "yourdomain.com" # Your domain
- name: smtp_user
value: "your-email@gmail.com:your-app-password"
- name: relayhost
value: "[smtp.gmail.com]:587"
ports:
- containerPort: 25
- containerPort: 587
- containerPort: 465
resources:
limits:
memory: "256Mi"
cpu: "250m"
---
apiVersion: v1
kind: Service
metadata:
name: postfix
spec:
selector:
app: postfix
ports:
- name: smtp
port: 25
targetPort: 25
- name: submission
port: 587
targetPort: 587
- name: smtps
port: 465
targetPort: 465
3. Postfix Configuration for Gmail Relay ¶
Create a ConfigMap for additional Postfix settings:
# postfix-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: postfix-main-cf
data:
main.cf: |
# Basic configuration
myhostname = mail.yourdomain.com
myorigin = /etc/mailname
mydestination = localhost
# Gmail relay configuration
relayhost = [smtp.gmail.com]:587
smtp_use_tls = yes
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_tls_security_options = noanonymous
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
# Important for sender rewriting
sender_canonical_classes = envelope_sender, header_sender
sender_canonical_maps = regexp:/etc/postfix/sender_canonical_maps
smtp_header_checks = regexp:/etc/postfix/header_checks
# Rate limiting to avoid Gmail limits
smtp_destination_concurrency_limit = 2
smtp_destination_rate_delay = 1s
# Prevent being marked as open relay
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination
4. Authentication and Header Rewriting ¶
SASL Password Secret:¶
kubectl create secret generic postfix-sasl \
--from-literal=sasl_passwd="[smtp.gmail.com]:587 your-email@gmail.com:your-app-password"
Header Rewriting ConfigMap:¶
# header-rewrite.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: postfix-header-rewrite
data:
header_checks: |
/^From:.*@.*/ REPLACE From: "Your Name" <your-email@gmail.com>
/^Reply-To:.*/ REPLACE Reply-To: "Your Name" <your-email@gmail.com>
/^Sender:.*/ REPLACE Sender: "Your Name" <your-email@gmail.com>
sender_canonical_maps: |
/.*/ your-email@gmail.com
5. Updated Deployment with ConfigMaps ¶
# updated-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postfix
spec:
replicas: 1
selector:
matchLabels:
app: postfix
template:
metadata:
labels:
app: postfix
spec:
containers:
- name: postfix
image: catatnight/postfix:latest
env:
- name: maildomain
value: "yourdomain.com"
volumeMounts:
- name: postfix-config
mountPath: /etc/postfix/main.cf
subPath: main.cf
- name: header-rewrite
mountPath: /etc/postfix/header_checks
subPath: header_checks
- name: sender-canonical
mountPath: /etc/postfix/sender_canonical_maps
subPath: sender_canonical_maps
- name: sasl-secret
mountPath: /etc/postfix/sasl_passwd
subPath: sasl_passwd
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- |
postmap /etc/postfix/sasl_passwd
postmap /etc/postfix/sender_canonical_maps
postfix reload
volumes:
- name: postfix-config
configMap:
name: postfix-main-cf
- name: header-rewrite
configMap:
name: postfix-header-rewrite
- name: sender-canonical
configMap:
name: postfix-header-rewrite
- name: sasl-secret
secret:
secretName: postfix-sasl
6. DNS Configuration for Better Deliverability ¶
Add these DNS records for your domain:
TXT @ "v=spf1 include:_spf.google.com ~all"
TXT _dmarc "v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.com"
TXT google._domainkey "google-site-verification=..."
7. Test the Setup ¶
# Test from inside the cluster
kubectl exec -it <postfix-pod> -- /bin/bash
# Send test email
echo "Test email" | mail -s "Test Subject" recipient@example.com \
-a "From: Your Name <your-email@gmail.com>"
8. Additional Deliverability Tips ¶
- Warm up the IP: Gradually increase email volume
- DKIM Signing: Consider using a DKIM signing service
- Consistent Headers: Ensure From, Reply-To, and Sender headers match
- Email Content: Avoid spam trigger words, use proper HTML/text alternatives
- Monitoring: Check Gmail's sending limits (500 recipients/day for free accounts)
- Bounce Handling: Implement proper bounce handling in your application
9. Alternative: Use Mailgun or SendGrid ¶
For production, consider using a dedicated email service:
# Using Mailgun as example
relayhost = [smtp.mailgun.org]:587
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
# sasl_passwd contains: [smtp.mailgun.org]:587 postmaster@yourdomain.com:api-key
Important Notes:¶
- Gmail Limits: Free accounts have daily sending limits
- App Passwords: Required if 2FA is enabled
- SPF/DKIM/DMARC: Configure these properly even when using Gmail as relay
- Rate Limiting: Respect Gmail's rate limits (100 emails/hour)
This setup ensures your emails appear to come from your Gmail address properly authenticated, reducing spam filter issues.
Updated by Daniele Cruciani about 1 month ago
- Description updated (diff)
Actions