Отправка письма с вложением

Отправка письма с вложением

Проблемы с кодировкой при отправке email писем посредством php мы уже разобрали в предыдущей части нашей статьи. Давайте разберёмся с оставшимися вопросами.

Итак, на повестке дня: использование вложений и вставка изображения в тело письма.

Наверняка многим на почту приходили красивые письма с вёрсткой и картинками. А отправляя письма собственноручно, приходит некрасивый текст. В данной статье мы научимся отправлять письма с красивой версткой и картинками, что часто бывает необходимо при отправке рассылок.

Если вы когда-нибудь сталкивались с отправкой таких писем, то, скорее всего у вас часто возникали следующие проблемы:

  • вложенный файл не открывается или открывается неправильно
  • не показывается текст
  • картинку можно скачать, но она не вставляется в тело письма.

Давайте, попробуем со всем этим разобраться.

Для отправки писем с вложениями используется специальный формат, который называется multipart. В заголовках (headers) он указывается как Content-type: multipart/mixed; boundary=... При этом тело письма состоит из кусочков (каждый кусочек — это часть письма, текст или вложение), которые разделяются значением boundary. Каждый кусочек имеет свои заголовки (конечно же Content-type, ну и другие).

Если кусочку ещё и задать Content-ID, то его можно вставлять в HTML (ссылка при этом будет выглядеть как «CID:<значение Content-ID>»).

Написаный ранее класс для работы с почтой я модифицировал под отправку multipart сообщений:

  1. class TEmail{
  2.   public $from_email;
  3.   public $from_name;
  4.   public $to_email;
  5.   public $to_name;
  6.   public $subject;
  7.   public $data_charset='UTF-8';
  8.   public $send_charset='windows-1251';
  9.   //Части сообщения - текст и т.п.
  10.   private $EOL;
  11.   private $parts=array();
  12.   //Конструктор
  13.   function __construct(){
  14.     $this->EOL=CHR(13).CHR(10);
  15.     }
  16.   //Функция, прикрепляющая файл
  17.   function attachment($content_type,$name,$fn,$content_id=''){
  18.     //Read data from the file...
  19.     $fp=fopen($fn,'rb');
  20.     if(!$fp)return false;
  21.     $str=fread($fp,filesize($fn));
  22.     fclose($fp);
  23.     $msg['attachment']=true;
  24.     $msg['content_type']=$content_type;
  25.     $msg['content_id']=$content_id; //Для вставки в тело письма
  26.     $msg['data']=$str;
  27.     $msg['name']=$name;
  28.     $msg['send_charset']='';
  29.     $msg['transfer_encoding']='base64';
  30.     array_push($this->parts,$msg);
  31.     }
  32.   //Функция, добавляющая тело сообщения
  33.   function body($content_type,$str){
  34.     $msg['attachment']=false;
  35.     $msg['content_type']=$content_type;
  36.     $msg['content_id']='';
  37.     $msg['data']=$str;
  38.     $msg['name']='';
  39.     $msg['send_charset']=$this->send_charset;
  40.     $msg['transfer_encoding']='8bit';//'quoted-printable';
  41.     array_push($this->parts,$msg);
  42.     }
  43.   //Функция для отправки multipart сообщения (с вложениями)
  44.   function send_multipart(){
  45.     $dc=$this->data_charset;
  46.     $sc=$this->send_charset;
  47.     $EOL=$this->EOL;
  48.     $boundary='a'.sha1(uniqid(time()));//любая строка, которой не будет в потоке данных.
  49.     //Encode some fields
  50.     $enc_to=mime_header_encode($this->to_name,$dc,$sc).' <'.$this->to_email.'>';
  51.     $enc_subject=mime_header_encode($this->subject,$dc,$sc);
  52.     if(!empty($this->from_email))
  53.        $enc_from=mime_header_encode($this->from_name, $dc, $sc).' <'.$this->from_email.'>';else
  54.        $enc_from='';
  55.     //Process data...
  56.     $multipart='';
  57.     for($i=0;$i<count($this->parts);$i++){
  58.       $ctype=$this->parts[$i]['content_type'];
  59.       $cname=$this->parts[$i]['name'];
  60.       $ccharset=$this->parts[$i]['send_charset'];
  61.       $ctenc=$this->parts[$i]['transfer_encoding'];
  62.       $cid=$this->parts[$i]['content_id'];
  63.       //Put file into multipart
  64.       $multipart.='--'.$boundary.$EOL;
  65.       $multipart.='Content-Type: '.$ctype.
  66.         (empty($ccharset)?'':'; charset='.$ccharset).
  67.         (empty($cname)?'':'; name='.$cname).$EOL;
  68.       if(!empty($cid))
  69.         $multipart.='Content-ID: <'.$cid.'>'.$EOL;
  70.       $multipart.='Content-Transfer-Encoding: '.$ctenc.$EOL;
  71.       //Different encodings
  72.       if($ctenc=='8bit'){//quoted-printable
  73.         $enc_body=$dc==$ccharset?
  74.           $this->parts[$i]['data']:
  75.           iconv($dc,$ccharset.'//IGNORE',$this->parts[$i]['data']);
  76.         $multipart.=$EOL.$enc_body.$EOL;
  77.         }else
  78.       if($ctenc=='base64'){
  79.         $multipart.=$EOL.chunk_split(base64_encode($this->parts[$i]['data']),76,$EOL).$EOL;
  80.         };
  81.       }
  82.     $multipart.='--'.$boundary.'--'.$EOL;
  83.     //
  84.     $headers='';
  85.     $headers.='Mime-Version: 1.0'.$EOL;
  86.     $headers.='Content-type: multipart/mixed; boundary='.$boundary.$EOL;
  87.     if(!empty($enc_from))
  88.        $headers.='From: '.$enc_from.$EOL;
  89.     //Send email
  90.     return mail($enc_to,$enc_subject,$multipart,$headers);
  91.     }
  92.   //Функция для отправки обычного сообщения
  93.   function send_single(){
  94.     //Get some global variables...
  95.     $dc=$this->data_charset;
  96.     $sc=$this->send_charset;
  97.     $EOL=$this->EOL;
  98.     $body=$this->parts[0]['data'];
  99.     $ctype=$this->parts[0]['content_type'];
  100.     $ccharset=$this->parts[0]['send_charset'];
  101.     //Encode some fields
  102.     $enc_to=mime_header_encode($this->to_name,$dc,$sc).' <'.$this->to_email.'>';
  103.     $enc_subject=mime_header_encode($this->subject,$dc,$sc);
  104.     if(!empty($this->from_email))
  105.        $enc_from=mime_header_encode($this->from_name, $dc, $sc).' <'.$this->from_email.'>';else
  106.        $enc_from='';
  107.     //Encode Body
  108.     $enc_body=$dc==$ccharset?$body:iconv($dc,$ccharset.'//IGNORE',$body);
  109.     //Form headers
  110.     $headers='';
  111.     $headers.='Mime-Version: 1.0'.$EOL;
  112.     $headers.='Content-type: '.$ctype.'; charset='.$ccharset.$EOL;
  113.     if(!empty($enc_from))
  114.        $headers.='From: '.$enc_from.$EOL;
  115.     //Send email
  116.     return mail($enc_to,$enc_subject,$enc_body,$headers);
  117.     }
  118.   function send(){
  119.     if(count($this->parts)==1) return $this->send_single(); else
  120.     if(count($this->parts)>1) return $this->send_multipart(); else
  121.       return false;
  122.     }
  123.   }

Тут функция send() проверяет количество «кусочков». Если «кусочек» один, то отправляет его как текст. Ведь multipart нам не нужен, если мы отправляем только текст.

Функции attachment() и body() прикрепляют текст или вложение. Принцип их работы, я думаю, понятен.

Отправка писем с вложениями не представляет сложности. Тут я прикрепляю картинку и zip-архив:

  1.   require_once(dirname(__FILE__).'/email_api.php');
  2.   echo('Trying to send emails...<br>');
  3.   //HTML email
  4.   echo('Email with attachment - sending...<br>');
  5.   $email=new TEmail;
  6.   $email->from_email='noreply@konservs.com';
  7.   $email->from_name='От "Записок Консерваторов"';
  8.   $email->to_email='*********';
  9.   $email->subject='Тема (ІЇҐЭЄ іїґэє)';
  10.   $email->body('text/html','Письмо в HTML с вложениями.<br>'.
  11.     'Картинка:'.
  12.     '<img src="cid:cid1">'.
  13.     '<h1>Header 1 (Заголовок 1)</h1>'.
  14.     '<h2>Header 2 (Заголовок 2)</h2>'.
  15.     '<h3>Header 3 (Заголовок 3)</h3>'.
  16.     '<h4>Header 4 (Заголовок 4)</h4>'.
  17.     '<h5>Header 5 (Заголовок 5)</h5>'.
  18.     'Тест: ІЇҐЭЄ іїґэє');
  19.   $DS=DIRECTORY_SEPARATOR;
  20.   $email->attachment('image/jpeg','logo.jpg',dirname(__FILE__).$DS.'files'.$DS.'test.jpg','cid1');
  21.   $email->attachment('application/octet-stream','test.zip',dirname(__FILE__).$DS.'files'.$DS.'test.zip');
  22.   if($email->send())
  23.     echo('Email with attachment - OK.<br>'); else
  24.     echo('Email with attachment - Error!<br>');

Пример письма, которое пришло мне.

Письмо с вложением и картинкой

Поздравляем! Вы научились отправлять письма с вложениями.

Комментарии

09.12.2014 05:37:54
Avatar of МиколаМикола
Постійно користуюся цим класом!
Спасибі!
26.12.2016 06:52:44
Avatar of МиколаМикола
ти не повіриш, але все ще користуюся)
20.09.2017 05:48:02
Avatar of
21.09.2017 04:03:52
Avatar of rElenaFutrElenaFut
Работа в интернете
Captcha Обновить
Go Top