Vous utilisez un navigateur obsolète, veuillez le mettre à jour.
Veuillez utiliser un navigateur internet moderne avec JavaScript activé pour naviguer sur OpenClassrooms.com
Une question ? Pas de panique, on va vous aider !
Bonjour,
Je tente de créer moi-même un webmail basé sur IMAP.
J'arrive à bien récupérer les images à l'intérieur du body ainsi que les attachements. Mais je rencontre deux soucis :
mb_convert_encodin($bodymsg, "UTF-8", "auto") ne semble pas marcher avec ISO-8859-1
Malgré imap_fetchbody j'obtien souvent plusieurs part dans mon body dont le message en plain text, le message en base64 et parfois les fichiers
Pouvez-vous m'aider à corriger ces problèmes ?
à toutes fins utiles mon code :
/** * @Route("/email/read/id={id}", name="email_read", methods={"GET", "POST"}) * @IsGranted("ROLE_USER") */ public function readInbox(Request $request, Imap $imap, $id, Packages $assetPackage): Response { $mbox = $this->logImap(""); if ($mbox === false) { die('La connexion a échoué. Vérifiez vos paramètres!'); } else { $uid = $id; $structure = imap_fetchstructure($mbox, $uid, FT_UID); var_dump($structure); $headerText = imap_fetchHeader($mbox, $uid, FT_UID); $header = imap_rfc822_parse_headers($headerText); $body = ""; $filename = ""; $attachments = ""; $messageNumber = $id; if (isset($structure->parts)) { var_dump($structure->subtype); switch ($structure->subtype) { case 'ALTERNATIVE': $body2 = imap_fetchbody($mbox, $uid, 2, FT_UID) ?? imap_fetchbody($mbox, $uid, 1.2, FT_UID); $body2 = $this->decodeCharset($body2); break; case 'PLAIN': $body2 = imap_fetchbody($mbox, $uid, 1, FT_UID) ?? imap_fetchbody($mbox, $uid, 1.1, FT_UID); break; case 'HTML': $possibleParts = [1.1, 1.2, 1, 1.0, 1.3]; foreach ($possibleParts as $part) { $body2 = imap_fetchbody($mbox, $uid, $part, FT_UID); if ($body2 !== null) { break; } } break; default: break; } if ($body2 !== null) { $body = quoted_printable_decode($body2); } } else { $body = imap_fetchbody($mbox, $uid, 1, FT_UID) ?? imap_fetchbody($mbox, $uid, 1.1, FT_UID); $body = quoted_printable_decode($body); $body = $this->detectAndDecodeCharset($body); var_dump($body); } // Handling for RELATED and MIXED subtypes if ($structure->subtype == 'RELATED') { $data = $this->handleRelatedSubtype($mbox, $uid, $structure, $assetPackage, $body); $body = $data['body']; $attachments = $data['attachments']; } if ($structure->subtype == 'MIXED') { $data = $this->handleMixedSubtype($mbox, $uid, $structure, $assetPackage, $body); $body = $data['body']; $attachments = $data['attachments']; } imap_close($mbox); if ($this->is_base64_encoded($body) == true) { $body = base64_decode($body); } if (strpos($body, '<') !== false && strpos($body, '>') !== false) { $allowed_tags = '<a><abbr><acronym><address><area><article><aside><audio><b><basefont><bdo><big><blockquote><br><button><canvas><caption><center><cite><code><col><colgroup><datalist><dd><del><details><dfn><dir><div><dl><dt><em><embed><fieldset><figcaption><figure><font><footer><form><h1><h2><h3><h4><h5><h6><head><header><hr><i><iframe><img><input><ins><kbd><keygen><label><legend><li><map><menu><meter><nav><noscript><object><ol><optgroup><option><output><p><param><pre><progress><q><rp><rt><ruby><s><samp><script><section><select><small><source><span><strike><style><strong><sub><sup><table><tbody><td><textarea><tfoot><th><thead><time><title><tr><track><tt><u><ul><var><video>>'; $body = strip_tags($body, $allowed_tags); $body = $this->deleteStyle($body); } $bodymsg = mb_convert_encoding($bodymsg, "UTF-8", $encoding); return $this->render('core\emails\readinbox.html.twig', [ 'header' => $header, 'corps' => $body, 'attachement' => $attachments, 'structure' => $structure, 'object' => "", 'attachments' => $attachments, 'id' => $messageNumber, ]); } } private function handleRelatedSubtype($mbox, $uid, $structure, $assetPackage, $body) { $attachments = []; // Array to hold attachment information if (isset($structure->parts)) { $parts = $structure->parts; $body2 = imap_fetchbody($mbox, $uid, 1.2, FT_UID) ?: imap_fetchbody($mbox, $uid, 1, FT_UID); $body = quoted_printable_decode($body2); $i = 0; foreach ($parts as $part) { if ($parts[$i]) { $i++; if (isset($parts[$i]) && $parts[$i]->ifid == 1) { $id = substr($parts[$i]->id, 1, -1); $imageid = "cid:" . $id; foreach ($parts[$i]->parameters as $object) { $filename = $assetPackage->getUrl("emails/inline/" . mb_decode_mimeheader($object->value)); $path = $this->getParameter('kernel_directory') . "/public/emails/inline/" . mb_decode_mimeheader($object->value); $attachment = imap_fetchbody($mbox, $uid, ($i + 1), FT_UID); if ($structure->parts[$i]->encoding == 3) { $attachment = base64_decode($attachment); } elseif ($structure->parts[$i]->encoding == 4) { $attachment = quoted_printable_decode($attachment); } else { echo "encod:" . $structure->parts[$i]->encoding . PHP_EOL; } file_put_contents($path, $attachment); // Add attachment information to the $attachments array $attachments[] = [ 'filename' => mb_decode_mimeheader($object->value), 'path' => $path, 'url' => $filename, 'content' => $attachment ]; $body = str_replace($imageid, $filename, $body); } } } } } // Return both the body and attachments return [ 'body' => $body, 'attachments' => $attachments ]; } private function handleMixedSubtype($mbox, $uid, $structure, $assetPackage, $body) { $attachments = []; $returnData = []; if (isset($structure->parts) && count($structure->parts)) { for ($e = 0; $e < count($structure->parts); $e++) { $attachments[$e] = ['is_attachment' => false, 'filename' => '', 'name' => '', 'attachment' => '']; if ($structure->parts[$e]->type != 1) { if ($structure->parts[$e]->ifdparameters) { foreach ($structure->parts[$e]->dparameters as $object) { if (strtolower($object->attribute) == 'filename') { $attachments[$e]['is_attachment'] = true; $attachments[$e]['filename'] = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $this->suppraccent(mb_decode_mimeheader($object->value))); } } } if ($structure->parts[$e]->ifparameters) { foreach ($structure->parts[$e]->parameters as $object) { if (strtolower($object->attribute) == 'name') { $attachments[$e]['is_attachment'] = true; $attachments[$e]['name'] = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $this->suppraccent(mb_decode_mimeheader($object->value))); } } } if ($attachments[$e]['is_attachment']) { $attachments[$e]['attachment'] = imap_fetchbody($mbox, $uid, ($e + 1), FT_UID); if ($structure->parts[$e]->encoding == 3) { $attachments[$e]['attachment'] = base64_decode($attachments[$e]['attachment']); } elseif ($structure->parts[$e]->encoding == 4) { $attachments[$e]['attachment'] = quoted_printable_decode($attachments[$e]['attachment']); } $path = $this->getParameter('kernel_directory') . "/public/emails/inline/" . $attachments[$e]['name']; file_put_contents($path, $attachments[$e]['attachment']); } } } } // Extracting and processing the body $bodymsg = quoted_printable_decode(imap_fetchbody($mbox, $uid, 1, FT_UID)); if (empty($bodymsg)) { $bodymsg = quoted_printable_decode(imap_fetchbody($mbox, $uid, 1.1, FT_UID)); } $crawler = new Crawler($bodymsg); $ltrDivs = $crawler->filter('div[dir=ltr]'); if ($ltrDivs->count() > 0) { $ltrDiv = $ltrDivs->first(); $extractedHtml = $ltrDiv->html(); $bodymsg = $extractedHtml; } $bodymsg = mb_convert_encoding($bodymsg, "UTF-8", "auto"); $body = $bodymsg; // Processing inline attachments $source = imap_fetchbody($mbox, $uid, 2, FT_UID); if (isset($structure->parts[0]->parts)) { $inlines = []; for ($j = 0; $j < count($structure->parts[0]->parts); $j++) { if ($structure->parts[0]->parts[$j]->type == 5) { $imageId = substr($structure->parts[0]->parts[$j]->id, 1, -1); $uniqueName = uniqid('img_') . "." . $structure->parts[0]->parts[$j]->subtype; $partNumber = ("1." . $j + 1); $inlines[$j] = ['is_inline' => true, 'name' => $uniqueName, 'filename' => iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $this->suppraccent(mb_decode_mimeheader($structure->parts[0]->parts[$j]->parameters[0]->value))), 'attachment' => base64_decode(imap_fetchbody($mbox, $uid, $partNumber, FT_UID))]; $path = $this->getParameter('kernel_directory') . "/public/emails/inline/" . $uniqueName; file_put_contents($path, $inlines[$j]['attachment']); $imageid = "cid:" . $imageId; $filename = $assetPackage->getUrl("emails/inline/" . $uniqueName); $body = str_replace($imageid, $filename, $body); } } } // Adding body and attachments to returnData array $returnData['body'] = $body; $returnData['attachments'] = $attachments; return $returnData; } private function decodeCharset($string) { $encoding = mb_detect_encoding($string, mb_detect_order(), true); if ($encoding === "ASCII") { $string = mb_convert_encoding($string, "UTF-8", $encoding); } elseif ($encoding === "UTF-8") { $string = quoted_printable_decode($string); } else { $string = iconv($encoding, 'UTF-8', quoted_printable_decode($string)); } // Decode the string to UTF-8 $string = mb_convert_encoding($string, "UTF-8", $encoding); return $string; } private function detectAndDecodeCharset($string) { $originalCharset = mb_detect_encoding($string); $string = mb_convert_encoding($string, 'UTF-8', $originalCharset); return $string; } private function is_base64_encoded($string) { // Remove any whitespace characters from the input string $string = trim($string); // Base64 encoding typically contains characters A-Z, a-z, 0-9, +, /, and sometimes = // Check if the decoded string is not false and if the decoded string contains only valid characters return base64_decode($string, true) !== false && preg_match('%^[a-zA-Z0-9/+]*={0,2}$%', $string); } private function contains_html_tags($string) { return preg_match("/<[^<]+>/", $string) === 1; } private function deleteStyle($bodymsg){ $crawler = new Crawler($bodymsg); // Find all <style> tags and remove them $crawler->filter('style')->each(function (Crawler $node) { $node->getNode(0)->parentNode->removeChild($node->getNode(0)); }); // Get the updated HTML after removing <style> tags $bodymsg = $crawler->html(); return $bodymsg; }
En vous remerciant
Cordialement
Vous pouvez rédiger votre message en Markdown ou en HTML uniquement.