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

    Проблемы с кодировкой при отправке 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 СтаниславСтанислав
    Куда?
    27.08.2019 03:50:19
    Avatar of ВадимВадим
    Как с вами связаться?
    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
    16.11.2019 08:18:12
    Avatar of ДенисДенис
    Здравствуйте! Могу заняться продвижением вашего сайта в Яндекс с оплатой за результат без предоплаты. Результат вы увидите уже через месяц. Если вас не устроит результат - вы ничего не платите! Переходите на сайт, чтобы узнать подробнее про предложение http://agressor-seo.ru. Денис.
    08.12.2019 12:57:05
    Avatar of ThomasAndersonThomasAnderson
    Hello
    I invite you to my team, I work with the administrators of the company directly.
    - GUARANTEED high interest on Deposit rates
    - instant automatic payments
    - multi-level affiliate program
    If you want to be a successful person write:
    Telegram: @Tom_proinvest
    Skype: live:.cid.18b402177db5105c Thomas Anderson

    http://bit.ly/2seNGnh
    28.03.2020 09:45:06
    Avatar of JamesMuhJamesMuh
    Today every person on Earth has been affected by the COVID-19 outbreak. Airplanes are grounded, borders are closed, businesses are shut, citizens are forced into quarantine, and governments are taking spontaneous emergency decisions undermining the principles of democracy.
    All this, if not stopped shortly, can lead to chaos and unrests.
    Currently HTTP://WWW.ST-lF.COM is proud to represent the world-wide scientific community, by fundraising for COVID-19 Vaccine Development.
    It is a responsibility of every human-being to put every effort to fight the deadly virus. Your support is needed to develop a vaccine ASAP! Every 1$ makes a difference.
    Please, take a moment to review our campaigns HTTP://WWW.ST-lF.COM
    Captcha Обновить
    Go Top