Ответы пользователя по тегу PHP
  • Как лучше всего организовать рассылку писем объемом до 100.000 в месяц?

    @xtreme
    Снимаю порчу по SSH :)
    Базовые очевидные вещи - SPF/DKIM/DMARC - это само собой разумеющееся. Мануалов - вагон. Сам где-то с полгода назад здесь же на тостере писал элементарные вещи для настройки почтового релея.
    100.000 в месяц - это примерно 3500 писем в день. Не сильно большая цифра.
    Думаю, сначала стоит понять, надо ли отсылать столько и что это будет.
    Если это рекламная рассылка с некоего сайта по базе мыл - если эти люди никогда не были на этом сайте - вся рассылка автоматически влетит в спам и дальше можно не читать.
    Если это рассылка реальным посетителям некоего сервиса - крайне желательно, чтобы рассылка шла с адреса, домен которого совпадает с доменом сервиса.
    Далее - если мы просто настроим сервер на отправку и начнем валить по 10000 и больше писем в день - ничего хорошего не выйдет. У популярных почтовых сервисов тоже есть системы, которые ведут базу серверов и если вдруг появляется какой-то новый сервер, который рассылает сразу кучу писем - этот сервер, как минимум, попадает в подозрительные. Если же начать с малого количества, каждые несколько дней наращивая количество - сервер заработает себе репутацию, что избавит от проблем с отправкой. Опять же - без спама и непрошеной почты, иначе все труды пойдут лесом.

    В письмах обязательно заголовок List-Unsubscribe с урлом для отписки от рассылки (популярные почтовики по нему рисуют кнопку отписки), помимо этого обязательно продублировать данную ссылку в тексте письма на видном месте с объяснением, что при клике на эту ссылку пользователь откажется от рассылки. Урл должен работать (отдавать корректный ответ HTTP 200), не должен заставлять пользователя куда-то логиниться и совершать дополнительных действий. Алгоритм четкий - пользователь кликнул на линк - открылся браузер, в нем страница с оповещением, что пользователь "такой-то" отписан от рассылки. И главное - после отписки - никаких рассылок этому пользователю, иначе подпортите репутацию у почтовиков.

    Если подходить серьезно - вам придется изучить особенности каждого популярного почтового сервиса. Завести на каждом из них аккаунт постмастера, чтобы отслеживать качество рассылок и вовремя принимать меры по улучшению. Например, mail.ru - очень любят, когда настроен DMARC и есть почта для отсылки отчетов постмастеру (FBL). Вам же придется после каждого цикла рассылки выгребать из этого ящика отчеты о недоставке и спам-репорты и оперативно исключать упоминаемые там адреса из списка рассылки (уменьшите у себя список, плюс, покажете почтовому сервису, что следите за своей рассылкой).
    Яндекс.почта - на удивление, вполне лояльна к любой почте, принимая все подряд, но безжалостно запихивает рассылку в папку спам при малейшем подозрении на неправильность. Крайне адекватный сервис постмастера, на котором можно посмотреть много важных параметров рассылки - где находятся письма у пользователей, как они туда попали, насколько интересны письма пользователям (процент просмотра письма) и т.д. Крайне полезный инструмент. Там же можно увидеть список пользователей, которые жмакнули "Спам" у себя в ящиках.
    Google - про существование сервиса постмастера у Гугла я сам только недавно узнал, но ничего особо интересного там не увидел.

    Насчет тайм-аутов - я лично использую дефолтные таймауты exim. При нормально раскачанном сервере их вполне хватает. Для примера сейчас "рабочая лошадка", рассылающая уведомления пользователям, за сутки разослала 93000 писем - от 1500 до 8000 писем в час.
    Ответ написан
  • Ошибка 502 Bad Gateway на POST запросах. Почему?

    @xtreme
    Снимаю порчу по SSH :)
    child 3275 exited on signal 9 (SIGKILL) after 89.296408 seconds from start

    Что-то PHP делает с залитым вами файлом целых 90 секунд, после чего fpm его успешно убивает, как повисший. Смотрите обработку файла картинки при POST-запросе. Возможно не стоит обрабатывать его сразу, а для начала сохранить оригинал, чтобы отпустить коннект, а уже потом проводить над ним какие-то магические действия в виде обрезки, конвертации, накладывания водяных знаков и т.д.
    Ответ написан
  • Как лучше изменять php-файлы на рабочем проекте?

    @xtreme
    Снимаю порчу по SSH :)
    Когда заливаете через CMS, файл по сути заливается во временный файл, а затем происходит move, который, в случае, если временный файл и целевой находятся на одном разделе файловой системы является атомарным (т.е. либо в один момент времени это старый файл, либо новый), либо, если происходит move между разделами - все равно происходит очень быстро.
    В случае, когда вы заливаете по ftp - сначала удаляется старый файл, т.е. он становится недоступным, а затем уже начинает подливаться новый. В этот момент и происходит "лажа".
    Выходов несколько:
    - про первый (не сказал бы, что он очень простой, но все равно довольно эффективный), вам уже написал D' Normalization во втором пункте.
    - второй - разливать файлы не по фтп, а, допустим, с помощью rsync из некоей директории, куда вы уже заливаете по ftp. То бишь - залили, проверили, что ничего больше заливать не надо - запустили на сервере rsync из этой директории в продакшн. rsync также копирует различающиеся файлы сначала во временный файл, а затем "мувит" на постоянное место.
    - третий - может быть с косяками, использовать, например, opcache в PHP и выставить в параметрах opcache не трогать файл, пока он не состарится, например, на несколько секунд. Секунды определяются эмпирически, в зависимости от скорости вашей заливки.
    - четвертый... а фиг знает, придумать можно много всего. Например, хранить файлы в SVN или GIT-репозитории, и по commit/push запускать post-hook, который, например, будет синхронизировать файлы тем же rsync или использовать какой-нибудь Jenkins... масса вариантов, главное не трогать самому файлы продакшна.
    Ответ написан
  • Ошибка компиляции php5.6 на freebsd 8.4. Где взять libiconv.la?

    @xtreme
    Снимаю порчу по SSH :)
    Я же вроде писал в соседней ветке - обнови libtool.
    Ответ написан
  • Не запускается apache 2.2 после обновления PHP. Как исправить?

    @xtreme
    Снимаю порчу по SSH :)
    У тебя (ничего, что на "ты"), скорее всего не включен модуль libphp5.so в httpd.conf (ну или в одном из конфигов).
    Обычно, если apache22, в конфиге /usr/local/etc/apache22/httpd.conf примерно на 75 строке должно быть такое:
    LoadModule php5_module        libexec/apache22/libphp5.so
    рядом с другими LoadModule. Либо в одном из конфиг-файлов.
    При деинсталляции php (и про portupgrade) эта строка удаляется, а обратно, возможно, не воткнулась.
    Ответ написан
  • Как лучше реализовывать рассылку новостей?

    @xtreme
    Снимаю порчу по SSH :)
    Для начала стоит изучить правила вашего хостинга. Вполне возможно, что после первой же рассылки хостер вас просто заблочит. Плюс к тому, т.к. вы на хостинге не один, могут возникнуть проблемы с правильным формированием писем (подписи-фигодписи, заголовки и др.), а также с их доставкой - IP-адрес сервера, на котором находится ваш сайт у хостера, уже может быть в блэклистах и заранее определяться почтовыми сервисами, как спам.
    Выход (кроме ухода на свой VDS и настройки своей почтовой системы) может быть действительно в покупке услуг сторонних проектов по формированию рассылки - их можно найти в поисковике. К тому же, при вашем количестве почты возможно вписаться в самый минимальный тариф, если вообще не в бесплатный.
    Ответ написан
  • Как настроить nginx для dev?

    @xtreme
    Снимаю порчу по SSH :)
    1. Настроить log_format для отображения нужной информации в access_log
    Например:
    log_format upstreamlog '$remote_addr - [$time_local] "$host" "$request" $status ($bytes_sent) "$http_referer" "$uri $args" [$request_time] '
      '"$gzip_ratio" Cache:"$upstream_cache_status" "$content_length" "$http_user_agent" "Upstream: $upstream_addr response $upstream_response_time sec."';


    2. Выставить у нужного виртхоста этот logformat
    access_log /var/log/nginx/my-virthost-nginx.access_log upstreamlog;


    3. Зарелоадить nginx
    service nginx reload

    4. Прицепиться к логу tail-ом в консоли.
    tail -f /var/log/nginx/my-virthost-nginx.access_log


    Чтобы было красивее - поставить пакет ccze из репозиториев (yum install ccze например) и цепляться к логу примерно так:
    tail -f /var/log/nginx/my-virthost-nginx.access_log | ccze -A
    Ответ написан
  • Как брать обновленные данные из базы?

    @xtreme
    Снимаю порчу по SSH :)
    Я тут не сильный специалист в плане кода, но...
    При выполнении update_color перед запросом в БД (или после) заставить пользователя зарелоадить страницу (это если некритично, что долго), либо Javascipt-ом менять в браузере нужный блок в CSS.
    Ответ написан
  • Как нужно делать рассылку со своего сайта (сервера)?

    @xtreme
    Снимаю порчу по SSH :)
    1. Изучить рекомендации по рассылкам у крупных почтовых сервисов (Google, Yandex, Mail.ru). При подготовке писем для рассылки строго следовать их рекомендациям.
    2. Зарегистрироваться в postmaster.yandex.ru, postmaster.mail.ru, чтобы следить за ходом рассылки писем.
    3. Отлавливать недоставленные письма, убирать их из листов рассылки, дабы не мусорить.
    4. Сделать механизм отписки от рассылки (это один из критериев пункта 1), причем 100% работающий в один клик.
    5. Мониторить нажатие кнопки "Спам" в вышеуказанных почтовых сервисах, также сразу исключать их из будущих рассылок.

    1к подписчиков - это мелочь. Можешь пробовать отсылать сразу все письма на свой почтовый релей (для 1к хватит и одного релея), даже почти дефолтно настроенный MTA будет рассылать с нужными интервалами.

    Обязательное условие - соблюдать все почтовые правила и не пренебрегать цифровыми подписями - SPF, DKIM, DMARC, правильные записи в DNS (A, MX, PTR).
    Ответ написан
  • Как разрешить ошибку mail(): Multiple or malformed newlines found in additional_header?

    @xtreme
    Снимаю порчу по SSH :)
    Я не PHP-программист, но принимал участие в борьбе с данной фичей. Багом назвать язык не поворачивается, поскольку это сообщение - последствия исправления бага в PHP, позволяющего отправлять неправильные письма.
    Если проштудировать diff исходников самого PHP того самого фикса - картина следующая:
    При формировании заголовков в письме, перенос строки должен выглядеть либо как \r\n либо как \n.
    Если между \r и \n есть какой-либо символ (там ловится \0), либо перепутан порядок символов, либо если встречается два \n\n подряд - формируется сообщение
    Multiple or malformed newlines found in additional_header

    Два символа \n подряд могут встретиться в заголовках, если встречается рядом два переноса строк. Допустим, заканчивается одна строка и после нее стоит еще одна пустая строка, состоящая только из переноса - получаем ошибку.

    Когда привели в порядок все заголовки - пало подозрение, что PHP ругается на разделение между заголовками и телом письма (там тоже пустая строка). В конце концов получилось обойти данную фичу тем, что кодировали само тело письма в base64 и выставляли Content-Transfer-Encoding: base64
    PHP ругаться перестал, письма стали отправляться, исправление костылей отложили "на потом".
    Ответ написан
  • Периодически не подгружаются картинки на сайте, почему?

    @xtreme
    Снимаю порчу по SSH :)
    Pending - это ожидание. Если у курильщика Chrome - тогда он ограничен 6 одновременными соединениями к одному ресурсу. Ты установил коннект, получил страницу и браузер начинает подгружать статику. И судя по браузеру "некурильщика" - у тебя там мелкие картинки, и на каждый файл надо установить соединение. С ограничением в 6 соединений, если у тебя сверху заливается нечто тормозящее - остальные будут курить до освобождения очереди.

    Включаю телепатический шлем...

    Как один из вариантов - объединить мелкие картинки в спрайты и грузить их одним коннектом, отображая с помощью CSS нужные участки в нужных местах. (Google PageSpeed тебе то же самое подскажет)
    Второй, как полумера - использовать кеш браузеров клиента, чтобы не грузить картинки каждый раз с сервера. Но в первый раз все равно придется загрузить их со страницы в любом случае.
    Далее, судя по всему у тебя либо подрезана скорость на доступ к веб-серверу, либо сервер откровенно тормозит. Картинку размером в 80КБ грузить секунду - это долго.
    Рискну предположить, что у тебя в качестве веб-сервера стоит апач. В таком случае рекомендую увести его например на 127.0.0.1:80, а перед ним на этом же сервере на внешний интерфейс воткнуть nginx с простым конфигом:
    (Естественно, путь до проекта и внешний IP-адрес подставить свои)
    server {
      listen 192.168.0.1:80;
      server_name my-super-puper-project;
      
      location ~ ^.+\.(jpg|png) {
        root /home/www/your-project-name;
        expires 1d;
      }
      location / {
        proxy_pass http://127.0.0.1:80;
      }
    }


    В этом случае картинки (jpg|png) будет отдавать легковесный nginx без участия apache, что значительно разгрузит твой сервер, а на apache будет уходить все остальное (в т.ч. и ЧПУ-ссылки). Если у тебя css и js также отдаются прямо с диска, а не генерятся на каждый запрос динамически, как сумасшедшие - можно их включить в конфиг к картинкам.
    Если с сетью порядок - браузер станет получать статические файлы гораздо быстрее, а значит время Pending тоже уменьшится, что благоприятно скажется на быстродействии.
    Ответ написан
  • Как зайти в почту гмайл от сервера?

    @xtreme
    Снимаю порчу по SSH :)
    Настроить для отправки свой почтовик не так сложно, как думается. SPF в DNS и генерация DKIM-ключей занимает насколько минут (если делать в первый раз). Установка exim и настройка, которая сводится к добавлению 4+1+1 строк к дефолтному конфигу, также займет насколько минут. (4+1 строк для dkim и еще одна с именем сервера)
    В результате имеем сервер для нормальной отправки подписанной почты, которая не валится в спам, если, конечно, этот самый спам не рассылать. Просто и эффективно.
    А уже прием почты можно сделать на публичных сервисах.
    Ответ написан
  • Как установить Xhprof, если его не устраивает версия php5-common?

    @xtreme
    Снимаю порчу по SSH :)
    К сожалению, дебиана под рукой нет, но, насколько я помню, в aptitude можно было выбрать версию пакета, если запустить aptitude без параметров. В твоем случае надо просто поставить соответствующую версию пакета, у которой в зависимостях стоит текущая версия php.
    А вообще, на боевых серверах профилировать - как-то неправильно. Я бы, наверное, сделал отдельный сервер для профилирования, и потом либо без реальных коннектов обошелся, либо завернул часть боевого трафика.
    Ответ написан