PHP 8.3.4 Released!

mb_send_mail

(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)

mb_send_mailEnvoie un mail encodé

Description

mb_send_mail(
    string $to,
    string $subject,
    string $message,
    array|string $additional_headers = [],
    ?string $additional_params = null
): bool

Envoie un courrier électronique. Les en-têtes et le corps du message sont convertis et encodés en accord avec mb_language(). mb_send_mail() est une version adaptée de mail(). Voir la fonction mail() pour plus de détails.

Liste de paramètres

to

to est l'adresse de destination du mail. Les adresses multiples peuvent être spécifiées en les séparant par des virgules. Ce paramètre n'est pas encodé automatiquement.

subject

Le sujet du mail.

message

Le message du mail.

additional_headers (optionnel)

chaîne de caractères ou tableau à insérer à la fin de l'en-tête mail.

Ce paramètre est typiquement utilisé pour ajouter des en-têtes supplémentaires (From, Cc, and Bcc). Les différents ajouts doivent être séparés par un CRLF (\r\n). Ce paramètre doit être validé afin d'éviter d'injection d'en-tête non désiré par des personnes malveillantes.

Si un tableau est fourni, ses clés sont les noms des en-têtes et ses valeurs sont les valeurs respectives des en-têtes.

Note:

Lors de l'envoi d'un mail, il doit contenir un en-tête From. Il peut être défini via le paramètre additional_headers ou en tant que valeur par défaut dans le php.ini.

Si vous ne le faîtes pas, une erreur similaire à : Warning: mail(): "sendmail_from" not set in php.ini or custom "From:" header missing sera émise. L'en-tête From définie également Return-Path sous Windows.

Note:

Si les messages ne sont pas reçus, tentez d'utiliser uniquement un LF (\n). Quelques agents de transfère de mails Unix (en particulier » qmail) remplace un LF par un CRLF automatiquement (ce qui résulte en un doublement du CR si CRLF est utilisé). Vous devez tenter cette correction en dernier recourt, sachant qu'elle ne respecte pas la » RFC 2822.

additional_params

additional_params est une ligne de paramètres MTA. Il est pratique lorsque vous voulez définir un Return-Path correct lorsque vous utilisez sendmail.

Ce paramètre est échappé par la fonction escapeshellcmd() en interne afin de prévenir les exécutions de commande. La fonction escapeshellcmd() prévient d'exécution de commande, mais autorise les paramètres additionnels. Pour des raisons de sécurité, ce paramètre doit être validé.

Depuis que la fonction escapeshellcmd() est appliquée automatiquement en interne, quelques caractères autorisés dans les adresses mails par les RFCs d'internet ne peuvent plus être utilisés. Les programmes qui doivent utiliser ces caractères, la fonction mail() ne peut plus être utilisée.

L'utilisateur faisant fonctionner le serveur Web doit être ajouté comme utilisateur de confiance dans la configuration de l'envoi de mails afin d'éviter l'ajout d'un en-tête 'X-Warning' dans le message lorsque l'enveloppe de l'envoyeur (-f) est définie comme utilisant cette méthode. Pour les utilisateurs de sendmail, ce fichier se trouve en utilisant le chemin /etc/mail/trusted-users.

Valeurs de retour

Cette fonction retourne true en cas de succès ou false si une erreur survient.

Historique

Version Description
8.0.0 additional_params is nullable now.
7.2.0 Le paramètre additional_headers accepte désormais un tableau.

Voir aussi

add a note

User Contributed Notes 16 notes

up
1
gordon at kanazawa-gu dot ac dot jp
21 years ago
If your server doesn't have mb_send_mail() enabled but you want to use non-ascii (multi-byte) chars in an email's subject or name headers, you can use something like the following:

$charset = "iso-2202-jp"; // japanese
$to = encode("japanese name 01", $charset) . " <to@email.com>";
$from = encode("japanese name 02", $charset) . " <from@email.com>";
$subject = encode("japanese text", $charset);
$message = "does not need to be encoded";
mail($to, $subject, $message, $from);

function encode($in_str, $charset) {
$out_str = $in_str;
if ($out_str && $charset) {

// define start delimimter, end delimiter and spacer
$end = "?=";
$start = "=?" . $charset . "?B?";
$spacer = $end . "\r\n " . $start;

// determine length of encoded text within chunks
// and ensure length is even
$length = 75 - strlen($start) - strlen($end);
$length = floor($length/2) * 2;

// encode the string and split it into chunks
// with spacers after each chunk
$out_str = base64_encode($out_str);
$out_str = chunk_split($out_str, $length, $spacer);

// remove trailing spacer and
// add start and end delimiters
$spacer = preg_quote($spacer);
$out_str = preg_replace("/" . $spacer . "$/", "", $out_str);
$out_str = $start . $out_str . $end;
}
return $out_str;
}
// for details on Message Header Extensions
// for Non-ASCII Text see ...
// http://www.faqs.org/rfcs/rfc2047.html
up
-1
dynamis at skillup dot jp
20 years ago
# self-fix...
I posted "encode_mimeheader" workaround on the day before. But I found that the code depends on platforms. :(

In some platforms, hedders(after the header splited into two or more lines) will appear in the body content.
The cause is that 'there are some platforms where the translation from \n to \r\n is apparently done for you'.
# See the post by "leon at ietsmet dot nl" about mail function (23-Apr-2003).

Now, all you have to do is just changing the glue string from "\r\n " to "\n ".

function encode_mimeheader($str, $indent = 0, $encoding = 'utf-8', $mail_encoding = 'iso-2022-jp')
{
..... lefted out (all same).....
$str = join("\r\n ", $lines); // RFC 2047,822 say newline must be ^\r\n, not only\n
return $str;
}

should be below in some platform...

function encode_mimeheader($str, $indent = 0, $encoding = 'utf-8', $mail_encoding = 'iso-2022-jp')
{
..... lefted out (all same).....
$str = join("\n ", $lines);
// Though RFC 2047,822 say newline must be \r\n, not only \n,
// in my platform, auto replacement will be done (accepts \n and \n\r\n -> \n\n)...
return $str;
}

# notice: In both code, 1 space after newline is essential (gule str is *not* only "\r\n" nor "\n").
# This space is ignored only between encoded-words.

c.f. about efficiency

Thinking about efficiency, my encode_mimeheader may have to determine where to split string into lines without mb_encode_mimeheader in the determining loop. But that loop will be repeated only one or a few times and this function will be usually used against not so long string. So, this loss is not critical in most case.
If you use only one encoding, you can easily check ascii or multi-byte char one by one accoding to the definition of the encoding and determining splitting point (this is far faster), but when you have to handle all encoding that is not so easy. At least, I don't want to touch. :p
To accept *any* encoding (encoding name will be passed as argument), you can use this code. This is because I post non-efficient code like this.
# Though I'm not sure whether the code actually work well with all encoding...
up
-1
RE: N03L in Japan
20 years ago
I have to use Japanese hankaku (single byte kana in (S)JIS) in mail subject and message,
so I tried the way that NO3L in Japan said, but I found there's a big problem.
In that way, mb_encode_mimeheader drop escape sequence from the head of encoded string from second line.
if you use long letter in subject, and if it includes multi byte string, It must crashed.
Therefore, if you want to use Japanese hankaku in mail subject, you might try like this.
Encoded subject letters in one line is not just 76 letters, so it is not based on RFC, but it work.

$intSubjectLength = mb_strlen($strSubject);
$intSeparateLength = 10;
for ($i=0; $i<ceil($intSubjectLength / $intSeparateLength); $i++) {
$arrSeparatedSubject[$i] = mb_substr($strSubject, $intIndex, $intSeparateLength);
$arrSeparatedSubject[$i] = mb_encode_mimeheader(mb_convert_encoding($arrSeparatedSubject[$i], "JIS", "EUC-JP"));
$intIndex = $intIndex + $intSeparateLength;
}
$strSubject = join("\n ", $arrSeparatedSubject);
up
-2
bredfern at calarts dot edu
19 years ago
Make sure that if you're using a form to type in the mail, that your form page has the right encoding, like if I want to send out a japanese email, by filling out a form, the form page needs this in the header:
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=SHIFT-JIS">
up
-3
Sohel Taslim
16 years ago
Easy and simple....
Send an email with Japanese contain.

<?php

/**
* @name : sendMail
* @author Taslim Mazumder Sohel
* @mailsohel62@yahoo.com
* Function for sending email
*with Japanese Email Body, Subject, Sender Name.
*
* @param String $to : Receiver mail address.
* @param String $subject : email subject.
* @param int $body : mail body text.
* @param array $from_email : Sender mail address.
* @param array $from_name : Sender Name.
*
*/
function sendMail($to, $subject, $body, $from_email,$from_name)
{
$headers = "MIME-Version: 1.0 \n" ;
$headers .= "From: " .
"".mb_encode_mimeheader (mb_convert_encoding($from_name,"ISO-2022-JP","AUTO")) ."" .
"<".$from_email."> \n";
$headers .= "Reply-To: " .
"".mb_encode_mimeheader (mb_convert_encoding($from_name,"ISO-2022-JP","AUTO")) ."" .
"<".$from_email."> \n";


$headers .= "Content-Type: text/plain;charset=ISO-2022-JP \n";


/* Convert body to same encoding as stated
in Content-Type header above */

$body = mb_convert_encoding($body, "ISO-2022-JP","AUTO");

/* Mail, optional paramiters. */
$sendmail_params = "-f$from_email";

mb_language("ja");
$subject = mb_convert_encoding($subject, "ISO-2022-JP","AUTO");
$subject = mb_encode_mimeheader($subject);

$result = mail($to, $subject, $body, $headers, $sendmail_params);

return
$result;
}

?>
up
-2
jc AT mega-bucks DOT co DOT jp
21 years ago
I was trying to send japanese email and had a hell of a time getting it to work. I finally stumbled across mb_send_mail() and it did everything I wanted *except* that it only send plain text emails ... sending HTML contents was impossible.

I finally whipped this up. I'm posting in case someone finds it useful.

function send_japanese_mail($to, $subject, $body, $from, $from_email, $is_html_content=false) {

$headers = "MIME-Version: 1.0\\n" ;
$headers .= "From: $from <$from_email>\\n";
$headers .= "Reply-To: $from <$from_email>\\n";

/* If the body is HTML or plain text set the Content-Type header accordingly */

if ($is_html_content) {
$headers .= "Content-Type: text/html;charset=ISO-2022-JP\\n";
/* turn all line breaks into BR tags */
$body = nl2br($body);
}
else {
$headers .= "Content-Type: text/plain;charset=ISO-2022-JP\\n";
}

/* need to convert body to same encoding as stated in Content-Type header above */

$body = mb_convert_encoding($body, "ISO-2022-JP","AUTO");

/* set any sendmail params, optional ... */
$sendmail_params = "-f$from_email";

/*
The subject is actually a "header" and can/will get mangled
if it contains non-ASCII characters. So we need to convert
the subject to something containing only ASCII characters.

First we convert the subject to the same encoding as the
body, then we use mb_encode_mimeheader() to make the subject
line all ASCII characters.
*/

mb_language("ja");
$subject = mb_convert_encoding($subject, "ISO-2022-JP","AUTO");
$subject = mb_encode_mimeheader($subject);

mail($to, $subject, $body, $headers, $sendmail_params);
}
up
-2
no dot email dot address at example dot com
21 years ago
Tested with PHP 4.2.2 on Linux: Please note that if you're using Unicode (mb_language("uni")) and you attempt to send mail with mb_send_mail(), you will need to base64_encode() the message body - mb_send_mail() doesn't do that for you. It does, however, issue the correct message headers, so you don't need to worry about that.

Also note that neither mb_language() nor mb_send_mail() is able to convert your message to UTF-8. *You* need to provide the UTF-8-encoded (and base64-encoded) message, and then mb_send_mail() will issue the correct message headers.

Here's an example of sending an UTF-8-encoded message with mb_send_mail():

mb_language("uni");
$body = chunk_split(base64_encode("International characters"));
mb_send_mail("someone@example.com", "Subject", $body);

If the receiving mail client supports UTF-8 properly, you will be able to send messages that contain a mix of all kinds of characters (e.g., you could send Thai, Chinese, and Danish characters in the same message). Not all mail clients support UTF-8, though. At the time of writing, some of the more popular Windows email clients - Eudora and Pegasus Mail - don't. There are a number of email clients with working support for UTF-8. These include Outlook Express, KMail, Mozilla, Netscape 6/7, Sylpheed, Evolution and others.
up
-4
Anonymous
14 years ago
If you have problem using mb_send_mail to send utf-8 mails, you have to know the following things (I've spent hours on the net before finding the correct php code) :

- You have to use the mb_encode_mimeheader function on the sender name and on the recipient name (on names, not on emails !).
- Subject and message are automatically encoded.
- Add - at least - the following header :

$headers = "Mime-Version: 1.0\n";
$headers .= "Content-Type: text/plain;charset=UTF-8\n";
$headers .= "From: $sender";

- Last but not least, beware of the internal encoding, which is needed by mb_encode_mimeheader function in order to encode properly. I had to set the internal encoding to UTF-8 in order to make it work properly :

mb_internal_encoding("UTF-8");
up
-3
contact-form at contactrobot dot com
11 years ago
While using the right tags mentioned in other comments (mb_internal_encoding, Content-Type, etc) ...

mb_send_mail would properly encode special characters in plain text emails, for both subject and message

mb_send_mail would not properly encode special characters in subject for multi-part messages (text+html)
up
-2
dynamis at skillup dot jp
20 years ago
As others say, mb_encode_mimeheader() seems to have a bug with JIS(ISO-2022-JP) encording. Token indicating start and end of multibyte char is inserted only before start of encoding and after the all.
We need the tokens at start and end of *all* encoded-text.
# PHP 4.3.2

So, we needs some workaround.

The post by "gordon at kanazawa-gu dot ac dot jp" seems to work well, but it doesn't. JIS nees some special tokens and base64_encode does'nt output them, so the code cannot used.

The post "RE: N03L in Japan", which simply splitting words in eash 10 chars is good enough in most case, there are some problem left. When there are some splited parts starting with ascii chars, 1 additional space will be inserted.
# RFC2047 only say within 76 words, shorter is not bad.

Additionally, thought it is really rare case, when we use "=?charset?" as literal string, we have to escape them.
# Some mailer can actually send this without escape and header will be broken. :(

Now, a little non-smart but maybe more accurate code is below function. I tested only with ISO-2022-JP, only in costomized phpBB2.0.5, only some cases.
As far as my test this code worked well, but I'm not sure.

# $str: source text
# $indent: ex. for "Subject: " header, give 9 and first line will be shorter than 76-1-9=66
# $encoding: source text encoding
# $mail_encoding: $str will be converted into this before base64 encode

function encode_mimeheader($str, $indent = 0, $encoding = 'utf-8', $mail_encoding = 'iso-2022-jp')
{
$start_delimiter = strtoupper("=?$mail_encoding?B?");
$start_pattern = strtoupper("=\\?$mail_encoding\\?B\\?");
$end_delimiter = '?=';

$str = mb_convert_encoding($str, $mail_encoding, $encoding);
$length = mb_strlen($str, $mail_encoding);
$max_part_length = 20; // enough short in most case (you can change this default value)

for ($i=0, $index=0; $index<$length; $i++) {
$part_length = $max_part_length;
$s = mb_substr($str, $index, $part_length, $mail_encoding);
// workaround for literally used start delimiter (without below, subject may break)
// note: mb_encode_mimeheader() don't encode ascii including start delimiter
if (preg_match('/^' . $start_pattern . '/i', $s))
{
$lines[$i] = $start_delimiter . base64_encode($start_delimiter) . "?=";
$index += strlen($start_delimiter);
continue;
}

$lines[$i] = mb_encode_mimeheader($s, $mail_encoding);
while (strlen($lines[$i]) > 76-1 - ($i?0:$indent)) { // max par line - first space - indent (first line only)
$part_length = floor($part_length * (76-1 - ($i?0:$indent)) / strlen($lines[$i])); // at least 1 decrement
$s = mb_substr($str, $index, $part_length, $mail_encoding);
$lines[$i] = mb_encode_mimeheader($s, $mail_encoding);
}

// workaround for starting new line with ascii (without below, 1 space may cut in)
// note: mb_encode_mimeheader() starts encode after encounterring multibyte char
if ($i > 0 && !preg_match('/^' . $start_pattern . '/i', $lines[$i]))
{
$p = strpos($lines[$i], $start_delimiter); //never 0 (false when not found)
$p = $p ? $p : strlen($lines[$i]);
$lines[$i] = $start_delimiter . base64_encode(substr($lines[$i], 0, $p)) . "?=";
$part_length = $p;
}
$index += $part_length;
}
$str = join("\r\n ", $lines); // RFC 2047,822 say newline must be ^\r\n, not only\n
return $str;
}
up
-3
phpguru at hotmail dot com
21 years ago
There is another way of encoding Japanese language to send email without worrying about mb_functions:

Download PHP Jcode from http://www.spencernetwork.org/
and use JcodeConvert function with base64_encode function for the e-mail header and the subject.

$email_to = "blah@blah.com";

$_POST["name"] = strip_tags(trim($_POST["name"]));
$name = "=?ISO-2022-JP?B?". base64_encode(JcodeConvert($_POST["name"], 2, 3)). "?=";
$_POST["email"] = strip_tags(trim($_POST["email"]));
$_POST["subject"] = strip_tags(trim($_POST["subject"]));
$email_subject = "=?ISO-2022-JP?B?". base64_encode(JcodeConvert($_POST["subject"], 2, 3)). "?=";
$_POST["body"] = strip_tags(trim($_POST["body"]));

$email_header = "From: $name <". $_POST["email"] .">\n";
$email_header .= "Reply-To: ". $_POST["email"] ."\n";
$email_header .= "Content-transfer-encoding: 7bit\n";
$email_header .= "Content-type: text/plain; charset=\"iso-2022-jp\"\n\n";

$email_body = "blah blah blah.\n"

mail($email_to, $email_subject, $email_body, $email_header);
up
-3
N03L in Japan
21 years ago
First of all, don't use nl2br in newer php versions unless you WANT to write xhtml...you'll get <br /> tags.

Secondly, you should use JIS, not ISO-2022-JP as the convert TO encoding. If you use ISO... mb_encode_mimeheader seems to fail. They're the same charset anyway.

Now here's why I am really writing. I just discovered that mb_send_mail and mb_encode_mimeheader cannot support hankaku (single byte kana in (S)JIS) at all. If you are making apps for the keitai (mobile) market, this won't do. Therefore, undo your overloading on the mail function and use regular mail and convert everything yourself like this. This is what we did. It seems to work for us. Your mileage may vary.

$strMBS = mb_convert_encoding($strMailBodySend, "JIS", "EUC-JP");

$strMS = mb_encode_mimeheader( mb_convert_encoding($strMailSubj, "JIS", "EUC-JP") );

mail($strToMail, $strMS, $strMBS, $strFrom);
up
-4
Anonymous
17 years ago
Be careful, mb_send_mail chokes if you try and send a multipart e-mail.
up
-4
Ran Hamada ( rhamada at sdcj dot co dot jp )
20 years ago
You may not use mb_encode_mimeheader() with mb_convert_encoding() to make subject as follows. It causes mojibake in several strings.
mb_encode_mimeheader( mb_convert_encoding($strMailSubj, "JIS", "EUC-JP") )

Set mb_internal_encoding() to *subject's* encoding and call mb_encode_mimeheader.

Example)

$__lang = mb_language();
$__enc = mb_internal_encoding();
mb_language("Japanese");
mb_internal_encoding( mb_detect_encoding($subject) );
#mb_internal_encoding( "EUC-JP" ); #just do when you know encoding of $subject
mail($to,
mb_encode_mimeheader($subject),
mb_convert_encoding($msg,"JIS","AUTO"),$header);
mb_internal_encoding( $__enc );
mb_language($__lang);
up
-6
Filip
8 years ago
I had to use mb_internal_encoding() also to get properly encoded message.
up
-6
noting@nowhere
16 years ago
Yes, as far as I understood the function encodes the entrire message body with base64 and that's why it can be used to send messages with attachments.
To Top