0

I have made several attempts to process form attachments and have had no luck, aside from the initial upload box in the html. I've read that it is possible using FormData, which my attempts have been centered around, but none of my attempts have led me to any progress. While I still have a series of non-working code (commented out, for reference), I have reverted all of my code back to it's last cohesive, functional state to make this post more concise.

How do I add an attachment to my outgoing emails?

HTML form

<form id="requestcreditform" enctype="multipart/form-data">
    <h1>Withdraw Credit</h1>

    <div class="formcontainer">
    
      <div class="container">
        <label for="clientn"><strong>Check Made To</strong></label>
        <input type="text" name="clientname" placeholder="" id="clientname" required><br />
        <label for="credit_requested"><strong>Credit Requested</strong></label>
        <input type="number" name="creditreq" placeholder="5000" id="creditreq" required>
        <label><b><br />Upload Contract:<br /><b></label>
        <input type="file" name="file" id="file" accept="image/*,.pdf" required> <br /><br />
        <input type="checkbox" id="expedited" name="expedited" value="1">
        <label for="expedited">Expedited Shipping (+$15)</label><br>      
        <p>This change will be reflected to your account upon submission and your credit will be processed shortly afterwards.   Please verify the requested credit is correct prior to hitting the "Request Check" button. Checks will be addressed to the client and shipped to the attorney's practice. Thank you.<br />
        </p>
      </div>
      
      <button id="submit_button" type="submit"><strong>Request Check</strong></button>
      
    </div>
    
</form>

JS

(function($){
  $('#requestcreditform').submit( function(event) {
  
    event.preventDefault();
    
    var endpoint = '<?php echo admin_url('admin-ajax.php');?>';
   
    var form = $('#requestcreditform').serialize();
    
    var formdata = new FormData;
    
    //file
    //$this = $(this);
    //file_data = $(this).prop('files')[0];
    //formdata.append('file', file_data);
    
    formdata.append('action', 'requestcredit');
    formdata.append('requestcredit', form);
    
    //file
    //formdata.append("file[]", file_data[0]);
    
    $.ajax(endpoint, {
      type: 'POST',
      data: formdata,
      processData: false,
      contentType: false,
 
      success:function(res) {
        alert(res.data);
        location.reload();
      },
      error: function(err) {
      }
    
    })
  })
})(jQuery)

PHP

add_action("wp_ajax_requestcredit", "request_credit1");
function request_credit1() {
    global $current_user;
    global $wpdb;
  
    //pull user data
    $current_user = wp_get_current_user();
    $user_id = $current_user->id;
  
    //get user name and address
    $user_fname_query = $wpdb->prepare("SELECT meta_value FROM oWC_usermeta WHERE user_id = %d AND meta_key = %s", $user_id, 'first_name');
    $user_fname = $wpdb->get_var($user_fname_query);
    
    $user_lname_query = $wpdb->prepare("SELECT meta_value FROM oWC_usermeta WHERE user_id = %d AND meta_key = %s", $user_id, 'last_name');
    $user_lname = $wpdb->get_var($user_lname_query);
    
    $name = $user_fname.' '.$user_lname;
    
    $user_address_query = $wpdb->prepare("SELECT meta_value FROM oWC_usermeta WHERE user_id = %d AND meta_key = %s", $user_id, 'user_registration_address');
    $user_address = $wpdb->get_var($user_address_query);
    
    //$name = $current_user->firstname . " " . $current_user->lastname;
    $email = $current_user->user_email;
    $phone = $current_user->phone;
    $approved_credit = $current_user->approved_credit;
    
    //POST
    $formdata = [];
    
    //text
    wp_parse_str($_POST['requestcredit'], $formdata);
    
    $credit_requested = $formdata['creditreq'];
    $checkmadeto = $formdata['clientname'];
    $expedited = $formdata['expedited'];
    
    $expedited_sum = $credit_requested;
    $expedited_price = 15;
    
    $check_type ='';
    
    if ($expedited == 1) {
        $expedited_sum = $credit_requested + $expedited_price;
        $check_type = 'expedited';
    }
    else {
        $check_type = 'standard';
    }
    
    //TRANSACTION TABLE
    //remaining credit
    $query = $wpdb->prepare("SELECT SUM(credit_amount) AS total FROM transaction_history WHERE (is_paid <> 1 OR is_paid IS NULL) AND user_id = %d", $user_id);
    $credit_total = $wpdb->get_var($query);
    
    $remaining_credit = $current_user->approved_credit;
    //$remaining_credit = $current_user->approved_credit - $credit_total;
    
     if ($credit_requested > $remaining_credit) {
        wp_send_json_success('Credit Request failed.  Please ensure you have entered a number within your remaining credit');
        exit;
    }
    //if requested amount is allowed
    else {
        //insert withdrawn credit into transaction history
        $wpdb->insert('transaction_history', array(
            'user_id' => $current_user->id,
            'credit_timestamp' => current_time( 'mysql' ),
            'credit_amount' => $expedited_sum,
            'clientname' => $checkmadeto,
            'transaction_type' => $check_type
        ));
        
        //MAIL
        //admin email - dynamic
        $admin_email = get_option('admin_email');

        //file
        $content = file_get_contents($fileName);
        $content = chunk_split(base64_encode($content));
        
        // main header (multipart mandatory)
        
        // carriage return type (RFC)
        $eol = "\r\n";
        
        //headers
        $headers[] = 'Content-Type: text/html; charset=UTF-8';
        $headers[] = 'From:' .$admin_email;

        //Set the recipient email address.
        $recipient = $admin_email;;

        //Set the email subject.
        $subject = "New CreditCapital Check Request from $name";

        // Build the email content.
        $email_content = 'Address Check To: '.$checkmadeto.$eol;
        $email_content .= 'Amount: $'.$credit_requested.$eol.$eol;
        
        $email_content .= 'Mailing Address:'.$eol;
        $email_content .= $name.$eol;
        $email_content .= $user_address.$eol.$eol;
        
        if ($expedited == 1) {
            $email_content .= 'Check Type: Expedited'.$eol.$eol;
        }
        else {
            $email_content .= 'Check Type: Standard'.$eol;
        }
        
        try {
          if (wp_mail($recipient, $subject, $email_content, $headers)) {
            wp_send_json_success('Credit Request for $'.$credit_requested. ' sent.');
          }
          else {
             wp_send_json_success('Credit Request failed.  Please ensure you have entered a number within your remaining credit');
          }
        } catch (Exception $e) {
           wp_send_json_success($e->getMessage());
        }
     }
}

The only headway I have made that I believe is in the right direction is with the email's header information, switching to a mixed content type, as such...

$headers = 'From:' .$admin_email . $eol;
$headers .= "MIME-Version: 1.0" . $eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"" . $separator . "\"" . $eol;
$headers .= "Content-Transfer-Encoding: 7bit" . $eol;
$headers .= "This is a MIME encoded message." . $eol;

I am trying to process the file similarly to how I do via POST, but I have had no luck - and the only recurring theme I see are these lines...

$filenameee =  $_FILES['file']['name'];
$fileName = $_FILES['file']['tmp_name'];
Pippo
  • 2,173
  • 2
  • 3
  • 16
jgdhnds
  • 11
  • 2
  • 1
    Neither AJAX nor HTML is required to add an attachment to an email. Since you've included code for these, should we assume that the problem resides in the AJAX call, i.e.transferring data to the server, or can we assume that that works and tha ctula process of attaching is the problem, or have you not determined where the problem is? – Tangentially Perpendicular May 11 '23 at 20:52
  • 1
    See https://stackoverflow.com/questions/4554664/how-to-send-an-email-with-attachment-in-wordpress for how to send an attachment with Wordpress email. – Barmar May 11 '23 at 20:55
  • @TangentiallyPerpendicular The problem certainly lies in my ability to pass and receive the attachment through the JS and php for the AJAX call. I tried tagging this as "FormData", as that's really where the issues lies, but I do not have enough reputation to do so. – jgdhnds May 11 '23 at 21:27
  • @Barmar That is the most useful thing I've seen so far. Much easier than all of the attempts with headers I've been attempting. Wild I haven't encountered it yet. That eliminates half of the possible problems. What's left to solve is my struggle with passing the file correctly using FormData. – jgdhnds May 11 '23 at 21:29
  • 1
    `formdata.append('file', file_data);` should work – Barmar May 11 '23 at 21:31
  • @Barmar This line (combined with wp_mail) got me to be able to send files, but the files have lost their name and extensions (though I can still open the images using a browser). `formdata.append('image', document.getElementById("file").files[0]);` When I try using `$_FILES["image"]["name"]` nothing is returned. Using `$_FILES["image"]["tmp_name"]` generates a random temporary name that has lost its extension. Must I temporarily upload the image to retain its name/extension? – jgdhnds May 12 '23 at 01:12
  • Bit weird that you are sending the serialized form separately here. If you simply want to send _all_ the form data, then you can pass the form element to the FormData constructor directly, `var formdata = new FormData($('#requestcreditform')[0]);` – CBroe May 12 '23 at 06:25
  • I'm not sure why you're losing the filename when you append that way. You can add an explicit filename by using the third argument to `formdata.append()`. But the default is supposed to come from the selected file. – Barmar May 12 '23 at 15:28

0 Answers0