PHPでTo、Cc、Bcc、テキストメール、HTMLメール、マルチパートメール、添付ファイル付きUTF-8メールを送信する

mamsendmail.phpの準備

本ページ下部にあるmamsendmail.phpファイルを準備する。

メールの送信

To、Cc、Bcc、テキスト+HTMLメール(マルチパートメール)+添付ファイル(ファイル名は半角のみ)があるUTF-8メールを送る
以下のソースコードのメールアドレスは存在しませんので、実際の送信先メールアドレスに変えて下さい。

<?php
include(__DIR__.'/mamsendmail.php');
mb_language("Japanese");
mb_internal_encoding("UTF-8");  //UTF-8でメールを送信する
//■送り元
$from="mamさんより<from@mam-mam.net>";
//■送り先
//  To又はCcには最低1つの送り先を入れる(Bccのみでは送れない場合がある)
//  複数送り先はカンマ(,)区切りで入れる
$to= "To1さんへ<to1@mam-mam.net>, To2さんへ<to2@mam-mam.net>";
$cc= "<cc1@mam-mam.net>, Cc2さんへ<cc2@mam-mam.net>, cc3@mam-mam.net";
$bcc="Bcc1さんへ<bcc1@mam-mam.net>, bcc2@mam-mam.net, <bcc3@mam-mam.net>";
//■件名
$subject="件名: 長い件名 を入れることもできます。半角も入れられます。23784sdarew!#$%&()=-~^|";
//■テキスト本文  不要なら $textBody="";
$textBody="タイトル\r\n  本文\r\n  テストメール";
//■HTML本文  不要なら $htmlBody="";
$htmlBody="
  <html>
  <head>
    <style>
      h3{color:red;font-size:32px;font-weight:bold;}
      p{color:black;font-size:20px;}
      img{width:100%;max-width:500px;}
    </style>
  </head>
  <body>
    <h3>タイトル</h3>
    <p>
      本文を入れたりしています。<br>
      <img src=\"cid:img1\"><br>
      <img src=\"cid:img2\"><br>
      <img src=\"cid:img3\"><br>
      テストメールです。
    </p>
  </body>
  </html>";
//■添付ファイル  不要なら $files=[];
$files=[__DIR__."/../imgs/0001s.jpg", __DIR__."/../imgs/0002s.jpg", __DIR__."/../imgs/0003s.jpg"];

//メールの送信
mamSendMail::send(
  $from,
  $to,$cc,$bcc,
  $subject,
  $textBody,  $htmlBody,
  $files
); 

mamsendmail.php

<?php
mb_language("Japanese");
mb_internal_encoding("UTF-8");  //UTF-8でメールを送信する

/*
  mamSendMail::send(引数)  UTF-8メール送信クラス
  引数の意味
    $from(必須)
      1つだけメールアドレスを入れる
      例1: $from="from@mam-mam.net";
      例2: $from="<from@mam-mam.net>";
      例3: $from="斎藤<from@mam-mam.net>";
    $to,$cc,$bcc($to又は$ccに宛先アドレスが1つ以上必須[bccだけでは送信できない場合がある])
      カンマ(,)区切りで複数の送り先アドレスを入れることができる
      例: $to="佐藤様<to1@mam-mam.net>, 山田様<to2@mam-mam.net>, to3@mam-mam.net, <to4@mam-mam.net>";
      ccとbccが不要であれば空文字にする  $cc="";$bcc="";
    $subject
      メールの件名
    $textBody
      テキストメール本文
      例: $textBody="テスト\r\n  本文\r\n";
    $htmlBody
      HTMLメール本文
      例: $htmlBody="<html><body><h1 style='font-size:20px;'>テスト</h1><p>本文</p></body></html>";
    注意事項:
    ・「$textBody="何か入っている",$htmlText="何か入っている"」
          ⇒マルチパート(テキストパートとHTMLパート)メールで送信
    ・「$textBody="",$htmlText="何か入っている"」
          ⇒HTMLメールで送信
    ・「$textBody="何か入っている",$htmlText=""」
          ⇒テキストメールで送信
    $files
      必要であればファイル名を配列で入れる
      例:$files=["C:/temp/1.jpg","C:/temp/2.png","C:/temp/3.png"]"
      不要であれば空配列を指定するか省略する
      $files=[];
*/
class mamSendMail{
  public static function send(
    string $from,
    string $to, string $cc, string $bcc,
    string $subject,
    string $textBody, string $htmlBody,
    array $files=[]
  ){
    //ファイルの確認
    for($i=0;$i<count($files);$i++){
      if(!file_exists($files[$i])){
        unset($files[$i]);
        $files=array_values($files);
      }
    }

    $fFrom=self::mamExplodeMailAddress($from);
    if(count($fFrom)==0){return false;}
    if(empty($fFrom[0]["name"])){
      $cFrom=$fFrom[0]["add"];
    }else{
      $cFrom=mb_encode_mimeheader($fFrom[0]["name"],"UTF-8","B","\r\n",10).$fFrom[0]["add"];
    }

    $fTo=self::mamExplodeMailAddress($to);
    //if(count($fTo)==0){return false;}
    $cTo="";
    for($i=0;$i<count($fTo);$i++){
      if(!empty($cTo)){$cTo.=",";}
      if(empty($fTo[$i]["name"])){
        $cTo.=$fTo[$i]["add"];
      }else{
        $cTo.=mb_encode_mimeheader($fTo[$i]["name"],"UTF-8").$fTo[$i]["add"];
      }
    }
    $fCc=self::mamExplodeMailAddress($cc);
    $cCc="";
    for($i=0;$i<count($fCc);$i++){
      if(!empty($cCc)){$cCc.=",";}
      if(empty($fCc[$i]["name"])){
        $cCc.=$fCc[$i]["add"];
      }else{
        $cCc.=mb_encode_mimeheader($fCc[$i]["name"],"UTF-8").$fCc[$i]["add"];
      }
    }
    $fBcc=self::mamExplodeMailAddress($bcc);
    $cBcc="";
    for($i=0;$i<count($fBcc);$i++){
      if(!empty($cBcc)){$cBcc.=",";}
      if(empty($fBcc[$i]["name"])){
        $cBcc.=$fBcc[$i]["add"];
      }else{
        $cBcc.=mb_encode_mimeheader($fBcc[$i]["name"],"UTF-8").$fBcc[$i]["add"];
      }
    }

    $cSubject=mb_encode_mimeheader($subject);

    $cHeaders=[
      "From"=>$cFrom,
      "Reply-To"=>$cFrom,
      "Content-Transfer-Encoding"=>"base64",
      "X-Mailer"=>"PHP Mailer",
    ];

    if(!empty($textBody)&&!empty($htmlBody)){
      //テキスト+HTML メールの場合
      $fHtmlBody=chunk_split(base64_encode($htmlBody));
      $fTextBody=chunk_split(base64_encode($textBody));
      $fBoundary="b1".uniqid("",true);

      if(count($files)==0){
        //添付ファイル無し
        $cHeaders["Content-Type"]='multipart/alternative; boundary="'.$fBoundary.'"';
        $cBody=
          "--".$fBoundary."\r\n".
          "Content-Type: text/plain; charset=UTF-8\r\n".
          "Content-Disposition: inline\r\n".
          "Content-Transfer-Encoding: base64\r\n".
          "\r\n".
          $fTextBody.
          "\r\n".
          "--".$fBoundary."\r\n".
          "Content-Type: text/html; charset=UTF-8\r\n".
          "Content-Disposition: inline\r\n".
          "Content-Transfer-Encoding: base64\r\n".
          "\r\n".
          $fHtmlBody.
          "\r\n".
          "--".$fBoundary."--\r\n";
      }else{
        //添付ファイル有り
        $fBoundary2="b2".uniqid("",true);
        $cHeaders["Content-Type"]='multipart/mixed; boundary="'.$fBoundary.'"';
        $cBody=
          "--".$fBoundary."\r\n".
          "Content-Type: multipart/alternative; boundary=\"".$fBoundary2."\"\r\n".
          "\r\n".
          "--".$fBoundary2."\r\n".
          "Content-Type: text/plain; charset=UTF-8\r\n".
          "Content-Disposition: inline\r\n".
          "Content-Transfer-Encoding: base64\r\n".
          "\r\n".
          $fTextBody.
          "\r\n".
          "--".$fBoundary2."\r\n".
          "Content-Type: text/html; charset=UTF-8\r\n".
          "Content-Disposition: inline\r\n".
          "Content-Transfer-Encoding: base64\r\n".
          "\r\n".
          $fHtmlBody.
          "\r\n".
          "--".$fBoundary2."--\r\n".
          "\r\n".
          "--".$fBoundary."\r\n";
        for($i=0;$i<count($files);$i++){
          if(preg_match('/\.gif$/i',$files[$i])){
            $hd="image/gif";
            $cd="inline";
          }else if(preg_match('/\.jpg$|\.jpeg$/i',$files[$i])){
            $hd="image/jpeg";
            $cd="inline";
          }else if(preg_match('/\.png$/i',$files[$i])){
            $hd="image/png";
            $cd="inline";
          }else{
            $hd="application/octet-stream";
            $cd="attachment";
          }
          $cBody.=
            "Content-Type: ".$hd."; name=\"".basename($files[$i])."\"\r\n".
            "Content-Disposition: ".$cd."; filename=\"".basename($files[$i])."\"\r\n".
            "Content-Transfer-Encoding: base64\r\n".
            "Content-ID: <img".($i+1).">\r\n".
            "Content-Location: ".basename($files[$i])."\r\n".
            "\r\n".
            chunk_split(base64_encode(file_get_contents($files[$i])));
          if($i==(count($files)-1)){
            $cBody.="--".$fBoundary."--\r\n";
          }else{
            $cBody.="--".$fBoundary."\r\n";
          }
        }
      }
    }else if(!empty($htmlBody)){
      //HTMLメールのみ
      if(count(files)==0){
        $cHeaders["Content-Type"]='text/html;charset=utf-8';
        $cBody=chunk_split(base64_encode($htmlBody));
      }
    }else{
      //テキストメールのみ
      if(count(files)==0){
        $cHeaders["Content-Type"]='text/plain;charset=utf-8';
        $cBody=chunk_split(base64_encode($textBody));
      }
    }

    if(!empty($cCc)){
      $cHeaders["Cc"]=$cCc;
    }
    if(!empty($cBcc)){
      $cHeaders["Bcc"]=$cBcc;
    }
    mail($cTo,$cSubject,$cBody,$cHeaders);
  }

  private static function mamExplodeMailAddress(string $add){
    $add=trim($add);
    if(empty($add)){return [];}
    $addresses=explode(",",$add);
    $ret=[];
    foreach($addresses as $address){
      $mail=["name"=>"", "add"=>$address];
      $s=mb_strpos($address,"<",0,"UTF-8");
      if($s!==false && $s>0){
        $e=mb_strpos($address,">",$s,"UTF-8");
        if($e!==false && $e>0){
          $mail["name"]=trim(mb_substr($address,0,$s));
          $mail["add"] =mb_substr($address,$s,$e);
        }
      }
      $ret[]=$mail;
    }
    return $ret;
  }
}