【问题标题】:How to embed images in html email如何在html电子邮件中嵌入图像
【发布时间】:2010-12-23 12:43:41
【问题描述】:

我正在尝试实现一个代码来发送带有嵌入图像的 HTML 电子邮件。

我已经尝试过带有图片的简单 HTML 电子邮件,但这张图片是从服务器获取的。

【问题讨论】:

  • >而且我不想使用任何像 PEAR 这样的库 为什么会这样?关于为什么需要重新发明轮子的任何合理论据?
  • @FractalizeR 我想了解它是如何工作的。

标签: php html image email


【解决方案1】:

这是我用来将图像嵌入 HTML 邮件和 PDF 文档的代码。

<?php
$logo_path = 'http://localhost/img/logo.jpg';
$type = pathinfo($logo_path, PATHINFO_EXTENSION);
$image_contents = file_get_contents($logo_path);
$image64 = 'data:image/' . $type . ';base64,' . base64_encode($image_contents);
?>
<img src="<?php echo $image64 ?>" />

【讨论】:

    【解决方案2】:

    我做了golang命令行来做这个工作,关键是做cid替换:

    https://github.com/gonejack/embed-email

    【讨论】:

      【解决方案3】:

      我强烈建议使用像 PHPMailer 这样的库来发送电子邮件。
      它更容易并自动为您处理大部分问题。

      关于显示嵌入(内嵌)图像,这是their documentation 上的内容:

      内嵌附件

      还有一种方法可以添加 附件。如果你想制作 HTML 包含图像的电子邮件 桌子,有必要附上 图像,然后将标签链接到它。为了 例如,如果您将图像添加为内联 带有 CID my-photo 的附件,你 将在 HTML 电子邮件中访问它 <img src="cid:my-photo" alt="my-photo" />

      详细来说,这里是要添加的功能 内联附件:

      $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 ');
      

      给你一个更完整的例子来说明它是如何工作的:

      <?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('name@yourdomain.com', 'First Last');
        $mail->AddAddress('whoto@otherdomain.com', '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!
      }
      ?>
      

      编辑:

      关于您的评论,您询问了如何发送带有嵌入图像的 HTML 电子邮件,所以我给了您一个示例来说明如何做到这一点。
      我告诉你的库可以使用 SMTP 以外的许多方法发送电子邮件。
      查看PHPMailer Example page 了解其他示例。

      一种或另一种方式,如果您不想以库支持的方式发送电子邮件,您可以(应该)仍然使用库来构建消息,然后按照您想要的方式发送。

      例如:

      您可以替换发送电子邮件的行:

      $mail->Send();
      

      有了这个:

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

      希望对您有所帮助。 如果您在使用它时遇到问题,请告诉我。

      【讨论】:

      • 嗨,卡洛斯,你很棒,但我对你给出的例子不满意,因为你使用 smtp 服务器解决了我的问题,而我没有使用 SMTP 服务器我正在使用简单的火 ftp 但是无论如何感谢您的帮助
      • 用替代方法更新了答案。希望有帮助!祝你好运:)
      • 我必须添加 $mail-&gt;IsHTML(true); 才能嵌入图像。
      【解决方案4】:

      根据 Arthur Halma 的回答,我执行了以下操作,可以正常使用 Apple、Android 和 iOS 邮件。

      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);
      }
      

      【讨论】:

        【解决方案5】:

        这是一种无需担心编码即可获取字符串变量的方法。

        如果您有 Mozilla Thunderbird,您可以使用它为您获取 html 图像代码。

        我在这里写了一个小教程,并附上了截图(这是针对powershell的,但这无关紧要):

        powershell email with html picture showing red x

        再说一遍:

        How to embed images in email

        【讨论】:

          【解决方案6】:

          我正在使用此功能查找我的信件中的所有图像并将其附加到邮件中。

          参数:获取您的HTML(您要发送的);
          返回:必要的HTML和标题,您可以在mail()中使用;

          用法示例:

          define("DEFCALLBACKMAIL", "yourmail@yourdomain.com"); // WIll be shown as "from".
          $final_msg = preparehtmlmail($html); // give a function your html*
          
          mail('your@mail.com', '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);  
          }
          

          【讨论】:

          • 请注意,编辑后的解决方案不再有效,因为随机放置了 * 而不是 ;在此行之后:$final_msg = preparehtmlmail($html)。更改后,它几乎可以完美运行:现在它仍然在 from 字段中显示 DEFFCALLBACKMAIL...
          • 这样有效吗?我试过了 file_name = \"$path\"\n 在电子邮件中说 file_name = Array
          • 因为 $path 是数组而不是字符串。试试 $path['path'] 。
          • 也应该在图片扩展上使用strtolower() :P
          • $_SERVER['DOCUMENT_ROOT'].$uri['path'];应该是:$_SERVER['DOCUMENT_ROOT'].'/'.$uri['path'];
          【解决方案7】:

          PHPMailer 能够从您的 HTML 电子邮件中自动嵌入图像。编写 HTML 时,您必须在文件系统中提供完整路径:

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

          它会自动转换为:

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

          【讨论】:

            【解决方案8】:

            您必须将您的电子邮件编码为多部分 mime,然后您基本上可以将电子邮件附加为附件。您在电子邮件中通过 cid 引用它们。

            或者,您不能将它们附加到电子邮件中并直接使用 URL,但大多数邮件程序会阻止这一点,因为垃圾邮件发送者会使用该技巧来检测电子邮件地址的活跃度。

            你没有说是什么语言,但这里有一个example

            【讨论】:

            • 先生,我如何将我的电子邮件编码为多部分 mime,这意味着有任何代码吗?
            猜你喜欢
            • 2011-10-06
            • 2015-03-14
            • 2020-12-14
            • 2016-11-06
            • 2012-02-10
            • 2017-08-31
            • 2019-08-13
            • 2010-10-29
            相关资源
            最近更新 更多