{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "Воронин: заметки с тегом php",
    "_rss_description": "воронин, voronin, it",
    "_rss_language": "ru",
    "_itunes_email": "",
    "_itunes_categories_xml": "",
    "_itunes_image": "",
    "_itunes_explicit": "",
    "home_page_url": "https:\/\/voronin.one\/tags\/php\/",
    "feed_url": "https:\/\/voronin.one\/tags\/php\/json\/",
    "icon": "https:\/\/voronin.one\/pictures\/userpic\/userpic@2x.jpg?1658757233",
    "authors": [
        {
            "name": "Алексей Воронин",
            "url": "https:\/\/voronin.one\/",
            "avatar": "https:\/\/voronin.one\/pictures\/userpic\/userpic@2x.jpg?1658757233"
        }
    ],
    "items": [
        {
            "id": "43",
            "url": "https:\/\/voronin.one\/all\/uvelichivaem-razmer-prinimaemogo-soobscheniya-v-iredmail\/",
            "title": "Увеличиваем размер принимаемого сообщения в iRedMail",
            "content_html": "<p>Увеличим размер почтового сообщения до 35Мб<\/p>\n<p>меняем настройки postfix<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">postconf -e message_size_limit=36700160\npostconf -e mailbox_size_limit=36700160<\/code><\/pre><p>перечитываем изменения службой postfix<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">sudo systemctl reload postfix<\/code><\/pre><p>редактируем php.ini<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">sudo mcedit \/etc\/php\/7.4\/fpm\/php.ini<\/code><\/pre><p>ищем переменные и меняем значения на нужные нам<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">memory_limit = 256M;\nupload_max_filesize = 35M;\npost_max_size = 37M;<\/code><\/pre><p>рестартим php<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">sudo systemctl restart php7.4-fpm<\/code><\/pre><p>редактируем конфиг roundcube<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">sudo mcedit \/opt\/www\/roundcubemail\/config\/config.inc.php<\/code><\/pre><p>ищем настройку максимального размера сообщения и меняем значение<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">$config[&#039;max_message_size&#039;] = &#039;35M&#039;;<\/code><\/pre><p>редактируем конфиг nginx<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">sudo mcedit \/etc\/nginx\/conf-enabled\/client_max_body_size.conf<\/code><\/pre><p>ищем переменную и меняем значение на своё<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">client_max_body_size 100m;<\/code><\/pre><p>проверяем правильность конфига<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">sudo nginx -t<\/code><\/pre><p>перечитываем изменения службой nginx<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">sudo systemctl reload nginx<\/code><\/pre>",
            "date_published": "2023-05-03T13:18:44+03:00",
            "date_modified": "2023-05-03T13:18:40+03:00",
            "tags": [
                "iRedMail",
                "nginx",
                "php",
                "postfix",
                "Roundcube"
            ],
            "_date_published_rfc2822": "Wed, 03 May 2023 13:18:44 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "43",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "38",
            "url": "https:\/\/voronin.one\/all\/proschay-yandeks-pochta\/",
            "title": "Прощай Яндекс почта",
            "content_html": "<p>Была у меня почта на Яндексе, уже была, т. к. последний сделал её платной. Что же, я перевёз свои 12 ящиков, и вы справитесь.<\/p>\n<p>Схема самая простая, сначала разворачиваем свой почтовый сервер (настраиваем его), затем перевозим ящики (по одному), бонусом тюним web-интерфейс Roundcube.<\/p>\n<p>Все представленные здесь решения являются бесплатными для личного пользования, ваша задача только оплата VDS.<\/p>\n<p>Системные требования для моих задач (12 ящиков, 1 основной домен и 3 элиаса):<\/p>\n<ul>\n<li>OC Linux<\/li>\n<li>CPU 1<\/li>\n<li>RAM 4 Гб<\/li>\n<li>HDD 100 Гб<\/li>\n<li>IP 1<\/li>\n<\/ul>\n<p>Возможно вам потребуется больше, тут всё зависит от бюджета и нагрузки, системные требования для iRedMail предполагают от 4Гб оперативной памяти, а для поддержки 500 клиентов так все 16Гб.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/image-38.png\" width=\"538\" height=\"224\" alt=\"\" \/>\n<\/div>\n<p>Я не буду останавливаться на развёртывание системы, в моём примере debian 11, многие хостеры это сделаю для вас автоматически.<br \/>\nНе забудьте прописать в DNS зону A, например mail.{domain}.ru<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/image-39.png\" width=\"447\" height=\"35\" alt=\"\" \/>\n<\/div>\n<p>Прошу обратить внимание, зону MX мы не трогаем, чтобы пока мы настраиваем новый сервер, не потерять сообщения приходящие на старый.<\/p>\n<p>коннектимся в консоль сервера и создаем пользователя с sudo<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">su -\napt update\napt install mc sudo -y\nuseradd {username}\npasswd {username}\nusermod -aG sudo {username}<\/code><\/pre><ul>\n<li>mc ставлю ради mcedit<\/li>\n<\/ul>\n<p>Логинимся под свеже созданным пользователем и назначаем серверу его имя как указывали в DNS<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">sudo hostnamectl set-hostname mail.{domain}.ru<\/code><\/pre><p>в файле «\/etc\/hosts» руками правим имя локалхоста<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">sudo mcedit \/etc\/hosts<\/code><\/pre><p>должно получиться так<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">127.0.0.1       mail.{domain}.ru localhost<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa.png\" width=\"486\" height=\"132\" alt=\"\" \/>\n<\/div>\n<p>проверяем<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">hostname -f<\/code><\/pre><p>Начинаем непосредственно установку сервера, для этого определяем ссылку на актуальный дистрибутив, переходим сюда: <a href=\"https:\/\/iredmail.com\/download.html\">https:\/\/iredmail.com\/download.html<\/a> , кликаем правой кнопкой мыши на стабильной версии и копируем ссылку на скачивание<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-1.png\" width=\"800\" height=\"254.01207937877\" alt=\"\" \/>\n<\/div>\n<p>в консоли идем в домашнюю папку и скачиваем дистрибутив<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">cd ~\nwget https:\/\/github.com\/iredmail\/iRedMail\/archive\/refs\/tags\/1.6.2.tar.gz<\/code><\/pre><p>распаковываем его, переходим в полученную папку делаем файл «iRedMail-1.6.2» исполняемым и запускаем установку<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">tar xvf 1.6.2.tar.gz\ncd iRedMail-1.6.2\/\nchmod +x iRedMail.sh\nsudo bash iRedMail.sh<\/code><\/pre><p>после того как скрипт скачет необходимые пакеты запустится визард, который поможет провести первоначальную настройку<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-2.png\" width=\"639\" height=\"349\" alt=\"\" \/>\n<\/div>\n<p>указываем путь, где будут храниться почтовые сообщения и бэкапы базы данных<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-3.png\" width=\"637\" height=\"351\" alt=\"\" \/>\n<\/div>\n<p>выбираем какой web-сервер будет установлен, ну как выбираем, соглашаемся с nginx<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-4.png\" width=\"631\" height=\"339\" alt=\"\" \/>\n<\/div>\n<p>далее выбираем какую базу данных будет использовать почтовый сервер (я выбираю MariaDB)<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-5.png\" width=\"635\" height=\"346\" alt=\"\" \/>\n<\/div>\n<p>придумываем и указываем пароль для администратора базы данных, можно сейчас записать, а можно дождаться окончания установки и получить все логины и пароли в первом письме<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-6.png\" width=\"637\" height=\"349\" alt=\"\" \/>\n<\/div>\n<p>указываем имя домена, не имя сервера, а имя домена!<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-7.png\" width=\"638\" height=\"350\" alt=\"\" \/>\n<\/div>\n<p>задаём пароль администратора почтового сервера<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-8.png\" width=\"639\" height=\"347\" alt=\"\" \/>\n<\/div>\n<p>указываем необходимые нам компоненты, для простого и лёгкого сервера я бы рекомендовал остановиться на почтовом web-клиенте Roundcube, web-панели администратора iRedAdmin и fail2ban для защиты от подбора паролей пользователей<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-9.png\" width=\"634\" height=\"347\" alt=\"\" \/>\n<\/div>\n<p>проверяем настройки и подтверждаем их<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-10.png\" width=\"586\" height=\"367\" alt=\"\" \/>\n<\/div>\n<p>теперь остаётся ждать, пока инсталляционный скрипт завершит свою работу<\/p>\n<p>после завершения установки подтвердите настройки файервола<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-11.png\" width=\"592\" height=\"95\" alt=\"\" \/>\n<\/div>\n<p>Я вас поздравляю, теперь можно получить доступ к ресурсам сервера по следующим адресам:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">- Roundcube webmail: https:\/\/mail.{domain}.ru\/mail\/\n- Web admin panel (iRedAdmin): https:\/\/mail.{domain}.ru\/iredadmin\/\n\n- Username: postmaster@{domain}.ru\n- Password: BTAyZswFv4VroUP2oPTUkaikMETc6pyY<\/code><\/pre><hr \/>\n<p>Если захотите добавить элиас домена через бесплатную админку этого сделать не получится, но можно внести значения напрямую в базу (работает как с MySQL, так и с PostgreSQL)<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">mysql -u root\nsql&gt; USE `vmail`;\nsql&gt; INSERT INTO `alias_domain` (`alias_domain`, `target_domain`) VALUES (&#039;{alias}.ru&#039;, &#039;{domain}.ru&#039;);<\/code><\/pre><p>удалить элиас так:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">mysql -u root\nsql&gt; USE `vmail`;\nsql&gt; DELETE FROM `alias_domain` WHERE `alias_domain` = &#039;{alias}.ru&#039;;<\/code><\/pre><hr \/>\n<p>На этом можно было бы и закончить, но есть моменты на которых я предлагаю остановиться, назовём это улучшения вашего сервера<\/p>\n<hr \/>\n<p><a href=\"https:\/\/voronin.one\/drafts\/cistema-indeksacii-lucene-dlya-dovecot-debian\/\">Система индексации lucene для Dovecot (debian)<\/a><\/p>\n<hr \/>\n<p><a href=\"https:\/\/voronin.one\/all\/otklyuchaem-protokol-pop3-iredmail\/\">Отключаем протокол pop3 (делал чисто для себя, т.к .не пользуюсь им, слишком устаревший)<\/a><\/p>\n<hr \/>\n<p><a href=\"https:\/\/voronin.one\/all\/vypuskaem-sertifikat-lets-encrypt-i-nastraivaem-avtomaticheskiy\/\">Выпускаем подтверждённый сертификат Let’s encrypt и настраиваем автоматический перевыпуск сертификата<\/a><\/p>\n<hr \/>\n<p><a href=\"https:\/\/voronin.one\/all\/uvelichivaem-razmer-prinimaemogo-soobscheniya-v-iredmail\/\">Как увеличить размер принимаемого сообщения, например до 35Мб?<\/a><\/p>\n<hr \/>\n<p><a href=\"https:\/\/voronin.one\/all\/obnovlyaem-clamav-na-territorii-rf\/\">Есть проблемы с антивирусом clamav на территории РФ, после первоначальной установки он у вас просто не запустится, т. к. не сможет обновить свои базы, как решить?<\/a><\/p>\n<hr \/>\n<p>готово! наш сервер готов принять письма<\/p>\n<p>Через Админку создаём пользовательские ящики, которые готовы принять письма<\/p>\n<p>Меняем запись MX в DNS, чтобы новые сообщения попадали уже на наш сервер<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/proschay-yandeks-pochta-1.png\" width=\"466\" height=\"35\" alt=\"\" \/>\n<\/div>\n<p>Ждём когда изменения вступят в силу, максимум 3 часа, вы увидите, как сообщения появятся в ящиках на новом сервере, всё — это значит пора перевозить старые письма. Для этого воспользуемся моим скриптом: <a href=\"https:\/\/voronin.one\/all\/skript-dlya-perenosa-elektronnoy-pochty-iz-odnogo-yaschika-v-dru\/\">https:\/\/voronin.one\/all\/skript-dlya-perenosa-elektronnoy-pochty-iz-odnogo-yaschika-v-dru\/<\/a><\/p>\n<p>Адресную книгу без проблем перенесёте через экспорт\/импорт.<br \/>\nА вот правила фильтрации в яндексе «фильдеперсовые», их только вручную можно перенести, хоть в Roundcube есть возможность подгрузить правила sieve из файла.<\/p>\n",
            "date_published": "2023-05-02T18:04:43+03:00",
            "date_modified": "2023-08-01T15:25:34+03:00",
            "tags": [
                "clamav",
                "Debian",
                "DNS",
                "dovecot",
                "iRedMail",
                "nginx",
                "php",
                "postfix",
                "Roundcube",
                "яндекс почта"
            ],
            "image": "https:\/\/voronin.one\/pictures\/proschay-yandeks-pochta.png",
            "_date_published_rfc2822": "Tue, 02 May 2023 18:04:43 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "38",
            "_e2_data": {
                "is_favourite": true,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/voronin.one\/pictures\/proschay-yandeks-pochta.png",
                    "https:\/\/voronin.one\/pictures\/image-38.png",
                    "https:\/\/voronin.one\/pictures\/image-39.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-1.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-2.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-3.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-4.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-5.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-6.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-7.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-8.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-9.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-10.png",
                    "https:\/\/voronin.one\/pictures\/pereezd-pochty-s-yandeksa-11.png",
                    "https:\/\/voronin.one\/pictures\/proschay-yandeks-pochta-1.png"
                ]
            }
        },
        {
            "id": "39",
            "url": "https:\/\/voronin.one\/all\/skript-dlya-perenosa-elektronnoy-pochty-iz-odnogo-yaschika-v-dru\/",
            "title": "скрипт для переноса электронной почты из одного ящика в другой",
            "content_html": "<p>Скрипт максимально простой, написан на php, так же потребуется модуль php-imap, работает из командной строки любого устройства (сервера). Принцип простой, скрипт подключается к исходному ящику по протоколу IMAP сканирует структуру почтовых папок, подключается к целевому ящику IMAP, воссоздаёт папки которых нет и загружает в них письма. Опционально может создать структуру папок локально и скачать в них письма в формате eml.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;?php\n\n\/\/папка, куда будет сохраняться структура ящика с письмами\n$path_to_mail = &#039;boxes&#039;;\n\n\/\/сохранять локально копию ящика\n$save_local_copy = 0;\n\n\/\/декодировать имя папки или нет для локальной копии\n$decode_folder_name = 1;\n\n\/\/данные ящика откуда переезжаем (например яндекс)\n$source_server = &#039;imap.yandex.ru&#039;;\n$source_port = &#039;993&#039;;\n$source_user = &#039;{user}@{domain}.ru&#039;;\n$source_pass = &#039;P@$$word&#039;;\n\n\/\/данные ящика куда переезжаем\n$target_server = &#039;mail.{domain}.ru&#039;;\n$target_port = &#039;993&#039;;\n$target_user = &#039;{user}@{domain}.ru&#039;;\n$target_pass = &#039;P@$$word&#039;;\n\nfunction check_folder_exist($folders_list, $check_folder_name) {\n  $fl_exist = false;\n  foreach ($folders_list as $val) {\n    if ($val-&gt;name == $check_folder_name) {\n      $fl_exist = true;\n    }\n  }\n  return $fl_exist;\n}\n\n$path_to_mail .= DIRECTORY_SEPARATOR.$source_user.DIRECTORY_SEPARATOR;\n\n$source_server_str = &quot;{&quot;.$source_server.&quot;:&quot;.$source_port.&quot;\/imap\/ssl}&quot;;\n$source_mbox = imap_open($source_server_str,$source_user,$source_pass)\n      or die(&quot;can&#039;t connect: &quot; . imap_last_error());\n\n$target_server_str = &quot;{&quot;.$target_server.&quot;:&quot;.$target_port.&quot;\/imap\/ssl}&quot;;\n$target_mbox = imap_open($target_server_str,$target_user,$target_pass)\n      or die(&quot;can&#039;t connect: &quot; . imap_last_error());\n\n$target_list = imap_getmailboxes($target_mbox, $target_server_str, &quot;*&quot;);\nif (is_array($target_list)) {\n    foreach ($target_list as $key =&gt; $val) {\n      $folder_name = str_replace($target_server_str,&#039;&#039;,$val-&gt;name);\n      $target_delimiter = $val-&gt;delimiter;\n    }\n} else {\n    echo &quot;imap_getmailboxes failed: &quot;.imap_last_error().&quot;\\n&quot;;\n}\n\n$source_list = imap_getmailboxes($source_mbox, $source_server_str, &quot;*&quot;);\nif (is_array($source_list)) {\n    foreach ($source_list as $key =&gt; $val) {\n        $source_full_folder_name = $val-&gt;name;\n        $source_delimiter = $val-&gt;delimiter;\n        $con=imap_open($source_full_folder_name, $source_user, $source_pass);\n        $number_msg=imap_num_msg($con);\n        $folder_name = str_replace($source_server_str,&#039;&#039;,$source_full_folder_name);\n        if ($decode_folder_name) {\n          $current_folder_name = mb_convert_encoding($folder_name, &quot;UTF8&quot;, &quot;UTF7-IMAP&quot;);\n        } else {\n          $current_folder_name = $folder_name;\n        }\n        $full_new_folder_name = $target_server_str.str_replace($source_delimiter,$target_delimiter,$folder_name);\n        echo $full_new_folder_name.&quot;\\n&quot;;\n        if (!(check_folder_exist($target_list, $full_new_folder_name))) {\n          echo &#039;папка &quot;&#039;.mb_convert_encoding($folder_name, &quot;UTF8&quot;, &quot;UTF7-IMAP&quot;).&#039;&quot; отсутствует на сервере, создаём&#039;.&quot;\\n&quot;;\n          \n          imap_createmailbox($target_mbox, $full_new_folder_name);\n        }\n        if ((!file_exists($path_to_mail.str_replace($source_delimiter,DIRECTORY_SEPARATOR,$current_folder_name))) and ($save_local_copy)) {\n            mkdir($path_to_mail.str_replace($source_delimiter,DIRECTORY_SEPARATOR,$current_folder_name), 0777, true);\n        }\n        echo mb_convert_encoding($folder_name, &quot;UTF8&quot;, &quot;UTF7-IMAP&quot;).&quot;: &quot;;\n        echo $number_msg.&quot;\\n&quot;;\n        for ($i = 1; $i &lt;= $number_msg; $i++) {\n          if (!imap_ping($con)) {\n              \/\/ если вдруг связь первалась, восстанавливаем\n              echo &quot;$i ой, reconnect $source_server\\n&quot;;\n              $i--;\n              $con=imap_open($val-&gt;name, $source_user, $source_pass);\n          }\n          if (!imap_ping($target_mbox)) {\n              \/\/ если вдруг связь первалась, восстанавливаем\n              echo &quot;$i ой, reconnect $target_server\\n&quot;;\n              $target_mbox = imap_open($target_server_str,$target_user,$target_pass);\n          }\n          echo &quot;.&quot;;\n          $headers = imap_fetchheader($con, $i, FT_PREFETCHTEXT);\n          $body = imap_body($con, $i);\n          imap_append($target_mbox, $full_new_folder_name, $headers.&quot;\\n\\n&quot;.$body,&quot;\\\\Seen&quot;);\n          if ($save_local_copy) {\n            file_put_contents($path_to_mail.str_replace($val-&gt;delimiter,DIRECTORY_SEPARATOR,$current_folder_name).DIRECTORY_SEPARATOR.str_pad($i, 8, &quot;0&quot;, STR_PAD_LEFT).&quot;.eml&quot;, $headers.&quot;\\n\\n&quot;.$body);\n          }\n        }\n        echo &quot;\\n&quot;;\n      imap_close($con);\n    }\n} else {\n    echo &quot;imap_getmailboxes failed: &quot;.imap_last_error().&quot;\\n&quot;;\n}\nimap_close($source_mbox);\nimap_close($target_mbox);\n\n?&gt;<\/code><\/pre><p>$path_to_mail — относительный путь к папке, где будет храниться локальная копия ящика, актуально когда «$save_local_copy = 1»<\/p>\n<p>$save_local_copy = 1 будет сохраняться локальная копия писем на жёстком диске, соответственно, если «0» — не будет<\/p>\n<p>$decode_folder_name = 1 имена папок будут декодированы в нормальный вид, если «0» — то будет использован формат UTF7, как они хранятся на сервере.<\/p>\n<p>Все письма, которые будут перенесены в новый ящик получат статус прочитанных, извините, я не заморачивался с перенесением флагов.<\/p>\n<p>Перед прочтением сообщения пингуется соединение с сервером IMAP, в случае его обрыва — соединение восстанавливается. Замедление совсем небольшое, зато надёжность вырастает многократно.<\/p>\n<p>Учитываются разделители вложенности папок (например у яндекса это «|», в iRedMail «\/»).<\/p>\n<p>Копирование писем допускается один раз, если вы прервёте процесс и запустите снова, часть сообщений задублируется.<\/p>\n",
            "date_published": "2023-05-02T18:04:04+03:00",
            "date_modified": "2023-05-02T18:04:01+03:00",
            "tags": [
                "imap",
                "imap2imap",
                "php"
            ],
            "_date_published_rfc2822": "Tue, 02 May 2023 18:04:04 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "39",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "33",
            "url": "https:\/\/voronin.one\/all\/avtomatiziruem-ochistku-pochtovogo-yaschika-po-raspisaniyu\/",
            "title": "автоматизируем очистку почтового ящика по-расписанию",
            "content_html": "<p>собственно subj, на примере яндекса<\/p>\n<p>я хочу удалять с сервера старые письма (старше недели) с уведомлениями, которые у меня накапливаются в отдельной папке<\/p>\n<p>для начала идём в настройки безопасности <a href=\"https:\/\/id.yandex.ru\/security\">https:\/\/id.yandex.ru\/security<\/a><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/image-23.png\" width=\"625\" height=\"323\" alt=\"\" \/>\n<\/div>\n<p>выбираем «Пароли приложений» <a href=\"https:\/\/id.yandex.ru\/profile\/apppasswords-list\">https:\/\/id.yandex.ru\/profile\/apppasswords-list<\/a><\/p>\n<p>и создаем новый пароль для приложения, нам требуется сгенерить пароль для доступа к Почте, указываем понятное нам название и генерим пароль<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/image-25.png\" width=\"668\" height=\"395\" alt=\"\" \/>\n<\/div>\n<p>на самом деле — это очень правильно, т. к. мы не будем хранить в ком-то скрипте свой основной пароль в открытом виде<\/p>\n<p>а дальше, собственно, сам скрипт<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;?php\n$auth_mail = &#039;user@yandex.ru&#039;; \/\/ логин\n$auth_pass = &#039;$tr0ngP@$$w0rd&#039;; \/\/ пароль\n$server = &#039;{imap.yandex.ru:993\/imap\/ssl}&#039;.&#039;INBOX&#039;; \/\/ подключение к серверу к папке входящие\n$filter_str = &#039;BEFORE &quot;&#039;.date(&#039;d-M-Y&#039;, strtotime(&#039;-7 days&#039;)).&#039;&quot;&#039;; \/\/ фильтр, чтобы получить письма старше 7 дней\n\n$imap = imap_open($server, $auth_mail, $auth_pass) or die(&quot;Не удалось подключиться: &quot;.imap_last_error());\n\/\/ подключаемся\n$some = imap_search($imap, $filter_str);\n\/\/ применяем фильтр\nif ($some !== false) {\n\/\/ если что-то нашли - в цикле обходим\n\tforeach ($some as $msg_id)\n\t\t{ \/\/  и помечаем на удаление каждое письмо с его id\n\t\t\techo &quot;delete message #&quot;.$msg_id.&quot;\\n&quot;;\n\t\t\timap_delete($imap, $msg_id);\n\t\t}\n}\n\/\/ окончательно удаляем отмеченные письма и отключаемся\nimap_expunge($imap);\nimap_close($imap);\n?&gt;<\/code><\/pre><p>обратите внимание, я в переменную «$server» добавил строку из двух частей, вторая чать в примере подключит вас к папке «Входящие», если вам надо выбрать другую папку — укажите свой путь, например:<\/p>\n<p><b>INBOX|&BCEEPgRGBEEENQRCBDg-<\/b> — это папка <b>Входящие — Соцсети<\/b>, записанная в кодировке UTF7-IMAP<\/p>\n<p>список папок можно получить командой<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">$list = imap_list($imap, &quot;{imap.yandex.ru}&quot;, &quot;*&quot;);\nif (is_array($list)) {\n\tforeach ($list as $val) {\n\t\techo mb_convert_encoding($val, &quot;UTF-8&quot;, &quot;UTF7-IMAP&quot;).&quot;\\n&quot;;\n\t\techo $val.&quot;\\n\\n&quot;;\n\t}\n}<\/code><\/pre><p>первой строкой будет выводится декодированное (читабельное) название, второй строкой исходное, которое и надо будет подставлять в свой скрипт выше<\/p>\n",
            "date_published": "2022-09-08T17:13:44+03:00",
            "date_modified": "2022-09-08T17:46:00+03:00",
            "tags": [
                "imap",
                "mail",
                "php",
                "yandex"
            ],
            "image": "https:\/\/voronin.one\/pictures\/image-23.png",
            "_date_published_rfc2822": "Thu, 08 Sep 2022 17:13:44 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "33",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/voronin.one\/pictures\/image-23.png",
                    "https:\/\/voronin.one\/pictures\/image-25.png"
                ]
            }
        },
        {
            "id": "22",
            "url": "https:\/\/voronin.one\/all\/php-ping-ustroystv\/",
            "title": "php пинг устройств",
            "content_html": "<p>проверим скриптом доступно ли устройство<\/p>\n<p>нашёл функцию на просторах:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">function ping($host, $timeout = 1) {\n    \/* ICMP ping packet with a pre-calculated checksum *\/\n    $package = &quot;\\x08\\x00\\x7d\\x4b\\x00\\x00\\x00\\x00PingHost&quot;;\n    $socket  = socket_create(AF_INET, SOCK_RAW, 1);\n    socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array(&#039;sec&#039; =&gt; $timeout, &#039;usec&#039; =&gt; 0));\n    socket_connect($socket, $host, null);\n    $ts = microtime(true);\n    socket_send($socket, $package, strLen($package), 0);\n    if (socket_read($socket, 255)) {\n        $result = microtime(true) - $ts;\n    } else {\n        $result = false;\n    }\n    socket_close($socket);\n    return $result;\n}<\/code><\/pre><p>возвращает в миллисекундах время ответа устройства или ничего не возвращает, если устройство выключено<\/p>\n<p>Внимание! требует повышение прав<\/p>\n",
            "date_published": "2021-11-17T11:16:52+03:00",
            "date_modified": "2021-11-17T11:16:41+03:00",
            "tags": [
                "php"
            ],
            "_date_published_rfc2822": "Wed, 17 Nov 2021 11:16:52 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "22",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "10",
            "url": "https:\/\/voronin.one\/all\/synology-chat-bot-download\/",
            "title": "Synology chat bot (download)",
            "content_html": "<p>сижу, допиливаю функцию, чтобы бот в ответ присылал пользователю файл...<br \/>\nфайл, само собой, будет генериться на лету, за это отвечает скрипт php и будет выдавать примерно следующее:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">header(&quot;Content-type: text\/plain&quot;);\n\theader(&quot;Content-Disposition: attachment; filename=список посещений офиса за &quot;.$monthes[date(&#039;n&#039;, strtotime($_REQUEST[&#039;month&#039;]))].&quot; &quot;.date(&#039;Y&#039;, strtotime($_REQUEST[&#039;month&#039;])).&quot;.log&quot;);\n\techo $log_str;<\/code><\/pre><p>а в самом боте есть вызов этой url, когда-то давно написал функцию<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">function answer_file($user_id,$text,$file,$bot_token)\n# $user_id - массив с id\n# $text - комментарий к файлу\n# $file - url на сам файл\n# $bot_token - токен бота\n{\n    $data = array (\n    &#039;text&#039;    =&gt; $text,\n    &#039;user_ids&#039;=&gt; $user_id,\n\t&#039;file_url&#039;=&gt; $file\n    );\n    $options = array(\n    &#039;http&#039; =&gt; array(\n        &#039;method&#039;  =&gt; &#039;POST&#039;,\n        &#039;content&#039; =&gt; &#039;payload=&#039;.json_encode( $data ),\n        &#039;header&#039;=&gt;  &quot;Content-Type: application\/json\\r\\n&quot; .\n                    &quot;Accept: application\/json\\r\\n&quot;\n        )\n    );\n    $context  = stream_context_create( $options );\n    $result = file_get_contents( &#039;https:\/\/server\/webapi\/entry.cgi?api=SYNO.Chat.External&amp;method=chatbot&amp;version=2&amp;token=%22&#039;.$bot_token.&#039;%22&#039;, false, $context );\n    $response = json_decode($result);\n    return $result;\n}<\/code><\/pre><p>ну, в целом работает, только я же запрашиваю не существующий файл, а скрипт с параметрами, типа:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">https:\/\/server\/bots\/get_tabel.php?action=get_log&amp;login=axl&amp;month=2021-09<\/code><\/pre><p>и получаю файл с именем <b>get_tabel.php<\/b><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_152636.png\" width=\"605\" height=\"230\" alt=\"\" \/>\n<\/div>\n<p>не такого результата я хотел, ох не такого<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_154131.png\" width=\"300\" height=\"248\" alt=\"\" \/>\n<\/div>\n<p>Хорошо, переходим к радикальному методу... т. е. с nginx на apache и используем .htaccess<br \/>\nв результате нам надо получить url вида:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">https:\/\/server\/bots\/logs\/axl\/2021-09\/список посещений офиса за сентябрь 2021.log<\/code><\/pre><p>приступим...<\/p>\n<p>накидаем .htassess, учтем что нам надо использовать скрипт, только когда запрашивается папка logs<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">RewriteEngine On\n \nRewriteCond %{SCRIPT_FILENAME} !-d\nRewriteCond %{SCRIPT_FILENAME} !-f\n \nRewriteRule ^logs\/.*$ .\/parse.php [L]<\/code><\/pre><p>я временно сделал parse.php чтобы отладить, потом, конечно же перенаправлю на основной скрипт<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;?php\n\n$path = $_SERVER[&#039;REQUEST_URI&#039;];\n$paths = explode(&#039;\/&#039;, $path);\n\necho &quot;&lt;pre&gt;&quot;;\nprint_r ($paths);\necho &quot;&lt;\/pre&gt;&quot;;\n\n?&gt;<\/code><\/pre><p>и результат запроса<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">Array\n(\n    [0] =&gt; \n    [1] =&gt; logs\n    [2] =&gt; axl\n    [3] =&gt; 2021-09\n    [4] =&gt; %D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D0%BF%D0%BE%D1%81%D0%B5%D1%89%D0%B5%D0%BD%D0%B8%D0%B9%20%D0%BE%D1%84%D0%B8%D1%81%D0%B0%20%D0%B7%D0%B0%20%D1%81%D0%B5%D0%BD%D1%82%D1%8F%D0%B1%D1%80%D1%8C%202021.log\n)<\/code><\/pre><p>вы не поверите, самое крутое, что htassecc заработал с первого раза 😁<\/p>\n<p>ну вот... после небольших манипуляций получился красивый результат:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_160516.png\" width=\"623\" height=\"236\" alt=\"\" \/>\n<\/div>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_160736.png\" width=\"351\" height=\"318\" alt=\"\" \/>\n<\/div>\n",
            "date_published": "2021-10-07T16:09:09+03:00",
            "date_modified": "2021-10-07T16:09:00+03:00",
            "tags": [
                "bot",
                "download",
                "file",
                "htaccess",
                "php",
                "Synology chat"
            ],
            "image": "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_152636.png",
            "_date_published_rfc2822": "Thu, 07 Oct 2021 16:09:09 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "10",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_152636.png",
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_154131.png",
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_160516.png",
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_160736.png"
                ]
            }
        },
        {
            "id": "9",
            "url": "https:\/\/voronin.one\/all\/synology-chat-2\/",
            "title": "Synology chat",
            "content_html": "<p>Сегодня сел писать очередного бота и был неприятно удивлён!  А их количество ограничено!!!<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_144545.png\" width=\"297\" height=\"234\" alt=\"\" \/>\n<\/div>\n<p>полез в документацию и правда, всего 5 штук можно создавать.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_144635.png\" width=\"506\" height=\"136\" alt=\"\" \/>\n<\/div>\n<p>мдя....  печалька... 🤔<\/p>\n<p>Ладно, поудалял, так сказать, временных, для экспериментов и создал «Мариванну». Почему такое имя? Она будет заведовать кадровыми делами, вернее автоматизировать кадровые дела...<\/p>\n<p>Начнём со статистики нашей СКУД. А закончим табелями... или ещё чем-нибудь.<\/p>\n",
            "date_published": "2021-10-07T14:54:19+03:00",
            "date_modified": "2021-10-07T14:53:33+03:00",
            "tags": [
                "bot",
                "php",
                "Synology chat"
            ],
            "image": "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_144545.png",
            "_date_published_rfc2822": "Thu, 07 Oct 2021 14:54:19 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "9",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_144545.png",
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-10-07_144635.png"
                ]
            }
        },
        {
            "id": "3",
            "url": "https:\/\/voronin.one\/all\/kropotlivaya-rabota-i-dolgozhdanny-uspeh\/",
            "title": "3 часть, «кропотливая работа и долгожданный успех»",
            "content_html": "<p><a href=\"https:\/\/voronin.one\/all\/kak-nelzya-otnositsya-k-korporativnym-klientam\/\">1 часть, «как нельзя относиться к корпоративным клиентам»<\/a><br \/>\n<a href=\"https:\/\/voronin.one\/all\/analiz-poluchenie-ishodnyh-dannyh\/\">2 часть, «анализ, получение исходных данных»<\/a><\/p>\n<blockquote>\n<p>Сделай шаг — дорога появится сама собой…<\/p>\n<\/blockquote>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_163318.png\" width=\"300\" height=\"225\" alt=\"\" \/>\n<\/div>\n<p>и мы приступим...<\/p>\n<p>вот требования graphisoft к сложности паролей:<br \/>\nВаш пароль должен:<\/p>\n<blockquote>\n<ul>\n<li>содержать не менее 6 символов<\/li>\n<li>содержать не менее одной буквы<\/li>\n<li>содержать не менее одной заглавной буквы<\/li>\n<li>содержать не менее одной цифры<\/li>\n<li>отличаться от вашего адреса электронной почты<\/li>\n<li>не содержать пробелов, знаков препинания, специальных или национальных символов.<\/li>\n<\/ul>\n<\/blockquote>\n<p>для начала хочу показать небольшую функцию для генерации паролей, фишка в том, что <b>пароль должен содержать минимум две цифры<\/b>, да-да... хрен вы зарегистрируетесь с одной цифрой, короче ловите функцию<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">function randomPassword() {\n    $alphabet = &quot;abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789&quot;;\n    $pass = array();\n    $alphaLength = strlen($alphabet) - 1;\n    for ($i = 0; $i &lt; 10; $i++) {\n        $n = rand(0, $alphaLength);\n        $pass[] = $alphabet[$n];\n    }\n\t$password = implode($pass);\n\t$password = substr_replace($password, rand(0,9), rand(1,3), 0);\n\t$password = substr_replace($password, rand(0,9), rand(4,7), 0);\n    return $password;\n}<\/code><\/pre><p>сразу оговорюсь, при регистрации 150 учёток ни разу не споткнулась 😇<\/p>\n<p>ну, вроде всё готово для реализации проекта.<\/p>\n<p>Настоятельно рекомендую зайти на первую страницу и сохранить cookie, чтобы было максимально похоже на действия человека. Так же часто не отправляйте запросы, я регистрировал по одному сотруднику раз в пять минут,  все таки есть опасность словить captcha. Большая активность — подозрительна. А так, раз в пять минут за ночь и пол дня всех зарегистрировал.<\/p>\n<p>Не буду грузить, расписывая каждое действие, пройдусь по самым главным моментам.<br \/>\nПри отправке данных используется три метода передачи:<\/p>\n<ul>\n<li>GET<\/li>\n<li>POST<\/li>\n<li>PUT<\/li>\n<\/ul>\n<p>пришлось их все учитывать в одной функции, чтобы не плодить сущностей<\/p>\n<p>так же данные формируются разными форматами<\/p>\n<ul>\n<li>application\/json<\/li>\n<li>application\/x-www-form-urlencoded<\/li>\n<\/ul>\n<p>я сейчас выложу мою монстровую функцию<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">function get_url($url, $method, $ctype, $referer, $data) {\n\t\/\/ $url - ссылка, на страницу\n\t\/\/ $method - метод передачи (GET, POST или PUT)\n\t\/\/ $ctype - 1, 2 или 3, смотри ниже\n\t\/\/ $referer - страница, с которой мы, якобы, перешли\n\t\/\/ $data - данные, если отправляем форму\n\t$ch = curl_init();\n\tcurl_setopt($ch, CURLOPT_URL, $url);\n\tcurl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n\tcurl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);\n\tif ($data!==&#039;&#039;) {\n\t\tif ($ctype == 1) {\n\t\t\t\/\/ если тип данных json\n\t\t\tcurl_setopt($ch, CURLOPT_POST, 1);\n\t\t\tcurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));\n\t\t} else if ($ctype == 2) {\n\t\t\t\/\/ если тип данных www-form\n\t\t\tcurl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));\n\t\t} else if ($ctype == 3) {\n\t\t\t\/\/ сложная конструкция, когда нам надо работать с полученным заголовком, чтобы вытащить оттуда token авторизации\n\t\t\tcurl_setopt($ch, CURLOPT_HEADER, 1);\n\t\t\tcurl_setopt($ch, CURLOPT_POST, 1);\n\t\t\tcurl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);\n\t\t\tcurl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));\n\t\t}\n\t}\n\tcurl_setopt($ch, CURLOPT_ENCODING, &#039;gzip, deflate&#039;);\n\t\/\/ формируем заголовок запроса\n\t$headers = array();\n\t$headers[] = &#039;Connection: keep-alive&#039;;\n\t$headers[] = &#039;Sec-Ch-Ua: \\&quot; Not;A Brand\\&quot;;v=\\&quot;99\\&quot;, \\&quot;Opera\\&quot;;v=\\&quot;79\\&quot;, \\&quot;Chromium\\&quot;;v=\\&quot;93\\&quot;&#039;;\n\t$headers[] = &#039;Dnt: 1&#039;;\n\t$headers[] = &#039;Sec-Ch-Ua-Mobile: ?0&#039;;\n\t$headers[] = &#039;User-Agent: Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/93.0.4577.63 Safari\/537.36 OPR\/79.0.4143.22&#039;;\n\tif ($ctype == 1) {\n\t\t\/\/ если тип данных json\n\t\t$headers[] = &#039;Content-Type: application\/json; charset=UTF-8&#039;;\n\t} else {\n\t\t\/\/ если тип данных www-form\n\t\t$headers[] = &#039;Content-Type: application\/x-www-form-urlencoded; charset=UTF-8&#039;;\n\t}\n\t$headers[] = &#039;Accept: application\/json, text\/javascript, *\/*; q=0.01&#039;;\n\t$headers[] = &#039;X-Requested-With: XMLHttpRequest&#039;;\n\t$headers[] = &#039;Sec-Ch-Ua-Platform: \\&quot;Windows\\&quot;&#039;;\n\t$headers[] = &#039;Sec-Fetch-Site: same-origin&#039;;\n\t$headers[] = &#039;Sec-Fetch-Mode: cors&#039;;\n\t$headers[] = &#039;Sec-Fetch-Dest: empty&#039;;\n\t$headers[] = &#039;Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7&#039;;\n\t$headers[] = &#039;Origin: &#039;.$referer;\n\t$headers[] = &#039;Referer: &#039;.$referer;\n\t\/\/ используем сформированный заголовок\n\tcurl_setopt($ch, CURLOPT_HTTPHEADER, $headers);\n\t\/\/ подключаем файл с cookie, сразу в него сохраняем и из него читаем\n\tcurl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__).&#039;\/cookie.txt&#039;);\n\tcurl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__).&#039;\/cookie.txt&#039;);\n\t$response = curl_exec($ch);\n\t\/\/ используем глобальную переменную, чтобы получить token авторизации, который возвращается в header\n\tglobal $header;\n\t$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);\n\t$header = substr($response, 0, $header_size);\n\t\/\/ возвращаем результатом полученный текст\n\treturn $response;\n\tif (curl_errno($ch)) {\n\t\techo &#039;Error:&#039; . curl_error($ch);\n\t}\n\tcurl_close($ch);\n}<\/code><\/pre><p>вот такая страхолюдина получилась в итоге<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_165916.png\" width=\"300\" height=\"190\" alt=\"\" \/>\n<\/div>\n<p>все действия по шагам:<\/p>\n<ol start=\"1\">\n<li>заполняем форму регистрации и отправляем запрос\n<ul>\n  <li>открываем главную страницу<\/li>\n  <li>переходим на страницу личного кабинета<\/li>\n  <li>проверяем, зарегистрирован ли уже e-mail<\/li>\n  <li>генерируем пароль<\/li>\n  <li>отправляем форму с данными<\/li>\n<\/ul>\n<\/li>\n<li>подтверждаем регистрацию\n<ul>\n  <li>результатом отправки регистрационной формы будет json с кодом подтверждения регистрации (ура! не надо лезть в почту пользователя и искать письмо)<\/li>\n  <li>в этом же json получаем graphisoft id пользователя, потребуется позже<\/li>\n  <li>подтверждаем регистрацию двумя запросами, как оказалось второй запрос тоже необходим<\/li>\n<\/ul>\n<\/li>\n<li>заходим в кабинет администратора и отправляем запрос на присоединение пользователя\n<ul>\n  <li>аккуратно логинемся в кабинет, получаем json с данными организации, на потребуется graphisoft id организации, для создания запроса на присоединение пользователя<\/li>\n  <li>формируем и отправляем запрос<\/li>\n<\/ul>\n<\/li>\n<li>заходим в кабинет пользователя и подтверждаем запрос\n<ul>\n  <li>аккуратно логинемся в кабинет пользователя<\/li>\n  <li>формируем запрос и подтверждаем присоединение к компании<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>ну и сам код:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;?php\n\n\/\/ данные регистрируемого сотрудника\n$fname = &#039;Иван&#039;;\n$sname = &#039;Петров&#039;;\n$email = &#039;user@domain.ru&#039;;\n$pasword = &#039;koo0ovo5Kamu&#039;;\n\n\/\/ данные администратора компании\n$admin_login = &#039;admin@domain.ru&#039;;\n$admin_password = &#039;P@5$w0rD&#039;;\n\n$header = &#039;&#039;;\n\nfunction get_url($url, $method, $ctype, $referer, $data) {\n\t$ch = curl_init();\n\tcurl_setopt($ch, CURLOPT_URL, $url);\n\tcurl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n\tcurl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);\n\tif ($data!==&#039;&#039;) {\n\t\tif ($ctype == 1) {\n\t\t\tcurl_setopt($ch, CURLOPT_POST, 1);\n\t\t\tcurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));\n\t\t} else if ($ctype == 2) {\n\t\t\tcurl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));\n\t\t} else if ($ctype == 3) {\n\t\t\tcurl_setopt($ch, CURLOPT_HEADER, 1);\n\t\t\tcurl_setopt($ch, CURLOPT_POST, 1);\n\t\t\tcurl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);\n\t\t\tcurl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));\n\t\t}\n\t}\n\tcurl_setopt($ch, CURLOPT_ENCODING, &#039;gzip, deflate&#039;);\n\t$headers = array();\n\t$headers[] = &#039;Connection: keep-alive&#039;;\n\t$headers[] = &#039;Sec-Ch-Ua: \\&quot; Not;A Brand\\&quot;;v=\\&quot;99\\&quot;, \\&quot;Opera\\&quot;;v=\\&quot;79\\&quot;, \\&quot;Chromium\\&quot;;v=\\&quot;93\\&quot;&#039;;\n\t$headers[] = &#039;Dnt: 1&#039;;\n\t$headers[] = &#039;Sec-Ch-Ua-Mobile: ?0&#039;;\n\t$headers[] = &#039;User-Agent: Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/93.0.4577.63 Safari\/537.36 OPR\/79.0.4143.22&#039;;\n\tif ($ctype == 1) {\n\t\t$headers[] = &#039;Content-Type: application\/json; charset=UTF-8&#039;;\n\t} else {\n\t\t$headers[] = &#039;Content-Type: application\/x-www-form-urlencoded; charset=UTF-8&#039;;\n\t}\n\t$headers[] = &#039;Accept: application\/json, text\/javascript, *\/*; q=0.01&#039;;\n\t$headers[] = &#039;X-Requested-With: XMLHttpRequest&#039;;\n\t$headers[] = &#039;Sec-Ch-Ua-Platform: \\&quot;Windows\\&quot;&#039;;\n\t$headers[] = &#039;Sec-Fetch-Site: same-origin&#039;;\n\t$headers[] = &#039;Sec-Fetch-Mode: cors&#039;;\n\t$headers[] = &#039;Sec-Fetch-Dest: empty&#039;;\n\t$headers[] = &#039;Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7&#039;;\n\t$headers[] = &#039;Origin: &#039;.$referer;\n\t$headers[] = &#039;Referer: &#039;.$referer;\n\tcurl_setopt($ch, CURLOPT_HTTPHEADER, $headers);\n\tcurl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__).&#039;\/cookie.txt&#039;);\n\tcurl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__).&#039;\/cookie.txt&#039;);\n\t$response = curl_exec($ch);\n\tglobal $header;\n\t$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);\n\t$header = substr($response, 0, $header_size);\n\treturn $response;\n\tif (curl_errno($ch)) {\n\t\techo &#039;Error:&#039; . curl_error($ch);\n\t}\n\tcurl_close($ch);\n}\n\n\/\/ удаляем старые куки\nif (file_exists(dirname(__FILE__).&#039;\/cookie.txt&#039;)) {\n   unlink(dirname(__FILE__).&#039;\/cookie.txt&#039;);\n}\t\t\n\/\/ заходим на главную\nget_url(&#039;https:\/\/graphisoft.com\/ru&#039;,&#039;GET&#039;,1,&#039;&#039;,&#039;&#039;);\n\/\/ переходим на форму пользователя\nget_url(&#039;https:\/\/graphisoftid.graphisoft.com\/Account\/ServiceLogin?Application=GRAPHISOFT&amp;ReturnUrl=https:\/\/graphisoft.com\/ru&#039;,&#039;GET&#039;,1,&#039;https:\/\/graphisoftid.graphisoft.com\/&#039;,&#039;&#039;);\n\/\/ переходим на форму регистрации\nget_url(&#039;https:\/\/graphisoftid.graphisoft.com\/#\/register\/3\/https%3a%2f%2fgraphisoft.com%2fru&#039;,&#039;GET&#039;,1,&#039;https:\/\/graphisoftid.graphisoft.com\/&#039;,&#039;&#039;);\n\n\/\/проверяем e-mail\n$check_mail = get_url(&#039;https:\/\/graphisoftid.graphisoft.com\/api\/user\/CheckEmail\/&#039;,&#039;PUT&#039;,2,&#039;https:\/\/graphisoftid.graphisoft.com\/&#039;,array(&quot;EmailAddress&quot; =&gt; $email));\nif ($check_mail == &#039;true&#039;) {\n\t$data = array(&#039;applicationName&#039; =&gt; null,\n\t\t\t\t  &#039;customDataObject&#039; =&gt; null,\n\t\t\t\t  &#039;redirectUrl&#039; =&gt; null,\n\t\t\t\t  &#039;emailHintLocalizationKey&#039; =&gt; null,\n\t\t\t\t  &#039;firstName&#039; =&gt; $fname,\n\t\t\t\t  &#039;lastName&#039; =&gt; $sname,\n\t\t\t\t  &#039;isValidated&#039; =&gt; true,\n\t\t\t\t  &#039;email&#039; =&gt; $email,\n\t\t\t\t  &#039;password&#039; =&gt; $pasword,\n\t\t\t\t  &#039;confirmPassword&#039; =&gt; $pasword,\n\t\t\t\t  &#039;isPrivacyPolicyAccepted&#039; =&gt; true,\n\t\t\t\t  &#039;companyName&#039; =&gt; &#039;ООО &quot;Рога и Копыта&quot;&#039;,\n\t\t\t\t  &#039;countryId&#039; =&gt; 186,\n\t\t\t\t  &#039;federated&#039; =&gt; false,\n\t\t\t\t  &#039;callbackUrl&#039; =&gt; &#039;https:\/\/graphisoft.com\/ru&#039;,\n\t\t\t\t  &#039;isDirty&#039; =&gt; true,\n\t\t\t\t  &#039;errors&#039; =&gt; array());\n\n\t\/\/echo json_encode($data).&quot;\\n&quot;;\n\n\t$ecoded_json = get_url(&#039;https:\/\/graphisoftid.graphisoft.com\/api\/user\/CreateUser&#039;,&#039;POST&#039;,1,&#039;https:\/\/graphisoftid.graphisoft.com\/&#039;,$data);\n\n\t$jsonObj = json_decode($ecoded_json);\n\n\tif ($jsonObj === null &amp;&amp; json_last_error() !== JSON_ERROR_NONE) {\n\t   echo &quot;у меня не получилось отправить регистрационную форму с данными...  извините\\n&quot;;\n\t} else {\n\t\t\/\/ удаляем старые куки\n\t\tunlink(dirname(__FILE__).&#039;\/cookie.txt&#039;);\n\t\tget_url($jsonObj-&gt;{&#039;VerificationURL&#039;}.$jsonObj-&gt;{&#039;VerificationCode&#039;},&#039;GET&#039;,1,&#039;&#039;,&#039;&#039;);\n\t\t$gsid_url = get_url(&#039;https:\/\/graphisoftid.graphisoft.com\/api\/user\/VerifyUser&#039;,&#039;PUT&#039;,2,&#039;https:\/\/graphisoftid.graphisoft.com\/&#039;,array(&quot;code&quot; =&gt; $jsonObj-&gt;{&#039;VerificationCode&#039;}));\n\t\t$parts = parse_url($gsid_url);\n\t\tparse_str($parts[&#039;query&#039;], $query);\n\t\t$user_gsid = $query[&#039;gsid&#039;];\n\t\tif ($user_gsid !== &#039;&#039;) {\n\t\t\techo &quot;пользователь &quot;.$email.&quot; успешно зарегистрирован (Graphisoft sid: &quot;.$user_gsid.&quot;)\\n&quot;;\n\t\t\t\/\/ удаляем старые куки\n\t\t\tunlink(dirname(__FILE__).&#039;\/cookie.txt&#039;);\n\t\t\t\/\/ заходим на главную\n\t\t\tget_url(&#039;https:\/\/graphisoft.com\/ru&#039;,&#039;GET&#039;,1,&#039;&#039;,&#039;&#039;);\n\t\t\tget_url(&#039;https:\/\/graphisoftid.graphisoft.com\/&#039;,&#039;GET&#039;,1,&#039;&#039;,&#039;&#039;);\n\t\t\t\/\/ авторизуемся под пользователем\n\t\t\t$data = array(&#039;email&#039; =&gt; $admin_login,\n\t\t\t\t\t\t  &#039;errors&#039; =&gt; array(),\n\t\t\t\t\t\t  &#039;isDirty&#039; =&gt; true,\n\t\t\t\t\t\t  &#039;isNullo&#039; =&gt; false,\n\t\t\t\t\t\t  &#039;password&#039; =&gt; $admin_password);\t\t\t\n\t\t\t$json_response = get_url(&#039;https:\/\/graphisoftid.graphisoft.com\/api\/Authenticate\/Login&#039;,&#039;POST&#039;,1,&#039;https:\/\/graphisoftid.graphisoft.com\/&#039;,$data);\n\t\t\t$obj = json_decode($json_response);\n\t\t\t$companyGsId = $obj-&gt;{&#039;Company&#039;}-&gt;{&#039;GsId&#039;};\n\t\t\t\/\/ Загружаем список подключенных пользователей\n\t\t\tforeach ($obj-&gt;{&#039;Company&#039;}-&gt;{&#039;CompanyUsers&#039;} as $user) {\n\t\t\t\t$users_list[] = array(&quot;FirstName&quot; =&gt; $user-&gt;{&#039;FirstName&#039;},&quot;LastName&quot; =&gt; $user-&gt;{&#039;LastName&#039;},&quot;EmailAddress&quot; =&gt; $user-&gt;{&#039;EmailAddress&#039;},&quot;GsId&quot; =&gt; $user-&gt;{&#039;GsId&#039;});\n\t\t\t}\n\n\n\t\t\t$data = array(&#039;companyGsId&#039; =&gt; $companyGsId,\n\t\t\t\t\t\t  &#039;email&#039; =&gt; $email,\n\t\t\t\t\t\t  &#039;errors&#039; =&gt; array(),\n\t\t\t\t\t\t  &#039;isDirty&#039; =&gt; true,\n\t\t\t\t\t\t  &#039;requestedGraphisoftUserId&#039; =&gt; $user_gsid);\n\t\t\tget_url(&#039;https:\/\/graphisoftid.graphisoft.com\/api\/user\/SendInvitation&#039;,&#039;PUT&#039;,2,&#039;https:\/\/graphisoftid.graphisoft.com\/&#039;,$data);\n\t\t\techo &quot;выслано приглашение присоединиться к компании\\n&quot;;\n\t\t\t\/\/ удаляем старые куки\n\t\t\tunlink(dirname(__FILE__).&#039;\/cookie.txt&#039;);\n\t\t\t\/\/ переходим на форму пользователя\n\t\t\tget_url(&#039;https:\/\/graphisoftid.graphisoft.com\/&#039;,&#039;GET&#039;,1,&#039;&#039;,&#039;&#039;);\n\t\t\t\/\/ авторизуемся под пользователем\n\t\t\t$data = array(&#039;email&#039; =&gt; $email,\n\t\t\t\t\t\t  &#039;errors&#039; =&gt; array(),\n\t\t\t\t\t\t  &#039;isDirty&#039; =&gt; true,\n\t\t\t\t\t\t  &#039;isNullo&#039; =&gt; false,\n\t\t\t\t\t\t  &#039;password&#039; =&gt; $pasword);\t\t\t\n\t\t\t$json_response = get_url(&#039;https:\/\/graphisoftid.graphisoft.com\/api\/Authenticate\/Login&#039;,&#039;POST&#039;,1,&#039;https:\/\/graphisoftid.graphisoft.com\/&#039;,$data);\n\t\t\t$obj = json_decode($json_response);\n\t\t\t$user_gsid = $obj-&gt;{&#039;GraphisoftUser&#039;}-&gt;{&#039;GsId&#039;};\n\t\t\tif ($user_gsid == &#039;&#039;) {\n\t\t\t\techo &quot;не смог зайти под пользователем в личный кабинет\\n&quot;;\n\t\t\t} else {\n\t\t\t\t$data = array(&#039;actionId&#039; =&gt; 2,\n\t\t\t\t\t\t\t  &#039;companyGsId&#039; =&gt; $companyGsId,\n\t\t\t\t\t\t\t  &#039;graphisoftUserGsId&#039; =&gt; $user_gsid,\n\t\t\t\t\t\t\t  &#039;reactionId&#039; =&gt; 1);\n\t\t\t\tget_url(&#039;https:\/\/graphisoftid.graphisoft.com\/api\/user\/ProcessingPendingRequest&#039;,&#039;PUT&#039;,1,&#039;https:\/\/graphisoftid.graphisoft.com\/&#039;,$data);\n\t\t\t\techo &quot;сотрудник подтвердил приглашение\\n&quot;;\n\t\t\t}\n\t\t} else {\n\t\t\techo &quot;у меня не получилось подтвердить регистрацию...  извините\\n&quot;;\n\t\t}\n\t}\n} else {\n\techo &quot;$email уже зарегистрирован в системе\\n&quot;;\n}\n\/\/ удаляем старые куки\nunlink(dirname(__FILE__).&#039;\/cookie.txt&#039;);\n?&gt;<\/code><\/pre><p>спасибо тем, кто дочитал до конца<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_172110.png\" width=\"300\" height=\"225\" alt=\"\" \/>\n<\/div>\n",
            "date_published": "2021-09-24T17:22:16+03:00",
            "date_modified": "2021-09-24T18:16:46+03:00",
            "tags": [
                "ArchiCAD",
                "Graphisoft",
                "id",
                "php",
                "автоматизация"
            ],
            "image": "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_163318.png",
            "_date_published_rfc2822": "Fri, 24 Sep 2021 17:22:16 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "3",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_163318.png",
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_165916.png",
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_172110.png"
                ]
            }
        },
        {
            "id": "2",
            "url": "https:\/\/voronin.one\/all\/analiz-poluchenie-ishodnyh-dannyh\/",
            "title": "2 часть, «анализ, получение исходных данных»",
            "content_html": "<p><a href=\"https:\/\/voronin.one\/all\/kak-nelzya-otnositsya-k-korporativnym-klientam\/\">1 часть, «как нельзя относиться к корпоративным клиентам»<\/a><\/p>\n<p>Всегда начинайте со сбора информации, это важно! Исходные данные определят направление и общую схему работы вашего решения.<\/p>\n<p>Любая задача решается по принципу «от общего к частному».<\/p>\n<p>давайте рассмотрим алгоритм действия администратора:<\/p>\n<ol start=\"1\">\n<li>регистрация пользователя на сайте graphisoft.com<\/li>\n<li>подтверждение регистрации в посте пользователя<\/li>\n<li>авторизация на сайте graphisoft.com под административной учетной записью<\/li>\n<li>отправка приглашения пользователю<\/li>\n<li>авторизация  на сайте graphisoft.com под пользовательской учетной записью<\/li>\n<li>подтверждение приглашения<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_111857.png\" width=\"300\" height=\"179\" alt=\"\" \/>\n<\/div>\n<p>Вроде, не сложно...  да и в процессе тестовой регистрации я не заметил использования captcha. Это очень важно, иначе полная автоматизация была бы невозможна.<\/p>\n<p>Какие данные нам нужны, чтобы проделать весь вышеописанный алгоритм?<br \/>\nданные пользователя:<\/p>\n<ul>\n<li>имя<\/li>\n<li>фамилия<\/li>\n<li>e-mail<\/li>\n<li>пароль (пароль будем генерировать с учетом требований безопасности graphisoft)<\/li>\n<\/ul>\n<p>данные администратора:<\/p>\n<ul>\n<li>e-mail<\/li>\n<li>пароль<\/li>\n<\/ul>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_112041.png\" width=\"300\" height=\"236\" alt=\"\" \/>\n<\/div>\n<p>Осталось выбрать инструмент для реализации задуманного, я решил остановиться на php, т. к. у нас уже есть некий фундамент автоматизации рутинных процессов, который имеет web интерфейс и уже написан на php. В качестве хранилища информации выступит база MariaDB 10.<\/p>\n<p>Использовать будем curl, это «наше всё» для работы с web серверами.<\/p>\n<p>Начнем аккуратно, тут спешка не нужна, будем максимально повторять действия пользователя:<br \/>\nдля начала откроем главную страницу и сохраним все cookies. Они будут, при первом открытии сайта вам сразу предложат принять cookie.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_120651.png\" width=\"677\" height=\"142\" alt=\"\" \/>\n<\/div>\n<p>файл для хранения cookie так и назовём «cookie.txt»<\/p>\n<p>очень удобно в браузере копировать все необходимые ключи для curl сразу в буфер обмена<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_121005.png\" width=\"767\" height=\"557\" alt=\"\" \/>\n<\/div>\n<pre class=\"e2-text-code\"><code class=\"\">curl &#039;https:\/\/graphisoftid.graphisoft.com\/&#039; \\\n  -H &#039;Connection: keep-alive&#039; \\\n  -H &#039;sec-ch-ua: &quot; Not;A Brand&quot;;v=&quot;99&quot;, &quot;Opera&quot;;v=&quot;79&quot;, &quot;Chromium&quot;;v=&quot;93&quot;&#039; \\\n  -H &#039;sec-ch-ua-mobile: ?0&#039; \\\n  -H &#039;sec-ch-ua-platform: &quot;Windows&quot;&#039; \\\n  -H &#039;DNT: 1&#039; \\\n  -H &#039;Upgrade-Insecure-Requests: 1&#039; \\\n  -H &#039;User-Agent: Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/93.0.4577.82 Safari\/537.36 OPR\/79.0.4143.50&#039; \\\n  -H &#039;Accept: text\/html,application\/xhtml+xml,application\/xml;q=0.9,image\/avif,image\/webp,image\/apng,*\/*;q=0.8,application\/signed-exchange;v=b3;q=0.9&#039; \\\n  -H &#039;Sec-Fetch-Site: none&#039; \\\n  -H &#039;Sec-Fetch-Mode: navigate&#039; \\\n  -H &#039;Sec-Fetch-User: ?1&#039; \\\n  -H &#039;Sec-Fetch-Dest: document&#039; \\\n  -H &#039;Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7&#039; \\\n  --compressed<\/code><\/pre><p>для ленивых предлагаю воспользоваться online сервисом <a href=\"https:\/\/incarnate.github.io\/curl-to-php\/\">https:\/\/incarnate.github.io\/curl-to-php\/<\/a><\/p>\n<p>Сконвертируем ключи командной строки curl в код php и получим следующее:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/ Generated by curl-to-PHP: http:\/\/incarnate.github.io\/curl-to-php\/\n$ch = curl_init();\n\ncurl_setopt($ch, CURLOPT_URL, &#039;https:\/\/graphisoftid.graphisoft.com\/&#039;);\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, &#039;GET&#039;);\n\ncurl_setopt($ch, CURLOPT_ENCODING, &#039;gzip, deflate&#039;);\n\n$headers = array();\n$headers[] = &#039;Connection: keep-alive&#039;;\n$headers[] = &#039;Sec-Ch-Ua: \\&quot; Not;A Brand\\&quot;;v=\\&quot;99\\&quot;, \\&quot;Opera\\&quot;;v=\\&quot;79\\&quot;, \\&quot;Chromium\\&quot;;v=\\&quot;93\\&quot;&#039;;\n$headers[] = &#039;Sec-Ch-Ua-Mobile: ?0&#039;;\n$headers[] = &#039;Sec-Ch-Ua-Platform: \\&quot;Windows\\&quot;&#039;;\n$headers[] = &#039;Dnt: 1&#039;;\n$headers[] = &#039;Upgrade-Insecure-Requests: 1&#039;;\n$headers[] = &#039;User-Agent: Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/93.0.4577.82 Safari\/537.36 OPR\/79.0.4143.50&#039;;\n$headers[] = &#039;Accept: text\/html,application\/xhtml+xml,application\/xml;q=0.9,image\/avif,image\/webp,image\/apng,*\/*;q=0.8,application\/signed-exchange;v=b3;q=0.9&#039;;\n$headers[] = &#039;Sec-Fetch-Site: none&#039;;\n$headers[] = &#039;Sec-Fetch-Mode: navigate&#039;;\n$headers[] = &#039;Sec-Fetch-User: ?1&#039;;\n$headers[] = &#039;Sec-Fetch-Dest: document&#039;;\n$headers[] = &#039;Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7&#039;;\ncurl_setopt($ch, CURLOPT_HTTPHEADER, $headers);\n\n$result = curl_exec($ch);\nif (curl_errno($ch)) {\n    echo &#039;Error:&#039; . curl_error($ch);\n}\ncurl_close($ch);<\/code><\/pre><p>осталось рассмотреть механизм php работы с почтовым ящиком, нам нужен по сути только механизм IMAP, не буду вас сильно грузить, оставлю готовый скрипт, который открывает почтовый ящик пользователя в режиме readonly и находит последнее письмо (если их несколько) от «register-noreply@graphisoft.com», расшифровывает тело письма и вытаскивает код подтверждения. Результатом работы скрипта будет ссылка на подтверждение регистрации или ничего, если письма не было.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;?php\n\n$auth_mail = &#039;username@mail.com&#039;;\n$auth_pass = &#039;P@$$woRd&#039;;\n\nfunction get_string_between($string, $start, $end){\n    $string = &#039; &#039; . $string;\n    $ini = strpos($string, $start);\n    if ($ini == 0) return &#039;&#039;;\n    $ini += strlen($start);\n    $len = strpos($string, $end, $ini) - $ini;\n    return substr($string, $ini, $len);\n}\n\n$imap   = imap_open(&#039;{imap.mail.com:993\/imap\/ssl}INBOX&#039;, $auth_mail, $auth_pass, OP_READONLY);\nif ($imap) {\n\t$some = imap_search($imap, &#039;FROM &quot;register-noreply@graphisoft.com&quot;&#039;, SE_UID);\n\tif (count($some)&gt;0) {\n\t\t$mail_body = base64_decode(imap_body($imap, $some[0]));\n\t\t$key = get_string_between($mail_body,&#039;&lt;span style=&quot;font-weight:bold;&quot;&gt;&#039;,&#039;&lt;\/span&gt;&#039;);\n\t\techo &#039;https:\/\/graphisoftid.graphisoft.com\/#\/verification\/&#039;.$key.&quot;\\n&quot;;\n\t}\n}\n?&gt;<\/code><\/pre><p>Вроде, все попробовали, ко всему готовы... В процессе реализации обязательно что-то всплывёт... но, в целом мы готовы!<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_122739.png\" width=\"300\" height=\"230\" alt=\"\" \/>\n<\/div>\n<p><a href=\"https:\/\/voronin.one\/all\/kropotlivaya-rabota-i-dolgozhdanny-uspeh\/\">3 часть, «кропотливая работа и долгожданный успех»<\/a><\/p>\n",
            "date_published": "2021-09-24T12:30:50+03:00",
            "date_modified": "2021-09-24T17:46:11+03:00",
            "tags": [
                "curl",
                "Graphisoft",
                "id",
                "imap",
                "php",
                "автоматизация"
            ],
            "image": "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_111857.png",
            "_date_published_rfc2822": "Fri, 24 Sep 2021 12:30:50 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "2",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_111857.png",
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_112041.png",
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_120651.png",
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_121005.png",
                    "https:\/\/voronin.one\/pictures\/izobrazhenie_2021-09-24_122739.png"
                ]
            }
        }
    ],
    "_e2_version": 4171,
    "_e2_ua_string": "Aegea 11.4 (v4171)"
}