программирование на PHP
Bullet (black) Email иконка RSS иконка
  • Урок 15. Отправка почты с вложениями.

    Сентябрь 15th, 2008 Александр 28 Комментариев

    Наш предыдущий урок, в котором мы разбирали способ организации обратной связи был достаточно простой. Тогда мы рассмотрели возможность отправки только текстовой информации. Как поступить если требуется отправить письмо с вложением? Ответ на этот вопрос вы получите в этом уроке. Рассмотрим один из наиболее типичных способов отправки почты с вложением, в состав которого будет входить материал из предыдущих моих публикаций.

    Детали

    Разберем по пунктам с чем нам сегодня придется столкнуться:

    1. Создание формы отправки сообщения.
    2. Upload файла на сервер, для последующей отправки как вложение.
    3. Составление письма и прикрепление файла. Функция отправки почты с вложением.

    Форма отправки сообщения.

    Форма будет представлять стандартную страницу с несколькими полями:

    1. Имя отправителя (обязательное поле);
    2. Электронный адрес отправителя (обязательное поле);
    3. Тема сообщения (обязательное поле);
    4. Текст сообщения (может оставаться пустым);
    5. Кнопка для выбора файла.

    В нашем примере будет учавствовать один исполнительный файл – index.php, файл с функциями – functions.inc.php и конфигурационный файл – config.inc.php. Также для хранения временных файлов необходимо создать папку tmp.

    index.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?php

    @include("config.inc.php");
    @include("functions.inc.php");

    if($_POST['do'] =='') {
        //Отображаем форму
        echo '<form action="" method="post" enctype="multipart/form-data">';
        echo 'Ваше имя: <input name="name" type="text" value=""><br/>';
        echo 'Ваш e-mail: <input name="mail" type="text" value=""><br/>';
        echo 'Тема сообщения: <input name="subj" type="text" value=""><br/>';
        echo 'Сообщение:<br/>';
        echo '<textarea name="text" rows=5 cols=20 wrap="off"></textarea><br/>';
        echo 'Файл (не более 300кб): <input type="file" name="FILE" size="30" />&nbsp;&nbsp;';
        echo '<input name="do" type="submit"  value="Отправить">';
        echo '</form>';

                  }

    Как обычно, в первую очередь подключаем файл с функциями и настройками. Далее, обычное условие проверяет наличие переменной $_POST['do'], при отсутствии которой производим вывод формы в браузер. Разумеется все это мы когда то рассматривали в предыдущих уроках, поэтому не будем заострять на этом внимание.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    if($_POST['do'] !='') {
        //Проверяем входящие данные (имя, е-мэйл)
         if($_POST['name'] !='') {
            if($_POST['subj'] !='') {
            if(checkmail($_POST['mail']) !== -1) {
                  //переопределяем переменные
                  $name =  strip_tags($_POST['name']);
                  $text =  $_POST['text'];
                  $email = $_POST['mail'];
                  $subj =  $_POST['subj'];
                  //Формируем текст сообщения
                  $message = "Отправитель ".$email."<br/>---------------------------<br/>";
                  $message .= $text."<br/>---------------------------<br/>
    С уважением, "
    .$name;

                  //Проверяем, существует ли файл.
    if($_FILES['FILE']['name'] !=''){
                    //Проверяем размер файла
       if($_FILES['FILE']['size'] != 0 AND $_FILES['FILE']['size']<=($maxsize*1024)) {
                //Проверяем загрузился ли файл на сервер
           if(is_uploaded_file($_FILES['FILE']['tmp_name']))   {
                //Перемещаем загруженный файл в необходимую папку $url
                if(move_uploaded_file($_FILES['FILE']['tmp_name'], $url."/".basename

    ($_FILES['FILE']['name']))) {

                        //XMail( $from, $to, $subj, $text, $filename)
                          if(xmail($from,$mailto,$subj,$message,$url."/".basename

    ($_FILES['FILE']['name']))!== FALSE) {
                           echo '<p>Сообщение отправлено<br/><a

    href="index.php">назад</a></p>'
    ;
    @unlink($url."/".basename($_FILES['FILE']['name']));
                          }
                    }    else { echo 'Произошла ошибка при перемещении

    файла в папку'
    .$url;}

                }  else { echo'Прозошла ошибка при загрузке файла на сервер';}

           } else {echo 'Размер файла не должен превышать '.$maxsize.' Кб';}
         }

            else {//Используем функцию отправки сообщения без вложения
                 if(sendmail($from,$mailto,$subj,$message) !== FALSE) {
                  echo '<p>Сообщение отправлено<br/><a

    href="index.php">назад</a></p>'
    ;

               }

               else { echo 'Отправка сообщения невозможна: повторите позднее<br/><a

    href="index.php">назад</a></p>'
    ;}
              }


             }  else {echo 'Отправка сообщения невозможна:введите корректный <b>e-

    mail</b><br/><a href="index.php">назад</a>'
    ;}

            }   else {echo 'Отправка сообщения невозможна: необходимо ввести

    <b>тему сообщения</b><br/><a href="index.php">назад</a>'
    ;}


        } else {echo 'Отправка сообщения невозможна: необходимо ввести

    <b>имя</b><br/><a href="index.php">назад</a>'
    ;}
        }
    ?>

    После нажатия на кнопку срабатывает другое условие, в котором $_POST['do'] существует. Внутри следует стандартная проверка имени отправителя и проверка эл.адреса знакомой нам функцией checkmail(). После этого наш скрипт проверяет наличие файла. Если он существует, то произведем проверку его размера (не более 300 кб) и помещаем в директорию для временного хранения (tmp). После того как функция по отправке почты вернула TRUE необходимо удалить файл. Это выполняем при помощи простой функции unlink(путь_до_файла)

    Функция отправки почты с вложением

    Чтобы отправить сообщение с вложением, будет использована функция xmail(). У данной функции будет несколько аргументов:

    1. $from - Отправитель письма. Смысл данной переменной мы рассмотрим ниже.
    2. $to - Адрес электронной почты, куда необходимо отправить сообщение.
    3. $subj – Тема письма.
    4. $text - Текст сообщения.
    5. $filename – имя файла (путь до файла), который необходимо отправить адресату.

    Если же файла не существует, мы поступаем как в уроке №11, т.е. отправляем простое текстовое сообщение, используя модифицированную функцию sendmail().

    functions.inc.php

    Как было указано выше, этот файл будет содержать 3 функции. Начнем с наиболее сложной – xmail().

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    function xmail( $from, $to, $subj, $text, $filename) {
    $f         = fopen($filename,"rb");
    $un        = strtoupper(uniqid(time()));
    $head      = "From: $from\n";
    $head     .= "To: $to\n";
    $head     .= "Subject: $subj\n";
    $head     .= "X-Mailer: PHPMail Tool\n";
    $head     .= "Reply-To: $from\n";
    $head     .= "Mime-Version: 1.0\n";
    $head     .= "Content-Type:multipart/mixed;";
    $head     .= "boundary=\"----------".$un."\"\n\n";
    $zag       = "------------".$un."\nContent-Type:text/html;\n";
    $zag      .= "Content-Transfer-Encoding: 8bit\n\n$text\n\n";
    $zag      .= "------------".$un."\n";
    $zag      .= "Content-Type: application/octet-stream;";
    $zag      .= "name=\"".basename($filename)."\"\n";
    $zag      .= "Content-Transfer-Encoding:base64\n";
    $zag      .= "Content-Disposition:attachment;";
    $zag      .= "filename=\"".basename($filename)."\"\n\n";
    $zag      .= chunk_split(base64_encode(fread($f,filesize($filename))))."\n";

    return @mail("$to", "$subj", $zag, $head);
    }

    Внутри функции формируются 2 переменные $head и $zag. Но для начала мы открываем файл, который был передан функции. Далее создаем вспомогательную переменную $un, содержащую особый уникальный id, генерируемый функцией uniq_id(). Он будет использоваться для указания границ.

    Формирование $head

    Отправляя сообщение, мы должны указать служебную информацию в заголовках, поэтому мы формируем переменную $head, которая содержит в себе адрес отправителя ($from), тему письма ($subj) , адресата ($to), название программы отправителя (X-Mailer: Freshcoder.ru) и указываем тип контента. В отличие от предыдущего урока, в  Content-type указываем multipart/mixed. Это  говорит о том, что сообщение смешанное, т.е. помимо текста содержит в себе вложение.

    Формированию $zag

    $zag в нашем случае является телом сообщения, в котором содержится текст сообщения и собственно наше вложение в особой кодировке. Для начала создаем границу (———$un), после которой указываем новый тип контента Content-type: text/html и кодировку отправки Content-transfer-encoding:8bit. Далее следует переменная содержащая текст письма – $text.

    Так как тело сообщения состоит не только из текста, но и из вложения, необходимы дополнительные манипуляции. Мы создаем вторую границу (———-$un), после которой следуют аттач. Content-type указываем application/octet-stream, имя name$filename. Обязательно указываем Content-transfer-encoding: Base64 и сообщаем что далее следует аттач (Content-Disposition: attachment). Теперь открытый файл читаем в строку ( fread($f,filesize($filename)) ), кодируем её функцией base64_encode() и разбиваем на куски функцией chunk_split(). Это стандартные операции при работе с вложением.

    Если код оформляется следующим образом:
    $zag = “————”.$un.”\n”;
    $zag .= Content-Type:text/html;\n”;

    то это значит, что  применяется стандартная операция “накапливания” переменной. Т.е. первоначально мы указываем первую часть переменной, далее при присваивании ей следующей части используем точку перед знаком равно. Это операция очень полезна. Теперь если вывести переменную в браузер то она будет содержать строку ————”.$un.”\nContent-Type:text/html;\n .В будущем мы рассмотрим несколько примеров с использованием данной операции.

    Завершающий этап функции – это возврат значения функции mail(), атрибутами которой как раз являются наши стандартные переменные ($from и $to) и сформированные внутри функции ($zag и $head). Если сообщение будет отправлено, то функция вернет TRUE.

    Напомню что для отправки простого сообщения используется измененная функция sendmail()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function sendmail($from,$to,$subj,$text) {
    $head      = "From: $from\n";
    $head     .= "To: $to\n";
    $head     .= "Subject: $subj\n";
    $head     .= "X-Mailer: Freshcoder.ru\n";
    $head     .= "Reply-To: $from\n";
    $head     .= "Mime-Version: 1.0\n";
    $head     .= 'Content-type: text/html; charset=windows-1251' . "\r\n";
    return @mail($to,$subj,$text,$head);
    }

    Единственное изменение в том, что заголовки формируются внутри функции, так же как и в функции xmail().

    Третяя функция checkmail() используется для проверки введенного электронного адреса на корректность. Работу этой функции мы рассматривали в этом уроке.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function checkmail($mail) {
    // режем левые символы и крайние пробелы
    $mail=trim($mail);
    // если пусто - выход
    if (strlen($mail)==0) return -1;
    if (!preg_match("/^[a-z0-9_-]{1,20}+(\.){0,2}+([a-z0-9_-]){0,20}@(([a-z0-9-]+\.)+(com|net|org|mil|".
    "edu|gov|arpa|info|biz|inc|name|[a-z]{2})|[0-9]{1,3}\.[0-9]{1,3}\.[0-".
    "9]{1,3}\.[0-9]{1,3})$/is",$mail))
    return -1;
    return $mail;
    }

    Файл конфигурации.

    Файл конфигурации содержит минимальные настройки, которые необходимы для корректной работы скрипта.

    1
    2
    3
    4
    5
    6
    $url = "tmp";
    $maxsize = 300;
    $from = "Сообщение с сайта %sitename%";
    //Адрес куда отправлять
    $mailto = "admin@site.ru";
    ?>

    Указываем имя папки, максимальный размер вложения (в кб) и адрес куда будет уходить письмо.

    Скрипт отправки почты с вложением

    Готовый вариант того что в итоге получилось, можно посмотреть ЗДЕСЬ.
    Скачать скрипт – sendmail.zip

    Полезное

    Отправка почты средствами PHP

    Заключение

    Если все было написано без ошибок и верно выставленных настройках, скрипт заработает сразу. Не гарантируется работа на бесплатных хостингах. Советую немного доработать этот скрипт в сторону ограничения количества отправляемых сообщений в минуту. Выполнить это можно простой установкой cookie у пользователя на 1 минуту, а потом создать условие, которое будет проверять наличие cookie.

    Многие продвинутые программисты с критикой относятся к функции mail() в PHP для отправки сообщения. Я полностью поддерживаю критику и публикую этот материал только из за того, что многим будет трудновато освоить готовые классы из PEAR. Сегодняшний урок  пригодиться в решении простых задач.

    Google Bookmarks БобрДобр.ru Memori.ru rucity.com МоёМесто.ru Mister Wong
    rss-лентаПодпишись на RSS, впереди много интересного.

    28 Responses to “Урок 15. Отправка почты с вложениями.”

    Страницы: [3] 2 1 » Show All

    1. 28
      slNo Gravatar Says:

      Александр, скрипт работает, все в порядке, только каждый раз приходит по 2 письма (что с вложением что без). в поле кому e-mail повторяется 2 раза (поэтому и приходит 2 письма)
      В чем может быть дело?
      переменной $mailto присвоен, естественно, 1 адрес.

    2. 27
      АлексNo Gravatar Says:

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

      Он в конце поста http://blog.webmasterschool.ru/archives/119#comment-1253

    3. 26
      learnchikNo Gravatar Says:

      Здравствуйте! Хочу сказать большое спасибо. Облазил весь интернет, чтобы найти корректный код отправки письма с вложениями. Ваш код четко работает. Посмотрите сами: http://nn.dekane.ru/order.php

      Только вот плохо, что без капчи. Будем теперь ждать, когда к этой форме капчу прилепят. я несколько раз пытался kcaptha прилепить ничего не выходит. Может кто поможет?

    4. 25
      pes092No Gravatar Says:

      Я извиняюсь конечно но не поскажете мне как сделать
      ————————-
      “Советую немного доработать этот скрипт в сторону ограничения количества отправляемых сообщений в минуту. Выполнить это можно простой установкой cookie у пользователя на 1 минуту, а потом создать условие, которое будет проверять наличие cookie.”
      ————————–
      Заранее спасибо.
      С уважением Евгений.

    5. 24
      АлександрNo Gravatar Says:

      Попробуйте использовать сочетание \r\n

    6. 23
      MaximusNo Gravatar Says:

      Спасибо за урок. Все работает. Только появилась одна проблема.
      Пример:
      $text = “Сообщение оставил(а)-”.$name.”
      \nПредприятие – “.$company;
      Игнорирует \n. Выводит в одну строку.

    7. 22
      voodyNo Gravatar Says:

      извините, а как вставить форму на страницу html?

    8. 21
      АлександрNo Gravatar Says:

      Если у вас качественный хостер, то письма, которые вы будете отправлять при помощи функции mail() то ничего страшного не будет. Просто при составлении заголовков и тема сообщения должна исключать слова-паразиты. Их можно выяснить методом научного тыка :) . Для простой отправки почты этого скрипта хватит.

    Страницы: [3] 2 1 » Show All

    Leave a Reply


freshcoder.ru © 2008 • При использовании материалов активная ссылка на сайт обязательна.
SEO Powered by Platinum SEO from Techblissonline