├── 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 | [](https://github.com/ramazancetinkaya/mysql-backup/blob/master/LICENSE)
4 | [](https://github.com/ramazancetinkaya/mysql-backup/issues)
5 | [](https://github.com/ramazancetinkaya/mysql-backup/stargazers)
6 | [](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 |
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 | 
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 |
--------------------------------------------------------------------------------