Update README.md
update
This commit is contained in:
@@ -1,218 +1,170 @@
|
|||||||
# Mail Stats - Postfix Summary Tool (v2026.1.1)
|
# Mail Stats - Postfix Summary Tool (v4.0.9)
|
||||||
|
|
||||||

|
📋 **Table of Contents**
|
||||||

|
- [Overview](#-overview)
|
||||||

|
- [Features](#-features)
|
||||||
|
- [Requirements](#-requirements)
|
||||||
---
|
- [Installation](#-installation)
|
||||||
|
- [Usage](#-usage)
|
||||||
## 📋 Table of Contents
|
- [Options](#-options)
|
||||||
|
- [Examples](#-examples)
|
||||||
1. [Overview](#overview)
|
- [Security & Hardening](#-security--hardening)
|
||||||
2. [Features](#features)
|
- [Notes](#-notes)
|
||||||
3. [Requirements](#requirements)
|
- [License](#-license)
|
||||||
4. [Installation](#installation)
|
- [Author](#-author)
|
||||||
5. [Usage](#usage)
|
|
||||||
6. [Options](#options)
|
|
||||||
7. [Examples](#examples)
|
|
||||||
8. [Security & Hardening](#security--hardening)
|
|
||||||
9. [Notes](#notes)
|
|
||||||
10. [License](#license)
|
|
||||||
11. [Author](#author)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🌟 Overview
|
## 🌟 Overview
|
||||||
|
**Mail Stats** is a secure, hardened, memory-safe Bash tool for summarizing Postfix mail logs. It provides:
|
||||||
|
- Filtering by sender, recipient, IP, queue ID, status, and date.
|
||||||
|
- Concise summary tables or detailed per-message views.
|
||||||
|
- Automatic processing of compressed logs (`.gz`) and `systemd` journals (`journalctl`).
|
||||||
|
- Color-coded terminal output for easier readability.
|
||||||
|
|
||||||
**Mail Stats** is a secure, hardened, memory-safe Bash tool for summarizing **Postfix** mail logs. It provides:
|
This tool is ideal for Senior DevOps engineers and server administrators who need fast, secure insights into sent, rejected, or deferred emails in a production environment.
|
||||||
|
|
||||||
* Filtering by sender, recipient, queue ID, and date
|
|
||||||
* Concise summary tables or detailed per-message views
|
|
||||||
* Automatic processing of compressed logs (`.gz`)
|
|
||||||
* Color-coded terminal output for easier readability
|
|
||||||
|
|
||||||
This tool is ideal for server administrators who need fast insights into sent, rejected, or deferred emails.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ✨ Features
|
## ✨ Features
|
||||||
|
- **Multi-Source Log Discovery:** Reads from `/var/log/mail.log`, `.gz` archives, or `journalctl`.
|
||||||
* **Color-coded output** for quick status recognition
|
- **Live Watch Mode:** Monitor emails in real-time (`tail -f` / `journalctl -f`).
|
||||||
* Filter by:
|
- **Smart Pagination:** Automatically pipes large outputs into `less` (preserving terminal colors).
|
||||||
|
- **New Year's Eve Bug Fix:** Intelligently handles the classic Syslog missing-year issue.
|
||||||
* Sender (`from`)
|
- **Regex Support:** Enable PCRE for advanced matching.
|
||||||
* Recipient (`to`)
|
- **Statistical Summaries:** Generates Top 10 IPs, Senders, Status breakdowns, and bandwidth usage.
|
||||||
* Queue ID (`id`)
|
- **Color-coded output** for quick status recognition (Sent, Deferred, Reject, Greylist).
|
||||||
* Date (`date`)
|
- **Excludes local deliveries** (`127.0.0.1`) unless explicitly filtered.
|
||||||
|
- **Limits CPU, memory, and file usage** for strict server safety.
|
||||||
* Use `-d ""` to search across all logs
|
|
||||||
* Summary or detailed per-message view
|
|
||||||
* Handles `.gz` compressed logs automatically
|
|
||||||
* Excludes local deliveries (`127.0.0.1`) unless filtered
|
|
||||||
* Limits CPU, memory, and file usage for safety
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🖥 Requirements
|
## 🖥 Requirements
|
||||||
|
Standard utilities found on almost all Linux distributions:
|
||||||
* Linux/Unix system
|
- Linux/Unix system with **Bash 4.x+**
|
||||||
* Bash 4.x+
|
- Postfix logs in `/var/log/` (e.g., `maillog*`, `mail.log*`) or `systemd`
|
||||||
* Postfix logs in `/var/log/` (e.g., `maillog*`, `mail.log*`)
|
- Core commands: `awk`, `grep`, `tail`, `sort`, `mktemp`, `flock`
|
||||||
* `awk`, `zcat`, `grep`, `find`, `sed` installed
|
- *Optional but recommended:* `less`, `zcat`/`zgrep`, `journalctl`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚡ Installation
|
## ⚡ Installation
|
||||||
|
|
||||||
Copy or clone the script:
|
Copy or clone the script:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo cp mail-stats /usr/local/bin/mail-stats
|
sudo curl -o /usr/local/sbin/mail-stats [https://raw.githubusercontent.com/YOUR_REPO/mail-stats.sh](https://raw.githubusercontent.com/YOUR_REPO/mail-stats.sh)
|
||||||
sudo chmod +x /usr/local/bin/mail-stats
|
sudo chmod +x /usr/local/sbin/mail-stats
|
||||||
```
|
```
|
||||||
|
*No additional dependencies required.*
|
||||||
No additional dependencies required.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠 Usage
|
## 🛠 Usage
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mail-stats [OPTIONS]
|
mail-stats [OPTIONS]
|
||||||
```
|
```
|
||||||
|
By default, it displays the last 10 mail log entries for today.
|
||||||
By default, it displays the **last 10 mail log entries** for today.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔧 Options
|
## 🔧 Options
|
||||||
|
|
||||||
| Option | Description |
|
### Filtering Options
|
||||||
| ------------------------- | ---------------------------------------- |
|
| Option | Name | Description |
|
||||||
| `-h, --help` | Show help message |
|
|---|---|---|
|
||||||
| `-l, --list NUMBER` | Number of records (default 10, max 1000) |
|
| `-d` | `--date` | Filter by date (e.g., `"Mar 27"`). Use `""` for all logs. Default is today. |
|
||||||
| `-f, --from EMAIL/DOMAIN` | Filter by sender |
|
| | `--time` | Filter by exact time or whole hour (e.g., `"14:30"` or `"14:"`). |
|
||||||
| `-t, --to EMAIL/DOMAIN` | Filter by recipient |
|
| `-f` | `--from` | Filter by sender email address or domain. |
|
||||||
| `-i, --id QUEUE_ID` | Show detailed view of specific queue ID |
|
| `-t` | `--to` | Filter by recipient email address or domain. |
|
||||||
| `-d, --date "MMM DD"` | Filter by date (e.g., `"Mar 27"`) |
|
| `-a` | `--ip` | Filter by source/relay IP address. |
|
||||||
|
| `-s` | `--status` | Filter by delivery status (e.g., `sent`, `reject`, `deferred`). |
|
||||||
|
| `-i` | `--id` | Search for a specific Queue ID (Enables Detail View). |
|
||||||
|
| | `--min-size`| Show only emails larger than specified BYTES. |
|
||||||
|
| `-R` | `--regex` | Treat filters (-f, -t, -a, -s) as Regular Expressions. |
|
||||||
|
|
||||||
|
### Output & Run Mode Options
|
||||||
|
| Option | Name | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `-l` | `--list` | Number of records to display (default 10, max 1000). |
|
||||||
|
| `-S` | `--summary` | Show aggregate statistics (Top IPs, Senders, Data usage). |
|
||||||
|
| `-c` | `--csv` | Output data in CSV format (disables colors). |
|
||||||
|
| `-w` | `--watch` | Live Watch Mode (`tail -f`). Shows new emails in real-time. |
|
||||||
|
|
||||||
|
### Misc Options
|
||||||
|
| Option | Name | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| | `--log-dir` | Custom path to log files (Default: `/var/log`). Whitelisted paths only. |
|
||||||
|
| `-h` | `--help` | Show the help message. |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📝 Examples
|
## 📝 Examples
|
||||||
|
|
||||||
Show last 20 emails:
|
**Show last 20 emails:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mail-stats -l 20
|
mail-stats -l 20
|
||||||
```
|
```
|
||||||
|
**Filter by sender or recipient:**
|
||||||
Filter by sender:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mail-stats -f "example@domain.com"
|
mail-stats -f "example@domain.com"
|
||||||
```
|
|
||||||
|
|
||||||
Filter by recipient:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mail-stats -t "recipient@domain.com"
|
mail-stats -t "recipient@domain.com"
|
||||||
```
|
```
|
||||||
|
**Detailed view for a specific Queue ID:**
|
||||||
Detailed view for Queue ID:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mail-stats -i 3F2A4B1C0
|
mail-stats -i 3F2A4B1C0
|
||||||
```
|
```
|
||||||
|
**Find all large emails (over 10MB) across all old logs (ignoring date):**
|
||||||
Filter by date:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mail-stats -d "Mar 27"
|
mail-stats -d "" --min-size 10485760
|
||||||
```
|
```
|
||||||
|
**Live monitor all incoming REJECTED emails in real-time:**
|
||||||
Search all logs:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mail-stats -d ""
|
mail-stats -w -s reject
|
||||||
|
```
|
||||||
|
**Show statistical summary of all emails sent to 'gmail.com' today:**
|
||||||
|
```bash
|
||||||
|
mail-stats -t gmail.com -S
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛡 Security & Hardening
|
## 🛡 Security & Hardening
|
||||||
|
|
||||||
1. **Resource Limits**
|
### Resource Limits
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ulimit -t 15 # CPU time
|
ulimit -t 15 # CPU time (Seconds)
|
||||||
ulimit -v 500000 # Virtual memory (kB)
|
ulimit -v 500000 # Virtual memory (kB)
|
||||||
ulimit -f 102400 # Max file size
|
ulimit -f 102400 # Max file size
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Single Instance Locking**
|
### Enterprise-Grade Protections
|
||||||
|
|
||||||
* Prevents simultaneous executions via `/tmp/mail-stats.lock`
|
|
||||||
|
|
||||||
3. **Temporary File Safety**
|
|
||||||
|
|
||||||
* Uses `mktemp` and cleans files on exit
|
|
||||||
|
|
||||||
4. **Safe Argument Handling**
|
|
||||||
|
|
||||||
* Limits input length and validates required arguments
|
|
||||||
|
|
||||||
5. **Memory-Safe Log Parsing**
|
|
||||||
|
|
||||||
* Skips overly long/short lines
|
|
||||||
|
|
||||||
6. **Old Temp File Cleanup**
|
|
||||||
|
|
||||||
* Deletes stale files older than 10 minutes
|
|
||||||
|
|
||||||
This script (version 4.0.9) is exceptionally secure and, from a Bash programming perspective, is among the best you can use for a production environment. It actively handles the vast majority of known vulnerabilities and security flaws.
|
This script (version 4.0.9) is exceptionally secure and, from a Bash programming perspective, is among the best you can use for a production environment. It actively handles the vast majority of known vulnerabilities and security flaws.
|
||||||
|
|
||||||
Here is a summary of how the script protects the system against specific types of attacks:
|
Here is a summary of how the script protects the system against specific types of attacks:
|
||||||
|
|
||||||
Command Injection: Secure. No user input (-f, -t, -s) is directly interpolated into a command execution string. All inputs are safely passed to AWK via variables (-v f_filt="$FROM_FILTER").
|
- **Command Injection:** Secure. No user input (`-f`, `-t`, `-s`) is directly interpolated into a command execution string. All inputs are safely passed to AWK via variables (`-v f_filt="$FROM_FILTER"`).
|
||||||
|
- **Directory Traversal:** Handled. A user cannot exploit the `--log-dir` parameter to process arbitrary system files (e.g., `--log-dir /etc`). The script strictly whitelists only the `/var/log` and `/var/log/mail` paths.
|
||||||
|
- **Symlink Attacks:** Handled. The script uses the secure system command `mktemp` to create temporary files (mapped to the system's `$TMPDIR`). The temporary file is immediately deleted upon script completion using the `trap` command, even if the script is forcefully terminated (Ctrl+C).
|
||||||
|
- **ReDoS (Regular Expression Denial of Service):** Handled. The script includes `ulimit -t 15`, meaning if someone enters an extremely complex regular expression that overwhelms the CPU, the Linux kernel will safely kill the script after 15 seconds. In "Live Watch" mode, regex is completely disabled just to be safe.
|
||||||
|
- **Terminal Escape Injection:** Handled. If an attacker sends an email with special non-printable characters in the subject (which could, for example, clear the screen or change terminal colors), the AWK function `sanitize()` strips these characters before they are printed to your screen.
|
||||||
|
- **Cross-User DoS (Blocking by other users):** Handled. The Lock file includes the user ID (`${UID}`). This means if the system has multiple administrators, one administrator cannot intentionally or unintentionally block the script from running for another administrator. Memory-safe log parsing skips overly long/short lines.
|
||||||
|
|
||||||
Directory Traversal: Handled. A user cannot exploit the --log-dir parameter to process arbitrary system files (e.g., --log-dir /etc). The script strictly whitelists only the /var/log and /var/log/mail paths.
|
**The only final security recommendation:**
|
||||||
|
Bash scripts themselves have no inherent security privileges—they only have the rights of the user executing them. Since `/var/log/mail.log` logs typically require elevated read permissions, ideally run this script as a user in the `adm` group (on Debian/Ubuntu systems, this is sufficient to read logs) so you don't have to run it directly as `root` every time.
|
||||||
|
|
||||||
Symlink Attacks: Handled. The script uses the secure system command mktemp to create temporary files. The temporary file is immediately deleted upon script completion using the trap command, even if the script is forcefully terminated (Ctrl+C).
|
|
||||||
|
|
||||||
ReDoS (Regular Expression Denial of Service): Handled. The script includes ulimit -t 15, meaning if someone enters an extremely complex regular expression that overwhelms the CPU, the Linux kernel will safely kill the script after 15 seconds. In "Live Watch" mode, regex is completely disabled just to be safe.
|
|
||||||
|
|
||||||
Terminal Escape Injection: Handled. If an attacker sends an email with special non-printable characters in the subject (which could, for example, clear the screen or change terminal colors), the AWK function sanitize() strips these characters before they are printed to your screen.
|
|
||||||
|
|
||||||
Cross-User DoS (Blocking by other users): Handled. The Lock file includes the user ID (${UID}). This means if the system has multiple administrators, one administrator cannot intentionally or unintentionally block the script from running for another administrator.
|
|
||||||
|
|
||||||
The only final security recommendation:
|
|
||||||
Bash scripts themselves have no inherent security privileges—they only have the rights of the user executing them. Since /var/log/mail.log logs typically require elevated read permissions, ideally run this script as a user in the adm group (on Debian/Ubuntu systems, this is sufficient to read logs) so you don't have to run it directly as root every time.
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚠ Notes
|
## ⚠ Notes
|
||||||
|
- Ignores local Postfix deliveries (`127.0.0.1`) by default unless specifically filtered.
|
||||||
* Ignores local Postfix deliveries (`127.0.0.1`) by default
|
- Seamlessly supports `.gz` compressed logs and `systemd` journals.
|
||||||
* Supports `.gz` compressed logs
|
- Detailed view (`--id`) shows: Date/Time, Client IP, Sender, Recipient, Status, Size, Subject, and exact Reason/SMTP response code.
|
||||||
* Detailed view (`--id`) shows:
|
|
||||||
|
|
||||||
* Date/Time
|
|
||||||
* Client IP
|
|
||||||
* Sender
|
|
||||||
* Recipient
|
|
||||||
* Status
|
|
||||||
* Reason
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📜 License
|
## 📜 License
|
||||||
|
MIT License – free to use, modify, and distribute.
|
||||||
MIT License – free to use, modify, and distribute
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 👤 Author
|
## 👤 Author
|
||||||
|
robott – GitHub
|
||||||
**robott** – [GitHub](https://git.robott.sk/robott)
|
|
||||||
Reference in New Issue
Block a user