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

    Проблемы с кодировкой при отправке 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 МиколаМикола
    ти не повіриш, але все ще користуюся)
    06.08.2019 02:58:45
    Avatar of РадикРадик
    Вопрос по ценам
    10.08.2019 02:08:56
    Avatar of СтаниславСтанислав
    Куда?
    20.08.2019 02:47:09
    Avatar of КириллКирилл
    денб добрый
    24.08.2019 02:28:42
    Avatar of АлександрАлександр
    заказ
    25.08.2019 01:28:58
    Avatar of FrankNutFrankNut
    Look at a seemlyoffers in place of you. http://rophegever.cf/9cako
    27.08.2019 03:50:19
    Avatar of ВадимВадим
    Как с вами связаться?
    27.08.2019 07:18:56
    Avatar of MaxMax
    Обратный звонок
    29.08.2019 04:36:38
    Avatar of DejansuetaDejansueta
    Акция! Завод тары упаковки Политор производит обмен старых поломанных пластиковых ящиков на новые. Условия. стоимость обмена на сайте.https://politor.kiev.ua/ru/prais/jashiki_dlja_ovoshej.html
    30.10.2019 08:28:20
    Avatar of KevinEnenoKevinEneno
    hi there
    I have just checked konservs.com for the ranking keywords and to see your SEO metrics and found that you website could use a boost.

    We will improve your SEO metrics and ranks organically and safely, using only whitehat methods

    Please check our pricelist here, we offer SEO at cheap rates.
    https://www.hilkom-digital.de/cheap-seo-packages/

    Start boosting your business sales and leads with us, today!

    regards
    Hilkom Digital Team
    support@hilkom-digital.de
    31.10.2019 11:31:24
    Avatar of MariaLonMariaLon
    Attn: Beneficiary
    THE WEB PROMOTION PROGRAM. We are pleased to inform you of the release of the results of our ES.INTERNATIONAL WEB PROMOTION PROGRAM. The result was released on the 28 OF OCTOBER 2019. Your e-Website was attached to ticket number 902089237-067 drew lucky numbers 9-24-06-18-05-26. Which consequently won our website lottery program in the 2nd category. Your website has therefore won the sum of €1, 710, 460.00. CONGRATULATION!!!!!!!!!!!
    All participants were selected through a computer ballot system drawn from 25,000 website addresses All over the world as part of our international website promotion program.
    To start your lottery claim and also for more enlightenment regarding to this, kindly contact your agent; Alan Nicolas Matias, FOREIGN OPERATION MANAGER OF Fenix Directo Seguros S.A. by telephone N?: +34 632 822 394, Email: alan@martinjoselaws.com
    Please fills the payment processing form below and retunes it to your claims agent to this email: alan@martinjoselaws.com Congratulations once again.
    Beneficiary Full name: -------------------- Website: --------------------
    Email Address: -------------------------- Tel: --------------------------
    Nationality: ------------------------ Mode of Payment: ----------
    Sincerely yours,
    MRS MARIA LOPEZ DANIEL.
    (ES.WEBSITE LOTTERY COORDINATOR)
    01.11.2019 07:29:44
    Avatar of ДенисДенис
    Здравствуйте! Могу заняться продвижением вашего сайта в Яндекс с оплатой за результат без предоплаты. Результат вы увидите уже через месяц. Если вас не устроит результат - вы ничего не платите! Переходите на сайт, чтобы узнать подробнее про предложение http://agressor-seo.ru. Денис.
    07.11.2019 04:10:25
    Avatar of Продвижение сайтаПродвижение сайта
    Могу заняться продвижением вашего сайта в Яндекс с оплатой за результат без предоплаты. Результат вы увидите уже через месяц. Если вас не устроит результат - вы ничего не платите. Подробнее по ссылке - http://agressor-seo.ru
    Captcha Обновить
    Go Top