Пользователь
0,0
рейтинг
20 января 2009 в 18:33

Администрирование → Sendmail-заглушка для Linux

Не так давно встала задача, установить заглушку для sendmail, дабы письма из PHP не отсылались на ложные адреса (при тестинге) или просто не возникала ошибка, а складывались аккуратно в папку. Аналогично тому, как это делает Денвер.
Далее…

Поиск по просторам интернета ничего не дал, кроме советов читать мануал к sendmail. Но терпение и упорство сделали свое дело. И, спустя несколько дней, на одном из форумов нахожу интересный шелл-скрипт.
Мне пришлось немного поправить его, для своих нужд. Итак, тело скрипта:

#!/bin/sh
prefix="/var/mail/sendmail/new"
numPath="/var/mail/sendmail"

if [ ! -f $numPath/num ]; then
echo "0" > $numPath/num
fi
num=`cat $numPath/num`
num=$(($num + 1))
echo $num > $numPath/num

name="$prefix/letter_$num.txt"
while read line
do
echo $line >> $name
done
chmod 777 $name
/bin/true

Скрипт сохраняем в папку /usr/bin под любым угодным вам именем и делаем исполняемым (sudo chmod +x). Я использовал fake_sendmail.sh.

Теперь все исходящие письма будут складываться в /var/mail/sendmail. Так же необходимо выставить для папки права на запись. (chmod 777 -R /var/mail/sendmail).

Примечание:
Для сбора писем почтовиком (о чем ниже), нужно в этой папке создать следующую структуру папок:
/var/mail/sendmail/
— cur
— new
— tmp
И дать права на запись.

Настройка PHP.
У меня стоит Кубунта, так что все пути относительно нее. Итак, находим в папке /etc/php5/apache2 файл php.ini и меняем в нем путь к sendmail на:

sendmail_path = /usr/bin/fake_sendmail.sh.

Все, на этом можно и закончить. Далее читать страждущим юзабилити.

Привязка локальной папки к KMail.
Запускаем KMail и переходим в опции создания нового аккаунта:
Settings -> Configure KMail -> Accounts -> Add.

Выбираем maildir mailbox, а в настройках этого аккаунта, собственно, путь к папке с письмами (/var/mail/sendmail).
Все, закончено. Теперь эти письма можно будет забирать почтовиком и читать в удобоваримом виде.
Alex Oleskevich @mariner
карма
80,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Администрирование

Комментарии (35)

  • +1
    полезно, спасибо(:
  • 0
    а не пробовали просто менять адресата на username@localhost?
    • +2
      а если по условиям задачи нужно потестить как рз генерацию адресатов?
      • –1
        письмо — это набор заголовков и текста, который идет после них. если вы замените заголовок «To:» на локальный адрес, а дополнительно создадите еще один заголовок, например «XXX-To:», куда запишете тестируемое поле, то вы решите вашу задачу. и вместо копания в гугле и терминале, вы просто добавите пару строк кода.
        • 0
          На вкус и цвет, как говорится…
          Лично мне проще один раз прикрутить скрипт и пользоваться чем каждый раз добавлять/убирать 2 строчки кода. Возможно Вы считаете по другому, но, повторюсь, кому как удобнее.
  • +1
    Здорово, что кто то додумался написать то, что мне самому писать было лень :) Спасибо огромное!
  • 0
    спасибо, мне просто так удобнее отлаживать письма для разных адресатов, да еще читаемо в почтовом клиенте!
  • +3
    Если мне не изменяет память, то для сендмайла достаточно написать в /etc/mail/mailertable

    . local:username

    где username — ваш логин. И тогда всю вашу почту сендмайл будет складывать в ваш почтовый ящик на вашей же машине.
    • 0
      Чтобы никто больше не мучился, вот неплохая инструкция по этому поводу:
      Сделайте бэкап sendmail.mc и sendmail.cf.

      Сначала проверьте, что /etc/mail/sendmail.mc содержит строку:

      FEATURE(`mailertable',`hash -o /etc/mail/mailertable.db')dnl

      Если её там нет — добавьте (у меня например не было).

      Скомпилируйте изменения конфига (мне лично тут потребовалось колдовство с chmod & chown):

      $ m4 /etc/mail/sendmail.mc>/etc/mail/sendmail.cf

      Добавьте изменения в /etc/mail/mailertable.
      (строка. local:username)

      Сгенерируйте базу mailertable.db:
      $ makemap hash /etc/mail/mailertable </etc/mail/mailertable

      Перезапустите sendmail.

      $ service sendmail restart

  • 0
    А для postfix достаточно добавить в /etc/postfix/main.cf строку «default_transport = error»
  • +2
    А не проще fakemail воспользоваться???
    • 0
      Она требует ставить либо Перл либо Питон (под виндой к примеру). а если уже есть cygwin — не проще ли просто прикрутить скриптик, чем возиться с указанными языками.
  • +2
    Хотелось бы в общих чертах понять, зачем ставить 777 на текстовые файлы?
    • +4
      Это эмуляция обычной работы под админом в Windows :)
    • 0
      chmod -R 777 любимая команда молодых пхп программистов, которым нравится Ubuntu
      • 0
        руки бы поотрывал за такое (:
  • 0
    Предлагаю тоже неплохой вариант, пишется общий лог, и в папке mail для каждого адреса создается свой лог (написано на sh.exe из cygwin):

    maildir="/d/www/mail"
    mainlog="/d/www/mail.log"
    tmpfile="/d/www/mail.tmp"

    function cleanup()
    {
    rm -f "$tmpfile"
    exit 1
    }

    trap cleanup ERR 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

    # Имя файла с логом (определяется из заголовка To:)
    filename="_unknown"

    # Красивый заголовок
    echo "-----------------------" >> "$mainlog"
    echo "-----------------------" >> "$tmpfile"

    while read line
    do
    [[ "${line#To: }" != "$line" ]] && filename="${line#To: }"
    echo "$line" >> "$mainlog"
    echo "$line" >> "$tmpfile"
    done

    echo >> "$mainlog"
    echo >> "$mainlog"

    echo >> "$tmpfile"
    echo >> "$tmpfile"

    mv "$tmpfile" "$maildir/$filename.log"

    Для подключения скрипта под Win пишем что-то вроде:

    sendmail_path = sh.exe /d/web-server/sendmail.sh

    в php.ini
  • –1
    Поправьте, пожалуйста, теги. Картину в профиле внимания портят. ;)
    • 0
      Метки через запятую перечисляться должны. Зачем минусовать? Хотя, как хотите. :)
  • +1
    Самый простой вариант:
    #!/bin/sh
    /usr/lib/python2.5/smtpd.py -n -c DebuggingServer localhost:25

    и все письма выводятся в консоль
  • 0
    Большое спасибо. Только-только встал вопрос о настройке sendmail в Убунте, а тут ваша статья, очень кстати.
    • 0
      Вы, наверное, что-то не совсем поняли. Тут нет никакого сендмейла :)
      • 0
        Мне именно это и нужно было. Тестирование на локальном сервере отправки почты для тестирования системы уведомлений :)
        Теперь меня интересуют вопросы: какой почтовый сервер выбрать, как его установить/настроить и прикрутить к пхп?
        • +1
          Если где-то в сети уже есть почтовик, то попробуйте nullmailer. Он просто перебрасывает почту на smarthost.
          • 0
            Спасибо.
  • 0
    спасибо, я исправлю. это мой первый пост.
  • 0
    Сегодня попросили реализовать такое и кинули ссылку на этот топик :)
    Скрипт упростил. Чтобы не запоминать номер в файле используется date с наносекундами. Ну и права конечно же.

    #!/bin/sh
    prefix="/mnt/php_mail"
    date=`date \+\%Y\%m\%d\%H\%M\%N`

    name="$prefix/$date.eml"
    while read line
    do
    echo $line >> $name
    done
    chmod 666 $name

    • 0
      у меня почему-то наносекунды не выводятся, просто N показует и все, хотя остальное — ок
    • 0
      Поправочка: нужно использовать IFS, а также $line должен быть в кавычках, иначе обрезаются пробелы по краям, что критично для заголовков писем. Они могут либо вообще не открываться в почтовых программах, либо быть обрезанными
      #!/bin/sh
      prefix="/var/www/sendmail"
      date=`date \+\%Y\%m\%d\%H\%M\%N`
      
      name="$prefix/$date.eml"
      while IFS= read line
      do
      echo "$line" >> $name
      done
      chmod 666 $name
      
  • 0
    Огромное спасибо за статью!
  • 0
    В Evolution (у меня Ubuntu 10.10) в параметрах «Тип сервера» нужно выбрать «Почтовые каталоги в формате Maildir»
  • 0
    Автору — спасибо!

    На случай, если в этот топик в поисках забежит ещё один джангист кроме меня:
    В django, начиная с версии 1.2, все извращения с sendmail остались позади.
    Существуют различные email-backends, в том числе file-backend

    Чтобы искалось: Django Sendmail Development Plug
  • 0
    единственная проблема с этим скриптом — при отправке из PHP формы сообщений сразу нескольким адресатам или при отправки копии письма себе (что одно и то же), этот скрипт все ложит в один файл, каким образом отслеживать конец сообщения и начинать писать в новый файл?
  • 0
    может кому-то пригодится, набрел на статью, описывающую скрипт-заглушку, написанный на самом php
    www.drupal.ru/node/31183

    Для себя немного переписал и на freebsd завелось нормально
    в php.ini
    sendmail_path = "/usr/local/bin/php /localetc/sendmail_stub/fake.php"

    и сам fake.php

    $sendMailStubObj = new SendMailStub();
    $sendMailStubObj->main();
    
    class SendMailStub
    {
        private $_saveEmailsPath = "/mnt/windev/tmp/__sendmail/"; //change path HERE
    
        function main()
        {
            //--- get email from the stream ---//
            $stream_data = '';
            $stream_handler = fopen('php://stdin', 'r');
            while ($t = fread($stream_handler, 2048)) {
                if ($t === chr(0))
                    break;
                $stream_data .= $t;
            }
            fclose($stream_handler);
    
            //save to file
            $fwrite_handler = fopen($this->_generateUniquePath(), 'w');
            fwrite($fwrite_handler, $stream_data);
            fclose($fwrite_handler);
        }
    
        private function _generateUniquePath()
        {
            $i = 0;
            do {
                $path = $this->_saveEmailsPath . $this->_generateFname($i);
                $i++;
    
                if($i > 100){
                    break;
                }
            } while (file_exists($path) == true);
    
            return $path;
        }
    
        private function _generateFname($i = 0)
        {
            $parts = array(
                date('Y-m-d_H-i-s'),
            );
    
            if ($i > 0) {
                $parts[] = "_{$i}";
            }
            $parts[] = ".eml";
    
            $fname = implode("", $parts);
    
            return $fname;
        }
    }
    
  • 0
    Будьте аккуратны с использованием этого варианта.

    while read line
    do 
        echo $line >> $name 
    done 
    

    будет интерпретировать текст письма как баш скрипт и, например, * заменит на список файлов в текущей директории.

    Правильный вариант
    while read line
    do 
        echo "$line" >> $name 
    done
    

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