How to Send PHP Errors by Email with Full Backtrace and Input Data
Introduction
When your PHP application crashes or behaves unexpectedly, it’s often due to unnoticed errors like undefined variables or broken logic. By learning how to send PHP errors by email with full backtrace and request input, you can catch bugs in real-time—even before users report them.
In this article, you’ll get a plug-and-play solution to automatically email yourself whenever a PHP error occurs, including:
- Notices
- Warnings
- Fatal Errors
- Uncaught Exceptions
We’ll also show how to capture full backtrace info, input data (GET/POST/SESSION), and provide reproduction steps using live data to send PHP errors by email.
7 Powerful Reasons Why Understanding BERT Token IDs Will Transform Your NLP Skills
Why Send PHP Errors by Email?
While tools like Sentry or Bugsnag offer advanced monitoring, you may want to start with a simple self-hosted solution — especially for small projects or tight environments to send PHP errors by email.
Benefits:
- Instant alerts via email
- No external service needed
- Reproducible context (trace + inputs)
- Ideal for debugging live systems
Part 1: Use in Vanilla PHP (error-monitor.php)
Step 1: Include Globally
Save the following code as error-monitor.php and include it at the top of your app:
require_once 'path/to/error-monitor.php';Step 2: Full Code – error-monitor.php
<?php
error_reporting(E_ALL);
ini_set('display_errors', 0);
ini_set('log_errors', 1);
set_error_handler('customErrorHandler');
set_exception_handler('customExceptionHandler');
register_shutdown_function('shutdownHandler');
function customErrorHandler($errno, $errstr, $errfile, $errline) {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$errorData = [
'type' => getFriendlyErrorType($errno),
'message' => $errstr,
'file' => $errfile,
'line' => $errline,
'trace' => print_r($trace, true),
'input' => getInputData()
];
sendErrorEmail($errorData);
return true;
}
function customExceptionHandler($exception) {
$errorData = [
'type' => 'Uncaught Exception: ' . get_class($exception),
'message' => $exception->getMessage(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'trace' => $exception->getTraceAsString(),
'input' => getInputData()
];
sendErrorEmail($errorData);
}
function shutdownHandler() {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
$errorData = [
'type' => getFriendlyErrorType($error['type']),
'message' => $error['message'],
'file' => $error['file'],
'line' => $error['line'],
'trace' => 'Backtrace not available (fatal error)',
'input' => getInputData()
];
sendErrorEmail($errorData);
}
}
function getFriendlyErrorType($type) {
return match($type) {
E_ERROR => 'Fatal Error',
E_WARNING => 'Warning',
E_NOTICE => 'Notice',
E_PARSE => 'Parse Error',
E_CORE_ERROR => 'Core Error',
E_COMPILE_ERROR => 'Compile Error',
default => 'Unknown Error',
};
}
function getInputData() {
return [
'GET' => $_GET,
'POST' => $_POST,
'FILES' => $_FILES,
'SESSION'=> $_SESSION ?? [],
'SERVER' => $_SERVER
];
}
function sendErrorEmail($data) {
if ($_ENV['APP_ENV'] !== 'production') return;
$to = 'admin@example.com';
$subject = '[PHP Error] ' . $data['type'];
$message = "<h2>{$data['type']}</h2>";
$message .= "<p><strong>Message:</strong> {$data['message']}</p>";
$message .= "<p><strong>File:</strong> {$data['file']}</p>";
$message .= "<p><strong>Line:</strong> {$data['line']}</p>";
$message .= "<pre><strong>Backtrace:</strong>\n" . htmlspecialchars($data['trace']) . "</pre>";
$message .= "<pre><strong>Input Data:</strong>\n" . htmlspecialchars(print_r($data['input'], true)) . "</pre>";
$headers = "From: error-monitor@yourdomain.com\r\n";
$headers .= "Content-Type: text/html; charset=UTF-8\r\n";
mail($to, $subject, $message, $headers);
}What It Will Automatically Capture
| Type | Captured? | Notes |
|---|---|---|
| Notices | ✅ | Undefined variables, missing array keys |
| Warnings | ✅ | Deprecated functions, include warnings |
| Uncaught Exceptions | ✅ | All uncaught throw new Exception() |
| Fatal Errors | ✅ | Caught using shutdownHandler() |
| Parse Errors | ❌ | Not catchable during execution |
Custom try/catch | ❌ | You must re-throw or log manually |
TL;DR: Do I Need to Modify Code to send PHP errors by email?
| Situation | Modify Code? |
| Plain PHP site | ❌ Just include once globally |
| Framework (Laravel, Symfony) | ✅ Add to bootstrapping |
| Using try/catch everywhere | ⚠️ Yes, call customExceptionHandler($e) manually |
| Want full control of reporting | ✅ Maybe wrap your code or use middleware |
Part 2: Use in Laravel
Laravel Integration
Add this to your AppServiceProvider:
public function boot() {
require_once base_path('error-monitor.php');
}Make sure to:
- Place
error-monitor.phpin your project root or/app/Services - Use
$_ENV['APP_ENV']or Laravel’sapp()->environment()insidesendErrorEmail()
Optional: Laravel Exception Handler
If you want better control, modify Laravel’s native exception handler:
// app/Exceptions/Handler.php
public function report(Throwable $e)
{
parent::report($e);
\customExceptionHandler($e); // Optional: Call from Laravel handler
}This approach gives you flexibility for both Laravel logging + custom email reporting.
Bonus: Only Send Emails in Production
To prevent spamming during development:
if ($_ENV['APP_ENV'] === 'production') {
sendErrorEmail($errorData);
}Pro Tips for send PHP errors by email
Integrate with Mailtrap during development for safe email testing.
Log errors to file using
file_put_contents()for offline access.Combine with tools like Monolog for advanced logging.
Conclusion
Setting up automated error emails in PHP gives you:
✅ Real-time visibility into crashes
✅ Contextual debugging info
✅ Easy reproduction of bugs
✅ Simple and free alternative to error monitoring tools
Whether you’re building a plain PHP app or using Laravel, this guide will help you stay ahead of production bugs without expensive monitoring tools.








Recent Comments