├── mysql-backup.png ├── composer.json ├── LICENSE ├── src ├── test.sql └── MySQLBackup.php └── README.md /mysql-backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramazancetinkaya/mysql-backup/HEAD/mysql-backup.png -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ramazancetinkaya/mysql-backup", 3 | "description": "A PHP library for backing up and restoring MySQL databases", 4 | "type": "library", 5 | "keywords": ["php", "pdo", "phpmailer", "mysql", "database", "backup", "restore"], 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Ramazan Çetinkaya", 10 | "email": "ramazancetinkayadev@hotmail.com", 11 | "homepage": "https://github.com/ramazancetinkaya" 12 | } 13 | ], 14 | "require": { 15 | "php": "^8.0", 16 | "phpmailer/phpmailer": "*" 17 | }, 18 | "autoload": { 19 | "psr-4": { 20 | "DatabaseBackupManager\\": "src/" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ramazan Çetinkaya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/test.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE users ( 2 | id INT AUTO_INCREMENT PRIMARY KEY, 3 | username VARCHAR(50) NOT NULL, 4 | email VARCHAR(100) NOT NULL, 5 | password_hash VARCHAR(255) NOT NULL, 6 | full_name VARCHAR(100), 7 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 8 | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 9 | UNIQUE KEY unique_username (username), 10 | UNIQUE KEY unique_email (email) 11 | ); 12 | 13 | INSERT INTO users (username, email, password_hash, full_name) 14 | VALUES 15 | ('john_doe', 'john@example.com', 'hash123', 'John Doe'), 16 | ('jane_smith', 'jane@example.com', 'pass456', 'Jane Smith'), 17 | ('mike_williams', 'mike@example.com', 'pwd789', 'Mike Williams'), 18 | ('sara_jackson', 'sara@example.com', 'secure123', 'Sara Jackson'), 19 | ('alex_carter', 'alex@example.com', 'password456', 'Alex Carter'), 20 | ('emily_wilson', 'emily@example.com', 'hashed789', 'Emily Wilson'), 21 | ('chris_brown', 'chris@example.com', 'pass123hash', 'Chris Brown'), 22 | ('lisa_miller', 'lisa@example.com', 'password789', 'Lisa Miller'), 23 | ('ryan_taylor', 'ryan@example.com', 'hashedpass', 'Ryan Taylor'), 24 | ('olivia_clark', 'olivia@example.com', 'securepwd', 'Olivia Clark'); 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

MySQL Backup & Restore Library

2 | 3 | [![License](https://img.shields.io/github/license/ramazancetinkaya/mysql-backup)](https://github.com/ramazancetinkaya/mysql-backup/blob/master/LICENSE) 4 | [![GitHub issues](https://img.shields.io/github/issues/ramazancetinkaya/mysql-backup)](https://github.com/ramazancetinkaya/mysql-backup/issues) 5 | [![GitHub stars](https://img.shields.io/github/stars/ramazancetinkaya/mysql-backup)](https://github.com/ramazancetinkaya/mysql-backup/stargazers) 6 | [![GitHub forks](https://img.shields.io/github/forks/ramazancetinkaya/mysql-backup)](https://github.com/ramazancetinkaya/mysql-backup/network) 7 | 8 |

An update with the necessary configuration settings for sending emails via PHPMailer is coming soon. Stay tuned.

9 | 10 |

11 | 12 | Logo 13 | 14 | 15 |

MySQL Backup & Restore Library

16 | 17 |

18 | A powerful and modern PHP library for backing up and restoring MySQL databases using PDO. 19 |
20 | Explore the docs » 21 |
22 |
23 | Report a Bug 24 | · 25 | New Pull Request 26 |

27 |

28 | 29 |
30 | 31 | ## 🌟 Star this Repository! 32 | 33 | If you find the MySQL Backup & Restore library helpful or interesting, consider giving it a star! ⭐️ 34 | 35 | Your star helps us grow and motivates us to continue improving the library. It also makes it easier for others to discover and benefit from this project. 36 | 37 | ### How to Star? 38 | 39 | 1. **Login to Your GitHub Account:** You need to have a GitHub account. 40 | 2. **Visit the Repository:** Go to the [MySQL Backup & Restore Repository](https://github.com/ramazancetinkaya/mysql-backup). 41 | 3. **Click the Star Button:** On the top-right corner of the page, you'll find a "Star" button. Click on it! 42 | 43 | That's it! Thank you for your support! 🚀 44 | 45 | ## Table of Contents 46 | 47 | * [Introduction](#introduction) 48 | * [About the Project](#about-the-project) 49 | * [Screenshot](#screenshot) 50 | * [Features](#features) 51 | * [Requirements](#requirements) 52 | * [Installation](#installation) 53 | * [Usage](#usage) 54 | * [Disclaimer](#disclaimer) 55 | * [Contributing](#contributing) 56 | * [Authors](#authors) 57 | * [License](#license) 58 | * [Copyright](#copyright) 59 | 60 | ## Introduction 61 | 62 | This library is meticulously crafted to cater to a wide spectrum of users, ranging from novices venturing into the field to seasoned developers seeking seamless integration and robust functionality. 63 | 64 | ## About the Project 65 | 66 | The MySQL Backup & Restore Library furnishes comprehensive functionalities tailored for the seamless backup and restoration of MySQL databases through PHP. Leveraging this library, developers can effectively safeguard vital data housed within MySQL databases, ensuring robust data integrity and facilitating swift recovery in the event of data loss or system failures. 67 | 68 | ### Screenshot 69 | 70 | ![Screenshot](mysql-backup.png) 71 | 72 | ## Features 73 | 74 | * Backup entire MySQL databases or specific tables. 75 | * Restore databases from backup files. 76 | * Generate SQL dumps in a structured format. 77 | * Automatic generation of backup filenames with date and time. 78 | * Archive backups in ZIP format. 79 | * Send backups via email. 80 | * Easy to integrate into existing PHP projects. 81 | 82 | ## Requirements 83 | 84 | - PHP version 8.0 or **higher** 85 | - PDO extension **enabled** 86 | - ZipArchive extension **enabled** 87 | - PHPMailer 88 | - MySQL database 89 | - Composer (for installation) 90 | 91 | ## Installation 92 | 93 | This library can be easily installed using [Composer](https://getcomposer.org/), a modern PHP dependency manager. 94 | 95 | ### Step 1: Install Composer 96 | 97 | If you don't have Composer installed, you can download and install it by following the instructions on the [official Composer website](https://getcomposer.org/download/). 98 | 99 | ### Step 2: Install the Library 100 | 101 | Once Composer is installed, you can install the `mysql-backup` library by running the following command in your project's root directory: 102 | 103 | ```bash 104 | composer require ramazancetinkaya/mysql-backup 105 | ``` 106 | 107 | ## Usage 108 | 109 | ```php 110 | require 'vendor/autoload.php'; // Include Composer's autoloader 111 | 112 | use DatabaseBackupManager\MySQLBackup; 113 | 114 | // Initialize PDO connection 115 | $db = new PDO('mysql:host=localhost;dbname=my_database', 'username', 'password'); 116 | 117 | // Create an instance of MySQLBackup 118 | $mysqlBackup = new MySQLBackup($db); 119 | ``` 120 | 121 | - Perform a database backup: 122 | ```php 123 | // Backs up all tables 124 | $backup = $mysqlBackup->backup(); 125 | 126 | // Backs up the specified tables 127 | $backup = $mysqlBackup->backup(['tablename1']); 128 | $backup = $mysqlBackup->backup(['tablename1', 'tablename2']); 129 | 130 | // Include table data in the backup or vice versa 131 | $backup = $mysqlBackup->backup(null, true); // Default is true 132 | 133 | // Archiving 134 | $backup = $mysqlBackup->backup(null, true, false); // Default is false 135 | 136 | // Send the backup file by email 137 | $backup = $mysqlBackup->backup(null, true, true, 'recipient@example.com'); // Default is null 138 | 139 | if ($backup) { 140 | echo "Database backup created successfully."; 141 | } else { 142 | echo "Database backup failed!"; 143 | } 144 | ``` 145 | 146 | - Perform a database restore: 147 | ```php 148 | // Restore a database 149 | $backupFile = 'backup_wordpress-2024-05-09_214345.sql'; 150 | $restore = $mysqlBackup->restore($backupFile); 151 | 152 | // Whether to drop existing tables before restoring data 153 | $restore = $mysqlBackup->restore($backupFile, true); // Default is true 154 | 155 | if ($restore) { 156 | echo "Database restored successfully."; 157 | } else { 158 | echo "Database restoration failed!"; 159 | } 160 | ``` 161 | 162 | ## Disclaimer 163 | 164 | This library is provided as-is without any warranties, expressed or implied. The use of this library is at your own risk, and the developers will not be liable for any damages or losses resulting from its use. 165 | 166 | While every effort has been made to ensure the accuracy and reliability of the code in this library, it's important to understand that no guarantee is provided regarding its correctness or suitability for any purpose. 167 | 168 | Users are encouraged to review and test the functionality of this library in their own environments before deploying it in production or critical systems. 169 | 170 | This disclaimer extends to all parts of the library and its documentation. 171 | 172 | **By using the Library, you agree to these terms and conditions. If you do not agree with any part of this disclaimer, do not use the Library.** 173 | 174 | --- 175 | 176 | This disclaimer was last updated on May 9, 2024. 177 | 178 | ## Contributing 179 | 180 | Contributions are welcome! If you find any issues or have suggestions for improvements, feel free to open an issue or create a pull request. 181 | 182 | ## Authors 183 | 184 | - **Ramazan Çetinkaya** - [@ramazancetinkaya](https://github.com/ramazancetinkaya) 185 | 186 | ## License 187 | 188 | This project is licensed under the MIT License. For more details, see the [LICENSE](LICENSE) file. 189 | 190 | ## Copyright 191 | 192 | © 2024 Ramazan Çetinkaya. All rights reserved. 193 | -------------------------------------------------------------------------------- /src/MySQLBackup.php: -------------------------------------------------------------------------------- 1 | 10 | * @version 1.0 11 | * @license MIT License 12 | * @link https://github.com/ramazancetinkaya/mysql-backup 13 | */ 14 | 15 | namespace DatabaseBackupManager; 16 | 17 | use PDO; 18 | use ZipArchive; 19 | use PHPMailer\PHPMailer\PHPMailer; 20 | use PHPMailer\PHPMailer\Exception; 21 | 22 | class MySQLBackup 23 | { 24 | 25 | /** 26 | * The PDO database connection instance 27 | * @var PDO 28 | */ 29 | private $db; 30 | 31 | /** 32 | * The directory to store backup files 33 | * @var string 34 | */ 35 | private string $backupFolder; 36 | 37 | /** 38 | * Constructor to initialize PDO connection. 39 | * 40 | * @param PDO $db PDO instance for database connection 41 | * @param string $backupFolder Path to the backup folder 42 | */ 43 | public function __construct(PDO $db, $backupFolder = 'backup') 44 | { 45 | $this->db = $db; 46 | $this->backupFolder = rtrim($backupFolder, '/') . '/'; 47 | $this->checkBackupFolder(); 48 | 49 | // Check if ZipArchive class is available 50 | if (!class_exists('ZipArchive')) { 51 | throw new Exception('ZipArchive class not found. Please enable the Zip module in your PHP configuration.'); 52 | } 53 | } 54 | 55 | /** 56 | * Check if the backup folder exists and has appropriate permissions. 57 | * If the folder does not exist, attempt to create it with appropriate permissions. 58 | * If the folder exists but does not have write permissions, attempt to set the permissions. 59 | * 60 | * @throws Exception If unable to create or set permissions for the backup folder. 61 | */ 62 | private function checkBackupFolder(): void 63 | { 64 | // Check if the backup folder exists 65 | if (!file_exists($this->backupFolder)) 66 | { 67 | // If the folder does not exist, attempt to create it 68 | if (!mkdir($this->backupFolder, 0755, true)) 69 | { 70 | // If unable to create the folder, throw an exception 71 | throw new Exception('Failed to create backup folder.'); 72 | } 73 | } 74 | 75 | // Check if the backup folder is writable 76 | if (!is_writable($this->backupFolder)) 77 | { 78 | // If the folder is not writable, attempt to set the permissions 79 | if (!chmod($this->backupFolder, 0755)) 80 | { 81 | // If unable to set permissions, throw an exception 82 | throw new Exception('Failed to set write permissions for backup folder.'); 83 | } 84 | } 85 | } 86 | 87 | /** 88 | * Backup the database tables. 89 | * 90 | * @param array|string|null $tables Names of the tables to backup. If null, all tables will be backed up. 91 | * @param bool $includeData Whether to include table data in the backup. 92 | * @param bool $archive Whether to archive the backup file. 93 | * @param string|null $emailRecipient Email address to send the backup file. 94 | * @return string Path to the generated backup file. 95 | * @throws Exception If backup process fails. 96 | */ 97 | public function backup($tables = null, $includeData = true, $archive = false, $emailRecipient = null) 98 | { 99 | try { 100 | // Disable foreign key checks during backup 101 | $this->db->exec('SET foreign_key_checks = 0'); 102 | 103 | // Start transaction to prevent any changes during backup 104 | $this->db->beginTransaction(); 105 | 106 | // Generate backup file name 107 | $backupFileName = $this->generateBackupFileName($tables); 108 | 109 | // Open backup file for writing 110 | $backupFile = fopen($backupFileName, 'w'); 111 | if (!$backupFile) { 112 | throw new Exception('Failed to open backup file for writing.'); 113 | } 114 | 115 | // Write header information to the backup file 116 | $this->writeBackupHeader($backupFile); 117 | 118 | // Backup tables 119 | if ($tables) { 120 | $this->backupTables($tables, $includeData, $backupFile); 121 | } else { 122 | $this->backupAllTables($includeData, $backupFile); 123 | } 124 | 125 | // Backup process finished 126 | fwrite($backupFile, "-- End of database backup process"); 127 | 128 | // Close the backup file 129 | fclose($backupFile); 130 | 131 | // If archive option is enabled, zip the backup file 132 | if ($archive) 133 | { 134 | $backupFileName = $this->archiveBackupFile($backupFileName); 135 | } 136 | 137 | // If email recipient is provided, send the backup file 138 | if ($emailRecipient) 139 | { 140 | $this->sendBackupByEmail($backupFileName, $emailRecipient); 141 | } 142 | 143 | // Commit transaction 144 | $this->db->commit(); 145 | 146 | return $backupFileName; 147 | } catch (Exception $e) { 148 | // Rollback transaction on failure 149 | $this->db->rollBack(); 150 | throw $e; 151 | } finally { 152 | // Re-enable foreign key checks 153 | $this->db->exec('SET foreign_key_checks = 1'); 154 | } 155 | } 156 | 157 | /** 158 | * Restore the database from a backup file. 159 | * 160 | * @param string $backupFilePath Path to the backup file. 161 | * @param bool $dropTables Whether to drop existing tables before restoring data. Default is true. 162 | * @throws Exception If restore process fails. 163 | */ 164 | public function restore($backupFilePath, $dropTables = true) { 165 | try { 166 | // Begin transaction 167 | $this->db->beginTransaction(); 168 | 169 | // Drop tables if requested 170 | if ($dropTables) { 171 | // Extract table names from backup file 172 | $tables = $this->extractTableNames($backupFilePath); 173 | 174 | // Drop tables from the database 175 | $this->dropTables($tables); 176 | } 177 | 178 | // Read backup file 179 | $backupContent = file_get_contents($backupFilePath); 180 | 181 | // Execute backup content as SQL queries 182 | $queries = explode(';', $backupContent); 183 | foreach ($queries as $query) { 184 | if (trim($query) !== '') { 185 | $this->db->exec($query); 186 | } 187 | } 188 | 189 | // Commit transaction 190 | $this->db->commit(); 191 | 192 | return true; 193 | } catch (Exception $e) { 194 | // Rollback transaction on failure 195 | $this->db->rollBack(); 196 | throw $e; 197 | } 198 | } 199 | 200 | /** 201 | * Extract table names from the backup file. 202 | * 203 | * @param string $backupFilePath Path to the backup file. 204 | * @return array Table names extracted from the backup file. 205 | */ 206 | private function extractTableNames($backupFilePath) { 207 | $backupContent = file_get_contents($backupFilePath); 208 | preg_match_all('/Table structure for table `(\w+)`/', $backupContent, $matches); 209 | return $matches[1]; 210 | } 211 | 212 | /** 213 | * Drop tables from the database. 214 | * 215 | * @param array $tables Table names to be dropped. 216 | * @throws Exception If dropping tables fails. 217 | */ 218 | private function dropTables($tables) { 219 | foreach ($tables as $table) { 220 | $this->db->exec("DROP TABLE IF EXISTS `$table`"); 221 | } 222 | } 223 | 224 | /** 225 | * Generate backup file name. 226 | * 227 | * @param array|string|null $tables Names of the tables to backup. 228 | * @return string Backup file name. 229 | */ 230 | private function generateBackupFileName($tables) 231 | { 232 | $dbName = $this->db->query('SELECT DATABASE()')->fetchColumn(); 233 | $fileName = $this->backupFolder . 'backup_' . $dbName . ($tables ? '-' . implode('_', (array) $tables) : '') . '-' . date('Y-m-d_His') . '.sql'; 234 | return $fileName; 235 | } 236 | 237 | /** 238 | * Write backup header information to the backup file. 239 | * 240 | * @param resource $backupFile File handle of the backup file. 241 | */ 242 | private function writeBackupHeader($backupFile) 243 | { 244 | fwrite($backupFile, "-- Database Backup Manager\n"); 245 | fwrite($backupFile, "-- This backup was created automatically by the Database Backup Manager\n"); 246 | fwrite($backupFile, "-- © " . date('Y') . " Ramazan Çetinkaya. All rights reserved.\n"); 247 | fwrite($backupFile, "-- https://github.com/ramazancetinkaya/mysql-backup\n"); 248 | fwrite($backupFile, "--\n"); 249 | fwrite($backupFile, "-- Host: " . $this->db->getAttribute(PDO::ATTR_CONNECTION_STATUS) . "\n"); 250 | fwrite($backupFile, "-- Generated on: " . date('Y-m-d H:i:s') . "\n"); 251 | fwrite($backupFile, "-- Server version: " . $this->db->getAttribute(PDO::ATTR_SERVER_VERSION) . "\n\n"); 252 | } 253 | 254 | /** 255 | * Backup specified tables. 256 | * 257 | * @param array|string $tables Names of the tables to backup. 258 | * @param bool $includeData Whether to include table data in the backup. 259 | * @param resource $backupFile File handle of the backup file. 260 | */ 261 | private function backupTables($tables, $includeData, $backupFile) 262 | { 263 | foreach ((array) $tables as $table) { 264 | $this->backupTableStructure($table, $backupFile); 265 | if ($includeData) { 266 | $this->backupTableData($table, $backupFile); 267 | } 268 | } 269 | } 270 | 271 | /** 272 | * Backup all tables in the database. 273 | * 274 | * @param bool $includeData Whether to include table data in the backup. 275 | * @param resource $backupFile File handle of the backup file. 276 | */ 277 | private function backupAllTables($includeData, $backupFile) 278 | { 279 | $stmt = $this->db->query("SHOW TABLES"); 280 | $tables = $stmt->fetchAll(PDO::FETCH_COLUMN); 281 | $this->backupTables($tables, $includeData, $backupFile); 282 | } 283 | 284 | /** 285 | * Backup table structure. 286 | * 287 | * @param string $tableName Name of the table to backup. 288 | * @param resource $backupFile File handle of the backup file. 289 | */ 290 | private function backupTableStructure($tableName, $backupFile) 291 | { 292 | $stmt = $this->db->prepare("SHOW CREATE TABLE $tableName"); 293 | $stmt->execute(); 294 | $tableStructure = $stmt->fetch(PDO::FETCH_ASSOC); 295 | fwrite($backupFile, "--\n-- Table structure for table `$tableName`\n--\n\n"); 296 | fwrite($backupFile, $tableStructure['Create Table'] . ";\n\n"); 297 | } 298 | 299 | /** 300 | * Backup table data. 301 | * 302 | * @param string $tableName Name of the table to backup. 303 | * @param resource $backupFile File handle of the backup file. 304 | */ 305 | private function backupTableData($tableName, $backupFile) { 306 | $stmt = $this->db->prepare("SELECT * FROM $tableName"); 307 | $stmt->execute(); 308 | $tableData = $stmt->fetchAll(PDO::FETCH_ASSOC); 309 | 310 | if (empty($tableData)) { 311 | fwrite($backupFile, "--\n-- No data found for table `$tableName`\n--\n\n"); 312 | return; 313 | } 314 | 315 | fwrite($backupFile, "--\n-- Dumping data for table `$tableName`\n--\n\n"); 316 | fwrite($backupFile, "INSERT INTO `$tableName` ("); 317 | $fields = array_keys($tableData[0]); 318 | fwrite($backupFile, "`" . implode("`, `", $fields) . "`"); 319 | fwrite($backupFile, ") VALUES\n"); 320 | foreach ($tableData as $row) { 321 | fwrite($backupFile, "("); 322 | $values = array_map(function($value) { 323 | return "'" . addslashes($value) . "'"; 324 | }, array_values($row)); 325 | fwrite($backupFile, implode(", ", $values)); 326 | fwrite($backupFile, "),\n"); 327 | } 328 | // Remove the trailing comma and newline character from the last row 329 | fseek($backupFile, -2, SEEK_END); 330 | fwrite($backupFile, ";\n\n"); 331 | } 332 | 333 | /** 334 | * Archive backup file. 335 | * 336 | * @param string $backupFileName Path to the backup file. 337 | * @return string Path to the archived backup file. 338 | * @throws Exception If archiving fails. 339 | */ 340 | private function archiveBackupFile($backupFileName) 341 | { 342 | $zipFileName = $backupFileName . '.zip'; 343 | $zip = new ZipArchive(); 344 | if ($zip->open($zipFileName, ZipArchive::CREATE) === TRUE) { 345 | $zip->addFile($backupFileName, basename($backupFileName)); 346 | $zip->close(); 347 | unlink($backupFileName); 348 | return $zipFileName; 349 | } else { 350 | throw new Exception('Failed to create zip archive.'); 351 | } 352 | } 353 | 354 | /** 355 | * Send backup file by email. 356 | * 357 | * @param string $backupFileName Path to the backup file. 358 | * @param string $recipient Email address of the recipient. 359 | * @throws Exception If sending email fails. 360 | */ 361 | private function sendBackupByEmail($backupFileName, $recipient) 362 | { 363 | $mail = new PHPMailer(true); 364 | 365 | try { 366 | // Server settings 367 | $mail->isSMTP(); 368 | $mail->Host = 'smtp.example.com'; // Gmail SMTP: smtp.gmail.com 369 | $mail->SMTPAuth = true; 370 | $mail->Username = 'your-email@example.com'; 371 | $mail->Password = 'your-email-password'; 372 | $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; 373 | $mail->Port = 587; 374 | 375 | // Recipients 376 | $mail->setFrom('from@example.com', 'Database Backup Manager'); 377 | $mail->addAddress($recipient); 378 | 379 | // Attach backup file 380 | $mail->addAttachment($backupFileName); 381 | 382 | // Content 383 | $mail->isHTML(true); 384 | $mail->Subject = 'Database Backup'; 385 | $mail->Body = ' 386 | 387 | 388 |

Hello,

389 |

Please find attached the database backup file you requested.

390 |

This backup was created automatically by the Database Backup Manager.

391 | 392 | 393 | '; 394 | $mail->send(); 395 | } catch (Exception $e) { 396 | throw new Exception('Backup email could not be sent. Mailer Error: ' . $mail->ErrorInfo); 397 | } 398 | } 399 | } 400 | --------------------------------------------------------------------------------