Sending emails in Japanese language was a challenge for me. Any email, which had a subject in Japanese language failed and was not being sent at all. I tried encoding the email subject, but nothing worked. I tweaked things until i found a solution. I then re-defined the wordpress core wp_mail() function to allow sending emails with Japanese language in subject. My solution is given below:

//wp_mail redefined, to send japanese subject line in emails.

function wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ) {

	// Compact the input, apply the filters, and extract them back out

	/**

	 * Filter the wp_mail() arguments.

	 *

	 * @since 2.2.0

	 *

	 * @param array $args A compacted array of wp_mail() arguments, including the "to" email,

	 *                    subject, message, headers, and attachments values.

	 */

	$atts = apply_filters( 'wp_mail', compact( 'to', 'subject', 'message', 'headers', 'attachments' ) );

	if ( isset( $atts['to'] ) ) {

		$to = $atts['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 ) );

	}

	global $phpmailer;

	// (Re)create it, if it's gone missing

	if ( !is_object( $phpmailer ) || !is_a( $phpmailer, 'PHPMailer' ) ) {

		require_once ABSPATH . WPINC . '/class-phpmailer.php';

		require_once ABSPATH . WPINC . '/class-smtp.php';

		$phpmailer = new PHPMailer( true );

	}

	// Headers

	if ( empty( $headers ) ) {

		$headers = array();

	} else {

		if ( !is_array( $headers ) ) {

			// Explode the headers out, so this function can take both

			// string headers and an array of headers.

			$tempheaders = explode( "\n", str_replace( "\r\n", "\n", $headers ) );

		} else {

			$tempheaders = $headers;

		}

		$headers = array();

		$cc = array();

		$bcc = array();

		// If it's actually got contents

		if ( !empty( $tempheaders ) ) {

			// Iterate through the raw headers

			foreach ( (array) $tempheaders as $header ) {

				if ( strpos($header, ':') === false ) {

					if ( false !== stripos( $header, 'boundary=' ) ) {

						$parts = preg_split('/boundary=/i', trim( $header ) );

						$boundary = trim( str_replace( array( "'", '"' ), '', $parts[1] ) );

					}

					continue;

				}

				// Explode them out

				list( $name, $content ) = explode( ':', trim( $header ), 2 );

				// Cleanup crew

				$name    = trim( $name    );

				$content = trim( $content );

				switch ( strtolower( $name ) ) {

					// Mainly for legacy -- process a From: header if it's there

					case 'from':

						if ( strpos($content, '<' ) !== false ) {

							// So... making my life hard again?

							$from_name = substr( $content, 0, strpos( $content, '<' ) - 1 );

							$from_name = str_replace( '"', '', $from_name );

							$from_name = trim( $from_name );

							$from_email = substr( $content, strpos( $content, '<' ) + 1 ); 							$from_email = str_replace( '>', '', $from_email );

							$from_email = trim( $from_email );

						} else {

							$from_email = trim( $content );

						}

						break;

					case 'content-type':

						if ( strpos( $content, ';' ) !== false ) {

							list( $type, $charset ) = explode( ';', $content );

							$content_type = trim( $type );

							if ( false !== stripos( $charset, 'charset=' ) ) {

								$charset = trim( str_replace( array( 'charset=', '"' ), '', $charset ) );

							} elseif ( false !== stripos( $charset, 'boundary=' ) ) {

								$boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '"' ), '', $charset ) );

								$charset = '';

							}

						} else {

							$content_type = trim( $content );

						}

						break;

					case 'cc':

						$cc = array_merge( (array) $cc, explode( ',', $content ) );

						break;

					case 'bcc':

						$bcc = array_merge( (array) $bcc, explode( ',', $content ) );

						break;

					default:

						// Add it to our grand headers array

						$headers[trim( $name )] = trim( $content );

						break;

				}

			}

		}

	}

	// Empty out the values that may be set

	$phpmailer->ClearAllRecipients();

	$phpmailer->ClearAttachments();

	$phpmailer->ClearCustomHeaders();

	$phpmailer->ClearReplyTos();

	// From email and name

	// If we don't have a name from the input headers

	if ( !isset( $from_name ) )

		$from_name = 'WordPress';

	/* If we don't have an email from the input headers default to wordpress@$sitename

	 * Some hosts will block outgoing mail from this address if it doesn't exist but

	 * there's no easy alternative. Defaulting to admin_email might appear to be another

	 * option but some hosts may refuse to relay mail from an unknown domain. See

	 * https://core.trac.wordpress.org/ticket/5007.

	 */

	if ( !isset( $from_email ) ) {

		// Get the site domain and get rid of www.

		$sitename = strtolower( $_SERVER['SERVER_NAME'] );

		if ( substr( $sitename, 0, 4 ) == 'www.' ) {

			$sitename = substr( $sitename, 4 );

		}

		$from_email = 'wordpress@' . $sitename;

	}

	/**

	 * Filter the email address to send from.

	 *

	 * @since 2.2.0

	 *

	 * @param string $from_email Email address to send from.

	 */

	$phpmailer->From = apply_filters( 'wp_mail_from', $from_email );

	/**

	 * Filter the name to associate with the "from" email address.

	 *

	 * @since 2.3.0

	 *

	 * @param string $from_name Name associated with the "from" email address.

	 */

	$phpmailer->FromName = apply_filters( 'wp_mail_from_name', $from_name );

	// Set destination addresses

	if ( !is_array( $to ) )

		$to = explode( ',', $to );

	foreach ( (array) $to as $recipient ) {

		try {

			// Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"

			$recipient_name = '';

			if( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) {

				if ( count( $matches ) == 3 ) {

					$recipient_name = $matches[1];

					$recipient = $matches[2];

				}

			}

			$phpmailer->AddAddress( $recipient, $recipient_name);

		} catch ( phpmailerException $e ) {

			continue;

		}

	}

	// Set mail's subject and body

	$phpmailer->Subject = $subject;

// Convert Japanese subject to ISO-2022-JP (JIS is essentially ISO-2022-JP)

 $subject = mb_convert_encoding ($subject, "JIS", "AUTO");

 // Now, base64 encode the subject

 $subject = base64_encode ($subject);

 // Add the encoding markers to the subject

 $subject = "=?iso-2022-jp?B?" . $subject . "?=";

 // Now, $subject can be placed as-is into the raw mail header.

$phpmailer->Subject = $subject;

	$phpmailer->Body    = $message;

	// Add any CC and BCC recipients

	if ( !empty( $cc ) ) {

		foreach ( (array) $cc as $recipient ) {

			try {

				// Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"

				$recipient_name = '';

				if( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) {

					if ( count( $matches ) == 3 ) {

						$recipient_name = $matches[1];

						$recipient = $matches[2];

					}

				}

				$phpmailer->AddCc( $recipient, $recipient_name );

			} catch ( phpmailerException $e ) {

				continue;

			}

		}

	}

	if ( !empty( $bcc ) ) {

		foreach ( (array) $bcc as $recipient) {

			try {

				// Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"

				$recipient_name = '';

				if( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) {

					if ( count( $matches ) == 3 ) {

						$recipient_name = $matches[1];

						$recipient = $matches[2];

					}

				}

				$phpmailer->AddBcc( $recipient, $recipient_name );

			} catch ( phpmailerException $e ) {

				continue;

			}

		}

	}

	// Set to use PHP's mail()

	$phpmailer->IsMail();

	// Set Content-Type and charset

	// If we don't have a content-type from the input headers

	if ( !isset( $content_type ) )

		$content_type = 'text/html';

	/**

	 * Filter the wp_mail() content type.

	 *

	 * @since 2.3.0

	 *

	 * @param string $content_type Default wp_mail() content type.

	 */

	$content_type = apply_filters( 'wp_mail_content_type', $content_type );

	$phpmailer->ContentType = "text/plain";

	// Set whether it's plaintext, depending on $content_type

	if ( 'text/html' == $content_type )

		$phpmailer->IsHTML( true );

	// If we don't have a charset from the input headers

	if ( !isset( $charset ) )

		$charset = get_bloginfo( 'charset' );

		$charset ='UTF-8';

	// Set the content-type and charset

	/**

	 * Filter the default wp_mail() charset.

	 *

	 * @since 2.3.0

	 *

	 * @param string $charset Default email charset.

	 */

	$phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );

	$phpmailer->CharSet ='UTF-8';

	// Set custom headers

	if ( !empty( $headers ) ) {

		foreach( (array) $headers as $name => $content ) {

			$phpmailer->AddCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );

		}

		if ( false !== stripos( $content_type, 'multipart' ) && ! empty($boundary) )

			$phpmailer->AddCustomHeader( sprintf( "Content-Type: %s;\n\t boundary=\"%s\"", $content_type, $boundary ) );

	}

	if ( !empty( $attachments ) ) {

		foreach ( $attachments as $attachment ) {

			try {

				$phpmailer->AddAttachment($attachment);

			} catch ( phpmailerException $e ) {

				continue;

			}

		}

	}

	/**

	 * Fires after PHPMailer is initialized.

	 *

	 * @since 2.2.0

	 *

	 * @param PHPMailer &$phpmailer The PHPMailer instance, passed by reference.

	 */

	 $phpmailer->ContentType = "text/plain";

	do_action_ref_array( 'phpmailer_init', array( &$phpmailer ) );

	// Send!

	try {

		return $phpmailer->Send();

	} catch ( phpmailerException $e ) {

		return false;

	}

}

Happy coding!

Yumna Tatheer

I am a Computer Science graduate and a part time blogger from Lahore, Pakistan. I am a PHP programmer and a wordpress expert.

More Posts

Follow Me:
Facebook