Conversation

Your input fuels progress! Share your tips or experiences on prioritizing mental wellness at work. Let's inspire change together!

Join the discussion and share your insights now!

Comments: 0

Sharpen your coding skills—try JavaScript challenges on TOOLX now!

advertisement

How to Detect File Changes and Send Email Alerts Using PHP

How to Detect File Changes and Send Email Alerts Using PHP

When managing a live PHP project, especially one deployed on a shared server or accessible by multiple developers, monitoring unauthorized changes to files is crucial. Even a single unexpected edit to your codebase can introduce bugs, vulnerabilities, or data loss.

In this guide, you'll learn how to create a secure file monitoring system in PHP that:

  1. Detects new, modified, or deleted files
  2. Captures the IP and location of the requestor
  3. Sends instant email alerts whenever suspicious changes occur
  4. Ensures only authorized users can trigger the scan
Let’s build it step by step.

🛡️ 1. Why Monitor File Changes?

There are many practical use cases for tracking file-level changes:

  • Protect against unauthorized tampering or backdoors
  • Alert on accidental overwrites or deletions during deployment
  • Detect file uploads or malware injections
  • Maintain version consistency across environments

🔐 2. Securing the Monitoring Script

Before you start scanning files, it's important to secure the script itself. Otherwise, someone could run the monitor remotely and flood your inbox with false alerts.

Here’s how to protect the script using a secret key in the URL:

$secretKey = '123456'; // Change this to something complex
if (!isset($_GET['key']) || $_GET['key'] !== $secretKey) {
    http_response_code(403);
    exit('❌ Unauthorized access');
}

Now only URLs like monitor.php?key=123456 will run the script.

📦 3. Snapshot Concept – The Core Idea

We’ll create a snapshot of the current state of your project using file hashes. This snapshot is stored in a JSON file and compared on each run to detect changes.

Snapshot Example:

{
  "/var/www/html/index.php": "82bcab457eb12ab8a6ddcc72ec34a3b5",
  "/var/www/html/config.php": "db12e344b021ff98c77..."
}

If the file is changed, added, or deleted, its hash comparison will differ or disappear.

📂 4. Detecting Changes (Added, Modified, Deleted)

Step 1: Create the current snapshot:

function getDirectorySnapshot($dir) {
    $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
    $snapshot = [];
    foreach ($iterator as $file) {
        if ($file->isFile() && basename($file) !== 'snapshot.json') {
            $path = $file->getRealPath();
            $snapshot[$path] = md5_file($path);
        }
    }
    return $snapshot;
}

Step 2: Load the previous snapshot:

$snapshotFile = __DIR__ . '/snapshot.json';
$previousSnapshot = file_exists($snapshotFile)
    ? json_decode(file_get_contents($snapshotFile), true)
    : [];

Step 3: Compare current and previous:

$currentSnapshot = getDirectorySnapshot($projectDir);
$added = array_diff_key($currentSnapshot, $previousSnapshot);
$deleted = array_diff_key($previousSnapshot, $currentSnapshot);
$modified = [];
foreach ($currentSnapshot as $file => $hash) {
    if (isset($previousSnapshot[$file]) && $previousSnapshot[$file] !== $hash) {
        $modified[$file] = $hash;
    }
}


📧 5. Sending Email Alerts

You can use a custom mailer function to notify your email address when real changes occur. Here's a simplified version of the logic:

$emailList = ['youremail@example.com'];

$message = "⚠️ File changes detected:\n\n";
$message .= "🟢 Added Files:\n" . implode("\n", array_keys($added)) . "\n\n";
$message .= "🟡 Modified Files:\n" . implode("\n", array_keys($modified)) . "\n\n";
$message .= "🔴 Deleted Files:\n" . implode("\n", array_keys($deleted)) . "\n\n";

foreach ($emailList as $toEmail) {
    sendProjectAlert($toEmail, "File Change Alert", $message);
}

You can customize the sendProjectAlert() method using PHPMailer, SendGrid, or basic mail() as per your setup.

🌍 6. Track IP and Location of Trigger

To track who accessed the script, you can use an IP API like ip-api.com.

function getIpInfo($ip) {
    $info = @file_get_contents("http://ip-api.com/json/{$ip}");
    return $info ? json_decode($info, true) : [];
}

$ip = $_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN';
$ipInfo = getIpInfo($ip);
$location = ($ipInfo['city'] ?? 'Unknown') . ', ' . ($ipInfo['country'] ?? '');

Include this in the email body for better tracking.

💾 7. Save Updated Snapshot

At the end of the scan, always update the snapshot:

file_put_contents($snapshotFile, json_encode($currentSnapshot, JSON_PRETTY_PRINT));

This ensures the next run has the most recent state to compare against.

✅ 8. Final Output

echo "Monitoring completed at " . date('Y-m-d H:i:s');

Optionally, you can log this to a file as well for auditing.

🚀 Bonus Tips:

  1. Automate the script using a cron job to run every hour.
  2. Use logging in addition to email for persistent records.
  3. Encrypt or protect your snapshot.json file from public access.
  4. Use real-time notification tools like Telegram or Slack for alerts if desired.

🧠 Conclusion:

By building this monitoring tool in PHP, you've added a strong layer of protection to your project. Whether you're running a business website, a CMS, or an API server, knowing when your files change—along with who triggered it—can save you from disaster.
This is a lightweight but powerful alternative to complex DevOps tools, and it's entirely in PHP.

📤 Complete code:

<?php
// Secure the URL with a secret key
$secretKey = '123456'; // Change this to a long, hard-to-guess key
if (!isset($_GET['key']) || $_GET['key'] !== $secretKey) {
    http_response_code(403); // Forbidden
    exit('❌ Unauthorized access');
}

require_once __DIR__ . '../../account/mailer.php';
// === CONFIGURATION ===
$projectDir = realpath(__DIR__ . '/..');
echo "Project dir: " . $projectDir . "\n";
$snapshotFile = __DIR__ . '/snapshot.json';
$emailList = ['youremail1@gmail.com', 'youremail2@gmail.com'];
// Helper to get IP info
function getIpInfo($ip) {
    $info = @file_get_contents("http://ip-api.com/json/{$ip}");
    return $info ? json_decode($info, true) : [];
}

// Create a snapshot of current files
function getDirectorySnapshot($dir) {
    $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
    $snapshot = [];
    foreach ($iterator as $file) {
        if ($file->isFile()) {
            $path = $file->getRealPath();
            if (basename($path) !== 'snapshot.json') {
                $snapshot[$path] = md5_file($path);
            }
        }
    }
    return $snapshot;
}

// Load previous snapshot
$previousSnapshot = file_exists($snapshotFile) ? json_decode(file_get_contents($snapshotFile), true) : [];
$currentSnapshot = getDirectorySnapshot($projectDir);
$added = array_diff_key($currentSnapshot, $previousSnapshot);
$deleted = array_diff_key($previousSnapshot, $currentSnapshot);
$modified = [];
foreach ($currentSnapshot as $file => $hash) {
    if (isset($previousSnapshot[$file]) && $previousSnapshot[$file] !== $hash) {
        $modified[$file] = $hash;
    }
}

// Only send email if real changes (excluding only snapshot.json)
if (!empty($added) || !empty($deleted) || !empty($modified)) {
    // Get IP and geolocation
    $ip = $_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN';
    $ipInfo = getIpInfo($ip);
    $city = $ipInfo['city'] ?? 'Unknown City';
    $country = $ipInfo['country'] ?? '';
    $location = "$city, $country";
    // Start email body
    $message = "Changes detected in your project at " . date('Y-m-d H:i:s') . "\n\n";
    $message .= "IP: $ip\nLocation: $location\n\n";
    // Added Files
    if ($added) {
        $message .= "🟢 Added Files:\n";
        foreach ($added as $file => $hash) {
            $message .= "+ $file\n";
        }
        $message .= "\n";
    }

    // Modified Files with changed line numbers
    if ($modified) {
        $message .= "🟡 Modified Files:\n";
        foreach ($modified as $file => $hash) {
            $lines = [];
            $oldLines = file_exists($file) ? @file($file) : [];
            $prevHash = isset($previousSnapshot[$file]) ? $previousSnapshot[$file] : '';
            if ($prevHash && file_exists($file)) {
                // Temp file to compare (simulate previous content)
                $tmpFile = tempnam(sys_get_temp_dir(), 'prev_');
                file_put_contents($tmpFile, file_get_contents($file));
                if (md5_file($tmpFile) !== $prevHash) {
                    $newLines = @file($file);
                    foreach ($newLines as $i => $line) {
                        if (!isset($oldLines[$i]) || $oldLines[$i] !== $line) {
                            $lines[] = $i + 1;
                        }
                    }
                    unlink($tmpFile);
                }
            }
            $lineStr = $lines ? " [Lines: " . implode(', ', $lines) . "]" : "";
            $message .= "- $file$lineStr\n";
        }
        $message .= "\n";
    }

    // Deleted Files
    if ($deleted) {
        $message .= "🔴 Deleted Files:\n";
        foreach ($deleted as $file => $hash) {
            $message .= "− $file\n";
        }
        $message .= "\n";
    }
    // Send alert to each email
    foreach ($emailList as $toEmail) {
        sendProjectAlert($toEmail, "Project File Changes Detected", $message);
    }
}

// Save new snapshot
file_put_contents($snapshotFile, json_encode($currentSnapshot, JSON_PRETTY_PRINT));
echo "Monitoring done.\n";


PHP PHP file change detection PHP monitor file changes file monitoring system in PHP PHP email alert file change track file changes in PHP detect file changes using PHP send email on file change PHP

advertisement