Email encodé en quoted-printable impossible à afficher sous Gmail

WRInaute occasionnel
Bonjour à tous.

Après avoir parcouru tous les topics disponibles et imaginables sur le sujet et n'ayant trouvé aucune solution à ce jour, j'en implore l'expertise des wrinautes ! :mrgreen:

Alors, techniquement c'est du php envoyé avec la fonction mail(), rien de plus classique jusque là.
Voici un extrait du header de Gmail :
Code:
Subject: Offre =?ISO-8859-15?B?U3DpY2lhbGUgTGFuY2VtZW50IDogLTIwJSBzdXIg?= tous les soins de la boutique
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary=af7fa4310add4daaa52f6c0b67ec6116

This is a multi-part message in MIME format.

--af7fa4310add4daaa52f6c0b67ec6116
Content-Type: text/plain; charset=ISO-8859-15
Content-transfer-encoding: 7bit

ici le text/plain avec des caractères non-reconnus, exemple : �

--af7fa4310add4daaa52f6c0b67ec6116
Content-Type: text/html; charset=ISO-8859-15
Content-transfer-encoding: 7bit

ici le code html avec des caractères non-reconnus, exemple : �

--af7fa4310add4daaa52f6c0b67ec6116
Le header est évidemment codé en CRLF ("\r\n").

La seule chose qui me chagrine ici, c'est qu'il y a des caractères non-reconnus dans le text-plain et le code html qui sont ni plus ni moins que les caractères spéciaux de notre langue "é" et "à" par exemple. Or le charset indiqué est bel et bien le bon ...

Et ça commence doucement à me rendre chèvre cette histoire, car j'ai tout essayé en quoted-printable avec l'utilisation de la fonction imap_8bit pour encodé le text/plain et le code html, et en base64. Le seul encodage qui a l'air de marcher est le 7bit mais pas pour Gmail, rien n'y fait !

A noter que j'ai testé mon code sous les webmails de Free (Zimbra & Horde), Yahoo! Mail, Windows Live Hotmail, RoundCube Webmail et donc Gmail. Les 2 webmails qui n'affichent pas l'email sont Horde et Gmail.

PS : Ce n'est pas la peine de me dire de passer à PHPMailer ou SwiftMailer, merci ! ;)

Merci de votre aide ! 8)
 
WRInaute occasionnel
spout a dit:
lunicrea a dit:
PS : Ce n'est pas la peine de me dire de passer à PHPMailer ou SwiftMailer, merci ! ;)
Tanpis pour toi si tu aimes bien réinventer la roue :mrgreen:
Courage :wink:
J'aime surtout avoir la pleine maitrise de ce que je propose à mes clients. Autrement dit, comprendre de A à Z toutes les fonctionnalités proposées par mon CMS/CRM made by moi ! 8)
 
WRInaute accro
Avoir un CMS ne t'empêche pas d'utiliser certaines classes ou modules tiers quand ils sont bien fait. ET vu comment cela peut être compliqué de coder un email propre avec un support optimum, que ce soit à cause de l'encodage, des méthodes d'envoi, de l'ajout de pièce jointe. mais bon on ne va pas épiloguer, vu que tu n'en veux pas. Bon courage !
 
WRInaute occasionnel
Heu ... Je vous rassure, je suis certes un développeur web mais je n'en reste pas moins un consultant qui s'aide de classes et de modules tiers !

Je ne suis pas non plus un névrosé de la réinvention de la roue.

Néanmoins, concernant ce problème-ci, j'aurai aimé éviter de re-développer tout mon environnement d'envoi d'email juste à cause d'un seul webmail, à savoir Gmail ;)

Voilà tout.
 
WRInaute occasionnel
Alleluyah !

J'y suis arrivé ! :D

Pour ceux que cela intéresse, voici la codification en php que j'ai employé :
  • Headers (En-tête) :
    Code:
    $boundary = '=_' . md5 (uniqid (rand()));
    $Headers  = 'From: '.$From.'\nSender: '.$From.'\nReply-To: '.$Replyto.'\nMIME-Version: 1.0\nX-Mailer: PHP/' . phpversion() . '\nContent-Type: multipart/alternative;\n' . chr(9) . 'boundary="' . $boundary.'"';
  • Encodage du subject (Objet) :
    Code:
    $string = "Insérez ici l'objet de votre email";
    $encoding = "ISO-8859-15";
    $pos=0;
    $split=36; // after 36 single bytes characters, if then comes MB, it is broken
    while ($pos<mb_strlen($string,$encoding))
    {
      $output=mb_strimwidth($string,$pos,$split,"",$encoding);
      $pos+=mb_strlen($output,$encoding);
      $_string.=(($_string)?' ':'').mb_encode_mimeheader($output,$encoding);
    }
    $subject=$_string;
  • Encodage du message :
    Code:
    // Assemblage partie plain text + partie html avec gestion du boundary
    $contenu = '--' . $boundary . '\nContent-Type: text/plain; charset="iso-8859-15"\nContent-Transfer-Encoding: 7bit\n\n' . $contenu_text . '\n--' . $boundary . '\nContent-Type: text/html; charset="iso-8859-15"\nContent-Transfer-Encoding: quoted-printable\n\n' . quotedPrintableEncode($contenu_html) . '\n--' . $boundary . '--\n';
  • La fonction quoteadPrintableEncode() :
    Code:
    /**
     * quoteadPrintableEncode()
     * 
     * Encodes data to quoted-printable standard.
     *
     * @param $input    The data to encode
     * @param $line_max Optional max line length. Should 
     *                  not be more than 76 chars
     *
     * @access private
     */
    
        function quotedPrintableEncode($input , $line_max = 76) {
          $lines = preg_split("/\r\n|\r|\n/", $input);
          $eol = "\n"; //Modifier cette partie en fonction de votre configuration CRLF/LF
          $escape = '=';
          $output = '';
    
          while (list(, $line) = each($lines)) {
            $linlen = strlen($line);
            $newline = '';
    
            for ($i = 0; $i < $linlen; $i++) {
              $char = substr($line, $i, 1);
              $dec = ord($char);
    
    // convert space at eol only
              if ( ($dec == 32) && ($i == ($linlen - 1)) ) {
                $char = '=20';
              } elseif ($dec == 9) {
    // Do nothing if a tab.
              } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) {
                $char = $escape . strtoupper(sprintf('%02s', dechex($dec)));
              }
    
    // $this->lf is not counted
              if ((strlen($newline) + strlen($char)) >= $line_max) {
    // soft line break; " =\r\n" is okay
                $output .= $newline . $escape . $eol;
                $newline = '';
              }
              $newline .= $char;
            }
            $output .= $newline . $eol;
          }
    // Don't want last crlf
          $output = substr($output, 0, -1 * strlen($eol));
    
          return $output;
        }

Me concernant le problème venait de la gestion en CRLF ("\r\n") qui ne convenait pas à la configuration de mon serveur et je me suis donc orienté vers une gestion en LF ("\n"). Et également dans la dernière ligne du message, à savoir "--af7fa4310add4daaa52f6c0b67ec6116" car il ne faut oublier les derniers tirets "--", ce qui donne au final "--af7fa4310add4daaa52f6c0b67ec6116--".

Bref, je n'ai pas réinventé la roue, j'ai juste débogué un dysfonctionnement au sein de mon application d'envoi d'emails ;)

Bon après-midi !
 
Discussions similaires
Haut