diff --git a/wp-admin/includes/file.php b/wp-admin/includes/file.php
index e1392505f4..64f80b0da2 100644
--- a/wp-admin/includes/file.php
+++ b/wp-admin/includes/file.php
@@ -1862,9 +1862,6 @@ function wp_privacy_generate_personal_data_export_group_html( $group_data ) {
  * @param int  $request_id  The export request ID.
  */
 function wp_privacy_generate_personal_data_export_file( $request_id ) {
-	// Maybe make this a cron job instead.
-	wp_privacy_delete_old_export_files();
-
 	if ( ! class_exists( 'ZipArchive' ) ) {
 		wp_send_json_error( __( 'Unable to generate export file. ZipArchive not available.' ) );
 	}
@@ -2025,13 +2022,18 @@ function wp_privacy_send_personal_data_export_email( $request_id ) {
 		return new WP_Error( 'invalid', __( 'Invalid request ID when sending personal data export email.' ) );
 	}
 
-/* translators: Do not translate LINK, EMAIL, SITENAME, SITEURL: those are placeholders. */
+	/** This filter is documented in wp-admin/includes/file.php */
+	$expiration      = apply_filters( 'wp_privacy_export_expiration', 3 * DAY_IN_SECONDS );
+	$expiration_date = date_i18n( get_option( 'date_format' ), time() + $expiration );
+
+/* translators: Do not translate EXPIRATION, LINK, EMAIL, SITENAME, SITEURL: those are placeholders. */
 $email_text = __(
 'Howdy,
 
 Your request for an export of personal data has been completed. You may
-download your personal data by clicking on the link below. This link is
-good for the next 3 days.
+download your personal data by clicking on the link below. For privacy
+and security, we will automatically delete the file on ###EXPIRATION###,
+so please download it before then.
 
 ###LINK###
 
@@ -2046,6 +2048,7 @@ All at ###SITENAME###
 	 * Filters the text of the email sent with a personal data export file.
 	 *
 	 * The following strings have a special meaning and will get replaced dynamically:
+	 * ###EXPIRATION###         The date when the URL will be automatically deleted.
 	 * ###LINK###               URL of the personal data export file for the user.
 	 * ###EMAIL###              The email we are sending to.
 	 * ###SITENAME###           The name of the site.
@@ -2063,6 +2066,7 @@ All at ###SITENAME###
 	$site_name = is_multisite() ? get_site_option( 'site_name' ) : get_option( 'blogname' );
 	$site_url = network_home_url();
 
+	$content = str_replace( '###EXPIRATION###', $expiration_date, $content );
 	$content = str_replace( '###LINK###', esc_url_raw( $export_file_url ), $content );
 	$content = str_replace( '###EMAIL###', $email_address, $content );
 	$content = str_replace( '###SITENAME###', wp_specialchars_decode( $site_name, ENT_QUOTES ), $content );
@@ -2207,22 +2211,3 @@ function wp_privacy_process_personal_data_export_page( $response, $exporter_inde
 
 	return $response;
 }
-
-/**
- * Cleans up export files older than three days old.
- *
- * @since 4.9.6
- */
-function wp_privacy_delete_old_export_files() {
-	$upload_dir   = wp_upload_dir();
-	$exports_dir  = trailingslashit( $upload_dir['basedir'] . '/exports' );
-	$export_files = list_files( $exports_dir );
-
-	foreach( (array) $export_files as $export_file ) {
-		$file_age_in_seconds = time() - filemtime( $export_file );
-
-		if ( 3 * DAY_IN_SECONDS < $file_age_in_seconds ) {
-			@unlink( $export_file );
-		}
-	}
-}
diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php
index 9cfee1a655..b281caa362 100644
--- a/wp-includes/default-filters.php
+++ b/wp-includes/default-filters.php
@@ -325,6 +325,8 @@ add_action( 'user_request_action_confirmed', '_wp_privacy_account_request_confir
 add_filter( 'user_request_action_confirmed_message', '_wp_privacy_account_request_confirmed_message', 10, 2 );
 add_filter( 'wp_privacy_personal_data_exporters', 'wp_register_comment_personal_data_exporter' );
 add_filter( 'wp_privacy_personal_data_erasers', 'wp_register_comment_personal_data_eraser' );
+add_action( 'init', 'wp_schedule_delete_old_privacy_export_files' );
+add_action( 'wp_privacy_delete_old_export_files', 'wp_privacy_delete_old_export_files' );
 
 // Cron tasks
 add_action( 'wp_scheduled_delete',            'wp_scheduled_delete'       );
diff --git a/wp-includes/functions.php b/wp-includes/functions.php
index 655a18ab4f..6d3c0e88c9 100644
--- a/wp-includes/functions.php
+++ b/wp-includes/functions.php
@@ -5934,3 +5934,51 @@ function wp_privacy_anonymize_data( $type, $data = '' ) {
 	 */
 	return apply_filters( 'wp_privacy_anonymize_data', $anonymous, $type, $data );
 }
+
+/**
+ * Schedule a `WP_Cron` job to delete expired export files.
+ *
+ * @since 4.9.6
+ */
+function wp_schedule_delete_old_privacy_export_files() {
+	if ( ! wp_next_scheduled( 'wp_privacy_delete_old_export_files' ) ) {
+		wp_schedule_event( time(), 'hourly', 'wp_privacy_delete_old_export_files' );
+	}
+}
+
+/**
+ * Cleans up export files older than three days old.
+ *
+ * The export files are stored in `wp-content/uploads`, and are therefore publicly
+ * accessible. A CSPRN is appended to the filename to mitigate the risk of an
+ * unauthorized person downloading the file, but it is still possible. Deleting
+ * the file after the data subject has had a chance to delete it adds an additional
+ * layer of protection.
+ *
+ * @since 4.9.6
+ */
+function wp_privacy_delete_old_export_files() {
+	$upload_dir   = wp_upload_dir();
+	$exports_dir  = trailingslashit( $upload_dir['basedir'] . '/exports' );
+	$export_files = list_files( $exports_dir, 100, array( 'index.html' ) );
+
+	/**
+	 * Filters the lifetime, in seconds, of a personal data export file.
+	 *
+	 * By default, the lifetime is 3 days. Once the file reaches that age, it will automatically
+	 * be deleted by a cron job.
+	 *
+	 * @since 4.9.6
+	 *
+	 * @param int $expiration The expiration age of the export, in seconds.
+	 */
+	$expiration = apply_filters( 'wp_privacy_export_expiration', 3 * DAY_IN_SECONDS );
+
+	foreach ( (array) $export_files as $export_file ) {
+		$file_age_in_seconds = time() - filemtime( $export_file );
+
+		if ( $expiration < $file_age_in_seconds ) {
+			unlink( $export_file );
+		}
+	}
+}
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 48790ee6ec..e3f2c895d1 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -4,7 +4,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '4.9.6-alpha-43094';
+$wp_version = '4.9.6-alpha-43095';
 
 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.