8

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?

2
  • 1
    Does this help serverfault.com/questions/121121/… ?
    – user9517
    Oct 16, 2012 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, 2012 at 12:14

4 Answers 4

10

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.

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 <[email protected]>"


# 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
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="[email protected]"
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

0

If you don't mind having all emails sent from msmtp-mta with the same "From" header you may use the following configuration. The aliases file is useful so that local recipients (ex: root) work

/etc/msmtprc:

account default
...
from [email protected]
# or from %[email protected]
set_from_header on

aliases /etc/aliases

/etc/aliases

default: [email protected]

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .