У меня были проблемы с тем, чтобы cron отправлял электронные письма. Мой интернет-провайдер требует, чтобы поле «От:» совпадало с адресом электронной почты, с которого отправляется электронное письмо, в противном случае письмо будет отклонено. Поскольку cron жестко кодирует поле «От:» на «root (Cron Daemon)», эти электронные письма не отправляются.
Я установил msmtp и могу без проблем отправлять электронные письма из командной строки. Фактически, я заключил некоторые из моих заданий cron в сценарий, который отправляет само письмо. Это нормально работает, но хотелось бы более элегантного решения.
Я изначально использовал пакет msmtp-mta
, которые просто символические ссылки /usr/lib/sendmail
к /usr/bin/msmtp
так что cron будет отправлять электронные письма с помощью msmtp. Поскольку это не сработало, я удалил пакет и поместил сценарий bash в /usr/lib/sendmail
вместо этого следует просто прочитать стандартный ввод и отправить электронное письмо с правильными заголовками:
#!/bin/bash
HEADERS="To: <myemail>
From: Cron <myotheremail>
Subject: Vixie-cron snooper ($@)
"
INPUT=$( cat /dev/stdin )
echo -e "$HEADERS""Stdin:\n$INPUT\n" | msmtp <myemail>
echo "$HEADERS""Stdin:\n$INPUT\n" > /tmp/vixielog
Однако это не дает желаемого эффекта. Я просто получаю почти пустое письмо и /tmp/vixielog
содержит то же самое:
To: <myemail>
From: Cron <myotheremail>
Subject: Vixie-cron snooper (-i -FCronDaemon -oem <myemail>)
Stdin:
Электронные письма приходят в нужное время, поэтому я знаю, что задание cron выполняется правильно, но я не получаю результата. Как я могу настроить этот подход, чтобы получить вывод команды в электронном письме?
В конце концов я пришел к следующему решению. Вместо того, чтобы использовать mstmp-mta
, Я написал свой собственный простой сценарий bash, который действует как мой MTA. Размещен в /usr/sbin/sendmail
, он заменяет заголовок From и отправляет электронное письмо.
#!/bin/bash
sed -e "s/From: root (Cron Daemon)/From: WHATEVER YOU LIKE/" | msmtp $BASH_ARGV
Надеюсь, это поможет всем, кто хочет облегчить решение проблемы.
Ему не нужно знать источник из заголовка почты (в предыдущих сообщениях это From: root (Cron Daemon)):
#!/bin/bash
# /usr/sbin/sendmail
# We write the sent letter to the stdin variable
stdin=$(cat)
# Text to which we will replace the From header:
__REPLACE_WITH="sender name <your.from.mail@domain.com>"
# Find the text between From: and To :, write it to the __FIND_WHAT variable.
__FIND_WHAT=$(echo $stdin | grep -o -P '(?<=From: ).*(?=To:)')
# grep command (above) adds a space to the variable at the end of the line. It must be deleted, otherwise the text replacement will not work.
# Remove the space at the end of the variable
__FIND_WHAT=$( echo $__FIND_WHAT | sed -e 's/\s$//g' )
# Replace the text __FIND_WHAT with __REPLACE_WITH
mail=$(echo "$stdin" | sed -e "s/$__FIND_WHAT/$__REPLACE_WITH/" )
# Send a letter, with the correct sender in the header of the letter.
echo -e "$mail" | msmtp $BASH_ARGV
Я сделал небольшую обертку для системных писем, она разбирает / etc / aliases и отправляет почту в правильном формате (через / usr / sbin / sendmail):
#!/bin/bash
stdin=$(cat)
mail=$(echo "$stdin" | sed "s/From: root (Cron Daemon)/From: ${4} ${4}@domain.com/g")
if [ -f /etc/aliases ]; then
if [ "grep ${1} /etc/aliases" != "" ]; then
exec < /etc/aliases
while read line
do
if [[ $line =~ ^${1}:\ (.*)$ ]] ; then
addr=${BASH_REMATCH[1]}
else
if [[ $line =~ ^default:\ (.*)$ ]] ; then
addr=${BASH_REMATCH[1]}
fi
fi
done
echo $addr
fi
else
addr="default@domain.com"
fi
mail=$(echo "$mail" | sed "s/To: ${4}/To: ${addr} /g")
echo -e "$mail" | msmtp --auto-from=on --read-envelope-from --maildomain=domain.com -t
Просто измените почту по умолчанию и почтовый домен