Index: src/wp-includes/class-wp-recovery-mode-email-service.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/wp-includes/class-wp-recovery-mode-email-service.php	(revision 45315)
+++ src/wp-includes/class-wp-recovery-mode-email-service.php	(date 1557968502000)
@@ -23,6 +23,13 @@
 	 */
 	private $link_service;
 
+	/**
+	 *
+	 * @since 5.3.0
+	 * @var string
+	 */
+	private $recovery_mode_email_address;
+
 	/**
 	 * WP_Recovery_Mode_Email_Service constructor.
 	 *
@@ -32,6 +39,7 @@
 	 */
 	public function __construct( WP_Recovery_Mode_Link_Service $link_service ) {
 		$this->link_service = $link_service;
+		$this->setup_recovery_mode_email_address();
 	}
 
 	/**
@@ -47,7 +55,7 @@
 	 * }
 	 * @return true|WP_Error True if email sent, WP_Error otherwise.
 	 */
-	public function maybe_send_recovery_mode_email( $rate_limit, $error, $extension ) {
+	public function maybe_send_recovery_mode_email( $rate_limit = 0, $error = array(), $extension = array(0) ) {
 
 		$last_sent = get_option( self::RATE_LIMIT_OPTION );
 
@@ -203,19 +211,16 @@
 		return $sent;
 	}
 
+
 	/**
-	 * Gets the email address to send the recovery mode link to.
 	 *
-	 * @since 5.2.0
-	 *
-	 * @return string Email address to send recovery mode link to.
 	 */
-	private function get_recovery_mode_email_address() {
+	private function setup_recovery_mode_email_address() {
 		if ( defined( 'RECOVERY_MODE_EMAIL' ) && is_email( RECOVERY_MODE_EMAIL ) ) {
-			return RECOVERY_MODE_EMAIL;
+			$this->recovery_mode_email_address =  RECOVERY_MODE_EMAIL;
 		}
 
-		return get_option( 'admin_email' );
+		$this->recovery_mode_email_address = get_option( 'admin_email' );
 	}
 
 	/**
@@ -265,4 +270,24 @@
 
 		return $cause;
 	}
+
+	/**
+	 * Gets the email address to send the recovery mode link to.
+	 *
+	 * @since 5.2.0
+	 *
+	 * @return string Email address to send recovery mode link to.
+	 */
+	private function get_recovery_mode_email_address() {
+		return $this->recovery_mode_email_address;
+	}
+
+	/**
+	 * @param string $recovery_mode_email_address
+	 */
+	public function set_recovery_mode_email_address( $recovery_mode_email_address ) {
+		$this->recovery_mode_email_address = $recovery_mode_email_address;
+	}
+
+
 }
Index: src/wp-includes/class-wp-recovery-mode.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/wp-includes/class-wp-recovery-mode.php	(revision 45315)
+++ src/wp-includes/class-wp-recovery-mode.php	(date 1557968220000)
@@ -464,4 +464,11 @@
 		wp_safe_redirect( $url );
 		exit;
 	}
+
+	/**
+	 * @return WP_Recovery_Mode_Email_Service
+	 */
+	public function get_email_service() {
+		return $this->email_service;
+	}
 }
Index: src/wp-login.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/wp-login.php	(revision 45315)
+++ src/wp-login.php	(date 1557968634000)
@@ -8,6 +8,13 @@
  * @package WordPress
  */
 
+$action_check = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'login';
+$recovery_actions = array( 'recovery_request', 'recovery_recieved' );
+if ( in_array( $action_check, $recovery_actions, true ) && ! defined( 'WP_RECOVERY_MODE_SESSION_ID' ) ) {
+	define( 'WP_RECOVERY_MODE_SESSION_ID', '1123456' );
+}
+
+
 /** Make sure that the WordPress bootstrap has run before continuing. */
 require( dirname( __FILE__ ) . '/wp-load.php' );
 
@@ -432,6 +439,50 @@
 	return true;
 }
 
+/**
+ * Handles sending recovery_link retrieval email to user.
+ *
+ * @since 5.3.0
+ *
+ * @return bool|WP_Error True: when finish. WP_Error on error
+ */
+function retrieve_recovery_link() {
+    $errors = new WP_Error();
+
+    if ( empty( $_POST['user_login'] ) || ! is_string( $_POST['user_login'] ) ) {
+        $errors->add( 'empty_username', __( '<strong>ERROR</strong>: Enter a username or email address.' ) );
+    } elseif ( strpos( $_POST['user_login'], '@' ) ) {
+        $user_data = get_user_by( 'email', trim( wp_unslash( $_POST['user_login'] ) ) );
+        if ( empty( $user_data ) ) {
+            $errors->add( 'invalid_email', __( '<strong>ERROR</strong>: There is no account with that username or email address.' ) );
+        }
+    } else {
+        $login     = trim( $_POST['user_login'] );
+        $user_data = get_user_by( 'login', $login );
+    }
+
+    if ( $errors->has_errors() ) {
+        return $errors;
+    }
+
+    if ( ! $user_data ) {
+        $errors->add( 'invalidcombo', __( '<strong>ERROR</strong>: There is no account with that username or email address.' ) );
+
+        return $errors;
+    }
+
+    if ( ! user_can( $user_data, 'resume_plugins' ) && user_can( $user_data, 'resume_themes' ) ) {
+        $errors->add( 'invaliduser', __( '<strong>ERROR</strong>: This account is unable to access recovery mode.' ) );
+
+        return $errors;
+    }
+
+    wp_recovery_mode()->get_email_service()->set_recovery_mode_email_address( $user_data->user_email );
+    wp_recovery_mode()->get_email_service()->maybe_send_recovery_mode_email( 0, array(), array() );
+
+    return true;
+}
+
 //
 // Main.
 //
@@ -444,7 +495,7 @@
 }
 
 // Validate action so as to default to the login screen.
-if ( ! in_array( $action, array( 'postpass', 'logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login', 'confirmaction', WP_Recovery_Mode_Link_Service::LOGIN_ACTION_ENTERED ), true ) && false === has_filter( 'login_form_' . $action ) ) {
+if ( ! in_array( $action, array( 'postpass', 'logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login', 'confirmaction', 'recovery_request', 'recovery_recieved', WP_Recovery_Mode_Link_Service::LOGIN_ACTION_ENTERED ), true ) && false === has_filter( 'login_form_' . $action ) ) {
 	$action = 'login';
 }
 
@@ -626,26 +677,94 @@
 		<input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
 		<p class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Get New Password' ); ?>" /></p>
 	</form>
+
+	<p id="nav">
+	<a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
+		<?php
+		if ( get_option( 'users_can_register' ) ) :
+			$registration_url = sprintf( '<a href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
+
+			echo esc_html( $login_link_separator );
+
+			/** This filter is documented in wp-includes/general-template.php */
+			echo apply_filters( 'register', $registration_url );
+	endif;
+		?>
+	</p>
+
+		<?php
+		login_footer( 'user_login' );
+
+		break;
+	case 'recovery_recieved':
+
+		$message = '<p class="message">' . __( 'Check your email for the recovery link.' ) . '</p>';
+
+		login_header( __( 'User action confirmed.' ), $message );
+		login_footer();
+		exit;
+
+	case 'recovery_request':
+		if ( $http_post ) {
+			$errors = retrieve_recovery_link();
+			if ( ! is_wp_error( $errors ) ) {
+				$redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : 'wp-login.php?checkemail=confirm';
+				wp_safe_redirect( $redirect_to );
+				exit();
+			}
+		}
+
+		$recovery_request_redirect = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
+		/**
+		 * Filters the URL redirected to after submitting the recovery_request form.
+		 *
+		 * @since 5.3.0
+		 *
+		 * @param string $recovery_request The redirect destination URL.
+		 */
+		$redirect_to = apply_filters( 'recovery_request_redirect', $recovery_request_redirect );
+
+
+
+		login_header( __( 'Lost Password' ), '<p class="message">' . __( 'Please enter your username or email address. You will receive a recovery link via email.' ) . '</p>', $errors );
+
+		$user_login = '';
+
+		if ( isset( $_POST['user_login'] ) && is_string( $_POST['user_login'] ) ) {
+			$user_login = wp_unslash( $_POST['user_login'] );
+		}
+
+		?>
+
+        <form name="recovery_request" id="recovery_request" action="<?php echo esc_url( site_url( 'wp-login.php?action=recovery_request', 'recovery_request' ) ); ?>" method="post">
+            <p>
+                <label for="user_login" ><?php _e( 'Username or Email Address' ); ?><br />
+                    <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" /></label>
+            </p>
+            <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
+            <p class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Request recovery email' ); ?>" /></p>
+        </form>
 
-	<p id="nav">
-	<a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
-		<?php
-		if ( get_option( 'users_can_register' ) ) :
-			$registration_url = sprintf( '<a href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
+        <p id="nav">
+            <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
+			<?php
+			if ( get_option( 'users_can_register' ) ) :
+				$registration_url = sprintf( '<a href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
 
-			echo esc_html( $login_link_separator );
+				echo esc_html( $login_link_separator );
 
-			/** This filter is documented in wp-includes/general-template.php */
-			echo apply_filters( 'register', $registration_url );
-	endif;
-		?>
-	</p>
+				/** This filter is documented in wp-includes/general-template.php */
+				echo apply_filters( 'register', $registration_url );
+			endif;
+			?>
+        </p>
 
 		<?php
 		login_footer( 'user_login' );
 
 		break;
 
+		
 	case 'resetpass':
 	case 'rp':
 		list( $rp_path ) = explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) );
