Отправка письма с прикрепленным файлом из Drupal

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

    Итак, по счастью, как правило, в Друпале изобретать велосипед приходится крайне редко, главное уметь найти готовое решение на drupal.org. Признаюсь, что пришлось потратить определенное время, чтобы его найти и именно по этому я пишу это сообщение, чтобы сэкономить Ваше время, если перед Вами встанет такая задача.

    Мой выбор пал на Mime Mail модуль (http://drupal.org/project/mimemail), другой альтернативы я не нашел.

    Для простоты понимания, разбавлю свое повествование примерами (позволю себе выбрать Drupal 6, что связано с тем, что сайта заказчика был на шестерке). Для начала сделаем формочку, для ввода письма и прикрепления файла:

    function custom_mail_form() {
    
      $form['#attributes'] = array('enctype' => "multipart/form-data"); // чтобы файлы передавались в функцию обработчик
    
      $form['mail_to'] = array(
        '#type' => 'textfield',
        '#title' => t('E-mail'),
        '#required' => TRUE,	
      );  
    
      $form['mail_subject'] = array(
        '#type' => 'textfield',
        '#title' => t('Subject'),
        '#required' => TRUE,	
      );  
    
      $form['mail_body'] = array(
        '#type' => 'textarea',
        '#title' => t('Body'),
        '#required' => TRUE,
      );
    
      $form['mail_attachment'] = array(
        '#type' => 'file', 
        '#title' => t('Attachment'), 
      );  
    
      $form['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Send'),
        );
    
      return $form;
    }
    
    


    В зависимости от задачи, можно не делать новую форму, а модиффицировать существующую, добавив поле file и функцию обработчик с помощью хука form_alter.

    Не буду останавиливаться на валидации данных формы, замечу, что, по крайней мере, поле 'mail_to' нужно отвалидировать. Напишу сразу обработчик этой формы:

    function custom_mail_form_submit($form, &$form_state) {
    
      $folder = file_directory_path()."/mail/"; // назначаем папку, куда будут загружаться прикрепляемые к письму файлы, она должна существовать и быть доступна для записи
    
      $attachment = array(); // массив для данных для прикрепленных файлов
    
      if ($file = file_save_upload('mail_attachment', array(), $folder)) { // загружаем файл
        $attachment[] = $file; // помещаем данные о загруженном файле в массив аттачментов
      } // в нашем примере аттачмент только один, но, вообще говоря, их может быть много
    
      if (module_exists('mimemail')) { // проверяем, что модуль включен
          $message_result = mimemail( // вызываем функцию mimemail, которая умеет отправлять письма с прикрепленными файлами
            variable_get('site_mail', ini_get('sendmail_from')), // адрес отправителя
            $form_state['values']['mail_to'], // адрес получателя
            $form_state['values']['mail_subject'], // тема письма
            $form_state['values']['mail_body'], // тело письма в формате HTML, его можно не указывать, если следующий параметр TRUE
            TRUE, // этот флаг указывает, что письмо нужно отправлять только в формате plaintext
            array(), // сюда можно послать дополнительные хедары для письма в виде ассоциативного массива
            check_plain($form_state['values']['mail_body']), // этим параметром мы должны отправить тело письма в формате plaintext, вместо функции check_plain() можно использовать любой другой удобный вам способ фильтрации html тегов
            $attachment, // а вот сюда передаем массив объектов типа files, в данном примере у нас один прикрепленный файл
            '' // в этом параметре можно передать текстовый идентификатор сообщения, параметр не обязательный
          ); // функция возвращает TRUE, если письмо отправлено успешно
    
          if($message_result) // проверяем результат отправки письма
    	drupal_set_message("Mail was sent to ".$form_state['values']['mail_to']);
          else
    	drupal_set_message("Mail was not sent to ".$form_state['values']['mail_to'], "error");	
    
          if(count($attachment))
            file_delete($attachment[0]->filepath); // удаляем с сайта прикрепленный к письму файл, чтобы не засорять файловую систему 
    
      }
      else{
        drupal_set_message("Please install <a href="http://drupal.org/project/mimemail">Mime Mail</a> module ".$mail, "error");  // просим установить необходимый нам для работы модуль	
      }
    }
    
    


    Надеюсь, коментариев в коде достаточно, чтобы понять, как это работет. Получатель получит письмо с одним прикрепленным файлом…

    Более подробно об использовании функции mimemail() можно почитать в README.txt модуля Mime Mail.

    P.S.: Благодарю за обсуждение материала и замечания. Помимо комментариев мне пришло несколько писем с ценными замечаниями. Думаю стоит поделиться тем, что написал мне rrromka:

    «Рассылать письма можно всем зарегистрированным пользователям (с фильтром по ролям, например) вне зависимости от того, подписывался пользователь на рассылку явно или нет. Нужно поставить модуль drupal.org/project/simplenews_roles, затем тут: admin/content/simplenews/types в настройках нужной рассылки (рассылка это термин из словаря, который автоматом создает simplenews) указать юзеров из какой роли прикрепить к этой рассылке. А потом как обычно: создаешь материал типа «рассылка», выбираешь рассылку и отправляешь.»

    Это замечание еще раз показывает то, что практически все типовые задачи уже решены на drupal.org нужно просто искать, задавать вопросы на специализированных форумах и больше практиковаться :-)

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 12

      +4
      Неплохо ;)

      Но есть небольшие вопросы/замечания:
      if (module_exists('mimemail'))…
      почему тогда нет
      if (module_exists('simplenews'))… ?

      и скажите, чем не угодила функцияя check_plain()?
      ничего личного. просто интересно.
        +1
        Большое спасибо за подсказку с check_plain()! исправил в тексте, действительно использование этой функции самый простой способ получения plaintext. В этом случае и первое замечание снимается :-)
        +2
        Модуль simplenews в связке с приведенным вами mimemail решает поставленную задачу без необходимости писать свой код.
          +1
          Да, решает, если мы хотим отправлять сообщение в рамках существующей подписки (simplenews.module,v 1.76.2.156 2010/05/19 строки 1712-1729). Но в проекте с которым я работал задача была более общая. Этим постом я не хотел показать велосипед, я хотел показать принцип использования функции mimemail(). Сходу я сейчас вижу следующие возможности использования этого подхода в других проектах, которыми занимаюсь:
          — оправка клиентом из веб-формы дизайнеру схемы замера помещения, для последующего дизайна интерьера,
          — отправка покупателю цифрового товара вместо предоставления ссылки на скачивание в интернет магазине.

            0
            Да, решает, если мы хотим отправлять сообщение в рамках существующей подписки

            Не понял о чем речь. Рассылать письма можно всем зарегистрированным пользователям (с фильтром по ролям, например) вне зависимости от того, подписывался пользователь на рассылку явно или нет.
              0
              это через simplenews? буду благодарен, если на напишите как это сделать, я не нашел. Как раз нужно разослать всем независимо от подписки.
          0
          Есть еще модуль messaging, отправка письма с прикрепленным файлом еще проще…
            0
            этим модулем не пользовался пока, спасибо за наводку, но, как я понял из описания, этот модуль — всего лишь удобная API прокладка, требующая дополнительной установки модуля, который будет посылать письма непосредственно, среди таких модулей есть и упомянутый в моей статье Mime Mail
            (http://drupal.org/project/messaging)
              +1
              да, но всё таки код будет выглядет намного проще чем просто mimemail, например она уже делает check_plain, возможность отправки несколькими способами, отправка по крону и т.д.
              Не «реклама», но использовал в нескольких сайтах :)
                0
                а есть по модулю какая-нибудь нормальная документация? или придется код читать?
                  0
                  есть в онлайне, но как всегда (как и с друпалом) неполная, быстрее код прочитать…
            0
            В drupal.org/project/mass_contact есть возможность прикреплять аттачи, тоже.

            Only users with full accounts can post comments. Log in, please.