Update README.md
This commit is contained in:
252
README.md
252
README.md
@@ -1,141 +1,191 @@
|
|||||||
# 📬 Postfix Mail Summary Script
|
# Postfix Mail Summary Script
|
||||||
|
|
||||||
A hardened, production-ready Bash script for analyzing Postfix mail logs with a **clean, readable output format**.
|

|
||||||
|
|
||||||
Designed with **security, performance, and portability** in mind.
|
Hardened, secure, and memory-safe Bash script for summarizing **Postfix** mail logs with filtering and detail views.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Features
|
## Table of Contents
|
||||||
|
|
||||||
- 📊 **Clean, formatted output** (with optional colors)
|
* [Overview](#overview)
|
||||||
- 🔍 **Filter by**:
|
* [Features](#features)
|
||||||
- Sender (`--from`)
|
* [Requirements](#requirements)
|
||||||
- Recipient (`--to`)
|
* [Installation](#installation)
|
||||||
- Queue ID (`--id`)
|
* [Usage](#usage)
|
||||||
- Date (`--date`)
|
* [Options](#options)
|
||||||
- ⚡ **Optimized log reading** (avoids full log parsing when possible)
|
* [Examples](#examples)
|
||||||
- 🛡️ **Hardened against**:
|
* [Security & Hardening](#security--hardening)
|
||||||
- Command injection
|
* [Notes](#notes)
|
||||||
- Regex/ReDoS attacks
|
* [License](#license)
|
||||||
- Memory leaks
|
|
||||||
- Log-based DoS
|
|
||||||
- 🧠 **Smart parsing** of Postfix logs (including `NOQUEUE` rejects)
|
|
||||||
- 🎯 **Portable** across Linux distributions
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📦 Requirements
|
## Overview
|
||||||
|
|
||||||
- Bash (>= 4.x recommended)
|
This script parses and summarizes Postfix log files located in `/var/log/`. It supports filtering by sender, recipient, queue ID, and date. The output can be a concise summary table or a detailed per-message view.
|
||||||
- Standard Linux utilities:
|
|
||||||
- `awk`
|
The script is hardened with:
|
||||||
- `grep`
|
|
||||||
- `sed`
|
* Resource limits
|
||||||
- `tail`
|
* Safe temporary file handling
|
||||||
- `find`
|
* Single-instance locking
|
||||||
- `zcat`
|
* Secure parsing and memory-safe processing
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚙️ Installation
|
## Features
|
||||||
|
|
||||||
|
* Summarizes Postfix logs with **color-coded output**.
|
||||||
|
* Filters by:
|
||||||
|
|
||||||
|
* Sender (`from`)
|
||||||
|
* Recipient (`to`)
|
||||||
|
* Queue ID (`id`)
|
||||||
|
* Date (`date`)
|
||||||
|
|
||||||
|
* **Use `-d ""` to search across all logs without date filtering**
|
||||||
|
* Displays summary or detailed view per message.
|
||||||
|
* Handles compressed logs (`.gz`) automatically.
|
||||||
|
* Safely deletes old temporary files.
|
||||||
|
* Avoids displaying internal local deliveries (`127.0.0.1`) unless explicitly filtered.
|
||||||
|
* Highlights **deferred**, **rejected**, and **greylisted** emails with color.
|
||||||
|
* Limits memory, CPU time, and file usage for safety.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* Linux or Unix-like system
|
||||||
|
* Bash 4.x+
|
||||||
|
* Postfix logs under `/var/log/` (e.g., `maillog*`, `mail.log*`)
|
||||||
|
* `awk`, `zcat`, `grep`, `find`, `sed` installed
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Clone or copy the script to your preferred location, e.g.:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.robott.sk/robott/mail-status.git
|
sudo cp postfix_summary.sh /usr/local/bin/postfix_summary
|
||||||
cd mail-status
|
sudo chmod +x /usr/local/bin/postfix_summary
|
||||||
chmod +x mail-status.sh
|
```
|
||||||
▶️ Usage
|
|
||||||
sudo ./mail-status.sh [OPTIONS]
|
|
||||||
📖 Options
|
|
||||||
Option Description
|
|
||||||
-h, --help Show help message
|
|
||||||
-l, --list NUMBER Show last X records (default: 10, max: 1000)
|
|
||||||
-f, --from Filter by sender (substring match)
|
|
||||||
-t, --to Filter by recipient (substring match)
|
|
||||||
-i, --id Filter by Queue ID
|
|
||||||
-d, --date "MMM DD" Filter by date (e.g. "Mar 27")
|
|
||||||
|
|
||||||
Search across all logs for a specific user:
|
No additional dependencies are required.
|
||||||
|
|
||||||
sudo ./mail-status.sh -f user@example.com -d ""
|
---
|
||||||
|
|
||||||
Or search for a specific date:
|
## Usage
|
||||||
|
|
||||||
sudo ./mail-status.sh -f user@example.com -d "Mar 23"
|
```bash
|
||||||
📌 Examples
|
postfix_summary.sh [OPTIONS]
|
||||||
|
```
|
||||||
|
|
||||||
Show last 10 records
|
By default, it shows the **last 10 mail log records** from today.
|
||||||
|
|
||||||
sudo ./mail-status.sh
|
---
|
||||||
|
|
||||||
Show last 50 records
|
## Options
|
||||||
|
|
||||||
sudo ./mail-status.sh -l 50
|
| Option | Description |
|
||||||
|
| ------------------------- | ------------------------------------------------ |
|
||||||
|
| `-h, --help` | Show this help message |
|
||||||
|
| `-l, --list NUMBER` | Show the last X records (default: 10, max: 1000) |
|
||||||
|
| `-f, --from EMAIL/DOMAIN` | Filter by sender email or domain |
|
||||||
|
| `-t, --to EMAIL/DOMAIN` | Filter by recipient email or domain |
|
||||||
|
| `-i, --id QUEUE_ID` | Show detail view for a specific queue ID |
|
||||||
|
| `-d, --date "MMM DD"` | Filter by date (e.g., `"Mar 27"`) |
|
||||||
|
|
||||||
Filter by sender
|
* **Use `-d ""` to search across all logs without date filtering** |
|
||||||
|
|
||||||
sudo ./mail-status.sh -f gmail.com
|
---
|
||||||
|
|
||||||
Filter by recipient
|
## Examples
|
||||||
|
|
||||||
sudo ./mail-status.sh -t example.com
|
Show last 20 emails:
|
||||||
|
|
||||||
Filter by Queue ID
|
```bash
|
||||||
|
postfix_summary.sh -l 20
|
||||||
|
```
|
||||||
|
|
||||||
sudo ./mail-status.sh -i 3F2A12345
|
Filter emails from a specific sender:
|
||||||
|
|
||||||
Filter by date
|
```bash
|
||||||
|
postfix_summary.sh -f "example@domain.com"
|
||||||
|
```
|
||||||
|
|
||||||
sudo ./mail-status.sh -d "Mar 27"
|
Filter emails sent to a specific recipient:
|
||||||
🖥️ Output Example
|
|
||||||
DATE-TIME ID CLIENT_IP SENDER RECIPIENT STATUS REASON
|
|
||||||
Mar-27-12:00:01 3F2A12345 192.168.1.10 user@gmail.com admin@example.com sent [OK]
|
|
||||||
Mar-27-12:01:05 NOQUEUE 45.12.34.56 spam@bad.com user@example.com REJECT [Policy]
|
|
||||||
🔐 Security Design
|
|
||||||
|
|
||||||
This script is designed with security-first principles:
|
```bash
|
||||||
|
postfix_summary.sh -t "recipient@domain.com"
|
||||||
|
```
|
||||||
|
|
||||||
✅ Protected Against:
|
Show detailed view of a specific queue ID:
|
||||||
|
|
||||||
Command injection
|
```bash
|
||||||
AWK injection
|
postfix_summary.sh -i 3F2A4B1C0
|
||||||
Regex-based DoS (ReDoS)
|
```
|
||||||
Malicious filenames
|
|
||||||
Memory exhaustion
|
|
||||||
Log flooding
|
|
||||||
|
|
||||||
🔒 Key Techniques:
|
Filter by a specific date:
|
||||||
|
|
||||||
Input length limiting
|
```bash
|
||||||
Substring matching (index() instead of regex)
|
postfix_summary.sh -d "Mar 27"
|
||||||
Safe file handling (find -print0, arrays)
|
```
|
||||||
Temporary file isolation (mktemp)
|
|
||||||
Automatic cleanup (trap)
|
|
||||||
No use of eval
|
|
||||||
⚡ Performance Optimizations
|
|
||||||
Reads only last 50,000 lines by default
|
|
||||||
Full log scan only when necessary (--date, --id)
|
|
||||||
Avoids unnecessary process spawning
|
|
||||||
Efficient AWK parsing with memory cleanup
|
|
||||||
🎨 Color Output
|
|
||||||
Automatically enabled when running in a terminal
|
|
||||||
Disabled when piping output (e.g., | less, | grep)
|
|
||||||
⚠️ Notes
|
|
||||||
Must be run as root (required for log access)
|
|
||||||
Works with standard Postfix logs:
|
|
||||||
/var/log/maillog
|
|
||||||
Rotated logs (maillog.*, .gz)
|
|
||||||
🛠️ Future Improvements (Optional)
|
|
||||||
Real-time monitoring (tail -f)
|
|
||||||
JSON export for SIEM tools (ELK, Splunk)
|
|
||||||
Fail2ban integration (auto-block IPs)
|
|
||||||
Spam pattern detection
|
|
||||||
📄 License
|
|
||||||
|
|
||||||
MIT License
|
Search across all logs without date filtering:
|
||||||
|
|
||||||
👨💻 Author
|
```bash
|
||||||
|
postfix_summary.sh -d ""
|
||||||
|
```
|
||||||
|
|
||||||
robott GitHub: https://github.com/robott
|
---
|
||||||
|
|
||||||
Powered by Gitea
|
## Security & Hardening
|
||||||
|
|
||||||
|
The script applies multiple security measures:
|
||||||
|
|
||||||
|
1. **Resource Limits**
|
||||||
|
Prevents excessive CPU or memory usage:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ulimit -t 15 # CPU time
|
||||||
|
ulimit -v 500000 # Virtual memory (kB)
|
||||||
|
ulimit -f 102400 # Max file size
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Single Instance Locking**
|
||||||
|
Prevents multiple simultaneous executions using `/tmp/postfix_summary.lock`.
|
||||||
|
|
||||||
|
3. **Temporary File Safety**
|
||||||
|
Uses `mktemp` to create secure temporary files and cleans them on exit.
|
||||||
|
|
||||||
|
4. **Safe Argument Handling**
|
||||||
|
Limits input length and validates required arguments.
|
||||||
|
|
||||||
|
5. **Memory-Safe Log Parsing**
|
||||||
|
Skips overly long or short lines to prevent potential buffer abuse.
|
||||||
|
|
||||||
|
6. **Old Temp File Cleanup**
|
||||||
|
Deletes stale files older than 10 minutes to prevent clutter or accidental data leak.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
* The script ignores local Postfix deliveries (`127.0.0.1`) in summary mode.
|
||||||
|
* Supports `.gz` compressed logs for backward compatibility.
|
||||||
|
* Detail view (`--id`) provides full information including:
|
||||||
|
|
||||||
|
* Date/Time
|
||||||
|
* Client IP
|
||||||
|
* Sender
|
||||||
|
* Recipient
|
||||||
|
* Status
|
||||||
|
* Reason
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License – feel free to use, modify, and distribute.
|
||||||
|
|||||||
Reference in New Issue
Block a user