Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Problem with special characters in headers #203

Closed
jomofcw opened this issue Apr 17, 2018 · 14 comments
Closed

Problem with special characters in headers #203

jomofcw opened this issue Apr 17, 2018 · 14 comments

Comments

@jomofcw
Copy link

jomofcw commented Apr 17, 2018

Hello,

Using zend-mail module 2.9.0, I encounter an issue when using some special characters in headers.
Here is the stack trace of the error :

[Tue Apr 17 14:28:32.479564 2018] [php7:error] [pid 3647] [client 192.168.1.36:54062] PHP Fatal error:  Uncaught Zend\\Mail\\Header\\Exception\\RuntimeException: Invalid header value detected in /home/myUser/myProject/vendor/zendframework/zend-mail/src/Header/HeaderValue.php:114
Stack trace:
#0 /home/myUser/myProject/vendor/zendframework/zend-mail/src/Header/AbstractAddressList.php(150): Zend\\Mail\\Header\\HeaderValue::assertValid('HIDENAME Eug\\xC3\\xA8n...')
#1 /home/myUser/myProject/vendor/zendframework/zend-mail/src/Header/AbstractAddressList.php(194): Zend\\Mail\\Header\\AbstractAddressList->getFieldValue(true)
#2 /home/myUser/myProject/vendor/zendframework/zend-mail/src/Headers.php(428): Zend\\Mail\\Header\\AbstractAddressList->toString()
#3 /home/myUser/myProject/vendor/zendframework/zend-mail/src/Transport/Sendmail.php(245): Zend\\Mail\\Headers->toString()
#4 /home/myUser/myProject/vendor/zendframework/zend-mail/src/Transport/Sendmail.php(125): Zend\\Mail\\Transport\\Sendmail->prepareHeaders(Object(Zend\\Mail\\Message))
#5 /home/myUser/myProject/ressource/iDdev/moteur/inc/classe/email/elementEmail.class.php(160): Zend\\Mail\\Transport\\Sendmail->send(Object(Zend\\Mail\\Message))
#6 /home/myUser/myProject/www/site/source/prive/inc/classe/e-commerce/elementContact.class.php(988): elementEmail->envoyer(Array, Array, 'Message Luminis...')
#7 /home/myUser/myProject/www/site/source/prive/modele/luminis/magasin/general/page/module/contact/processus.inc.php(105): elementContact->enregistrer(Array, Array)
#8 /home/myUser/myProject/ressource/iDdev/moteur/inc/classe/page/bloc/elementModule.class.php(61): include('/home/myUser/...')
#9 /home/myUser/myProject/ressource/iDdev/moteur/inc/classe/page/bloc/elementModule.class.php(68): elementModule->{closure}(Object(elementModule), '/home/myUser/...', NULL)
#10 /home/myUser/myProject/ressource/iDdev/moteur/inc/classe/generale/bloc.class.php(195): elementModule->processus_charger('/home/myUser/...', Array)
#11 /home/myUser/myProject/ressource/iDdev/moteur/inc/classe/page/elementPage.class.php(801): IDcms_classe_bloc->assembler(Array)
#12 /home/myUser/myProject/ressource/iDdev/moteur/inc/classe/page/elementPage.class.php(1426): elementPage->assembler()
#13 /home/myUser/myProject/ressource/iDdev/moteur/inc/classe/page/elementPage.class.php(1435): elementPage->assembler_traiter()
#14 /home/myUser/myProject/ressource/iDdev/moteur/inc/classe/moteur.class.php(358): elementPage->assembler_afficher()
#15 /home/myUser/myProject/ressource/iDdev/moteur/inc/classe/moteur.class.php(279): Moteur::proceder_suite()
#16 /home/myUser/myProject/ressource/iDdev/moteur/moteur.php(37): Moteur::proceder()
#17 /home/myUser/myProject/www/site/source/public/_base.php(37): require_once('/home/myUser/...')
#18 {main}
  thrown in /home/myUser/myProject/vendor/zendframework/zend-mail/src/Header/HeaderValue.php on line 114, referer: http://www.mydomain.com/contact

Do you need me to provide more ? Just ask !
Thanks for your work.

@jomofcw jomofcw changed the title Probelm with special characters in headers Problem with special characters in headers Apr 17, 2018
@michalbundyra
Copy link
Member

@jomofcw Can you provide an example header? What 'special characters' are you using?

@jomofcw
Copy link
Author

jomofcw commented Apr 17, 2018

@webimpress here is the headers that seems to be the problem (after many test case to isolate it) :

$message->setFrom('my@mail.com','HIDENAME Eugène');

The character "è" is the special one which make it crash. Replacing it by "é" still crash (and probably with each others special chars).

@michalbundyra
Copy link
Member

@jomofcw Hm... Isn't it right? As I understand from #28 - either è and é are non-us-ascii characters, so these are not allowed in the header value.

@jomofcw
Copy link
Author

jomofcw commented Apr 17, 2018

@webimpress, previously, when I used zend-mail from ZendFramework v1 I add no problem with those special characters... and anyway, it's commonly used in name in france for example.
So it may be a solution to use it in header... nop ? Or anyway, zend-mail shall "process" it to avoid this type of error, nop ?

@michalbundyra
Copy link
Member

@jomofcw Encode using base64, the question if it should be done automatically or not...

@jomofcw
Copy link
Author

jomofcw commented Apr 17, 2018

@webimpress I understand.
Currently, I replace the special chars by its basics équivalent ("è" with "e" for example), but it's not respectfull of the user input...

If I do it on my own, in your opinion, when and how shall I encode it base64 ? Something like that (but it sounds like wrong to me as it return something not human readable) :

$message->setFrom('my@mail.com',base64_encode('HIDENAME Eugène'));

@glensc
Copy link
Contributor

glensc commented Apr 17, 2018

provide complete standalone reproducer.

taking things out of context is not reproducible, the line itself on it's own is not incorrect.

likely the encoding in $message is not set to utf-8 for some reason.

@jomofcw
Copy link
Author

jomofcw commented Apr 17, 2018

@glensc dunno if it's what you mean, but here is the method code where I build and send the message :

    function envoyer($expediteur,$destinataires,$objet,$site    =    null,$chemin_piece_jointe = null)
    {
        if    ($this->assembler(null,$site)&&!empty($this->sortie_resultat))
        {
            
            $message_parties    =    array();
            
            $html            =    new Zend\Mime\Part($this->sortie_resultat);
            $html->type        =    Zend\Mime\Mime::TYPE_HTML;
            $html->charset    =    'utf-8';
            $html->encoding    =    Zend\Mime\Mime::ENCODING_QUOTEDPRINTABLE;
            array_push($message_parties,$html);
            
            if ($chemin_piece_jointe != null)
            {
                // Attachement de la pièce joint au mail
                $piece_jointe                =    new Zend\Mime\Part(fopen($chemin_piece_jointe,'r'));
                $piece_jointe->type            =    'application/xls';
                $chemin_piece_jointe_details=    pathinfo($chemin_piece_jointe);
                $piece_jointe->filename        =    (preg_match('`formulaire_retour_`',$chemin_piece_jointe_details['basename'])?'hors-delais.xls':$chemin_piece_jointe_details['basename']);
                $piece_jointe->disposition    =    Zend\Mime\Mime::DISPOSITION_ATTACHMENT;
                $piece_jointe->encoding        =    Zend\Mime\Mime::ENCODING_BASE64;
                array_push($message_parties,$piece_jointe);
            }
            
            $corps    =    new Zend\Mime\Message();
            $corps->setParts($message_parties);
            
            $message    =    new    Zend\Mail\Message('utf-8');
            
            if    (!is_array($expediteur))
                $expediteur    =    array($expediteur);
            $message->setFrom($expediteur[0],(!empty($expediteur[1])?$expediteur[1]:null));
            
            if    (!is_array($destinataires))
                $destinataires    =    array('to'=>$destinataires);
            foreach    ($destinataires    as    $type=>$destinataire_liste)
            {
                if    (!is_array($destinataire_liste))
                    $destinataire_liste    =    array($destinataire_liste);
                foreach    ($destinataire_liste    as    $destinataire)
                {
                    if    (!is_array($destinataire))
                        $destinataire    =    array($destinataire);
                    if    (defined('DEV_MODE')&&DEV_MODE)// Filtre pour éviter que des e-mails ne soient envoyé à des clients depuis le DEV
                    {
                        if    (!preg_match(DEV_EMAIL_MASQUE,$destinataire[0]))
                            continue;
                    }
                    if    (empty($type)||!in_array($type,array('cc','bcc','to')))
                        $type    =    'to';

                    switch    ($type)
                    {
                        case    'cc':
                            $message->addCc(strtolower($destinataire[0]),(!empty($destinataire[1])?$destinataire[1]:null));
                            break;
                        case    'bcc':
                            $message->addBcc(strtolower($destinataire[0]),(!empty($destinataire[1])?$destinataire[1]:null));
                            break;
                        case    'to':
                        default:
                            $message->addTo(strtolower($destinataire[0]),(!empty($destinataire[1])?$destinataire[1]:null));
                            break;
                    }
                }
            }
            $message
                ->setReplyTo($expediteur[0],(!empty($expediteur[1])?$expediteur[1]:null))
                ->setSubject(strip_tags($objet))
                ->setBody($corps)
            ;
            
            if    (count($message_parties)>1)
            {
                $contentTypeHeader = $message->getHeaders()->get('Content-Type');
                $contentTypeHeader->setType('multipart/related');
            }
            
            $transport = new Zend\Mail\Transport\Sendmail();
            $transport_resultat    =    $transport->send($message);
            
            return    $transport_resultat;
        }
        return    false;
    }

@glensc
Copy link
Contributor

glensc commented Apr 17, 2018

standalone means that if i take your script it actually runs in my environment. and it contains only necessary code to show the problem, nothing else.

<?php

require 'vendor/autoload.php';

// YOUR CODE HERE

@michalbundyra
Copy link
Member

@jomofcw

Try this:

$message->setFrom('my@mail.com', '=?UTF-8?B?'.base64_encode('HIDENAME Eugène').'?=');

But as I said - maybe it should be done automatically inside the library...

@jomofcw
Copy link
Author

jomofcw commented Apr 17, 2018

@webimpress it doesn't change anything (strange...).

@glensc you'll find the code and the stack trace below :

<?php
// phpinfo();
// die('ok');

require_once(__DIR__.'/../../../../vendor/autoload.php');

$expediteur		=	$destinataire	=	array('my@mail.com','NOM Prénom');
$objet			=	'Test e-mail';
$contenu_html	=	'<html><body>Test e-mail</body></html>';

$message_parties	=	array();

$html			=	new Zend\Mime\Part($contenu_html);
$html->type		=	Zend\Mime\Mime::TYPE_HTML;
$html->charset	=	'utf-8';
$html->encoding	=	Zend\Mime\Mime::ENCODING_QUOTEDPRINTABLE;
array_push($message_parties,$html);

$corps	=	new Zend\Mime\Message();
$corps->setParts($message_parties);

$message	=	new	Zend\Mail\Message('utf-8');

$message
	->setFrom(strtolower($expediteur[0]),$expediteur[1])
	->addTo(strtolower($destinataire[0]),$destinataire[1])
	->setReplyTo($expediteur[0],$expediteur[1])
	->setSubject(strip_tags($objet))
	->setBody($corps)
;

if	(count($message_parties)>1)
{
	$contentTypeHeader = $message->getHeaders()->get('Content-Type');
	$contentTypeHeader->setType('multipart/related');
}

$transport = new Zend\Mail\Transport\Sendmail();
$transport_resultat	=	$transport->send($message);
[Tue Apr 17 17:40:42.583809 2018] [php7:error] [pid 3647] [client 192.168.1.36:58492] PHP Fatal error:  Uncaught Zend\\Mail\\Header\\Exception\\RuntimeException: Invalid header value detected in /home/myUser/myProject/vendor/zendframework/zend-mail/src/Header/HeaderValue.php:114
Stack trace:
#0 /home/myUser/myProject/vendor/zendframework/zend-mail/src/Header/AbstractAddressList.php(150): Zend\\Mail\\Header\\HeaderValue::assertValid('NOM Pr\\xC3\\xA9nom <nv...')
#1 /home/myUser/myProject/vendor/zendframework/zend-mail/src/Transport/Sendmail.php(171): Zend\\Mail\\Header\\AbstractAddressList->getFieldValue(true)
#2 /home/myUser/myProject/vendor/zendframework/zend-mail/src/Transport/Sendmail.php(122): Zend\\Mail\\Transport\\Sendmail->prepareRecipients(Object(Zend\\Mail\\Message))
#3 /home/myUser/myProject/www/site/source/public/test.php(39): Zend\\Mail\\Transport\\Sendmail->send(Object(Zend\\Mail\\Message))
#4 {main}
  thrown in /home/myUser/myProject/vendor/zendframework/zend-mail/src/Header/HeaderValue.php on line 114

Does it help, please ?

@glensc
Copy link
Contributor

glensc commented Apr 18, 2018

yes. of course, because i was able to run the code on my machine.

i created gist of your problem: https://gist.github.com/glensc/c3787087a9cd083fa3d7d071f0b450c2 (git clone to see history)

but your fix is simple:

@@ -18,7 +18,8 @@ array_push($message_parties,$html);
 $corps =       new Zend\Mime\Message();
 $corps->setParts($message_parties);

-$message       =       new     Zend\Mail\Message('utf-8');
+$message       =       new     Zend\Mail\Message();
+$message->setEncoding('utf-8');

Zend\Mail\Message does not have constructor parameter, you need to use setEncoding to set encoding.

if this solved your problem, please close issue yourself.

@froschdesign
Copy link
Member

@jomofcw
Look also in the documentation of the message class.

@jomofcw
Copy link
Author

jomofcw commented Apr 18, 2018

@glensc great ! it works ;-).
Thanks for your precious help. Thanks to @froschdesign also.

I should have find it on my own, sorry for your time.

@jomofcw jomofcw closed this as completed Apr 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants