diff --git src/wp-includes/pluggable.php src/wp-includes/pluggable.php
index 5edd0c760c..0cb207172b 100644
--- src/wp-includes/pluggable.php
+++ src/wp-includes/pluggable.php
@@ -233,42 +233,6 @@ if ( ! function_exists( 'wp_mail' ) ) :
 			return $pre_wp_mail;
 		}
 
-		if ( isset( $atts['to'] ) ) {
-			$to = $atts['to'];
-		}
-
-		if ( ! is_array( $to ) ) {
-			$to = explode( ',', $to );
-		}
-
-		if ( isset( $atts['subject'] ) ) {
-			$subject = $atts['subject'];
-		}
-
-		if ( isset( $atts['message'] ) ) {
-			$message = $atts['message'];
-		}
-
-		if ( isset( $atts['headers'] ) ) {
-			$headers = $atts['headers'];
-		}
-
-		if ( isset( $atts['attachments'] ) ) {
-			$attachments = $atts['attachments'];
-		}
-
-		if ( ! is_array( $attachments ) ) {
-			$attachments = explode( "\n", str_replace( "\r\n", "\n", $attachments ) );
-		}
-
-		if ( isset( $atts['embeds'] ) ) {
-			$embeds = $atts['embeds'];
-		}
-
-		if ( ! is_array( $embeds ) ) {
-			$embeds = explode( "\n", str_replace( "\r\n", "\n", $embeds ) );
-		}
-
 		global $phpmailer;
 
 		// (Re)create it, if it's gone missing.
@@ -284,10 +248,15 @@ if ( ! function_exists( 'wp_mail' ) ) :
 			};
 		}
 
-		// Headers.
+		// Process Headers First.
 		$cc       = array();
 		$bcc      = array();
 		$reply_to = array();
+		$charset  = get_bloginfo( 'charset' );
+
+		if ( isset( $atts['headers'] ) ) {
+			$headers = $atts['headers'];
+		}
 
 		if ( empty( $headers ) ) {
 			$headers = array();
@@ -323,25 +292,6 @@ if ( ! function_exists( 'wp_mail' ) ) :
 
 					switch ( strtolower( $name ) ) {
 						// Mainly for legacy -- process a "From:" header if it's there.
-						case 'from':
-							$bracket_pos = strpos( $content, '<' );
-							if ( false !== $bracket_pos ) {
-								// Text before the bracketed email is the "From" name.
-								if ( $bracket_pos > 0 ) {
-									$from_name = substr( $content, 0, $bracket_pos );
-									$from_name = str_replace( '"', '', $from_name );
-									$from_name = trim( $from_name );
-								}
-
-								$from_email = substr( $content, $bracket_pos + 1 );
-								$from_email = str_replace( '>', '', $from_email );
-								$from_email = trim( $from_email );
-
-								// Avoid setting an empty $from_email.
-							} elseif ( '' !== trim( $content ) ) {
-								$from_email = trim( $content );
-							}
-							break;
 						case 'content-type':
 							if ( str_contains( $content, ';' ) ) {
 								list( $type, $charset_content ) = explode( ';', $content );
@@ -350,7 +300,6 @@ if ( ! function_exists( 'wp_mail' ) ) :
 									$charset = trim( str_replace( array( 'charset=', '"' ), '', $charset_content ) );
 								} elseif ( false !== stripos( $charset_content, 'boundary=' ) ) {
 									$boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '"' ), '', $charset_content ) );
-									$charset  = '';
 								}
 
 								// Avoid setting an empty $content_type.
@@ -358,14 +307,25 @@ if ( ! function_exists( 'wp_mail' ) ) :
 								$content_type = trim( $content );
 							}
 							break;
+						case 'from':
+							if ( ! empty( $content ) ) {
+								$addresses = $phpmailer->parseAddresses( $content, null, $charset );
+								if ( ! empty( $addresses[0]['name'] ) ) {
+									$from_name = $addresses[0]['name'];
+								}
+								if ( ! empty( $addresses[0]['address'] ) ) {
+									$from_email = $addresses[0]['address'];
+								}
+							}
+							break;
 						case 'cc':
-							$cc = array_merge( (array) $cc, explode( ',', $content ) );
+							$cc = array_merge( (array) $cc, $phpmailer->parseAddresses( $content, null, $charset ) );
 							break;
 						case 'bcc':
-							$bcc = array_merge( (array) $bcc, explode( ',', $content ) );
+							$bcc = array_merge( (array) $bcc, $phpmailer->parseAddresses( $content, null, $charset ) );
 							break;
 						case 'reply-to':
-							$reply_to = array_merge( (array) $reply_to, explode( ',', $content ) );
+							$reply_to = array_merge( (array) $reply_to, $phpmailer->parseAddresses( $content, null, $charset ) );
 							break;
 						default:
 							// Add it to our grand headers array.
@@ -376,6 +336,38 @@ if ( ! function_exists( 'wp_mail' ) ) :
 			}
 		}
 
+		if ( isset( $atts['to'] ) ) {
+			$to = $atts['to'];
+		}
+
+		if ( ! is_array( $to ) ) {
+			$to = $phpmailer->parseAddresses( $to, null, $charset );
+		}
+
+		if ( isset( $atts['subject'] ) ) {
+			$subject = $atts['subject'];
+		}
+
+		if ( isset( $atts['message'] ) ) {
+			$message = $atts['message'];
+		}
+
+		if ( isset( $atts['attachments'] ) ) {
+			$attachments = $atts['attachments'];
+		}
+
+		if ( ! is_array( $attachments ) ) {
+			$attachments = explode( "\n", str_replace( "\r\n", "\n", $attachments ) );
+		}
+
+		if ( isset( $atts['embeds'] ) ) {
+			$embeds = $atts['embeds'];
+		}
+
+		if ( ! is_array( $embeds ) ) {
+			$embeds = explode( "\n", str_replace( "\r\n", "\n", $embeds ) );
+		}
+
 		// Empty out the values that may be set.
 		$phpmailer->clearAllRecipients();
 		$phpmailer->clearAttachments();
@@ -457,14 +449,8 @@ if ( ! function_exists( 'wp_mail' ) ) :
 			foreach ( (array) $addresses as $address ) {
 				try {
 					// Break $recipient into name and address parts if in the format "Foo <bar@baz.com>".
-					$recipient_name = '';
-
-					if ( preg_match( '/(.*)<(.+)>/', $address, $matches ) ) {
-						if ( count( $matches ) === 3 ) {
-							$recipient_name = $matches[1];
-							$address        = $matches[2];
-						}
-					}
+					$recipient_name = $address['name'] ?? '';
+					$address        = $address['address'];
 
 					switch ( $address_header ) {
 						case 'to':
@@ -489,7 +475,7 @@ if ( ! function_exists( 'wp_mail' ) ) :
 		// Set to use PHP's mail().
 		$phpmailer->isMail();
 
-		// Set Content-Type and charset.
+		// Set Content-Type and Charset.
 
 		// If we don't have a Content-Type from the input headers.
 		if ( ! isset( $content_type ) ) {
@@ -512,11 +498,6 @@ if ( ! function_exists( 'wp_mail' ) ) :
 			$phpmailer->isHTML( true );
 		}
 
-		// If we don't have a charset from the input headers.
-		if ( ! isset( $charset ) ) {
-			$charset = get_bloginfo( 'charset' );
-		}
-
 		/**
 		 * Filters the default wp_mail() charset.
 		 *
diff --git tests/phpunit/tests/pluggable/wpMail.php tests/phpunit/tests/pluggable/wpMail.php
index 85e3b46f61..dd452400c4 100644
--- tests/phpunit/tests/pluggable/wpMail.php
+++ tests/phpunit/tests/pluggable/wpMail.php
@@ -441,7 +441,7 @@ class Tests_Pluggable_wpMail extends WP_UnitTestCase {
 		$this->assertSame( 1, $ma->get_call_count() );
 
 		$expected_error_data = array(
-			'to'                       => array( 'an_invalid_address' ),
+			'to'                       => array(),
 			'subject'                  => 'Testing',
 			'message'                  => 'Test Message',
 			'headers'                  => array(),
@@ -625,4 +625,17 @@ class Tests_Pluggable_wpMail extends WP_UnitTestCase {
 			$this->assertStringContainsString( 'cid:' . $key, $mailer->get_sent()->body, 'The cid ' . $key . ' is not referenced in the mail body.' );
 		}
 	}
+	/**
+	 * @ticket 62940
+	 */
+	public function test_wp_mail_single_line_utf8_header() {
+		$headers = 'From: =?UTF-8?B?VGVzdA==?= <test@example.com>';
+		wp_mail( 'test@test.com', 'subject', 'message', $headers );
+
+		$mailer = tests_retrieve_phpmailer_instance();
+		// phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
+		$this->assertSame( 'test@example.com', $mailer->From );
+		$this->assertSame( 'Test', $mailer->FromName );
+		// phpcs:enable
+	}
 }
