I have a file field in my CPT. When an admin uploads a file into this field, I need to generate an email. Is there a simple way to do this, or do I have to create a plugin?

  • Check edit_post or save_post action.
    – Emetrop
    Aug 18, 2015 at 18:40
  • Thanks, I came across the following answer but I still don't really know how to run code when a post is saved/updated rather than when it's initially created: wordpress.stackexchange.com/a/19539/11634
    – drake035
    Nov 29, 2015 at 19:08
  • @drake035 save_post fires every time, regardless of creation or update - like @Milo says, you can use post_updated instead. Can you clarify in your question what the name of the custom field is, and how you allow the user to set it (are you using custom code or a plugin like ACF?) Dec 1, 2015 at 13:22

5 Answers 5


If you have registered that CPT and added uploads functionality, then you can write email functionality in that only. However, if it comes from any other plugin or theme, then either you will need to edit its code or create a plugin if sufficient hook is available.

If there is no custom hook available and you are going to use some generic WordPress hook e.g. save_post for your attachment, then make sure to check for your CPT's post type before running email functionality, otherwise it will be applied for all the attachments.

e.g. you can check on save_post hook, if the post_type is attachment and the current screen is of your CPT, then send email.

  • Thanks but save_post fires not just on publish/update but also when the new post admin page loads which is not what I want.
    – drake035
    Nov 29, 2015 at 19:09

The 3rd argument passed to the save_post action ($update) will be false on initial post creation and true for any subsequent post save.

You can also use the post_updated action, which won't fire on initial post creation.


If your file upload is using Media Manager (upload.php) then the file will end up being an attachment to the post. If that's true, then:

add_action('add_attachment', 'my_email_function', 10, 1);

is how you would do it - relying on the firing of the 'add_attachment' hook.

Of course you need to write the code for my_email_function($post_ID), which ought to examine the role of $current_user as well as the post_type of the attachment's parent post -- to make sure are emailing when the conditions are correct. I have not tested this but it ought to be very close to correct:

function my_email_function($post_ID) {
    global $current_user;
    $cur_user = get_currentuserinfo();

    $parent_post = wp_get_post_parent_id( $post_ID );
    if ( $parent_post ) // make sure we got a post back, not "false"
        if ( ( 'my_cpt' === $parent_post->post_type ) && user_can( $cur_user, 'administrator' ) ) {  
       // do email function here

Everytime you upload a file, an attachment post is newly created, so post_updated hook or the 3rd argument of save_post hook can't help you.

You said that you have a "field" where admins can updload files. This makes me guess that you are using some custom field in your CPT to store the attachment ID or url.

In that case, you can use updated_postmeta hook to listen to changes on the meta key used to store the value.

Note that this hook is fired only when a field is updated, so won't be fired when it first saved.

A sample, untested and proof of concept code is:

add_action( 'updated_postmeta', function( $metaId, $postId, $metaKey, $metaValue ) {

   // replace "your-meta-key" with the actual meta key where attachment info is saved
   if (  $metaKey !== 'your-meta-key' )
     return; // do nothing if the meta key is not the right one 

   // replace "your-ctp-slug" with the actual CPT slug
   if ( get_post_field( 'post_type', $postId ) !== 'your-ctp-slug' )
     return; // do nothing if the post type is not the right one

   // if here, the field where attachment is stored has been updated, send the email

     '[email protected]',
     'Attachment updated.'
     "The attachment {$metaValue} has been updated"

}, 10, 4 ); 

Maybe something like this. (Untested)

add_action('post_updated', 'custom_post_updated_actions', 10, 3);

function custom_post_updated_actions($post_ID, $post_after, $post_before) {

    if('custom-post-type-slug' == $post_after->post_type) {

        // run wp_mail() function here.  
        // You could pass any data from the $post_after and 
        // $post_before objects that you wish (both are object type WP_Post)

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.