Форма обратной связи с прикреплением файла (Send attachments with PHP Mail())

16.07.2017

Форма обратной связи с прикреплением файла (attach)

Самый простой внешний вид формы обратной связи с тремя полями и полем для прикрепления файла:

<form id="feedback-form" enctype="multipart/form-data" method="post">
  <div class="form-group">
    <label for="nameFF">Name</label>
    <input id="nameFF" name="nameFF" type="text" placeholder=" " required>
  </div>
  <div class="form-group">
    <label for="contactFF">E-mail</label>
    <input id="contactFF" name="contactFF" type="email" placeholder=" " required>
  </div>
  <div class="form-group">
    <label for="projectFF">About your Project</label>
    <input id="projectFF" name="projectFF" type="text" placeholder=" " required>
  </div>
  <div class="control-file">
    <label for="fileFF">Attach file</label>
    <input id="fileFF" name="fileFF" type="file">
  </div>
  <button class="btn" type="submit" id="submitFF">Send</button>
</form>

Даже добавим пару правил для стилей, чтобы форма была понятного вида:

<style>
  label{
    display: block;
    margin: 20px 0 2px;
  }
  .btn{
    margin: 20px 0 0;
  }
</style>

Самое главное содержимое файла mail.php

<?php
if (isset ($_POST['contactFF'])) {
  $to = "to@gmail.com";
  $from = "from@gmail.com";
  $subject = "Заполнена контактная форма на сайте ".$_SERVER['HTTP_REFERER'];
  $message = "Имя: ".$_POST['nameFF']."\nКонтакты ".$_POST['contactFF']."\nПроект: ".$_POST['projectFF']."\n\nIP: ".$_SERVER['REMOTE_ADDR'];

  $boundary = md5(date('r', time()));
  $filesize = '';
  $headers = "MIME-Version: 1.0\r\n";
  $headers .= "From: " . $from . "\r\n";
  $headers .= "Reply-To: " . $from . "\r\n";
  $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n";
  $message="
Content-Type: multipart/mixed; boundary=\"$boundary\"

--$boundary
Content-Type: text/plain; charset=\"utf-8\"
Content-Transfer-Encoding: 7bit

$message";
     if(is_uploaded_file($_FILES['fileFF']['tmp_name'])) {
         $attachment = chunk_split(base64_encode(file_get_contents($_FILES['fileFF']['tmp_name'])));
         $filename = $_FILES['fileFF']['name'];
         $filetype = $_FILES['fileFF']['type'];
         $filesize = $_FILES['fileFF']['size'];
         $message.="

--$boundary
Content-Type: \"$filetype\"; name=\"$filename\"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=\"$filename\"

$attachment";
     }
   $message.="
--$boundary--";

  if ($filesize < 10000000) { // проверка на общий размер всех файлов. Многие почтовые сервисы не принимают вложения больше 10 МБ
    mail($to, $subject, $message, $headers);
    echo $_POST['nameFF'].', Ваше сообщение отправлено, спасибо!';
  } else {
    echo 'Извините, письмо не отправлено. Размер всех файлов превышает 10 МБ.';
  }
}
?>

Содержимое файла mail.js, перед подключением этого файла, подключаем jQuery.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

Затем скрипт mail.js

$(function() {

  // E-mail Ajax Send
  // https://denis-creative.com/contact-form-with-attached-file/
  // http://shpargalkablog.ru/2014/05/email-file-php.html
  // http://shpargalkablog.ru/2014/05/feedback-form-file.html
  document.getElementById('feedback-form').addEventListener('submit', function(evt){
    var http = new XMLHttpRequest(), f = this;
    var th = $(this);
    evt.preventDefault();
    http.open("POST", "mail.php", true);
    http.onreadystatechange = function() {
      if (http.readyState == 4 && http.status == 200) {
        alert(http.responseText);
        if (http.responseText.indexOf(f.nameFF.value) == 0) { // очистить поля формы, если в ответе первым словом будет имя отправителя (nameFF)
          th.trigger("reset");
        }
      }
    }
    http.onerror = function() {
      alert('Извините, данные не были переданы');
    }
    http.send(new FormData(f));
  }, false);

});

Полезная инфа:

Комментарии (22) к “Форма обратной связи с прикреплением файла (Send attachments with PHP Mail())”

  • Дмитрий

    Доброго времени ! Форма просто супер, даже без танцев с бубном, как это обычно бывает !!!

    Подскажите а как сделать чтобы и людям, отправившим запрос, приходило письмо к примеру от webmaster@домен
    с такими же данными и припиской в конце:

    Спасибо за обращение!
    В ближайшее время наши сотрудники свяжутся с Вами.
    Это сообщение отправлено с сайта (в скобках ссылка на сайт)

    Буду очень признателен если поможете. Уже создал папку с закладками вашего блога …

    Ответить
  • Владимир

    Салют!
    Благодарю за материал.
    Вопрос: Почему не срабатывает оповещение о превышении лимита?
    OpenServer Apache 2.4, PHP 5.6

    Ответить
  • JulieNeuch

    День добрый.
    Спасибо за ресурс.

    Ответить
  • Ольга

    Обычно требуется прикрепить файл, выбрав с компьютера, но мне нужно прикрепить жестко только один файл, и не с компьютера, а с сайта, на котором расположена форма обратной связи. Можно ли, в принципе, это сделать, и как?

    Ответить
    • Denis Creative

      К сожалению, не подскажу.
      Если файл уже находится на внешнем ресурсе, а не на компьютере, тогда может проще просто давать ссылку в письме?..

      Ответить
  • Elena

    Почему-то файлы в pdf не отправляются((

    Ответить
    • Denis Creative

      А в другом формате отправляются?

      Ответить
      • Elena

        Картинки jpg отправляются, другие не смотрела форматы…

        Ответить
        • Denis Creative

          Не знаю, в коде формы нет никакого фильтра по форматам файлов. Возможно настройки хостинга, можете обратиться в ТП хостинга, может они помогут, если сама форма работает и другие форматы отправляет.

          Ответить
  • Владимир

    Почему приходят пустые файлы? т.е. весят 0 байт

    Ответить
    • Denis Creative

      Тестировал на разных сайтах и серверах, проблем не замечал, главное, не менять код, потому как при попытке “красиво отформатировать” файл mail.php – он совсем переставал работать. Поэтому попробуйте поменять только адресата и отправителя, а сам код не изменять.

      Ответить
      • Владимир

        Так и делаю, все равно приходит пустой файл, и еще не приходят другие данные с формы (имя,емаил,о проекте), т.е. в письме только файл(пустой) и ip отправителя

        Ответить
        • Denis Creative

          Может какие-то настройки хостинга, точно не скажу, не сталкивался…
          Попробуйте, если есть возможность, свой код на другом сервере.

          Ответить
          • Владимир

            Буду разбираться, но все равно Спасибо за помощь

          • Владимир

            Очень странно, на почте gmail все работает отлично, вот на яндекс.почте все именно так как я описывал

          • Denis Creative

            Если хостинг в Украине, тогда могут быть такие проблемы с Yandex и Mail.ru

  • belleRic

    Hello i am new user and i would to ask you, How to disable avatar?

    Ответить
  • Елена

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

    $("#form-help").validate({
      rules: {
        nameFF: "required",
        phoneFF: "required",
        emailFF: "required",
        message: "required",
      },
      messages: {
        nameFF: "<p style='font-size:10px; color:red;'>Укажите Ваше имя.</p>",
        phoneFF: "<p style='font-size:10px; color:red;'>Укажите Ваш номер телефона.</p>",
        emailFF: "<p style='font-size:10px; color:red;'>Укажите Ваш email.</p>",
        message: "<p style='font-size:10px; color:red;'>Опишите задачу.</p>",
      },
      
      submitHandler: function(form){
    
        document.getElementById('form-help').addEventListener('submit', function(evt){
          var http = new XMLHttpRequest(), f = this;
          var th = $(this);
          evt.preventDefault();
          http.open("POST", "help.php", true);
          http.onreadystatechange = function() {
            if (http.readyState == 4 && http.status == 200) {
              alert(http.responseText);
              if (http.responseText.indexOf(f.nameFF.value) == 0) {
                th.trigger("reset");
              }
            }
          }
          http.onerror = function() {
            alert('Извините, данные не были переданы');
          }
          http.send(new FormData(f));
        }, false);
      }
    });
    
    Ответить
  • MelvinCeS

    Годнота

    Ответить
  • Michelle

    Have you ever thought about adding a little
    bit more than just your articles? I mean, what you say is fundamental
    and everything. Nevertheless think of if you added some great pictures or
    video clips to give your posts more, “pop”! Your content is
    excellent but with images and videos, this site could certainly be one of the greatest in its field.
    Terrific blog!

    Ответить
    • Denis Creative

      Thanks for the idea, I’ll try to add more graphic content. It’s just that I have hundreds of notes in drafts, and there is no time to arrange even the text, not to mention the pictures or videos, but the idea is worthwhile.

      Ответить

Оставить комментарий