Project

General

Profile

Actions

Milestone #79

open

setup Redmine Using internal mailserver

Milestone #79: setup Redmine Using internal mailserver

Added by Daniele Cruciani about 1 month ago. Updated about 1 month ago.

Status:
confirmed
Priority:
wishlist
Start date:
Due date:
% Done:

90%

Estimated time:
Sprint:

Description

Yes, absolutely! You can configure your Redmine instance to use this Postfix mail server as its SMTP relay. Here's how to set it up:

1. First, Update Redmine Configuration

Create or update a ConfigMap for Redmine's email configuration:

# redmine-email-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: redmine-email-config
data:
  configuration.yml: |
    default:
      email_delivery:
        delivery_method: :smtp
        smtp_settings:
          address: "postfix"  # Postfix service name in Kubernetes
          port: 587
          domain: "yourdomain.com"
          authentication: :none  # No auth to Postfix (internal traffic)
          enable_starttls_auto: false  # Postfix handles TLS to Gmail
          openssl_verify_mode: 'none'  # For self-signed certs if needed

2. Mount the Configuration in Redmine Deployment

Update your Redmine deployment to use this ConfigMap:

# redmine-deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redmine
spec:
  template:
    spec:
      containers:
      - name: redmine
        volumeMounts:
        - name: email-config
          mountPath: /usr/src/redmine/config/configuration.yml
          subPath: configuration.yml
      volumes:
      - name: email-config
        configMap:
          name: redmine-email-config

3. Alternative: Using Redmine Environment Variables

If your Redmine image supports environment variables for email configuration:

# redmine-deployment-env.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redmine
spec:
  template:
    spec:
      containers:
      - name: redmine
        env:
        - name: REDMINE_EMAIL_DELIVERY_METHOD
          value: "smtp"
        - name: REDMINE_SMTP_HOST
          value: "postfix"  # Kubernetes service name
        - name: REDMINE_SMTP_PORT
          value: "587"
        - name: REDMINE_SMTP_DOMAIN
          value: "yourdomain.com"
        - name: REDMINE_SMTP_STARTTLS_AUTO
          value: "false"
        - name: REDMINE_SMTP_AUTHENTICATION
          value: "none"

4. Test Redmine Email Functionality

Method 1: Test from Redmine Console

# Access Redmine pod
kubectl exec -it redmine-pod -- /bin/bash

# Start Rails console
bundle exec rails console

# Test email sending
ActionMailer::Base.mail(
  from: 'redmine@yourdomain.com',
  to: 'test@example.com',
  subject: 'Test from Redmine',
  body: 'This is a test email from Redmine'
).deliver_now

Method 2: Use Redmine's Test Function

  1. Log into Redmine as Admin
  2. Go to Administration → Settings → Email notifications
  3. Click "Send a test email"
  4. Enter your email address

5. Customizing Redmine's "From" Address

To ensure Redmine uses your Gmail address properly:

Option A: Configure in Redmine Settings

# Update configuration.yml
email_delivery:
  smtp_settings:
    # ... existing settings ...
  # Add email_from setting
email_from: '"Redmine" <your-email@gmail.com>'

Option B: Use Postfix Header Rewriting

Ensure your Postfix header_checks ConfigMap handles Redmine emails:

# Update header_checks in postfix ConfigMap
header_checks: |
  # Rewrite ALL From headers to use your Gmail
  /^From:.*/ REPLACE From: "Redmine System" <your-email@gmail.com>
  
  # Or be more specific for Redmine emails
  /^From:.*redmine.*/ REPLACE From: "Redmine" <your-email@gmail.com>
  /^From:.*@yourdomain.com/ REPLACE From: "Redmine" <your-email@gmail.com>
  
  # Ensure proper headers
  /^Reply-To:.*/ REPLACE Reply-To: "Redmine" <your-email@gmail.com>
  /^Sender:.*/ REPLACE Sender: your-email@gmail.com

6. Complete Example with Bitnami Redmine

If you're using the Bitnami Redmine chart:

# values.yaml for Bitnami Redmine
smtpHost: "postfix"
smtpPort: 587
smtpUser: ""
smtpPassword: ""
smtpProtocol: ""
smtpTls: false
smtpAuth: ""
extraEnvVars:
  - name: REDMINE_EMAIL_FROM
    value: "your-email@gmail.com"

7. Verify the Flow

The email flow will be:

Redmine → Postfix (K8s Service) → Gmail SMTP → Recipient
           ↑                            ↑
       No auth needed             Uses your Gmail auth
       (internal traffic)         (App Password)

8. Common Issues and Solutions

Issue 1: Connection refused

# Check Postfix is running
kubectl get pods -l app=postfix

# Check logs
kubectl logs postfix-pod

# Test connectivity from Redmine pod
kubectl exec redmine-pod -- telnet postfix 587

Issue 2: Emails not sending

# Check Postfix mail queue
kubectl exec postfix-pod -- postqueue -p

# Check Postfix logs
kubectl logs postfix-pod | grep -i "sasl\|tls\|relay"

Issue 3: Gmail rejecting emails

# Check for authentication errors
kubectl logs postfix-pod | grep -i "authentication\|535\|550"

9. Monitoring Email Delivery

# Add sidecar for mail log monitoring
# postfix-deployment-with-sidecar.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postfix
spec:
  template:
    spec:
      containers:
      - name: postfix
        # ... existing postfix container ...
      - name: mail-log-tailer
        image: alpine:latest
        command: ["sh", "-c"]
        args:
          - tail -f /var/log/mail.log
        volumeMounts:
        - name: mail-logs
          mountPath: /var/log

10. Quick Test Commands

# Test email sending from within cluster
cat << EOF | kubectl run -it --rm --image=alpine:latest test-email -- sh
apk add mailx
echo "Test email body" | mail -s "Test Subject" test@example.com \
  -r "Redmine <your-email@gmail.com>" \
  -S smtp="postfix:587"
EOF

This setup allows Redmine to send notifications (issue updates, password resets, etc.) through your Postfix relay, which then sends them via Gmail with your Gmail address as the sender. The emails should have better deliverability since they're properly authenticated through Gmail's SMTP servers.

Updated by Daniele Cruciani about 1 month ago Actions #1

  • Description updated (diff)

Updated by Daniele Cruciani about 1 month ago Actions #2

Alternative

Using Gmail Directly from Kubernetes (No Postfix)

This is actually simpler and often more reliable. Here's how to configure Redmine and other services to use Gmail SMTP directly.

1. Why Go Direct to Gmail?

Advantages:

  • Simpler setup
  • No intermediate mail server to maintain
  • Better deliverability (Gmail's reputation)
  • Built-in TLS/security
  • Monitoring via Gmail

Disadvantages:

  • Gmail's sending limits (500 recipients/day free, 2,000/day GSuite)
  • Requires app password for each service
  • No queuing if Gmail is down

2. Redmine Direct Gmail Configuration

Option A: Redmine Configuration File

Create a ConfigMap for Redmine:

# redmine-gmail-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: redmine-email-config
data:
  configuration.yml: |
    default:
      email_delivery:
        delivery_method: :smtp
        smtp_settings:
          address: "smtp.gmail.com"
          port: 587
          domain: "gmail.com"  # or your custom domain
          authentication: :plain
          enable_starttls_auto: true
          user_name: "your-email@gmail.com"
          password: "your-app-password-here"
          openssl_verify_mode: 'peer'
        # Optional: Force specific sender address
        email_from: '"Redmine Notifications" <your-email@gmail.com>'
  
  # For newer Redmine versions using environment variables
  .env: |
    REDMINE_EMAIL_DELIVERY_METHOD=smtp
    REDMINE_SMTP_HOST=smtp.gmail.com
    REDMINE_SMTP_PORT=587
    REDMINE_SMTP_USER=your-email@gmail.com
    REDMINE_SMTP_PASSWORD=your-app-password
    REDMINE_SMTP_STARTTLS_AUTO=true
    REDMINE_SMTP_AUTHENTICATION=plain
    REDMINE_EMAIL_FROM="Redmine <your-email@gmail.com>"

Option B: Redmine Deployment with Environment Variables

# redmine-deployment-gmail.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redmine
spec:
  template:
    spec:
      containers:
      - name: redmine
        env:
        # Gmail SMTP Configuration
        - name: REDMINE_EMAIL_DELIVERY_METHOD
          value: "smtp"
        - name: REDMINE_SMTP_HOST
          value: "smtp.gmail.com"
        - name: REDMINE_SMTP_PORT
          value: "587"
        - name: REDMINE_SMTP_DOMAIN
          value: "gmail.com"
        - name: REDMINE_SMTP_USER
          valueFrom:
            secretKeyRef:
              name: gmail-credentials
              key: username
        - name: REDMINE_SMTP_PASSWORD
          valueFrom:
            secretKeyRef:
              name: gmail-credentials
              key: password
        - name: REDMINE_SMTP_AUTHENTICATION
          value: "plain"
        - name: REDMINE_SMTP_ENABLE_STARTTLS_AUTO
          value: "true"
        - name: REDMINE_EMAIL_FROM
          value: '"Redmine" <your-email@gmail.com>'
        - name: REDMINE_EMAIL_SUBJECT_PREFIX
          value: "[Redmine]"
        # For Bitnami Redmine image
        - name: SMTP_HOST
          value: "smtp.gmail.com"
        - name: SMTP_PORT
          value: "587"
        - name: SMTP_USER
          valueFrom:
            secretKeyRef:
              name: gmail-credentials
              key: username
        - name: SMTP_PASSWORD
          valueFrom:
            secretKeyRef:
              name: gmail-credentials
              key: password
        - name: SMTP_PROTOCOL
          value: ""
        - name: SMTP_AUTH
          value: "login"
        - name: SMTP_TLS
          value: "true"

Create Gmail Credentials Secret:

kubectl create secret generic gmail-credentials \
  --from-literal=username='your-email@gmail.com' \
  --from-literal=password='your-16-char-app-password'

3. Other Services Using Gmail Directly

Jenkins:

# jenkins-values.yaml (if using Helm)
controller:
  JCasC:
    defaultConfig: true
    configScripts:
      email: |
        unclassified:
          mailer:
            charset: "UTF-8"
            replyToAddress: "your-email@gmail.com"
            smtpHost: "smtp.gmail.com"
            smtpPort: 587
            smtpAuthUsername: "your-email@gmail.com"
            smtpAuthPassword: ${SMTP_PASSWORD}
            useSsl: false
            useTls: true
  additionalSecrets:
    - name: smtp-password
      value: "your-app-password"
  envVars:
    - name: SMTP_PASSWORD
      valueFrom:
        secretKeyRef:
          name: gmail-credentials
          key: password

GitLab:

# gitlab-values.yaml
global:
  appConfig:
    email:
      enabled: true
      from: "gitlab@yourdomain.com"
      display_name: "GitLab"
      subject_suffix: ""
      smtp:
        enabled: true
        address: "smtp.gmail.com"
        port: 587
        user_name: "your-email@gmail.com"
        password:
          secret: gmail-credentials
          key: password
        authentication: "login"
        starttls_auto: true
        openssl_verify_mode: "peer"

WordPress:

# wordpress-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
spec:
  template:
    spec:
      containers:
      - name: wordpress
        env:
        - name: WORDPRESS_DB_HOST
          value: "mysql"
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-password
              key: password
        # SMTP Configuration via WP Mail SMTP plugin
        - name: WPMS_SMTP_HOST
          value: "smtp.gmail.com"
        - name: WPMS_SMTP_PORT
          value: "587"
        - name: WPMS_SMTP_USER
          valueFrom:
            secretKeyRef:
              name: gmail-credentials
              key: username
        - name: WPMS_SMTP_PASS
          valueFrom:
            secretKeyRef:
              name: gmail-credentials
              key: password
        - name: WPMS_SMTP_AUTH
          value: "true"
        - name: WPMS_SMTP_SECURE
          value: "tls"
        - name: WPMS_FROM_EMAIL
          value: "your-email@gmail.com"
        - name: WPMS_FROM_NAME
          value: "WordPress Site"

Generic Application (Node.js/Python/etc.):

# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    spec:
      containers:
      - name: app
        env:
        - name: SMTP_HOST
          value: "smtp.gmail.com"
        - name: SMTP_PORT
          value: "587"
        - name: SMTP_USER
          valueFrom:
            secretKeyRef:
              name: gmail-credentials
              key: username
        - name: SMTP_PASSWORD
          valueFrom:
            secretKeyRef:
              name: gmail-credentials
              key: password
        - name: EMAIL_FROM
          value: '"My App" <your-email@gmail.com>'

4. Centralized SMTP Secret Management

Create a single secret for all services:

# Create generic Gmail secret
kubectl create secret generic smtp-gmail \
  --from-literal=host='smtp.gmail.com' \
  --from-literal=port='587' \
  --from-literal=username='your-email@gmail.com' \
  --from-literal=password='your-app-password' \
  --from-literal=from-email='your-email@gmail.com' \
  --from-literal=from-name='Kubernetes Services'

5. Using Sidecar SMTP Proxy (Alternative)

If apps don't support SMTP configuration easily, use a sidecar:

# smtp-sidecar.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-with-smtp
spec:
  template:
    spec:
      containers:
      - name: main-app
        # Your main application
        env:
        - name: SMTP_HOST
          value: "localhost"  # Points to sidecar
        - name: SMTP_PORT
          value: "1025"
      
      - name: smtp-proxy
        image: namshi/smtp
        env:
        - name: RELAY_HOST
          value: "smtp.gmail.com"
        - name: RELAY_PORT
          value: "587"
        - name: RELAY_USERNAME
          valueFrom:
            secretKeyRef:
              name: gmail-credentials
              key: username
        - name: RELAY_PASSWORD
          valueFrom:
            secretKeyRef:
              name: gmail-credentials
              key: password
        ports:
        - containerPort: 1025

6. Testing Gmail Connection

Create a test pod to verify SMTP works:

# test-smtp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-smtp
spec:
  containers:
  - name: test
    image: alpine:latest
    command: ["sh", "-c"]
    args:
      - |
        apk add --no-cache swaks
        echo "Testing Gmail SMTP..."
        swaks \
          --to recipient@example.com \
          --from your-email@gmail.com \
          --server smtp.gmail.com:587 \
          --auth LOGIN \
          --auth-user "your-email@gmail.com" \
          --auth-password "$(cat /etc/smtp/password)" \
          -tls
    env:
    - name: SMTP_PASSWORD
      valueFrom:
        secretKeyRef:
          name: gmail-credentials
          key: password
    volumeMounts:
    - name: smtp-password
      mountPath: /etc/smtp
  volumes:
  - name: smtp-password
    secret:
      secretName: gmail-credentials
  restartPolicy: Never

7. Monitoring and Limits

Gmail Limits to Know:

  • Free Gmail: 500 recipients/day, 100 emails/hour
  • G Suite: 2,000 recipients/day, 1,500 emails/hour
  • Message size: 25MB total, ~20MB after encoding

Create a Monitoring Sidecar:

# monitoring sidecar
- name: smtp-monitor
  image: python:3.9-alpine
  command: ["python", "-c"]
  args:
    - |
      import smtplib, time, os
      from email.mime.text import MIMEText
      
      def test_smtp():
          try:
              server = smtplib.SMTP('smtp.gmail.com', 587)
              server.starttls()
              server.login(os.getenv('SMTP_USER'), os.getenv('SMTP_PASSWORD'))
              server.quit()
              print(f"{time.ctime()}: SMTP OK")
              return True
          except Exception as e:
              print(f"{time.ctime()}: SMTP FAILED - {e}")
              return False
      
      while True:
          test_smtp()
          time.sleep(300)  # Test every 5 minutes
  env:
  - name: SMTP_USER
    valueFrom:
      secretKeyRef:
        name: gmail-credentials
        key: username
  - name: SMTP_PASSWORD
    valueFrom:
      secretKeyRef:
        name: gmail-credentials
        key: password

8. Handling Multiple Gmail Accounts

If you need different sender addresses:

# Create multiple secrets
kubectl create secret generic gmail-redmine \
  --from-literal=username='redmine@gmail.com' \
  --from-literal=password='app-pass-1'

kubectl create secret generic gmail-jenkins \
  --from-literal=username='jenkins@gmail.com' \
  --from-literal=password='app-pass-2'

kubectl create secret generic gmail-alerts \
  --from-literal=username='alerts@gmail.com' \
  --from-literal=password='app-pass-3'

9. Security Best Practices

  1. Use App Passwords, not your main password
  2. Regularly rotate app passwords (every 90 days)
  3. Monitor usage in Google Account → Security
  4. Set up alerts for unusual activity
  5. Use separate accounts for different services if possible

10. Troubleshooting Common Issues

Error: "534-5.7.14 Please log in"

# Enable access for "less secure apps" temporarily
# Or visit: https://accounts.google.com/DisplayUnlockCaptcha

Error: "550-5.7.1 Daily sending limit exceeded"

  • Reduce email volume
  • Queue emails and send in batches
  • Consider a paid service for high volume

Error: "Connection refused"

# Check if port 587 is open from your cluster
kubectl run -it --rm --image=alpine:latest test-net -- nc -zv smtp.gmail.com 587

# If blocked, use 465 with SSL instead
SMTP_PORT: "465"
SMTP_TLS: "true"  # not STARTTLS

11. Complete Example: Redmine with Gmail

Here's the full setup:

# 1. Create Gmail secret
kubectl create secret generic gmail-redmine \
  --from-literal=username='your-email@gmail.com' \
  --from-literal=password='abcd efgh ijkl mnop'

# 2. Apply Redmine configuration
kubectl apply -f redmine-gmail.yaml

Where redmine-gmail.yaml is:

# redmine-gmail.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redmine
spec:
  template:
    spec:
      containers:
      - name: redmine
        image: redmine:latest
        env:
        - name: REDMINE_SMTP_HOST
          value: "smtp.gmail.com"
        - name: REDMINE_SMTP_PORT
          value: "587"
        - name: REDMINE_SMTP_USER
          valueFrom:
            secretKeyRef:
              name: gmail-redmine
              key: username
        - name: REDMINE_SMTP_PASSWORD
          valueFrom:
            secretKeyRef:
              name: gmail-redmine
              key: password
        - name: REDMINE_SMTP_AUTHENTICATION
          value: "plain"
        - name: REDMINE_SMTP_ENABLE_STARTTLS_AUTO
          value: "true"
        - name: REDMINE_EMAIL_FROM
          value: '"Redmine" <your-email@gmail.com>'
---
apiVersion: v1
kind: Service
metadata:
  name: redmine
spec:
  ports:
  - port: 3000
  selector:
    app: redmine

This direct approach is simpler and often works better than running your own Postfix when you're just using Gmail as the outgoing mail server anyway.

Updated by Daniele Cruciani about 1 month ago Actions #3

  • Status changed from new to confirmed
  • Assignee set to Daniele Cruciani
  • % Done changed from 0 to 90

Done by

setup config in config/configuration.yml file

Actions

Also available in: PDF Atom