Иногда требуется организовать отправку писем с картинками. Мне это понадобилось для системы мониторинга. Чтобы скрипт отправлял мне графики. Для этого можно написать программы на любых языках, но самое переносимое решение, работающие на любых системах, — это shell.
Этот пример легко адаптировать к любым надобностям и даже перенести на другие языки, хотя там, возможно, есть более удобные средства для работы с MIME.
Будем формировать письмо с двумя вложенными контейнерами:
На верхнем уровне тип будет multipart/related
. В этом
контейнере первым будет идти текстовый контейнер, а далее
картинки.
Состоит из двух альтернатив (multipart/alternative
).
Первая — обычный текст для клиентов, которые не понимают HTML.
Вторая — HTML. Здесь будут ссылки на картинки.
Просто кодируются в base64.
# список картинок
# он нам понадобится дважды, поэтому кладём его в переменную
# (у такого подхода есть нехорошее ограничение -- имена картинок
# не могу содержать, например, пробелов; но мы закроем на это глаза)
export graph='http http-state loadavg memory ping proc uwsgi'
(
# формируем заголовки письма,
# начало контейнера верхнего уровня,
# первую часть контейнера с текстом (именно текстовую)
# и начало контейнера с HTML
t=`date '+%Y:%m:%d %H:%M:%S'`
cat <<TEXT
To: xxxxx@gmail.com
From: yyyyy@rol.ru
Return-Path: yyyyy@rol.ru
Subject: BHost $t
X-Mailer: BHost dayly report
MIME-Version: 1.0
Content-Type: multipart/related; boundary=XXXXXXXXXXXXXXXXXXXX
--XXXXXXXXXXXXXXXXXXXX
Content-Type: multipart/alternative; boundary=YYYYYYYYYYYYYYYYYYYY
--YYYYYYYYYYYYYYYYYYYY
Content-Type: text/plain; charset=utf8
HTML not supported by email client
--YYYYYYYYYYYYYYYYYYYY
Content-Type: text/html; charset=utf8
Content-Transfer-Encoding: base64
TEXT
# Формируем тело HTML-письма
(
# вывод нескольких полезных команд,
# отражающий текущее положение дел,
# прогоняем через sed, чтобы придать
# всему HTML-вид
(
echo '--- uptime'
uptime
echo '--- who'
who
echo '--- last -10'
last -10
echo '--- df'
df
echo '--- free'
free
echo '--- nginx'
wget -qO- http://localhost:81/stub
echo '--- django'
nc 127.0.0.1 18019
echo '--- ps'
ps auxwwwf
echo '--- netstat'
netstat -ant
echo '--- eof'
) | sed '
s-&-\&-g
s-<-\<-g
s->-\>-g
s-"-\"-g
s- -\ -g
s-\t-\ \ -g
s-^-<nobr>-
s-$-</nobr><br>-
1 i \
<tt>
$ a \
</tt>'
# добавляем ко всему этому ссылки на картинки
# вида
# <img src="cid:N@w-report"><br>
j=0
for i in $graph
do
j=$(($j+1))
echo "<img src=\"cid:$j@w-report\"><br>"
done
# и всё это кодируем в base64
) | openssl enc -a
# закрываем контейнер с HTML
cat <<"TEXT"
--YYYYYYYYYYYYYYYYYYYY--
TEXT
# теперь прикрепляем картинки
# в цикле формируем части для каждой
# картинки из списка
j=0
for i in $graph
do
j=$(($j+1))
echo '--XXXXXXXXXXXXXXXXXXXX'
echo "Content-Type: image/png; name=\"$j.png\""
echo 'Content-Transfer-Encoding: base64'
echo "X-Attachment-Id: $j@w-report"
echo "Content-ID: <$j@w-report>"
echo ''
cat "../../../var/rrd-graph/$i-1d.png" | openssl enc -a
done
echo '--XXXXXXXXXXXXXXXXXXXX--'
# и весь результат отправляем по почте
#
) 2>report.log |
msmtp --logfile msmtp2.log \
--host=smtp.gmail.com --port=587 --protocol=smtp \
--auth=on --user=xxx@xxx.xx \
--tls=on --tls-certcheck=off \
--read-envelope-from --read-recipients
Готово.
Если вы планируете запусать это дело из cron
или ещё как-то автоматически,
то очень полезно будет добавить в начало что-то типа
export LANG=C
export TZ='Europe/Moscow'
cd "${0%/*}"
Успехов!