Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesPHPMailer throws the “Could not access file” error when it cannot read the file you pass to methods such as addAttachment() or addEmbeddedImage(). The file may be missing, the path may resolve differently than expected, or the web server user may not have permission to access it.
This problem is especially common when using relative paths, upload directories, shared hosting, temporary files, or scripts executed from different working directories. A path that looks correct in your project may not be the same path PHP sees at runtime.
As an Amazon Associate I earn from qualifying purchases.
To fix it, you need to confirm the real file location, check that PHP can read it, and account for server restrictions such as ownership, permissions, open_basedir, or disabled access to certain directories. Practical checks before calling addAttachment() can quickly reveal whether the issue is the path, the file itself, or the hosting environment.
What the “Could Not Access File” Error Means in PHPMailer
In PHPMailer, the message “Could not access file” usually appears when you call methods such as addAttachment() or addEmbeddedImage() and PHPMailer cannot read the file you asked it to include. The file path may look correct in your PHP code, but PHPMailer still has to resolve that path from the running script’s environment, confirm that the file exists, and open it with the permissions available to the web server or PHP process.
#1 Best Overall
A typical failing example looks like this:
$mail->addAttachment('uploads/invoice.pdf');
If uploads/invoice.pdf is not located relative to the script’s current working directory, or if the file exists but cannot be read by PHP, PHPMailer throws the error before sending the email. The same can happen with embedded images:
$mail->addEmbeddedImage('images/logo.png', 'logo_cid');
This error is not usually an SMTP problem. It does not mean your mail server rejected the message, your credentials are wrong, or the recipient address is invalid. The failure happens earlier, while PHPMailer is building the MIME message and trying to attach local file content. If PHPMailer cannot open the file, it cannot encode it into the email, so the send process is stopped.
What PHPMailer is checking
When you add a file, PHPMailer needs the path to point to a real, readable file on the server. In practical terms, all of the following must be true:
- The path passed to
addAttachment()oraddEmbeddedImage()must be correct. - The file must exist at that exact location on the server, not just on your local computer.
- The file must not be a directory.
- The PHP process must have permission to read the file.
- Server restrictions such as
open_basedirmust allow PHP to access that location.
For example, this call may work on a development machine but fail after deployment:
$mail->addAttachment('C:\Users\me\Desktop\report.pdf');
On a Linux hosting server, that Windows path has no meaning. Similarly, this may fail if the script is executed from a different directory than expected:
$mail->addAttachment('../files/report.pdf');
Relative paths depend on the current working directory, which is not always the same as the directory containing the PHP file. This is especially common in frameworks, cron jobs, CMS plugins, and routed applications where the entry point may be public/index.php rather than the file where the mail code is written.
How the error commonly appears
Depending on how your code handles PHPMailer exceptions, you may see the error as an exception, a returned error message, or part of $mail->ErrorInfo. For example:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Could not access file: uploads/invoice.pdf
That filename in the message is the path PHPMailer attempted to use. It is the first value to inspect when diagnosing the problem. If the path is relative, convert it mentally or programmatically into the full server path and check whether the file is really there.
The most reliable way to think about this error is: PHPMailer was asked to attach or embed a file, but PHP could not read that file from the server filesystem. The fix is therefore usually found in path construction, upload handling, filesystem permissions, or hosting restrictions rather than in mail transport settings.
Common Causes: Wrong Paths, Missing Files, and Permissions
PHPMailer raises “Could not access file” when the path passed to addAttachment(), addEmbeddedImage(), or a related method cannot be opened by the PHP process. In most cases, the file is not where the script thinks it is, the path is being resolved from a different working directory, or the web server user does not have permission to read it. The error is usually not caused by SMTP settings; it happens before the message is sent, while PHPMailer is preparing the MIME body.
Wrong or misleading file paths
A common mistake is passing a browser URL or a relative path that does not match PHP’s current execution context. PHPMailer expects a server-side filesystem path, not a public web address. For example, this is usually wrong:
$mail->addAttachment('https://example.com/uploads/invoice.pdf');
Instead, pass the local path to the file on disk, such as:
Rank #2
$mail->addAttachment('/var/www/example.com/public/uploads/invoice.pdf');
Relative paths can also fail when the script is executed from a different directory than expected. A file path like uploads/invoice.pdf may work from one controller or test script but fail from a cron job, queue worker, included PHP file, or framework entry point. PHP resolves relative paths based on the current working directory, not necessarily the directory containing the file where addAttachment() is written.
Recommended Free Tools
Missing files or files created too late
The file may simply not exist at the moment PHPMailer tries to attach it. This often happens with generated PDFs, exported CSV files, image uploads, or temporary files. For instance, a script may create invoice.pdf, then store the wrong filename in the database, or delete the temporary file before calling addAttachment(). Upload handling can also be involved: if a file was uploaded through a form but not moved from PHP’s temporary upload directory using move_uploaded_file(), the path saved for later use may no longer be valid.
- Wrong filename: the database stores
invoice-123.pdf, but the actual file isinvoice_123.pdf. - Wrong directory: the file is saved in
/storage/app/uploads, but PHPMailer is given/public/uploads. - Temporary file removed: a generated report is deleted before the email is built.
- Case mismatch:
Report.pdfandreport.pdfare different files on Linux servers.
Permission and ownership problems
Even when the path is correct and the file exists, PHP still needs read access. On many Linux servers, PHP runs as a user such as www-data, apache, nginx, or a hosting-account user. If the attachment is owned by another user and has restrictive permissions, PHPMailer cannot open it. A file with permissions like 600 may be readable only by its owner, while a directory without execute permission cannot be traversed even if the file itself is readable.
| Problem | Example | Practical fix |
|---|---|---|
| File not readable | -rw------- invoice.pdf |
Allow the PHP user to read it, commonly with suitable group ownership and 640 or 644. |
| Directory not accessible | drwx------ uploads/ |
Ensure the PHP user can traverse the directory, commonly using 750 or 755 as appropriate. |
| Wrong owner | Files created by a deploy user, read by www-data |
Set ownership or group membership so PHP can read uploaded and generated files. |
Shared hosting adds a few extra pitfalls. Some providers restrict access outside the account’s home directory with open_basedir, disable access to certain temporary directories, or run cron jobs under a different user than web requests. A path that works in the browser may fail in a scheduled script, and a file created by a command-line process may not be readable by the PHP-FPM pool serving the site. When diagnosing this error, check the exact path, confirm the file exists at send time, and verify that the same PHP user running the mail script can read both the file and every directory above it.
How to Verify File Paths Before Calling addAttachment()
Before passing a file to addAttachment(), verify that PHP can see and read the exact path you are about to use. PHPMailer does not search for files automatically; it receives a string path and asks PHP to open that file. If the path is wrong, points to a directory, references a file outside the allowed filesystem area, or cannot be read by the web server user, PHPMailer will throw the “Could not access file” error.
A practical approach is to check the file with PHP first, then call addAttachment() only after the checks pass. Use file_exists() to confirm the path exists, is_file() to make sure it is a regular file, and is_readable() to confirm PHP has permission to read it. This is especially useful when the filename comes from a database, an upload form, or dynamically generated invoice/report .
$filePath = __DIR__ . '/uploads/invoice-123.pdf';
if (!file_exists($filePath)) {
die('Attachment not found: ' . $filePath);
}
if (!is_file($filePath)) {
die('Attachment path is not a file: ' . $filePath);
}
if (!is_readable($filePath)) {
die('Attachment is not readable: ' . $filePath);
}
Free tools Windows power users keep installed
One-click scans. No signup required.
$mail->addAttachment($filePath, 'invoice-123.pdf');
When diagnosing the problem, print or log the resolved path rather than guessing. A common mistake is assuming the script runs from the same directory as the PHP file being edited. Relative paths can resolve differently depending on the entry point, framework router, cron job, or include structure. Using __DIR__ helps anchor the path to the current PHP file’s directory.
error_log('Attachment path: ' . $filePath);
error_log('Real path: ' . realpath($filePath));
error_log('Current working directory: ' . getcwd());
realpath() can help reveal the actual filesystem location, but it returns false if the file does not exist. That makes it useful for diagnostics, not as the only way to build paths. If realpath($filePath) is empty or false, the file path is probably wrong, the file has not been created yet, or part of the directory chain is inaccessible.
Checklist before adding the attachment
- Confirm the final string path: log the value passed to
addAttachment(). - Check existence: use
file_exists($filePath). - Check file type: use
is_file($filePath), not justfile_exists(). - Check readability: use
is_readable($filePath). - Check the working directory: compare
getcwd()with where you think the script is running. - Check generated files: make sure PDFs, CSVs, or images are fully written before attaching them.
If you are attaching an uploaded file, verify the temporary upload path before using it. For example, $_FILES['document']['tmp_name'] should exist and be readable during the same request. If you move the upload first with move_uploaded_file(), attach the new destination path, not the old temporary path.
$uploadPath = __DIR__ . '/uploads/' . basename($_FILES['document']['name']);
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
if (move_uploaded_file($_FILES['document']['tmp_name'], $uploadPath)) {
if (is_readable($uploadPath)) {
$mail->addAttachment($uploadPath);
}
}
For files created by another process, such as a PDF generator or scheduled export, add a verification step after generation. Confirm that the file size is greater than zero with filesize() and that PHP can read it from the same process that sends the email. This avoids trying to attach a file that exists in name only, is still being written, or was created in a different directory than expected.
Using Absolute Paths Instead of Relative Paths
When PHPMailer reports “Could not access file” during addAttachment() or addEmbeddedImage(), relative paths are often the source of the problem. A path like uploads/invoice.pdf is not resolved relative to the file where you wrote the code in every situation. It is resolved relative to PHP’s current working directory, which can change depending on how the script is executed, included, routed through a framework, or triggered by a cron job.
For example, this may work when you open one PHP file directly, but fail when the same mail-sending code is called from another script:
$mail->addAttachment('uploads/invoice.pdf');
A safer approach is to build an absolute filesystem path before passing it to PHPMailer. An absolute path points to the file from the server’s root directory, not from the URL and not from the current PHP script location. On Linux hosting it may look like /home/account/public_html/uploads/invoice.pdf. On Windows it may look like C:\inetpub\wwwroot\site\uploads\invoice.pdf.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallBuild paths from a known directory
Use constants such as __DIR__ to anchor the path to the directory of the current PHP file. This avoids surprises caused by includes, front controllers, or command-line execution:
$filePath = __DIR__ . '/uploads/invoice.pdf';
$mail->addAttachment($filePath);
If your mail script is inside a subdirectory, adjust the path accordingly:
$filePath = __DIR__ . '/../uploads/invoice.pdf';
$mail->addAttachment($filePath, 'invoice.pdf');
The second argument to addAttachment() is optional, but useful. It lets you control the filename shown to the recipient while keeping the real server path private and stable.
Do not use URLs for attachments
PHPMailer expects a local filesystem path for addAttachment(), not a public web URL. This is a common mistake:
$mail->addAttachment('https://example.com/uploads/invoice.pdf');
Instead, use the server path to the same file:
$mail->addAttachment('/home/account/public_html/uploads/invoice.pdf');
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Rank #4
If the file exists only on a remote server, download it first to a temporary local file, verify it was saved correctly, and then attach that local file. For generated PDFs or reports, save the output to a known directory before calling addAttachment().
Check the resolved path before sending
Before passing the file to PHPMailer, print or log the final path during testing. This quickly reveals whether PHP is looking in the expected location:
$filePath = __DIR__ . '/uploads/invoice.pdf';
error_log('Attachment path: ' . $filePath);
if (!file_exists($filePath)) {
throw new Exception('Attachment file not found: ' . $filePath);
}
if (!is_readable($filePath)) {
throw new Exception('Attachment file is not readable: ' . $filePath);
}
$mail->addAttachment($filePath);
__DIR__gives the directory of the current PHP file.getcwd()shows PHP’s current working directory, which may be different.realpath()can confirm the canonical absolute path, but returnsfalseif the file does not exist.
On shared hosting, the absolute path is usually not the same as the domain name. A browser URL such as https://example.com/uploads/file.pdf may map internally to /home/username/public_html/uploads/file.pdf. Hosting control panels often show this path in file manager details, PHP info pages, or application settings. Once you use the real filesystem path and confirm the file exists and is readable, PHPMailer can access the attachment consistently across direct requests, includes, framework routes, and scheduled tasks.
Fixing File Permission and Ownership Problems
Even when the attachment path is correct, PHPMailer can still throw “Could not access file” if the PHP process is not allowed to read the file. This commonly happens after files are uploaded by FTP, generated by a cron job, created by another system user, or stored outside the public web directory. PHPMailer does not bypass the operating system’s file access rules; when you call addAttachment() or addEmbeddedImage(), PHP must be able to open that file for reading.
Start by checking the file’s permissions and owner on the server. On Linux hosting, a file such as /home/example/app/storage/invoices/invoice-1024.pdf may exist, but it may be owned by a different user than the one running PHP, such as root, deploy, or another cPanel account. Directories in the path also need execute permission so PHP can traverse them. A readable file inside an unreadable directory will still fail.
Recommended permission checks
- Files: commonly
0644, allowing the owner to write and others in the allowed context to read. - Directories: commonly
0755, allowing traversal into the directory. - Private storage: use tighter permissions if PHP runs as the same user that owns the files.
- Uploads: confirm the final moved file is readable after
move_uploaded_file().
On a VPS or dedicated server, you can inspect the path with commands such as ls -l and namei -l. The second command is especially useful because it shows permissions for every directory in the path. If your file is owned by the wrong user, adjust ownership to match the PHP/web user used by your stack. Depending on the server, this may be www-data, apache, nginx, or the hosting account user.
| Problem | Example fix |
|---|---|
| File is not readable by PHP | chmod 644 invoice.pdf |
| Directory cannot be traversed | chmod 755 storage storage/invoices |
| File owned by the wrong user | chown www-data:www-data invoice.pdf |
| Generated file created with restrictive permissions | Set permissions after creation with chmod($file, 0644) |
In PHP, add a small access check before handing the file to PHPMailer. This makes the failure clearer and separates a PHPMailer issue from a filesystem issue. For example, verify the file exists and is readable before calling addAttachment():
$file = '/home/example/app/storage/invoices/invoice-1024.pdf'; if (!is_file($file) || !is_readable($file)) { throw new RuntimeException('Attachment is missing or not readable: ' . $file); } $mail->addAttachment($file, 'invoice-1024.pdf');
Shared hosting can add extra restrictions. Some providers use open_basedir, CageFS, jailed shells, or account isolation, which prevents PHP from reading files outside approved directories even if Unix permissions look correct. In that case, move attachments into an allowed application storage directory, update the configured base directory, or ask the host to confirm which paths PHP can access. If SELinux or AppArmor is enabled, the file may also need the correct security context, not just standard permissions. After changing ownership, permissions, or server policy, retry the same absolute path with is_readable() before testing PHPMailer again.
Recommended Free Tools
Debugging PHPMailer Attachment Issues in PHP
When PHPMailer reports “Could not access file”, debug the attachment step separately from the email-sending step. The SMTP server is usually not involved yet; the failure commonly happens before delivery, when PHPMailer tries to read the local file passed to addAttachment() or addEmbeddedImage(). Start by logging the exact path your PHP code is using, then confirm that the same path exists and is readable from the PHP process running on the web server.
Check the path before adding the file
A practical debugging pattern is to validate the file immediately before calling addAttachment(). This helps distinguish a PHPMailer issue from a filesystem issue. For example, if a user uploads an invoice and you later attach it, inspect the resolved path, existence, file type, and readability before PHPMailer receives it.
$filePath = __DIR__ . '/uploads/invoice.pdf';
if (!file_exists($filePath)) {
error_log('Attachment missing: ' . $filePath);
} elseif (!is_file($filePath)) {
error_log('Attachment path is not a file: ' . $filePath);
} elseif (!is_readable($filePath)) {
error_log('Attachment not readable: ' . $filePath);
} else {
$mail->addAttachment($filePath, 'invoice.pdf');
}
If this check fails, PHPMailer is only exposing the underlying problem. If it passes but PHPMailer still fails, inspect whether the path changes between the check and the attachment call, whether the file is deleted by cleanup code, or whether a temporary upload file is being referenced after the request lifecycle has moved on.
Enable PHPMailer diagnostics
For mail transport problems, PHPMailer can emit SMTP debug output, but attachment file access errors may occur before SMTP communication. Still, enabling exceptions and capturing errors gives a clearer failure point. Use a try/catch block around the attachment and send process, and log the exception message together with the attachment path.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
$mail = new PHPMailer(true);
try {
$attachment = realpath(__DIR__ . '/uploads/report.pdf');
if ($attachment === false || !is_readable($attachment)) {
throw new RuntimeException('Attachment cannot be read');
}
$mail->addAttachment($attachment, 'report.pdf');
$mail->isSMTP();
$mail->SMTPDebug = 2;
$mail->Debugoutput = 'error_log';
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitches $mail->send();
} catch (Exception $e) {
error_log('PHPMailer error: ' . $mail->ErrorInfo);
} catch (RuntimeException $e) {
error_log($e->getMessage() . ': ' . ($attachment ?? 'unresolved path'));
}
Compare CLI and web server behavior
A common trap is testing a script from the command line and assuming it will behave the same through Apache, Nginx, PHP-FPM, or a hosting control panel. The CLI user may be different from the web server user, and the working directory may also differ. Log getcwd(), __DIR__, and the resolved attachment path during a real web request. If CLI works but the browser fails, focus on ownership, permissions, PHP-FPM pool users, open_basedir restrictions, and paths that only exist in the CLI environment.
- Relative path mismatch:
uploads/file.pdfmay resolve differently depending on the entry script. - Temporary upload issue: files in
$_FILES['tmp_name']should be attached or moved before the request ends. - Hosting isolation: shared hosting may block access outside the account directory.
- Case-sensitive filenames:
Invoice.pdfandinvoice.pdfare different on many Linux servers. - Symlink restrictions: a symlinked attachment may point to a location PHP cannot read.
For embedded images, apply the same checks before calling addEmbeddedImage(). The file must be accessible on the server filesystem; a browser URL such as https://example.com/logo.png is not a local readable path for PHPMailer. Download it first or reference the actual server path, such as /home/account/public_html/assets/logo.png. Once the path is absolute, the file exists, and the PHP process can read it, PHPMailer attachment errors usually disappear.
Frequently Asked Questions
How do I know which file path PHPMailer is actually trying to attach?
Before calling addAttachment(), print or log the full path you are passing to PHPMailer. Use checks like file_exists($path), is_readable($path), and realpath($path) to confirm PHP can see the file. If realpath() returns false, the path is wrong or the file is not accessible from the current PHP process.
Should I use a relative path or an absolute path with addAttachment()?
An absolute path is usually safer because relative paths depend on the script’s current working directory, which may not be the same as the file’s location. For example, use something like __DIR__ . '/uploads/invoice.pdf' instead of just 'uploads/invoice.pdf'. This makes the attachment path predictable even if the script is included from another file or run from a different directory.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Why does file_exists() return true but PHPMailer still says “Could not access file”?
This often happens when the file exists but PHP cannot read it due to permissions, ownership, or restrictions such as open_basedir. Check is_readable($path) as well as file_exists($path). On Linux hosting, the file and its parent directories must be readable by the web server user, such as www-data, apache, or the account user used by PHP-FPM.
What permissions should attachment files and folders have on a web server?
In most cases, folders should be executable and readable by the PHP process, commonly 755, and files should be readable, commonly 644. Avoid using 777 unless your host specifically requires it, because it can create security risks. Also check ownership, because correct numeric permissions may still fail if the file belongs to another user that PHP cannot access.
Can shared hosting or server settings cause this error even when my code is correct?
Yes, shared hosting often restricts which directories PHP can access using settings like open_basedir, disabled functions, jailed file systems, or separate users for FTP and PHP. Files uploaded outside the allowed web or account directory may be invisible to PHPMailer. If local path checks fail unexpectedly, check your hosting control panel error logs or ask the host which absolute paths PHP is allowed to read.
Bottom Line
PHPMailer’s “Could not access file” error almost always means PHP cannot read the file you passed to addAttachment() or an embedded image method. Check the real filesystem path, confirm the file exists with file_exists(), use an absolute path when possible, and make sure the web server user has permission to read it.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11If the path and permissions look correct, review hosting restrictions such as open_basedir, temporary upload handling, symlinks, chrooted environments, or files stored outside the allowed directory. Once you verify the exact path PHP sees and test readability before calling PHPMailer, the fix is usually straightforward.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




