Trust, but verify: control of unsent messages in Bitrix with notification to the admin

Background



Once I had a need to check the presence of unsent messages in "1C-Bitrix: Site Management" (hereinafter Bitrix) and receive notifications about it. Problems with sending mail were extremely rare, but rather unpleasant events. these were usually orders, registration confirmations and other important letters.



The difficulty was that if the method of sending mail used by Bitrix stopped working (most likely the reason for this), then sending a notification using the same method would be unreliable .



Googling , I did not find something free and ready-made, but I came across a lot of questions / answers about unsent messages from Bitrix - how to find them, what might be the reasons for their appearance, etc. Therefore, I considered it necessary to share my solution.



A task



  1. Get details for connecting to the database from the Bitrix site config
  2. Connect to DB
  3. Check the number of unsent emails
  4. Compare the quantity with the limit
  5. Make a decision to send a notification




Implementation



The shell script will receive 3 parameters:



  1. The path to the Bitrix site config (path_to_bxdb_config)
  2. Database query text (single_num_value_query)
  3. Maximum allowable value (max_num_value)


For correct operation, the database query must return a single numeric value.



Check_bx_db_value.sh script code
#!/bin/bash
#
# Site: https://github.com/AlexeyGogolev/check-bx-db-value
#
mysql="$(which mysql)" #    mysql
php="$(which php)" #    php
declare -A CLParams #    
declare -a CLParams_keys #      
declare -A DBSettings #    
declare -a DBSettings_keys #       
DBSettings_keys=(DBLogin DBPassword DBName)
CLParams_keys=(path_to_bxdb_config single_num_value_query max_num_value)
param_num=0 #   
#   
for key in "${CLParams_keys[@]}" ; do 
    ((param_num++))                 
    CLParams[$key]=${!param_num}    # ${!param_num}  - $1 $2... 
done
#    ,  
if  [ -z "${CLParams[${CLParams_keys[$param_num-1]}]}" ] ; then
    printf "Script compares result returned by <${CLParams_keys[1]}> to given <${CLParams_keys[2]}>.\nIf the result more than the given value, then exit with code 1, else exit 0.\n"
    printf "Usage: \n\t$(basename ${BASH_SOURCE[0]}) " ; for key in "${CLParams_keys[@]}" ; do printf "<$key> "; done ; printf "\n"
    printf "Example: \n\t$(basename ${BASH_SOURCE[0]}) \"/www/ab.cd/bitrix/php_interface/dbconn.php\" \"select count(id) from b_event where SUCCESS_EXEC<>'Y'\" 5\n" 
    exit 10
fi
#        
if ! [ -s "${CLParams[path_to_bxdb_config]}" ] ; then 
    printf "File ${CLParams[path_to_bxdb_config]} doesn't exist or empty.\n"
    exit 20
fi
#          " "
echo ${CLParams[single_num_value_query]} | grep -i -q -E 'delete|update|insert|drop' && printf "query \n${CLParams[single_num_value_query]}\nisn't allowed\n" && exit 30
#     php-config -n --  php.ini , -r --     <?...?>
for key in "${DBSettings_keys[@]}" ; do 
    DBSettings[$key]="$($php -n -r 'include("'${CLParams[path_to_bxdb_config]}'"); print $'$key';')"
done
#   mysql    (  )
export MYSQL_PWD=${DBSettings[DBPassword]}
#     : -N --    ; -B - (batch) -   ""  ; -e  
num_value=`${mysql} -u ${DBSettings[DBLogin]} -N -B -e "use ${DBSettings[DBName]}; ${CLParams[single_num_value_query]}"`
#  
echo "Result of the query (from DB ${DBSettings[DBName]}): ${num_value}, ${CLParams_keys[2]}: ${CLParams[max_num_value]}"
#  
if [ $num_value -gt ${CLParams[max_num_value]} ]; then
    exit 1
fi




An example of calling the script ab_cd_unsent_check.sh
#!/bin/bash
check_bx_db_value.sh \
«/www/ab.cd/bitrix/php_interface/dbconn.php» \
«select count(id) from b_event where SUCCESS_EXEC<>'Y'» \
2






Checking execution results with script completion codes
:



$ ./ab_cd_unsent_check.sh && echo "success" || echo "failure"


:



Result of the query (from DB ab_cd): 0, max_num_value: 2
success


.



$ ./ab_cd_unsent_check.sh && echo "success" || echo "failure"


:



Result of the query (from DB ab_cd): 4, max_num_value: 2
failure




Everything works as it should! In the first case, the value in the database does not exceed the specified one, the script issues code 0 upon completion. In the second, the value in the database exceeds the specified one, the script ends with an error code.



Configuring monit



In this article, I will provide an example of a monit configuration for sending messages to e-mail.

It is assumed that monit is already installed and configured on the machine.



To increase reliability, in the monitrc config you should specify an account on a mail server that is different from that used by Bitrix to send letters . In addition, by configuring and running additional scripts in the monit configuration, you can send messages to instant messengers and social networks .



Example monit configuration
check program ab_cd_unsent_check with path /home/bitrix/scripts/ab_cd_unsent_check.sh
every 2 cycles
    group mail
if status != 0 then alert


/etc/monit.d/.



To simplify the demonstration, this example has 2 cycles set (here 1 cycle = 30 sec).

So that monit does not send false alerts, in real conditions, you need to set so many cycles so that letters have time to leave - it is selected empirically. Here you should take into account the average number of messages generated by the site, and the speed (time) of their processing by the mail server.



To check the configuration work in the terminal, run:

# systemctl restart monit
# monit status


we get:

No unsent messages




With unsent messages




This is how monit notifications look like:

Unsent messages appeared!




All messages have been sent (now everything is fine).




Sending notifications from monit works correctly.



Conclusion



I hope the solution turned out to be quite versatile and suitable for other tasks.



That's all! The sources for the article can be downloaded here .



PS Who is it not difficult to share in the comments - do you have similar tasks?

If so, how are they resolved?



All Articles