November 19, 2012

Битрикс. Корпоративный портал. Правило обработки писем на php.

Всем привет! Данный пост будет с минимумом комментариев и по большей части будет состоять лишь из полезного кода.

Итак, возникла необходимость автоматического создания сообщения в конкретной рабочей группе при отправке письма на специализированный почтовый ящик (который привязан в корпортале) с темой письма вида #имя_рабочей_группы#.

По сути таким функционалом обладает стандартное почтовое правило “добавление сообщений в форумы соцсети” которое отчего то не работало (ТП также не смогла ничем помочь). Поэтому было принято решение написать свою реализацию правила на php.

Листинг кода:

Условие на php

<?php

    if(preg_match_all('%#(.*)#%is', $arMessageFields['SUBJECT'], $matches, PREG_SET_ORDER)) {
        $name = $matches[0][1];
        CModule::IncludeModule("socialnetwork");

        $res = CSocNetGroup::GetList(array("ID" => "DESC"),array("NAME" => $name),false,false,array());
        if($group = $res->Fetch()) {
            return true;
        } else {
            preg_match_all('%%is', $arMessageFields['FIELD_FROM'], $matches, PREG_SET_ORDER);
            $headers = "From: noreply@portal.site.ru\r\n";
            $headers .= "Content-type: text/plain; charset=utf-8\r\n";
            mail($matches[0][1], "Группа не существует", "Данная рабочая группа не существует", $headers);
            return false;
        }
    } else {
        preg_match_all('%%is', $arMessageFields['FIELD_FROM'], $matches, PREG_SET_ORDER);
        $headers = "From: noreply@portal.site.ru\r\n";
        $headers .= "Content-type: text/plain; charset=utf-8\r\n";
        mail($matches[0][1], "Неправильный формат темы письма", "Пример: #Рабочая группа#", $headers);
        return false;
    }

Правило

<?php

    CModule::IncludeModule("blog");
    CModule::IncludeModule("socialnetwork");

    //Проверка на существование пользователя
    if(preg_match_all('%%is', $arMessageFields['FIELD_FROM'], $matches_email, PREG_SET_ORDER)) {
        $filter = Array("EMAIL" => $matches_email[0][1]);
        $sql = CUser::GetList(($by="id"), ($order="desc"), $filter);
        if($t = $sql->Fetch()) {
            $id_user = $t["ID"];
        }
    }

    $arBlog = CBlog::GetByOwnerID($id_user);
    if(is_array($arBlog)) $blog_id = $arBlog["ID"];

    //Если пользователь существует и существует его блог
    if(isset($id_user) && isset($blog_id)) {
        //Повторная проверка на существование рабочей группы
        if(preg_match_all('%#(.*)#%is', $arMessageFields['SUBJECT'], $matches, PREG_SET_ORDER)) {
            $name = $matches[0][1];
            $res = CSocNetGroup::GetList(array("ID" => "DESC"), array("NAME" => $name), false, false, array());
            if($group = $res->Fetch()) {
                //Attach/Begin
                //добавляем к задаче вложения
                $dbr_attach = CMailAttachment::GetList(Array("NAME"=>"ASC", "ID"=>"ASC"), Array("MESSAGE_ID"=>$arMessageFields['ID']));
                while ($dbr_attach_arr = $dbr_attach->GetNext()) {
                    if ($dbr_attach_arr["FILE_NAME"]=='1.tmp' ||
                        preg_match_all('/\.(?:exe|html|phtml|pl|js|htm|py|php|php4|php3|phtml|shtml)$/i', $dbr_attach_arr["FILE_NAME"], $p_matches, PREG_PATTERN_ORDER))
                        continue;
                    $attach_id = $dbr_attach_arr["ID"];
                    //$fid[] = $attach_id;
                    //$dbr = $DB->Query("SELECT * FROM b_mail_msg_attachment WHERE ID=".intval($attach_id));
                    $dbr = CMailAttachment::GetByID($attach_id);
                    if($dbr_arr = $dbr->Fetch()) {
                        $fname = $_SERVER['DOCUMENT_ROOT']."/upload/from_mail/".$dbr_attach_arr["FILE_NAME"];
                        $handle = fopen($fname, 'wb');
                        fwrite($handle, $dbr_arr["FILE_DATA"]);
                        fclose($handle);
                        $arFile = CFile::MakeFileArray($fname);
                        $arFile["old_file"] = "";
                        $arFile["del"] = "Y";
                        $arFile["MODULE_ID"] = "blog";
                        $fid[] = CFile::SaveFile($arFile, "blog");
                        $fid[] = $dbr_arr;
                    }
                }

                if(isset($fid)) {
                    $msg .= "Вложения:\r\n";
                    foreach ($fid as $value) {
                        if($value["FILE_NAME"]!="1.tmp" && $value["FILE_NAME"]!="") $msg .= "[".$value["FILE_NAME"]."](/upload/from_mail/".$value["FILE_NAME"].")\r\n";
                    }
                }
                //Attach/End

                $arFields= array(
                    "TITLE" => " ",
                    "DETAIL_TEXT" => $arMessageFields["BODY"]."\r\n\r\n".$msg,
                    //"DETAIL_TEXT" => print_r($fid,true),
                    "DETAIL_TEXT_TYPE" => "text3",
                    "DATE_PUBLISH" => date("d.m.Y H:i:s"),
                    "PUBLISH_STATUS" => "P",
                    "CATEGORY_ID" => "",
                    "PATH" => "/person/personal/user/$id_user/blog/#post_id#/",
                    "URL" => "admin-blog-s1",
                    "PERMS_POST" => Array(),
                    "PERMS_COMMENT" => Array (),
                    "SOCNET_RIGHTS" => Array(
                        "UA", "SG".$group["ID"] //Доступно автору и группе пользователей рабочей группы
                    ),
                    "=DATE_CREATE" => "now()",
                    "AUTHOR_ID" => $id_user, //ID автора
                    "BLOG_ID" => $blog_id, //в какой блог добавляем
                );

                $newID= CBlogPost::Add($arFields);

                $arFields["ID"] = $newID;
                $arParamsNotify = Array(
                    "bSoNet" => true,
                    "UserID" => $id_user,
                    "user_id" => $id_user,
                    "SOCNET_GROUP_ID" => $group["ID"],
                );
                CBlogPost::Notify($arFields, array(), $arParamsNotify);
            }
        }
    }
    //Если пользователя не существует
    else {
        $headers = "From: noreply@portal.site.ru\r\n";
        $headers .= "Content-type: text/plain; charset=utf-8\r\n";
        mail($matches_email[0][1], "Email не найден", "Пользователь с таким email не найден на портале.",$headers);
    }
  • Для аттачей нужно предварительно создать директорию /upload/from_mail/
  • Поиск верного направления занял 3 дня т.к. только на третий день от ТП Битрикс удалось получить рабочий пример создания сообщения в блоге рабочей группы. Затем уже туда дописали функционал для аттачей и проверку на наличие пользователя на портале.