Отправка с сервера писем с вложениями. Утилита mutt.

В этом видео:
– скрипт для обнаружения новых файлов;
– выбор файла из списка новых файлов для последующей отправки;
– отправка выбранного файла по почте;
– настройка утилиты mutt.

(детали ниже)

Сегодня я расскажу как можно отправлять с сервера нотификации себе на почту с вложениями (что понятно из заголовка=).
Если у вас на сервере производится какой-либо мониторинг, то получать особо важные нотификации хочется как можно быстрее, даже если вы находитесь не за компьютером. Смартфоны сейчас есть у большинства. По этому одним из вариантов получения экстренных нотификаций будет – получение email-ов. Можно настроить на своём почтовом клиенте получение писем через push уведомления и новое письмо будет у вас на телефоне как только его вам отправят.
Со способом получение важной информации разобрались, теперь нужно научиться отправлять её с сервера где осуществляется мониторинг.

В предыдущих видео я рассказывал о своей системе домашнего видеонаблюдения. В случае если камера обнаружила какое-либо движение, она делает снимки и видеозаписи, загружает полученный материал на сервер.
В моём случае требуется получение информации о том что камера что-то задетектила как можно быстрее, плюс хотелось бы чтобы в этой информации были примеры снимков (один-два)- да бы сразу понять кого задетектила камера. Мне не хочется подключаться к серверу по фтп и не проверять все загруженные файлы. Обычно это не меньше 10-15 снимков. Это не удобно. По этому пара снимков в почте самое то.

Итого задача следующая – в случае если на сервер камера загрузила новые снимки – переслать несколько мне на почту.
Для решения данной задачи я написал следующий скрипт:
$ cat monitoringscript.sh
#!/bin/bash
# Declare variables.
declare -i DefaultTime=10003
tempCurrentTime=`date +%H%M`
CurrentTime=`echo "1$tempCurrentTime"`
declare -i NumberToSend=0
FileToSend="Null"
FuleToSendFullPath="Null"
declare -i DefaultNumberOfFiles=`find /home/camerahome/snapshots/FI9821P_00626E55E3A3/snap -type f | wc -l`

while [ $DefaultTime -le $CurrentTime ]
do
CurrentNumberOfFiles=`find /home/camerahome/snapshots/FI9821P_00626E55E3A3/snap -type f | wc -l`
if [ $CurrentNumberOfFiles -eq $DefaultNumberOfFiles ]
then
sleep 60
elif [ $CurrentNumberOfFiles -gt $DefaultNumberOfFiles ]
then
NumberToSend=$(( ( $CurrentNumberOfFiles - $DefaultNumberOfFiles ) / 2 ))
FilesNamesArray=( `ls -t /home/camerahome/snapshots/FI9821P_00626E55E3A3/snap` )
FileToSend=${FilesNamesArray[$NumberToSend]}
FuleToSendFullPath=`echo "/home/camerahome/snapshots/FI9821P_00626E55E3A3/snap/${FilesNamesArray[$NumberToSend]}"`
# debug lines
# echo -e "\n This is a elif section CurrentNumberOfFiles=$CurrentNumberOfFiles >= DefaultNumberOfFiles=$DefaultNumberOfFiles ; NumberToSend=$NumberToSend ; FilesNamesArray=$FilesNamesArray ; FileToSend=$FileToSend ; FuleToSendFullPath=$FuleToSendFullPath"
# end of debug
DefaultNumberOfFiles=$CurrentNumberOfFiles
mutt -s "HomeCamera is reporting - MovementDetected, see attachment" МойМейл@bk.ru -a $FuleToSendFullPath < /home/camerahome/snapshots/Message.txt mutt -s "HomeCamera is reporting - MovementDetected, see attachment" МойМейл@gmail.com -a $FuleToSendFullPath < /home/camerahome/snapshots/Message.txt sleep 45 elif [ $CurrentNumberOfFiles -lt $DefaultNumberOfFiles ] then DefaultNumberOfFiles=$CurrentNumberOfFiles sleep 5 else echo -e "\n Something Strange.\n Here is a dump:\n DefaultTime=$DefaultTime ; CurrentTime=$CurrentTime ; NumberToSend=$NumberToSend ; CurrentNumberOfFiles=$CurrentNumberOfFiles ; DefaultNumberOfFiles=$DefaultNumberOfFiles > /home/camerahome/snapshots/CameraScript_error_log.txt"
sleep 30
fi
tempCurrentTime=`date +%H%M`
CurrentTime=`echo "1$tempCurrentTime"`
done

exit 0
По умолчанию данный скрипт каждую минуту проверяет наличие новых файлов (можно сделать и чаще). Если есть новые файлы – отправляет письмо, если файлов нет – ждёт следующую минуту.
Так как я ещё не научился делать сервисы – я сделал скрипт который запускается по крону и работает в фоне. Для того чтобы избежать каких-либо сбоев в случае если, например, скрипт зависнет, прекратит работу по какой-либо причине – в кроне предусмотрен автоматический запуск скрипта каждую ночь, а скрипт сам себя останавливает за несколько минут до своего перезапуска. Я сделал это ночью – так как ночью я меньше всего ожидаю получение каких-либо данных с камеры – я практически всегда ночью дома и камера ничего не фиксирует.

В процессе работы скрипта для его автоматического перезапуска я использую несколько переменных значение которых равно контрольному значению – когда нужно осуществить перезапуск скрипта и переменной со значением текущего времени. Как выяснилось, некоторые значения последней переменной трактуются системой как шестнадцатеричные, а не десятичные. Всё дело в том что я использую утилиту date для получения текущего значения времени. Утилита date выдаёт данные в виде HM (0000 ; 1024 ; 1512 ; 2359) – лично меня они интересуют в таком виде. В полночь когда значение переходит от 23 часов к нулю в переменную с текущим значением времени записываются значения вида 0000, 0001. В значении сохраняемом в переменной на первом месте стоит ноль, это вызывает сбой так как я сравниваю с десятичным числом – для обхода данной проблемы я формирую значение переменной текущего времени путём добавления единицы перед информацией получаемой из утилиты date – есть и другие методы решения данной проблемы – точное определение содержимого переменной как десятичного (в баше я не нашёл подходящего решения – если вы знаете – напишите, пожалуйста в комментариях), так же можно удалять нули в значении переменной – те что стоят в самом начале. Я лично выбрал добавление в начале единицы – решение простое, работает стабильно и в итоге скрипт делает то что мне нужно.
Если время позволяет [ $DefaultTime -le $CurrentTime ] – скрипт работает. Далее происходит считывание количества файлов в директории куда происходит загрузка снимков камерой. Если текущее количество файлов больше того количества что было минуту назад – происходит отправка письма.
Количество файлов определяется с использованием утилиты find и wc.

Если скрипт определил, что нужно отправлять письмо, то нужно понять какой снимок нужно отправлять – отправлять самый новый снимок неправильно. Там обычно ничего нет – движение уже закончилось или объект уже выходил из кадра – кусок руки, головы или тп получать не имеет смысла – правильнее всего отправить какой-либо снимок из середины новых файлов. Например, было десять файлов, стало 20 – значит нужно отправить 15й.
Это осуществляется следующей конструкцией с использованием списков ‘FilesNamesArray‘.
Так как файлы сортируются от самого нового, получается обратный подсчёт, по этому отправляется не 15, а 5 файл (обратный порядок).
Далее выбранный файл передаётся утилите mutt, она отправляет письмо заранее заданному получателю.

Установка mutt очень проста, перейдёт сразу к настройке.
Настройки хранятся индивидуально для каждого пользователя в его домашнем каталоге.
Вот пример моих настроек – содержимое файла настроек так же есть в посте у меня на сайте
$ cat ~/.muttrc
set imap_user = "UserNamegmail.com"
set imap_pass = "YourAccountPassword"

#set smtp_url = "smtp://UserNamesmtp.gmail.com:587/"
set smtp_url = "smtps://UserNamegmail.com@smtp.gmail.com:465/"
set smtp_pass = "YourAccountPassword"
set from = "UserNamegmail.com"
set realname = "Alexander Yakovlev"

#To use TLS you should add also the following directives:
set ssl_starttls=yes
set ssl_force_tls=yes

set folder = "imaps://imap.gmail.com:993"
set spoolfile = "+INBOX"
set postponed="+[Gmail]/Drafts"

set header_cache=~/.mutt/cache/headers
set message_cachedir=~/.mutt/cache/bodies
set certificate_file=~/.mutt/certificates

set move = no
Тут нужно указать имя вашего smtp сервера, используемый порт, логин и пароль. Всё достаточно просто.
Для данной задачи я завёл отдельный почтовый ящик. Иногда может возникнуть проблема с устареванием используемых мейл клиентов. Например, если вы используете очень старый смартфон и обновлений для него уже не выходило несколько лет, то мейл клиент может перестать работать. Протоколы, сертификаты для работы почты постоянно усовершенствуются, старые версии периодически становятся устаревшими и больше не поддерживаются, например, Гуглом. Для обхода таких ограничений у того же Гугла есть позможность активации специального режима вашего аккаунта в котором будут поддерживаться устаревшие версии.
По этому если у вас вдруг перестанет или не будет работать на сервере какой-либо мейл клиент, попробуйте активировать данную опцию на своём мейл сервисе (Allow less secure app).
Allowing less secure apps to access your account.
Настроить отдельный почтовый ящик для вашего мониторинг сервера можно не только для безопасности, но и для более удобной фильтрации писем у себя на смартфоне.

Возвращаемся обратно к скрипту.
В самом скрипте для отправки письма нужно вызвать утилиту mutt, передать ей адрес получателя, тему письма, указать путь к файлу вложения. Так же можете передать текст письма, он может храниться в отдельном файле. Конечно содержимое этого файла может формироваться отдельно, например, вашим же скриптом, добавляться какая-то индивидуальная информация – если у вас много камер то информация о той камере которая сработала, Если у вас сервер логирования, то часть лога, сгенерировавшего алерт, возможно что-то ещё.
mutt -s "HomeCamera is reporting - MovementDetected, see attachment" МойМейл@bk.ru -a $FuleToSendFullPath < /home/camerahome/snapshots/Message.txt
Настраивать интервал сканирования новых файлов данным скриптом можно произвольно - хоть каждую секунду, регулировать это можно с помощью команды sleep.

Есть ещё два замечания - для более оптимальной работы скрипта, для увеличения скорости его работы и уменьшения потребляемой памяти желательно иметь как можно меньше файлов у вас в директории со снимками (если у вас там будут тысячи файлов, то скрипту придётся обрабатывать очень много файлов, нежели если бы там было пара десятков) - по этому результаты каждого дня лучше переносить в отдельную директорию. О том как это настроено у меня - я рассказывал в своём предыдущем видео о настройке FTP для системы видео наблюдения. Это было первое замечание.
Второе. Если вы как и я используете FTP в связке с mutt или любым другим клиентом которому необходим доступ к файлам в домашней директории, то вам нужно будет создать симлинк на этот файл, сам файл перенести в поддиректорию. Как вы видите на экране - файл sent ссылается на файл в поддиректории. Так как записывать в домашнюю директорию пользователь не может по соображениям безопасности FTP доступа, а программе mutt нужен доступ к файлу sent находящийся в домашней директории пользователя, то мне пришлось создать симлинк на этот файл.

На этом всё. Задавайте свои вопросы в комментариях или во вконтакте.
Если понравилось - Подписывайтесь на канал и расскажите о моём канале своим друзьям.
Удачи!

Использованные ссылки:
Allowing less secure apps to access your account.
Why use user@privatedomain@smtp.gmail.com in Mutt configuration file?
Using Gmail with mutt, the minimal way (IMAP update)