I have been tasked to add full unicode support inside our software.
We use Curl to send request to the server, and I am very new to php.
We want to support this type of email:
沙发模型@gmail.com
I tried to create accounts with that name and it fails for both gmail and outlook. But before dropping the feature i need to be 100% sure only utf-8 emails are allowed worldwide. So i want to support wide strings not just utf-8.
Our test database table look like this:

Here how an user is registered:
$result = mysqli_query($this->m_conn, "INSERT INTO ".self::TABLE_NAME."(EMAIL, LICENSE_KEYS, COMPUTER_CODES, IPS) VALUES ('$email', '$license', 'null', 'null')");
if (!$result)
Logger::ExitWithMessage($email, "DB: unable to insert user. SQL error:". mysqli_error($this->m_conn));
If i try to add a chinese user to our test table:
$robertoEmail = "roberto_沙发模型@hotmail.com";
$robertoLicense = "371C-5BE3-6EF4-9DBC-7F65";
$result = mysqli_query($this->m_conn, "INSERT INTO ".self::TABLE_NAME."(EMAIL, LICENSE_KEYS, COMPUTER_CODES, IPS) VALUES ('$robertoEmail', '$robertoLicense', 'null', 'null')");
if (!$result)
Logger::ExitWithMessage($robertoEmail, "DB: unable to insert user. SQL error:". mysqli_error($this->m_conn));
When I check the table, I get this “roberto_æ²™å‘æ¨¡åž‹@hotmail.com” as the email:

The email stored in the database is broken. But something strange i query the table with the roberto user(roberto_沙发模型@hotmail.com) it works:
$robertoEmail = "roberto_沙发模型@hotmail.com";
$query = mysqli_query($this->m_conn, "SELECT * FROM `". self::TABLE_NAME. "` WHERE EMAIL='$robertoEmail'");
if (!$query)
Logger::ExitWithMessage($email, "DB: Can't select. SQL error:". mysqli_error($this->m_conn));
$user = mysqli_fetch_array($query);
mysqli_free_result($query);
if (!$user)
{
error_log("GetUser failed");
return;
}
// Everything worked!
Even more strange if i try to manually add roberto to the table:
INSERT INTO `LICENSES_TABLE`(`EMAIL`, `LICENSE_KEYS`, `COMPUTER_CODES`, `IPS`) VALUES ('roberto_沙发模型@hotmail.com', '371C-5BE3-6EF4-9DBC-7F65', 'null', 'null')
I get this:

The email is reported as “[email protected]”.
How to properly support unicode emails in a mysqli based server?
Thanks!
While it is not relevant. Here how our C++ application send request to the server
RequestResult NetWork::sendRequest(const bool isPost, const std::string& relativeUri, const std::string& body) const
{
CURL* handle = curl_easy_init();
if (!handle)
return RequestResult();
/* First set the URL that is about to receive our POST. This URL can
* just as well be a https:// URL if that is what should receive the
* data.
*/
curl_easy_setopt(handle, CURLOPT_URL, ("https://www.mywebsite.com/" + relativeUri).c_str());
// Skip SSL verification.
// Not required when server use a certificate signed by a trusted CA.
// @See: https://stackoverflow.com/questions/56739554/is-https-without-ssl-verification-secure-for-local-application
{
/*
* If you want to connect to a site who isn't using a certificate that is
* signed by one of the certs in the CA bundle you have, you can skip the
* verification of the server's certificate. This makes the connection
* A LOT LESS SECURE.
*
* If you have a CA cert for the server stored someplace else than in the
* default bundle, then the CURLOPT_CAPATH option might come handy for
* you.
*/
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L);
/*
* If the site you're connecting to uses a different host name that what
* they have mentioned in their server certificate's commonName (or
* subjectAltName) fields, libcurl will refuse to connect. You can skip
* this check, but this will make the connection less secure.
*/
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L);
}
// Specify the request type
curl_easy_setopt(handle, CURLOPT_POST, (int)isPost);
// Specify the body
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, body.c_str());
// Specify the write callbaks
RequestResult requestResult;
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &requestResult.res);
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
// Perform the request
const CURLcode res = curl_easy_perform(handle);
// Check result
if (res == CURLE_OK)
{
long http_code = 0;
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_code);
requestResult.success = http_code < 400;
}
else
{
_TRACE(requestResult.res);
}
// Cleanup
curl_easy_cleanup(handle);
return requestResult;
}
As you can see in the declaration the body is a std::string not a wide string. I dont know how it magically works but if email is (roberto_沙发模型@hotmail.com) then the sendRequest body contains (roberto_æ²™å‘æ¨¡åž‹@hotmail.com). The request is sent and the server understand that the real email is (roberto_沙发模型@hotmail.com)
