3

I have had some trouble with getting cron to send emails. My ISP requires that the "From:" field match the email address the email is being sent from, otherwise the email is rejected. As cron hardcodes the "From:" field to "root (Cron Daemon)", these emails are not being sent.

I have set up msmtp and can send emails with no problem from the command line. In fact I have wrapped some of my cron jobs in a script that sends the email itself. This works fine, but I would like a more elegant solution.

I originally used the package msmtp-mta, which just symlinks /usr/lib/sendmail to /usr/bin/msmtp so that cron will send emails using msmtp. Since that didn't work, I removed the package and put a bash script in /usr/lib/sendmail instead that should just read from standard input and send an email with the right headers:

#!/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

However, this doesn't have the desired effect. I just receive an almost empty email and /tmp/vixielog contains the same:

To: <myemail>
From: Cron <myotheremail>
Subject: Vixie-cron snooper (-i -FCronDaemon -oem <myemail>)

Stdin:

The emails come at the right time, so I know the cron job is being run properly, but I am not getting the output. How could I adjust this approach to get the output of the command in the email?

  • 1
    Does this help serverfault.com/questions/121121/… ? – user9517 Oct 16 '12 at 10:11
  • Thanks but that isn't what I'm looking for. I can send emails by wrapping each cron entry separately, but that is too cumbersome. I'm looking for a more elegant solution. – robin Oct 16 '12 at 12:14
5

Eventually I came to the following solution. Rather than using mstmp-mta, I wrote my own simple bash script that acts as my MTA. Placed in /usr/sbin/sendmail, it replaces the From header and sends the email on.

#!/bin/bash

sed -e "s/From: root (Cron Daemon)/From: WHATEVER YOU LIKE/" | msmtp $BASH_ARGV

Hopefully this helps anybody else who wants a lightweight solution to the problem.

| improve this answer | |
1

It doesn't need to know source from mail header (previous posts it 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
| improve this answer | |
0

I've made little wrapper for system mails, it parses /etc/aliases and send mail in correct format (through /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 

Just change default mail and mail domain

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.