Project

General

Profile

Milestone #78

Updated by Daniele Cruciani about 1 month ago

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**: 
 1. Enable 2FA on your Google account 
 2. Generate an App Password: `Security > App passwords > Generate` 
 3. Note down the generated 16-character password 

 ## 2. **Kubernetes Deployment** 

 ### **Mail Server Configuration (Postfix)** 

 ```yaml 
 # 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: 

 ```yaml 
 # 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: 
 ```bash 
 kubectl create secret generic postfix-sasl \ 
   --from-literal=sasl_passwd="[smtp.gmail.com]:587 your-email@gmail.com:your-app-password" 
 ``` 

 ### Header Rewriting ConfigMap: 
 ```yaml 
 # 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** 

 ```yaml 
 # 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** 

 ```bash 
 # 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** 

 1. **Warm up the IP**: Gradually increase email volume 
 2. **DKIM Signing**: Consider using a DKIM signing service 
 3. **Consistent Headers**: Ensure From, Reply-To, and Sender headers match 
 4. **Email Content**: Avoid spam trigger words, use proper HTML/text alternatives 
 5. **Monitoring**: Check Gmail's sending limits (500 recipients/day for free accounts) 
 6. **Bounce Handling**: Implement proper bounce handling in your application 

 ## 9. **Alternative: Use Mailgun or SendGrid** 

 For production, consider using a dedicated email service: 

 ```yaml 
 # 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.

Back