# Job Application Form With CV Upload

> Adds a [wpide_job_application] shortcode where candidates send their details and a CV (PDF or Word, size-limited); the CV is attached to the email you receive and then deleted from the server.

- Type: PHP
- Runs: Run everywhere
- Category: [Forms](https://wpide.com/library/category/forms/)
- Tags: jobs, upload, shortcode
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/form-job-application/

## Code

```php
$wpide_jobs = array(
    'to'     => '',      // Recipient; empty = admin email.
    'max_mb' => 5,       // Maximum CV size.
    'types'  => array( 'pdf' => 'application/pdf', 'doc' => 'application/msword', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ),
);

add_action( 'template_redirect', function () use ( $wpide_jobs ) {
    if ( empty( $_POST['wpide_job_nonce'] ) ) {
        return;
    }

    $back = remove_query_arg( 'wpide_job', wp_get_referer() ? wp_get_referer() : home_url( '/' ) );
    $done = function ( $status ) use ( $back ) {
        wp_safe_redirect( add_query_arg( 'wpide_job', $status, $back ) . '#wpide-job' );
        exit;
    };

    if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['wpide_job_nonce'] ) ), 'wpide_job' ) ) {
        $done( 'expired' );
    }
    if ( ! empty( $_POST['wpide_job_hp'] ) ) {
        $done( 'sent' );
    }

    $name     = str_replace( array( '<', '>', '"' ), '', sanitize_text_field( wp_unslash( isset( $_POST['wpide_job_name'] ) ? $_POST['wpide_job_name'] : '' ) ) );
    $email    = sanitize_email( wp_unslash( isset( $_POST['wpide_job_email'] ) ? $_POST['wpide_job_email'] : '' ) );
    $position = sanitize_text_field( wp_unslash( isset( $_POST['wpide_job_position'] ) ? $_POST['wpide_job_position'] : '' ) );
    $letter   = sanitize_textarea_field( wp_unslash( isset( $_POST['wpide_job_letter'] ) ? $_POST['wpide_job_letter'] : '' ) );
    $file     = isset( $_FILES['wpide_job_cv'] ) ? $_FILES['wpide_job_cv'] : null; // phpcs:ignore

    if ( '' === $name || ! is_email( $email ) || ! $file || UPLOAD_ERR_OK !== $file['error'] ) {
        $done( 'invalid' );
    }
    if ( $file['size'] > $wpide_jobs['max_mb'] * MB_IN_BYTES ) {
        $done( 'size' );
    }

    require_once ABSPATH . 'wp-admin/includes/file.php';
    $upload = wp_handle_upload( $file, array( 'test_form' => false, 'mimes' => $wpide_jobs['types'] ) );

    if ( empty( $upload['file'] ) ) {
        $done( 'type' );
    }

    $to   = is_email( $wpide_jobs['to'] ) ? $wpide_jobs['to'] : get_option( 'admin_email' );
    $sent = wp_mail( $to, sprintf( 'Application: %s – %s', $position ? $position : 'Open application', $name ), "Name: $name\nEmail: $email\nPosition: $position\n\n$letter", array( 'Reply-To: ' . $name . ' <' . $email . '>' ), array( $upload['file'] ) );

    wp_delete_file( $upload['file'] );
    $done( $sent ? 'sent' : 'error' );
} );

add_shortcode( 'wpide_job_application', function ( $atts ) use ( $wpide_jobs ) {
    $atts     = shortcode_atts( array( 'position' => '' ), $atts, 'wpide_job_application' );
    $messages = array(
        'sent'    => 'Thank you for applying! We will review your application and be in touch.',
        'invalid' => 'Please fill in your name and email and attach your CV.',
        'size'    => sprintf( 'Your CV is too large. The maximum size is %d MB.', $wpide_jobs['max_mb'] ),
        'type'    => 'Please upload your CV as a PDF or Word document.',
        'expired' => 'The form expired. Please try again.',
        'error'   => 'Sorry, your application could not be sent. Please email us directly.',
    );
    $status = isset( $_GET['wpide_job'] ) ? sanitize_key( $_GET['wpide_job'] ) : '';

    $html  = '<div id="wpide-job" class="wpide-form wpide-job-form">';
    $html .= isset( $messages[ $status ] ) ? '<p class="wpide-form-notice" role="status">' . esc_html( $messages[ $status ] ) . '</p>' : '';
    $html .= '<form method="post" action="" enctype="multipart/form-data">';
    $html .= '<p><label for="wpide-job-name">Full name</label><br><input id="wpide-job-name" name="wpide_job_name" required autocomplete="name"></p>';
    $html .= '<p><label for="wpide-job-email">Email</label><br><input type="email" id="wpide-job-email" name="wpide_job_email" required autocomplete="email"></p>';
    $html .= '<p><label for="wpide-job-cv">CV (PDF or Word, max ' . (int) $wpide_jobs['max_mb'] . ' MB)</label><br><input type="file" id="wpide-job-cv" name="wpide_job_cv" required accept=".pdf,.doc,.docx"></p>';
    $html .= '<p><label for="wpide-job-letter">Why are you a great fit?</label><br><textarea id="wpide-job-letter" name="wpide_job_letter" rows="6"></textarea></p>';
    $html .= '<input type="hidden" name="wpide_job_position" value="' . esc_attr( $atts['position'] ) . '">';
    $html .= '<p style="position:absolute;left:-9999px;" aria-hidden="true"><input name="wpide_job_hp" tabindex="-1" autocomplete="off"></p>';
    $html .= wp_nonce_field( 'wpide_job', 'wpide_job_nonce', false, false );
    $html .= '<p><button type="submit">Send application</button></p></form></div>';

    return $html;
} );
```

## Notes

Use [wpide_job_application position="Senior Designer"] to name the role and change the size limit and recipient at the top; CVs are never kept on the server.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Job Application Form With CV Upload" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
