Skip to content

nitinoneview/postfix-gmail-relay

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

Postfix Gmail Relay Setup (RHEL 8)

Configure Postfix on RHEL 8 to send outbound mail through Gmail's SMTP relay (port 587), instead of trying to deliver directly over port 25 — which most ISPs/home networks block.


🧩 The Problem

By default, Postfix tries to deliver mail directly to the recipient's mail server over port 25 (standard SMTP). On a home network (broadband/WiFi), the ISP blocks outbound port 25 to prevent spam — this is an almost universal residential ISP policy in India (Airtel, Jio, BSNL, etc.) and elsewhere.

Symptom in logs (journalctl -u postfix):

connect to alt4.gmail-smtp-in.l.google.com[142.250.101.27]:25: Connection refused
status=deferred (connect to alt4.gmail-smtp-in.l.google.com[142.250.101.27]:25: Connection refused)

This is not a Postfix config bug — it's the network blocking the connection. The fix is to stop trying to deliver mail directly, and instead route (relay) all outbound mail through an authenticated service like Gmail on port 587 (Submission port, used for authenticated mail clients — generally not blocked).


🏗️ How It Works (Architecture)

[Your App/Script/Cron]
        │
        │  (local, via "mail" command or sendmail)
        ▼
   [Postfix - localhost]
        │
        │  authenticates using Gmail App Password
        │  connects on port 587 (TLS encrypted)
        ▼
  [smtp.gmail.com:587]
        │
        ▼
  [Recipient's Inbox]
  • Postfix = Mail Transfer Agent (MTA) running locally on your RHEL box. It accepts mail from local users/scripts (e.g. mail command, cron job alerts, application notifications).
  • Relay / Smarthost = Instead of Postfix resolving the recipient's mail server itself, it forwards everything to Gmail's SMTP server, which then handles final delivery.
  • SASL Authentication = Postfix logs into your Gmail account (using an App Password, not your real password) before Gmail accepts mail from it.
  • TLS Encryption = The connection between Postfix and Gmail is encrypted (smtp_tls_security_level = encrypt), required for port 587.

This relay pattern is exactly what's used in production environments — servers/apps rarely send mail directly to the internet; they go through a relay (Gmail, AWS SES, SendGrid, Mailgun, etc.).


📁 Files Involved

File Purpose Edited By You?
/etc/postfix/main.cf Main Postfix config — relay host, TLS, SASL settings ✅ Yes
/etc/postfix/sasl_passwd Stores Gmail address + App Password (plaintext, root-only) ✅ Yes (create new)
/etc/postfix/sasl_passwd.db Hashed/indexed version of the above, auto-generated ⚙️ Auto (via postmap)

✅ Prerequisites

  • RHEL 8 with Postfix installed (postfix package)
  • A Gmail account with 2-Step Verification enabled
  • A Gmail App Password (16 characters) — generate at: https://myaccount.google.com/apppasswords

    Your normal Gmail login password will not work here. Google requires a separate App Password for SMTP apps.


🚀 Setup Steps

1. Install the SASL plugin

Postfix needs this to authenticate with Gmail.

sudo dnf install cyrus-sasl-plain -y

2. Create the credentials file

sudo nano /etc/postfix/sasl_passwd

Add this single line (replace with your Gmail and App Password, no spaces in the password):

[smtp.gmail.com]:587    youraccount@gmail.com:your16charapppassword

3. Hash the credentials file and lock down permissions

sudo postmap /etc/postfix/sasl_passwd
sudo chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
sudo chown root:root /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
  • postmap converts the plain text file into a fast-lookup .db file that Postfix actually reads.
  • chmod 600 ensures only root can read/write it — important since it holds a credential in plaintext.

4. Configure Postfix to use Gmail as relay

sudo nano /etc/postfix/main.cf

Add at the end of the file:

relayhost = [smtp.gmail.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
smtp_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt

⚠️ Before adding: check if smtp_tls_security_level already exists earlier in the file:

grep -n "smtp_tls_security_level" /etc/postfix/main.cf

If it does (commonly set to may by default), comment out the old line instead of having two conflicting entries (see Troubleshooting below).

5. Restart Postfix

sudo systemctl restart postfix

6. Send a test mail

echo "Test mail from RHEL via Gmail relay" | mail -s "Postfix Relay Test" youraccount@gmail.com

7. Verify in logs

sudo journalctl -u postfix -n 20 --no-pager

Success looks like:

status=sent (250 2.0.0 OK ... gsmtp)

Failure (still blocked/misconfigured) looks like:

status=deferred (connect to ... Connection refused)

🔧 Troubleshooting

Warning: overriding earlier entry: smtp_tls_security_level=may

This means smtp_tls_security_level is defined twice in main.cf — once by default (may) and once by you (encrypt). Postfix uses the later value, but logs a warning every restart.

Fix — find both entries:

grep -n "smtp_tls_security_level" /etc/postfix/main.cf

Comment out the older/default one (replace <LINE_NUMBER> with the line number of the may entry):

sudo sed -i '<LINE_NUMBER>s/^smtp_tls_security_level = may$/#&/' /etc/postfix/main.cf
sudo systemctl restart postfix

This comments the line out (prefixes #) rather than deleting it — safer, reversible.

Mail stuck in queue / still "Connection refused"

  • Confirm you're using port 587 in relayhost, not 25.
  • Confirm sasl_passwd.db exists — re-run postmap if you edited sasl_passwd after the first setup.
  • Check the mail queue: mailq
  • Force a retry: sudo postqueue -f

Mail sent but not arriving

  • Check Gmail Spam/Junk folder — first-time senders from a new server often land there.
  • Confirm the App Password wasn't regenerated/revoked in your Google Account.

📚 What This Teaches (Concepts)

Concept Why It Matters
Port 25 vs Port 587 25 = direct server-to-server SMTP (often ISP-blocked); 587 = authenticated client submission (standard for app/relay use)
Smarthost / Relay pattern Production systems rarely deliver mail directly — they relay through a trusted provider (Gmail, SES, SendGrid, Mailgun)
SASL Authentication How Postfix proves its identity to an external mail provider
TLS encryption in mail transport Protects credentials and mail content in transit
Reading Postfix logs (journalctl -u postfix) Core sysadmin/production-support troubleshooting skill
Config file conflict debugging (grep -n) Common pattern for resolving "duplicate setting" issues in any .conf/.cf file

🗂️ Repo Structure

postfix-gmail-relay/
├── README.md                  ← this file
├── main.cf.snippet            ← the exact lines to add to main.cf
└── sasl_passwd.example        ← template for the credentials file (no real password)

⚠️ Security Note

  • Never commit your real sasl_passwd file (with actual App Password) to GitHub.
  • This repo includes only an .example template — always .gitignore the real file.
  • Treat the App Password like any other secret/credential.

About

Postfix SMTP relay setup via Gmail on RHEL 8 — fixes port 25 ISP blocking

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors