
Upload files to an order to attach them to the WooCommerce Order Completed email.
Update 26 August 2022: Shane asked how to upload files so that they are not public. I suggested using the wp-content/uploads/woocommerce_uploads
directory as it is .htaccess protected. Over a few emails Shane dived into the WooCommerce source and found a solution with the plupload_default_params
and upload_dir
filters – essentially if the upload is from a WooCommerce order then the files are uploaded to the protected woocommerce_uploads
directory.
As this functionality is not needed by everyone I converted the code (version 0.3) to the a PHP class and used a true/false member variable to determine where to upload attachments. This update also included code to inform the admin when CMB2 is not active.
Update 4 January 2023: Gaja asked if the attachments could be shown in the customer’s View Order page in their account. It was an easy addition. Version 0.5 of the code includes this. See the screenshot near the end of the post.
Update 13 September 2023: Enabled HPOS support by changing get_post_meta() calls to $order->get_meta() versions.
CMB2 does not yet support HPOS but I reported it and they’ve developed a fix that should be in the next release.
I previously wrote about conditionally attaching files to WooCommerce order email to the Completed order email.
A client asked how to attach custom photos of a product to the Completed order email. This meant that the list of files to attach to the email could not be a static list as it was for the other plugin. I copied and tweaked the meta box code form the Tracking Info to WooCommerce order post to allow for a list of files to be uploaded and associated with each order. CMB2 has the ‘file_list’ field type that allows the upload of multiple files. It is primarily intended for galleries but is perfect for this.
The files are attached via the ‘woocommerce_email_attachments‘ filter and checking that the email is the ‘customer_completed_order‘ one. The list of attachments is in the post meta and includes the attachment ID and url. The
url is not useful here as the path to the file is needed so it can be attached. The get_attached_file() API call retrieves this.
Upload before sending email
For the shop manager, the most important thing is to note is that the files must be uploaded before the order is marked Complete.
View attachments in customer’s View Order page
Gaja asked if the attachments could be shown in the customer’s View Order page in their account. Someone asked the same question on a Facebook group. It wasn’t hard to add this. Version 0.5 of the code includes this new feature.
I added an ‘Attached documents‘ section below the address section.
The code
The settings for the ‘file_list‘ field limits it to image uploads (‘query_args‘ parameter). This can be commented out or edited to allow for different file types.
Hey, is there a way to make this usable to add files to an order note and then send this to a customer? these files are individual per order and can change up to once a day. i would like to use woo to keep track of what was sent when. thanks
@Felix – Maybe the code could be changed to attach the files when you add a note to the order – on line 36, change ‘customer_completed_order’ to ‘customer_note’. To keep track, your note would have to say what was in the email, it would not be a record of the files sent.
Hi,
I tried implementing your code but I’m not sure what went wrong. I edited out the query_args parameter because I wanted to attach a PDF file. Upon testing with the last part back in the code, I just got an empty space with ‘ ‘ in the email body.
Can you help me? Cheers
Actually you can ignore my previous comment, I didn’t realize that by “the files must be uploaded before the order is marked Complete” you meant one has to do it in two steps, I was uploading the file and marking the order as complete at the same time before hitting the update button on the order ^^’
@Hugo – Yes, it has to be done in two steps. There’s an underlying issue that others have found in my tracking info code where the tracking info has to be added and then change order status. It’s on my todo list to investigate that. The solution to that may benefit the situation you see.
Hi @damien, just to confirm so I would need to (1) Select files and click Update (2) mark the order as complete and click Update. Is this what you meant? Thanks!
@2023gonnarock – That’s exactly it. This is because WooCommerce sends the emails before CMB2 saves the PDF info.
There is a filter that will delay sending emails for 10 seconds:
// Defer emails for 10 seconds to allow time for CMB2 to save the tracking data. add_filter( 'woocommerce_defer_transactional_emails', '__return_true' );
You can add that to the init() function to see if it works. Comment out if it doesn’t and stick with the two step approach.
Hi,
I am trying to find a way so that the files being attached are not public, in my case the customer can order an assessment and i want to be able to attach that assessment to the order but it contains personal information.
Any ideas how to do this?
@Shane: Mmm, tough one.
I know that WooCommerce puts uploads under
wp-content/uploads/woocoommerce_uploads
which it protects with a .htaccess file. This means that the files cannot be accessed directly and have to go through the WooCommerce download script. This concept could be an option.I had a quick look at how it gets the uploaded file there – it uses the
'upload_dir'
filter (fromwp-includes/functions.php
) in woocommerce/includes/admin/class-wc-admin-post-types.php.So, you could probably do something similar – the post type would be a
'shop_order'
. There’s probably another filter to allow your new uploads directory to be visible to the CMB2 File Upload panel.If there isn’t too much data maybe you could store it with order meta and have an extra tab or section in the order details that the customer views.
Hi, some questions: 1) should the code be placed in the function.php file (in the child theme)? 2) can coexist together with this other : https://www.damiencarbery.com/2020/01/add-tracking-info-to-woocommerce-order/
@Giuseppe:
1) You can copy the code (except the opening https://www.damiencarbery.com/2018/10/how-to-use-my-code-snippets/
2) The code should be able to coexist with the tracking info code. It works on the email content and the other code changes the attachments.
Please do let me know if it does work for you.
Thanks for the reply. Actually I have already entered the two codes and everything works perfectly.
Just one detail: in your tracking code I had to eliminate this line because it didn’t let me send any order emails.
// Defer emails for 10 seconds to allow time for CMB2 to save the tracking data. add_filter( 'woocommerce_defer_transactional_emails', '__return_true' );
@Giuseppe: Thanks for the update. That add_filter() line should add the order email to the WooCommerce/Status/Scheduled Actions/Pending list. Is wp-cron active?
The 10 second delay is to allow shop managers enter the tracking info and update the status to Completed at the same time (without it the Order Completed email is sent before the tracking info is saved and therefore it is not available to add to the email). If this does happen to you then it is okay to comment out that line.
Hi, yes I understood its function but I saw that leaving it no woocommerce email is sent. If I delete that row, everything works fine: first entering the tracking data and then changing the order status to complete. wp-cron is active.
I installed your 2 snippets as plugins (not in the function.php file) and everything works fine.
– but eliminating that line of code that I told you:
// Defer emails for 10 seconds to allow time for CMB2 to save the tracking data. add_filter( 'woocommerce_defer_transactional_emails', '__return_true' );
My concern now is: with future updates of woocommerce, will you release updates of your plugins? For example, even the CMB plugin (https://it.wordpress.org/plugins/cmb2/) hasn’t been updated for 10 months.
Hello and thanks for your work.
@Giuseppe – The hooks and filters I use will probably not change in WooCommerce so my code will continue to work. CMB2 has not been updated because it does not need to be updated to work.
If one of my plugins stops working please tell me and I will investigate it. I don’t have time to check my snippets each time WooCommerce or WordPress release an update.
How can I integrate this code into woocommerce to make it work properly?
I need it to attach pdf files in addition to photos is it possible?
@Igor – All my code snippets are written as small plugins that you can upload and activate. Please look at the information at: https://www.damiencarbery.com/2018/10/how-to-use-my-code-snippets/
The code already supports images and PDF files.
Hello thank you for the code, It saved my day
I realized that sometimes the PDF is attached while at other times it fails. Is there a need to allow a few seconds delay between attach an update the status of order to complete?
@Anthony – It is best to attach the files and save/update the order, then update the status and save again. This is because WooCommerce sends the emails before CMB2 saves the PDF info.
There is a filter that will delay sending emails for 10 seconds:
// Defer emails for 10 seconds to allow time for CMB2 to save the tracking data. add_filter( 'woocommerce_defer_transactional_emails', '__return_true' );
You can add that to the init() function to see if it works. Comment out if it doesn’t and stick with the two step approach.
Damien amazing piece of code, exactly what I was looking for. I just have one question. Is possible to get rid off this classic Wordpress media uploader and fire browser native OS window for uploading files and upload them inside subfolder woocommerce_upload/invoices? So they are not visible in media library?
Best, Rok
@Rok – I don’t know how to hide items in Media Library. When you upload files to
woocommerce_uploads
directory they will be listed in Media Library but cannot be viewed because of the .htaccess file in the directory.Media Library is created with Backbone.js which, AFAIK, uses REST API to get the media items (probably
/wp-json/wp/v2/media
). I could not understand the JS involved. I used a REST API log plugin but it did not list any REST API accesses. I suggest asking on wordpress.stackexchange.com.Hi,
Is it possible to show the attachment in woo-commerce account ? To downlaod directly from the customer’s account ?
Regards, Gaja
@Gaja – Thanks for the prompt – I have been planning to update the code to implement this. I have added code to include an ‘Attached Documents’ sections in the customer’s View Order page (version 0.5 of the plugin code). See screenshot at the end of the post.
Hi there! After activating the module, the block for uploading files does not appear on the order page. Any solution?
@Constantin: Please ensure that CMB2 plugin is active.
Can we put a checkbox option that will make the plugin update the order status to “completed” as well?
@sacar – You can select the Completed status from the dropdown on the left of the screen and click Update.