web-dev-qa-db-fra.com

Comment intégrer des images dans un e-mail HTML

J'essaie d'implémenter un code pour envoyer des e-mails HTML avec une image intégrée.

J'ai déjà essayé pour un simple email HTML avec image mais cette image est prise depuis le serveur.

41
amol

Je recommanderais fortement d'utiliser une bibliothèque comme PHPMailer pour envoyer des e-mails.
C'est plus facile et gère la plupart des problèmes automatiquement pour vous.

Concernant l'affichage des images intégrées (en ligne), voici ce qui se passe leur documentation :

Pièces jointes en ligne

Il existe un moyen supplémentaire d'ajouter une pièce jointe. Si vous souhaitez créer un e-mail HTML avec des images incorporées dans le bureau, il est nécessaire de joindre l'image, puis de lui associer la balise. Par exemple, si vous ajoutez une image en tant que pièce jointe en ligne avec le CID ma-photo, vous y accéderez dans l'e-mail HTML avec <img src="cid:my-photo" alt="my-photo" />.

En détail, voici la fonction pour ajouter une pièce jointe en ligne:

$mail->AddEmbeddedImage(filename, cid, name);
//By using this function with this example's value above, results in this code:
$mail->AddEmbeddedImage('my-photo.jpg', 'my-photo', 'my-photo.jpg ');

Pour vous donner un exemple plus complet de la façon dont cela fonctionnerait:

<?php
require_once('../class.phpmailer.php');
$mail = new PHPMailer(true); // the true param means it will throw exceptions on     errors, which we need to catch

$mail->IsSMTP(); // telling the class to use SMTP

try {
  $mail->Host       = "mail.yourdomain.com"; // SMTP server
  $mail->Port       = 25;                    // set the SMTP port
  $mail->SetFrom('[email protected]', 'First Last');
  $mail->AddAddress('[email protected]', 'John Doe');
  $mail->Subject = 'PHPMailer Test';

  $mail->AddEmbeddedImage("rocks.png", "my-attach", "rocks.png");
  $mail->Body = 'Your <b>HTML</b> with an embedded Image: <img src="cid:my-attach"> Here is an image!';

  $mail->AddAttachment('something.Zip'); // this is a regular attachment (Not inline)
  $mail->Send();
  echo "Message Sent OK<p></p>\n";
} catch (phpmailerException $e) {
  echo $e->errorMessage(); //Pretty error messages from PHPMailer
} catch (Exception $e) {
  echo $e->getMessage(); //Boring error messages from anything else!
}
?>

Modifier:

En ce qui concerne votre commentaire, vous avez demandé comment envoyer du courrier électronique HTML avec des images intégrées, alors je vous ai donné un exemple de la façon de procéder.
La bibliothèque dont je vous ai parlé peut envoyer des e-mails en utilisant de nombreuses méthodes autres que SMTP.
Jetez un œil à la page d'exemple de PHPMailer pour d'autres exemples.

D'une manière ou d'une autre, si vous ne souhaitez pas envoyer l'e-mail de la manière prise en charge par la bibliothèque, vous pouvez (devez) toujours utiliser la bibliothèque pour créer le message, puis vous l'envoyez comme vous le souhaitez.

Par exemple:

Vous pouvez remplacer la ligne qui envoie l'e-mail:

$mail->Send();

Avec ça:

$mime_message = $mail->CreateBody(); //Retrieve the message content
echo $mime_message; // Echo it to the screen or send it using whatever method you want

J'espère que ça t'as aidé. Faites-moi savoir si vous rencontrez des problèmes pour l'utiliser.

73
Carlos Lima

J'utilise cette fonction qui trouve toutes les images dans ma lettre et les joint au message.

Paramètres: Prend votre HTML (que vous voulez envoyer);
Return: Le code HTML et les en-têtes nécessaires, que vous pouvez utiliser dans mail();

Exemple d'utilisation:

define("DEFCALLBACKMAIL", "[email protected]"); // WIll be shown as "from".
$final_msg = preparehtmlmail($html); // give a function your html*

mail('[email protected]', 'your subject', $final_msg['multipart'], $final_msg['headers']); 
// send email with all images from html attached to letter


function preparehtmlmail($html) {

  preg_match_all('~<img.*?src=.([\/.a-z0-9:_-]+).*?>~si',$html,$matches);
  $i = 0;
  $paths = array();

  foreach ($matches[1] as $img) {
    $img_old = $img;

    if(strpos($img, "http://") == false) {
      $uri = parse_url($img);
      $paths[$i]['path'] = $_SERVER['DOCUMENT_ROOT'].$uri['path'];
      $content_id = md5($img);
      $html = str_replace($img_old,'cid:'.$content_id,$html);
      $paths[$i++]['cid'] = $content_id;
    }
  }

  $boundary = "--".md5(uniqid(time()));
  $headers .= "MIME-Version: 1.0\n";
  $headers .="Content-Type: multipart/mixed; boundary=\"$boundary\"\n";
  $headers .= "From: ".DEFCALLBACKMAIL."\r\n";
  $multipart = '';
  $multipart .= "--$boundary\n";
  $kod = 'utf-8';
  $multipart .= "Content-Type: text/html; charset=$kod\n";
  $multipart .= "Content-Transfer-Encoding: Quot-Printed\n\n";
  $multipart .= "$html\n\n";

  foreach ($paths as $path) {
    if(file_exists($path['path']))
      $fp = fopen($path['path'],"r");
      if (!$fp)  {
        return false;
      }

    $imagetype = substr(strrchr($path['path'], '.' ),1);
    $file = fread($fp, filesize($path['path']));
    fclose($fp);

    $message_part = "";

    switch ($imagetype) {
      case 'png':
      case 'PNG':
            $message_part .= "Content-Type: image/png";
            break;
      case 'jpg':
      case 'jpeg':
      case 'JPG':
      case 'JPEG':
            $message_part .= "Content-Type: image/jpeg";
            break;
      case 'gif':
      case 'GIF':
            $message_part .= "Content-Type: image/gif";
            break;
    }

    $message_part .= "; file_name = \"$path\"\n";
    $message_part .= 'Content-ID: <'.$path['cid'].">\n";
    $message_part .= "Content-Transfer-Encoding: base64\n";
    $message_part .= "Content-Disposition: inline; filename = \"".basename($path['path'])."\"\n\n";
    $message_part .= chunk_split(base64_encode($file))."\n";
    $multipart .= "--$boundary\n".$message_part."\n";

  }

  $multipart .= "--$boundary--\n";
  return array('multipart' => $multipart, 'headers' => $headers);  
}
30
Arthur Halma

PHPMailer a la possibilité d'incorporer automatiquement des images de votre e-mail HTML. Vous devez donner le chemin complet dans le système de fichiers, lors de l'écriture de votre HTML:

<img src="/var/www/Host/images/photo.png" alt="my photo" />

Il se convertira automatiquement en:

<img src="cid:photo.png" alt="my photo" />
15
donis

Sur la base de la réponse d'Arthur Halma, j'ai fait ce qui suit qui fonctionne correctement avec le courrier d'Apple, Android & iOS mail.

define("EMAIL_DOMAIN", "yourdomain.com");

public function send_email_html($to, $from, $subject, $html) {
  preg_match_all('~<img.*?src=.([\/.a-z0-9:_-]+).*?>~si',$html,$matches);
  $i = 0;
  $paths = array();
  foreach ($matches[1] as $img) {
    $img_old = $img;
    if(strpos($img, "http://") == false) {
      $uri = parse_url($img);
      $paths[$i]['path'] = $_SERVER['DOCUMENT_ROOT'].$uri['path'];
      $content_id = md5($img);
      $html = str_replace($img_old,'cid:'.$content_id,$html);
      $paths[$i++]['cid'] = $content_id;
    }
  }
  $uniqid   = md5(uniqid(time()));
  $boundary = "--==_mimepart_".$uniqid;

  $headers = "From: ".$from."\n".
  'Reply-to: '.$from."\n".
  'Return-Path: '.$from."\n".
  'Message-ID: <'.$uniqid.'@'.EMAIL_DOMAIN.">\n".
  'Date: '.gmdate('D, d M Y H:i:s', time())."\n".
  'Mime-Version: 1.0'."\n".
  'Content-Type: multipart/related;'."\n".
  '  boundary='.$boundary.";\n".
  '  charset=UTF-8'."\n".
  'X-Mailer: PHP/' . phpversion();

  $multipart = '';
  $multipart .= "--$boundary\n";
  $kod = 'UTF-8';
  $multipart .= "Content-Type: text/html; charset=$kod\n";
  $multipart .= "Content-Transfer-Encoding: 7-bit\n\n";
  $multipart .= "$html\n\n";
  foreach ($paths as $path) {
    if (file_exists($path['path']))
      $fp = fopen($path['path'],"r");
      if (!$fp)  {
        return false;
      }
    $imagetype = substr(strrchr($path['path'], '.' ),1);
    $file = fread($fp, filesize($path['path']));
    fclose($fp);
    $message_part = "";
    switch ($imagetype) {
      case 'png':
      case 'PNG':
            $message_part .= "Content-Type: image/png";
            break;
      case 'jpg':
      case 'jpeg':
      case 'JPG':
      case 'JPEG':
            $message_part .= "Content-Type: image/jpeg";
            break;
      case 'gif':
      case 'GIF':
            $message_part .= "Content-Type: image/gif";
            break;
    }
    $message_part .= "; file_name = \"$path\"\n";
    $message_part .= 'Content-ID: <'.$path['cid'].">\n";
    $message_part .= "Content-Transfer-Encoding: base64\n";
    $message_part .= "Content-Disposition: inline; filename = \"".basename($path['path'])."\"\n\n";
    $message_part .= chunk_split(base64_encode($file))."\n";
    $multipart .= "--$boundary\n".$message_part."\n";
  }
  $multipart .= "--$boundary--\n";
  mail($to, $subject, $multipart, $headers);
}
2
djunod

Vous devez coder votre e-mail en tant que mime en plusieurs parties, puis vous pouvez essentiellement joindre des e-mails en tant que pièces jointes. Vous les référencez par cid dans l'e-mail.

Alternativement, vous ne pouvez pas les joindre à l'e-mail et utiliser directement les URL, mais la plupart des programmes de messagerie bloquent cela car les spammeurs utilisent l'astuce pour détecter la vivacité des adresses e-mail.

Vous ne dites pas quelle langue mais en voici une exemple .

1
cletus

Voici un moyen d'obtenir une variable chaîne sans avoir à vous soucier du codage.

Si vous avez Mozilla Thunderbird , vous pouvez l'utiliser pour récupérer le code image html pour vous.

J'ai écrit un petit tutoriel ici, complet avec une capture d'écran (c'est pour PowerShell, mais ça n'a pas d'importance pour ça):

email powershell avec image html montrant un x rouge

Et encore:

Comment intégrer des images dans un e-mail

1
bgmCoder