0

wp_mail attachment not working, when the form is filled with an attachment the email is sent but with no attachment received. in wp_mail documentation they said t should add something like that:

$attachments = array(
    '/path/to/file1.jpg',
    '/path/to/file2.png'
);

but there are random people who will attach random files with random name like gorilla05.png gamelf5.jpg. so the file name will change and i don't know which path to use in this case.

code.php in use:

    <?php
if(isset($_POST['submit']) && strpos($_SERVER['HTTP_REFERER'], 'https://example.com/custom-file/') !== false) {
    $to = '[email protected]'; // Replace with your own email address
    $subject = $_POST['subject']; // Get the value of the subject field from the form
    $message = "Name: " . $_POST['name'] . "<br><br>";
    $message .= "Email: " . $_POST['email'] . "<br><br>";
    $message .= "Message: " . $_POST['message'] . "<br><br>";

    $headers = array('Content-Type: text/html; charset=UTF-8');


    if (wp_mail($to, $subject, $message, $headers, $attachments)) {
        wp_redirect('/thank-you-contact-form-sent'); // Replace with the URL of your thank-you page
        exit();
    } else {
        wp_redirect('/sorry-contact-form-not-sent'); // Replace with the URL of your sorry page
        exit();
    }
}
?>

form.html:

<form action="code.php" id="code" enctype="multipart/form-data" method="post">
<div class="form-group"><label for="name">Name:</label>
<input id="name" class="form-control" name="name" type="text" /></div>
<div class="form-group"><label for="email">Email:</label>
<input id="email" class="form-control" name="email" type="email" /></div>
<div class="form-group"><label for="subject">Subject:</label>
<input id="subject" class="form-control" name="subject" type="text" /></div>
<div class="form-group"><label for="message">Message:</label>
<textarea id="message" class="form-control" name="message" rows="5"></textarea></div>
&nbsp;
<div class="form-group"><label for="image">Image (PNG or JPG, max 2MB):</label>
<input id="image" class="form-control" accept=".png,.jpg" name="image" required="" type="file" /></div>
&nbsp;
<div class="form-group"><button class="btn btn-primary" style="width: 100%;" name="submit" type="submit">Send Message</button></div>
</form>

EDIT

This is the code that i'm using now. There's a small problem with it, when i submit the form, it sends email to my admin email which is what i want but it also send an email to the email in the form. i want that is sent just to my admin email + it would be great if there are some securities that i can add to protect from spammers. thanks so much.

<?php
if(isset($_POST['submit']) && strpos($_SERVER['HTTP_REFERER'], 'https://example.com/custom/') !== false) {

    $to = '[email protected]';   
    $subject = $_POST['subject'];    
    $message = "Name: " . $_POST['name'] . "<br><br>";
    $message .= "Email: " . $_POST['email'] . "<br><br>";    
    $message .= "Message: " . $_POST['message'] . "<br><br>";   
    $headers = array('Content-Type: text/html; charset=UTF-8');

   // Allow just png and jpg maximum file size 2mb
    if ($_FILES['image']['error'] == UPLOAD_ERR_OK) {       
       
        $maxFileSize = 2000000;        
        $fileSize = $_FILES['image']['size'];
        
        if ($fileSize > $maxFileSize) {           
            die('File too large! Maximum file size is 2mb.');

        }           
        
       $allowedExtensions = array('png', 'jpg');    
       $fileExtension = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
       
        if (!in_array($fileExtension, $allowedExtensions)) {           
           die('Invalid file extension. Just png and jpg extensions are allowed! ');                 
        }     
    }     
     
     $attachments = array();
     
     // Handle the uploaded file
     if ($_FILES['image']['error'] == UPLOAD_ERR_OK) {
        $tmp_name = $_FILES['image']['tmp_name'];
        $filename = basename($_FILES['image']['name']);
        $destination = sys_get_temp_dir() . '/' . $filename; // Use system temp directory

        // Move the file to the temporary directory
        if (move_uploaded_file($tmp_name, $destination)) {
            $attachments = array($destination);
        }
    } 

// Send email with attachments, and redirect to thank you page
if (wp_mail($to, $subject, $message, $headers, $attachments)) {
        foreach($attachments as $file) {
            unlink($file); // Remove file from temp directory after sending
        }
        // Redirect thank you page
        wp_redirect('/thank-you-contact-form-sent'); // Replace with the URL of your thank-you page
        exit();
    } else {
        foreach($attachments as $file) {
            unlink($file); // Remove file from temp directoryI apologize, it seems that my previous response was cut off. Here's the rest of the modified code:

        }
        wp_redirect('/sorry-contact-form-not-sent'); // Replace with the URL of your sorry page
        exit();
    }
}


?>

2 Answers 2

0

You don't need to know the file names before, you'll have access to them.

I saw you using $subject = $_POST['subject']; - this means the subject will be the value of the input with the name of "subject". In your case, this one :

<input id="subject" class="form-control" name="subject" type="text" /></div>

We can use the same logic to get the files, but instead of $_POST, we'll look in $_FILES. Your file form has the name of "image", so the location will be $_FILES['image']. We can then handle the upload. I wrote a small example to show you how you would do that, but you should add some validation on it, depending on your use case :

if(isset($_POST['submit']) && strpos($_SERVER['HTTP_REFERER'], 'https://example.com/custom-file/') !== false) {
    $to = '[email protected]'; // Replace with your own email address
    $subject = $_POST['subject']; // Get the value of the subject field from the form
    $message = "Name: " . $_POST['name'] . "<br><br>";
    $message .= "Email: " . $_POST['email'] . "<br><br>";
    $message .= "Message: " . $_POST['message'] . "<br><br>";

    $headers = array('Content-Type: text/html; charset=UTF-8');

    // Handle the uploaded file
    if ($_FILES['image']['error'] == UPLOAD_ERR_OK) {
        $tmp_name = $_FILES['image']['tmp_name'];
        $filename = basename($_FILES['image']['name']);
        $upload_dir = wp_upload_dir();
        $destination = $upload_dir['basedir'] . '/' . $filename;

        // Move the file to the uploads directory
        if (move_uploaded_file($tmp_name, $destination)) {
            $attachments = array($destination);
        }
    }

    if (wp_mail($to, $subject, $message, $headers, $attachments)) {
        wp_redirect('/thank-you-contact-form-sent'); // Replace with the URL of your thank-you page
        exit();
    } else {
        wp_redirect('/sorry-contact-form-not-sent'); // Replace with the URL of your sorry page
        exit();
    }
}

EDIT

If you want to send the files as attachments, you can use the $attachments parameter for wp_mail(), like so :

wp_mail($to, $subject, $message, $headers, $attachments)

But you will need to store them on the server, at least until the email is sent. The $attachments parameter needs to be an array of strings that point to the file location for them to be attached, so we'll still need to upload the files, but after they were attached we can just delete them. Here's an example :

if(isset($_POST['submit']) && strpos($_SERVER['HTTP_REFERER'], 'https://example.com/custom-file/') !== false) {
    $to = '[email protected]'; // Replace with your own email address
    $subject = $_POST['subject']; // Get the value of the subject field from the form
    $message = "Name: " . $_POST['name'] . "<br><br>";
    $message .= "Email: " . $_POST['email'] . "<br><br>";
    $message .= "Message: " . $_POST['message'] . "<br><br>";

    $headers = array('Content-Type: text/html; charset=UTF-8');

    $attachments = array();

    // Handle the uploaded file
    if ($_FILES['image']['error'] == UPLOAD_ERR_OK) {
        $tmp_name = $_FILES['image']['tmp_name'];
        $filename = basename($_FILES['image']['name']);
        $destination = sys_get_temp_dir() . '/' . $filename; // Use system temp directory

        // Move the file to the temporary directory
        if (move_uploaded_file($tmp_name, $destination)) {
            $attachments = array($destination);
        }
    }

    if (wp_mail($to, $subject, $message, $headers, $attachments)) {
        foreach($attachments as $file) {
            unlink($file); // Remove file from temp directory after sending
        }
        wp_redirect('/thank-you-contact-form-sent'); // Replace with the URL of your thank-you page
        exit();
    } else {
        foreach($attachments as $file) {
            unlink($file); // Remove file from temp directory after sending
        }
        wp_redirect('/sorry-contact-form-not-sent'); // Replace with the URL of your sorry page
        exit();
    }
}

This still doesn't handle validation, but you can see the logic in it.

4
  • this worked thanks so much and I liked the logic that you used. There's just something that I need to modify that the file to be send as attachment to email but not stored on WordPress uploads directory. Can you adjust the code to do this. thanks
    – PC Welcome
    May 25, 2023 at 18:12
  • @PCWelcome My pleasure, I edited my answer.
    – alex
    May 25, 2023 at 21:49
  • file is not stored anymore thanks so much. There's a small problem with it, when i submit the form, it sends email to my admin email which is what i want but it also send an email to the email in the form. i made an edit to my first post with details...
    – PC Welcome
    May 26, 2023 at 18:00
  • for the email sent twice it's because i'm using 2 contact forms, i'm trying to resolve it and will give the full code when i finish. it would be great if there are some securities that i can add to protect from spammers. thanks so much.
    – PC Welcome
    May 27, 2023 at 19:16
1

thanks so much for alex you help me a lot my friend.

Note: this use wp_mail function to send emails, I use WordPress SMTP Plugin to send emails.

1/ I had a problem when i use

if(isset($_POST['submit'])) {

at the beginning of the code, i can't login with my wordpress admin account and i fix it by using secret key verification.

if(isset($_POST['submit']) && isset($_POST['secret_key']) && $_POST['secret_key'] === 'xx1485DD-x?58xtT') {

and this in the form: (replace xx1485Dcc by any value that you want):

<input type="hidden" name="secret_key" value="xx1485Dcc">

2/ when i received the form on my email and i want to replay, the replay email is set to my email and not to the email in the form. i fix it by replacing:

$headers = array('Content-Type: text/html; charset=UTF-8');

by:

$headers = array('Content-Type: text/html; charset=UTF-8', 'Reply-To: ' . $_POST['email']); // with Reply to the sender

and you can also add:

// Send reply email outside the conditional statement for message email
$replyTo = $_POST['email'];
$replySubject = $_POST['subject'];
$replyMessage = $_POST['message'];
$replyHeaders = array('Content-Type: text/html; charset=UTF-8', 'From: mysite <[email protected]>');
// Send reply email
wp_mail($replyTo, $replySubject, $replyMessage, $replyHeaders);

3/ i've also added this to accept just attachment png and jpg maximum 2mb size:

// Allow just png and jpg maximum file size 2mb
    if ($_FILES['image']['error'] == UPLOAD_ERR_OK) {       
       
        $maxFileSize = 2000000;        
        $fileSize = $_FILES['image']['size'];
        
        if ($fileSize > $maxFileSize) {           
            die('File too large! Maximum file size is 2mb.');

        }           
        
       $allowedExtensions = array('png', 'jpg');    
       $fileExtension = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
       
        if (!in_array($fileExtension, $allowedExtensions)) {           
           die('Invalid file extension. Just png and jpg extensions are allowed! ');                 
        }     
    }

4/ this add attachment to the email and upload it to and upload it to wordpress upload directory. in my case: /var/www/html/wp-content/uploads

$attachments = array();
     
// Handle the uploaded file
     if ($_FILES['image']['error'] == UPLOAD_ERR_OK) {
        $tmp_name = $_FILES['image']['tmp_name'];
        $filename = basename($_FILES['image']['name']);
        $destination = sys_get_temp_dir() . '/' . $filename; // Use system temp directory

        // Move the file to the temporary directory
        if (move_uploaded_file($tmp_name, $destination)) {
            $attachments = array($destination);
        }
    }

5/ this is to Remove file from temp directory after sending, because i don't want to keep any file on my wordpress. someone can have virus and change it extension to png or jpg and upload it to my website.

unlink($file); // Remove file from temp directory

7/ i used also some mesures to prevent spam like captcha: a/ by using a captcha plugin and add it's sortcut to the form b/ bu using honeypot, This is a hidden field in the form that is intended to be left blank by human users, but is likely to be filled in by bots. You can then check for the presence of a value in this field during form submission, and reject any submissions that have a value in the honeypot field. add this in php code:

// Check for honeypot value hidden filled in by bots
    if (!empty($_POST['honeypot'])) {
        die('Sorry, your submission was rejected due to suspected spam.');
    }

and this hidden field on the form:

<input type="hidden" name="honeypot" value="">

c/ by blocking any url to be sibmited in the form message. when i put this code at the end of php code, it deosn't work, so I added it to the top and it works.

// Block URLs in message field https http www and domains
    $messageText = $_POST['message'];
    if (preg_match('/\b(?!https?:\/\/|www\.)\w+\.\w+/i', $messageText)) {
        die('Sorry, we do not allow URLS in the form.');
    }

added just after:

if(isset($_POST['submit']) && isset($_POST['secret_key']) && $_POST['secret_key'] === 'xx1485DD-x?58xtT') {

8/ i created 2 wordpress pages, to redirect to them after the form is submitted. a/ when message is sent:

example.com/thank-you-contact-form-sent

page content: Thank you for contacting us. We will get back to you soon.

b/ when message not sent:

example.com/sorry-contact-form-not-sent

page content: Sorry, there was an error sending your message. Please try again later.

finally, this is the complete:

PHP code:

<?php

if(isset($_POST['submit']) && isset($_POST['secret_key']) && $_POST['secret_key'] === 'xx1485DD') {
    
            // Block URLs in message field https http www and domains
    $messageText = $_POST['message'];
    if (preg_match('/\b(?!https?:\/\/|www\.)\w+\.\w+/i', $messageText)) {
        die('Sorry, we do not allow URLS in the form.');
    }

    $to = '[email protected]';   
    $subject = $_POST['subject'];    
    $message = "Name: " . $_POST['name'] . "<br><br>";
    $message .= "Email: " . $_POST['email'] . "<br><br>";    
    $message .= "Message: " . $_POST['message'] . "<br><br>";   
    $headers = array('Content-Type: text/html; charset=UTF-8', 'Reply-To: ' . $_POST['email']); // with Reply to the sender

   // Allow just png and jpg maximum file size 2mb
    if ($_FILES['image']['error'] == UPLOAD_ERR_OK) {       
       
        $maxFileSize = 2000000;        
        $fileSize = $_FILES['image']['size'];
        
        if ($fileSize > $maxFileSize) {           
            die('File too large! Maximum file size is 2mb.');

        }           
        
       $allowedExtensions = array('png', 'jpg');    
       $fileExtension = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
       
        if (!in_array($fileExtension, $allowedExtensions)) {           
           die('Invalid file extension. Just png and jpg extensions are allowed! ');                 
        }     
    }     
     
     $attachments = array();
     
// Handle the uploaded file
     if ($_FILES['image']['error'] == UPLOAD_ERR_OK) {
        $tmp_name = $_FILES['image']['tmp_name'];
        $filename = basename($_FILES['image']['name']);
        $destination = sys_get_temp_dir() . '/' . $filename; // Use system temp directory

        // Move the file to the temporary directory
        if (move_uploaded_file($tmp_name, $destination)) {
            $attachments = array($destination);
        }
    } 

// Send email with attachments, Reply to the sender and redirect to thank you page
if (wp_mail($to, $subject, $message, $headers, $attachments)) {
        foreach($attachments as $file) {
            unlink($file); // Remove file from temp directory after sending
        }
        // Redirect thank you page
        wp_redirect('/thank-you-contact-form-sent'); // Replace with the URL of your thank-you page
        exit();
    } else {
        foreach($attachments as $file) {
            unlink($file); // Remove file from temp directoryI apologize, it seems that my previous response was cut off. Here's the rest of the modified code:

        }
        wp_redirect('/sorry-contact-form-not-sent'); // Replace with the URL of your sorry page
        exit();
    }
}
// Send reply email outside the conditional statement for message email
$replyTo = $_POST['email'];
$replySubject = $_POST['subject'];
$replyMessage = $_POST['message'];
$replyHeaders = array('Content-Type: text/html; charset=UTF-8', 'From: your site <[email protected]>');
// Send reply email
wp_mail($replyTo, $replySubject, $replyMessage, $replyHeaders);


// Spam securities:

// Check for honeypot value hidden filled in by bots
    if (!empty($_POST['honeypot'])) {
        die('Sorry, your submission was rejected due to suspected spam.');
    }
    


?>

form:

<form action="" id="contact-order" enctype="multipart/form-data" method="post">
<input type="hidden" name="secret_key" value="xx1485DD">
<input type="hidden" name="honeypot" value="">
<div class="form-group"><label for="name">Name:</label>
<input id="name" class="form-control" name="name" type="text" required /></div>
<div class="form-group"><label for="email">Email:</label>
<input id="email" class="form-control" name="email" type="email" required /></div>
<div class="form-group"><label for="subject">Subject:</label>
<input id="subject" class="form-control" name="subject" type="text" required /></div>
<div class="form-group"><label for="message">Message:</label>
<textarea id="message" class="form-control" name="message" rows="5" required></textarea></div>
<br>
<br>
<br>
<div class="form-group"><label for="image">Image (PNG or JPG, max 2MB):</label>
<input id="image" class="form-control" accept=".png,.jpg" name="image" type="file" /></div>
<br>
<br>
<br>
<div class="form-group"><button class="btn btn-primary" style="width: 100%;" name="submit" type="submit">Send Message</button></div>
</form>

big thanks again for alex

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.