1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Send mail script help

Discussion in 'Tomato Firmware' started by kthaddock, Dec 10, 2012.

  1. kthaddock

    kthaddock Network Guru Member

    I'm trying to get my sendmail script to work, all working exept
    If I test with putty and command line I get:
    Have you guy's any tips ?

    kthaddock
     
  2. koitsu

    koitsu Network Guru Member

    What's the problem?
     
  3. kthaddock

    kthaddock Network Guru Member

    Code:
    #!/bin/sh
    SMTP="smtp.yourisp.com"
    FROM="router@domain.com"
    FROMNAME="Your Router"
    TO="you@domain.com"
     
    echo "Subject: WAN state notification" >/tmp/mail.txt
    echo "From: \"$FROMNAME\"<$FROM>" >>/tmp/mail.txt
    echo "Date: `date -R`" >>/tmp/mail.txt
    echo "I just got connected to the Interwebz." >>/tmp/mail.txt
    echo "My new IP is: `nvram get wan_ipaddr`" >>/tmp/mail.txt
    echo "" >>/tmp/mail.txt
    echo "--- " >>/tmp/mail.txt
    echo "Your friendly router." >>/tmp/mail.txt
    echo "" >>/tmp/mail.txt
     
    cat /tmp/mail.txt | /usr/sbin/sendmail -S"$SMTP" -f"$FROM" $TO
     
    rm /tmp/mail.txt
    When sending "date" it isn't show up in mail from that script.
     
  4. mvsgeek

    mvsgeek Addicted to LI Member

    I'm just an old MVS dinosaur, but you might try this...

    echo "Date: " `date -R` >>/tmp/mail.txt
     
  5. kthaddock

    kthaddock Network Guru Member

    Thanks but didn't work :eek:
     
  6. koitsu

    koitsu Network Guru Member

    There's no explanation for the problem you're reporting unless $PATH when running that script from whatever method you're using (not the CLI itself) lacks /bin in its path. I would suggest using fully-expanded path names for all utilities, i.e. /bin/date, /bin/nvram, and so on. It may be that $PATH contains another date utility (such as in /opt/bin) that does not support -R or --rfc-2822 flags. Alternately you could use /bin/date +"%a, %d %b %Y %T %z" to get the same output as -R, and that will work consistently across multiple *IXes and date commands.

    Your script also has other issues, such as lack of space after the double-quotes surrounding the real name but before the bracket of the Email address. In fact, your script isn't going to work at all with that bug.

    I would also suggest you stick the contents of your backtick commands into variables at the top, rather than do them inline, i.e. date="`/bin/date -R`" and wanip="`/bin/nvram get wan_ipaddr`" then refer to them in the rest of your script via $date and $wanip.

    Finally, please stop using /tmp/mail.txt as the filename. Use something more random, such as /tmp/mail.txt.$$ ($$ will get expanded to the PID of the /bin/sh instance). I.e. do tmpfile="/tmp/mail.txt.$$", then use $tmpfile therein. You should also use /bin/rm -f to remove the file rather than just rm.
     
  7. kthaddock

    kthaddock Network Guru Member

    Thank you koitsu !
    I get it to work with your suggestions, can you look at it and se if I missed something importent.
    I couldn't use ":" after Date and From so I used " - " .
    Code:
    #!/bin/sh
    SMTP="smtp.yourisp.com"
    FROM="router@domain.com"
    FROMNAME="Your Router"
    TO="you@domain.com"
     
    date="`/bin/date +"%a, %d %b %Y %T %z`"
    wanip="`/bin/nvram get wan_ipaddr`"
    tmpfile="/tmp/mail.txt.$$"
     
    echo "Subject: WAN state notification" >>/$tmpfile
    echo "From - \"$FROMNAME\" <$FROM>" >>/$tmpfile
    echo "Date -" $date >>/$tmpfile
    echo "I just got connected to the Interwebz" >>/$tmpfile
    echo "My new IP is:" $wanip >>/$tmpfile
    echo "" >>/$tmpfile
    echo "---" >>/$tmpfile
    echo "Your friendly router." >>/$tmpfile
    echo "" >>/$tmpfile
     
    cat /$tmpfile | /usr/sbin/sendmail -S"$SMTP" -f"$FROM" $TO
     
    /bin/rm -f $tmpfile
     
  8. koitsu

    koitsu Network Guru Member

    I don't think you understand SMTP correctly, sadly. For Email clients' sakes, those need to be From: and Date:. You also need an extra newline after the SMTP headers and the actual content of the mail. There's absolutely no reason using colon after those words would tickle any problem. You should also be quoting variables whenever possible (you've moved the variable expansion outside of the quotes for reasons I do not understand), and you've also got slashes in front of $tmpfile for no good reason (this will get expanded to //tmp/mail.txt.$$ which will work but it's awful habit).

    You know, there's an easier way to do this that you probably aren't familiar with, which is called a heredoc. Hell, why don't I just write the script for you.

    Code:
    #!/bin/sh
    SMTP="smtp.server"
    FROM="router@domain.com"
    FROMNAME="Your Router"
    TO="some@address"
     
    cat="/bin/cat"
    rm="/bin/rm"
    sendmail="/usr/sbin/sendmail"
    date="`/bin/date +"%a, %d %b %Y %T %z`"
    wanip="`/bin/nvram get wan_ipaddr`"
    tmpfile="/tmp/mail.txt.$$"
     
    $cat << EOF > $tmpfile
    From: "$FROMNAME" <$FROM>
    Subject: WAN state notification
    Date: $date
     
    I just got connected to the Interwebz.
    My new IP is: $wanip
     
    ---
    Your friendly router.
     
    EOF
     
    $sendmail -S"$SMTP" -f"$FROM" "$TO" < $tmpfile
    $rm -f $tmpfile
    
    And I can confirm this works fine. If you want to see it work yourself, change the tmpfile assignment to a static location (i.e. /tmp/mail.txt) and remove the $sendmail and $rm calls at the end, then see the file in /tmp yourself.

    Once this is
     
  9. kthaddock

    kthaddock Network Guru Member

    Okey, well I give it a try and I must confess I'm not a programmer. Thank you for your patient.
    I have tested your script and date isn't displayed in my mail client " Thunderbird"
    kthaddock :(
     
  10. basmaf

    basmaf Serious Server Member

    Change the date line to
    date="`/bin/date +"%a, %d %b %Y %T %z\"`"
     
  11. koitsu

    koitsu Network Guru Member

    Sorry, my mistake (and in two ways). Please change the line to:
    Code:
    date="`/bin/date +'%a, %d %b %Y %T %z'`"
    
    This should address the issue. (Yes, welcome to quoting hell -- this is one of the biggest problems with shell scripts. Backticks, double-quotes, and apostrophes all in one. The quoting order matters as well.)

    The quoting order matters too, by the way. For example if you were to swap the apostrophes and backticks, you'd end up with $date containing the literal string /bin/date +"%a, %d %b %Y %T %z", which obviously isn't what you want. :)

    And if backtick ever bothers you, you can use $( and ) instead, i.e. date="$(/bin/date ...)".
     
  12. kthaddock

    kthaddock Network Guru Member

    Thank you, koitsu and basmaf
    I have tested boths "date" suggests and none working.
    Code:
    date="`/bin/date +"%a, %d %b %Y %T %z\"`"
    Code:
    date="`/bin/date +'%a, %d %b %Y %T %z'`"
    I get this in my mail client.
    I have to do this:
    Code:
    #!/bin/sh
    SMTP="smtp.server"
    FROM="router@domain.com"
    FROMNAME="Your Router"
    TO="some@address"
     
    cat="/bin/cat"
    rm="/bin/rm"
    sendmail="/usr/sbin/sendmail"
    date="`/bin/date +'%a, %d %b %Y %T %z'`"
    wanip="`/bin/nvram get wan_ipaddr`"
    tmpfile="/tmp/mail.txt.$$"
     
    $cat << EOF > $tmpfile
    From: "$FROMNAME" <$FROM>
    Subject: WAN state notification
                                  <<< space here
    Date: $date
    I just got connected to the Interwebz.
    My new IP is: $wanip
     
    ---
    Your friendly router.
     
    EOF
     
    $sendmail -S"$SMTP" -f"$FROM" "$TO" < $tmpfile
    $rm -f $tmpfile
    
     
  13. koitsu

    koitsu Network Guru Member

    So it seems I have to explain how Email works. Sigh. The format of an Email message is as
    follows:

    Code:
    {smtp header}
    {...}
    {blank line}
    {body of email message}
    {...}
    
    An actual Email, including part of the SMTP envelope, as well as SMTP headers and the content itself:

    Code:
    From my@address Wed Dec 12 04:28:05 2012
    Date: Wed, 12 Dec 2012 04:28:05 -0800
    From: Jeremy Chadwick <my@address>
    To: some@address.com
    Subject: Fwd: [outages] Google Incident Report - December 10, 2012
    Message-ID: <20121212122805.GA46615@home.system.lan>
    MIME-Version: 1.0
    Content-Type: text/plain; charset=us-ascii
    Content-Disposition: inline
    User-Agent: Mutt/1.5.21 (2010-09-15)
     
    Nice analysis from Google regarding the outage.
     
    > Here's the report as to what happened during the 18 minutes, from
    > 8:54 to 9:00 AM and then from 9:04 to 9:16 AM PST.
    >
    > http://static.googleusercontent.com/external_content/untrusted_dlcp/www.google.com/en/us/appsstatus/ir/plibxfjh8whr44h.pdf
    
    Look very closely there. You'll see the From:, To:, Subject:, and Date: headers all there in the SMTP header section. The Date: header is where/how your Email client determines when the Email was sent to you.

    If you want the actual date inside of the body of the message, you can put it somewhere after the blank line. It all depends on what you want, but you should still keep it in the SMTP header section too. The only exception to this rule is that you should not use the word "From" (without a colon, and case-sensitive) at the start of a line inside the body of the message.

    BTW, I forgot to add the To: line to the SMTP header section.

    So anyway, to improve the script again, here you go:

    Code:
    #!/bin/sh
    SMTP="smtp.server"
    FROM="router@domain.com"
    FROMNAME="Your Router"
    TO="some@address"
     
    cat="/bin/cat"
    rm="/bin/rm"
    sendmail="/usr/sbin/sendmail"
    date="`/bin/date +'%a, %d %b %Y %T %z'`"
    wanip="`/bin/nvram get wan_ipaddr`"
    tmpfile="/tmp/mail.txt.$$"
     
    $cat << EOF > $tmpfile
    From: "$FROMNAME" <$FROM>
    To: $TO
    Subject: WAN state notification
    Date: $date
     
    Date: $date
    I just got connected to the Interwebz.
    My new IP is: $wanip
     
    ---
    Your friendly router.
     
    EOF
     
    $sendmail -S"$SMTP" -f"$FROM" "$TO" < $tmpfile
    $rm -f $tmpfile
    
    And just to make it crystal clear: the two Date: lines you see there are intentional. The first one is part of the SMTP header (as I showed you), the other is part of the body of the message. Note that I also added the To: header; I should have done that from the get-go, sorry about that.

    The order of the headers doesn't matter either, so if you wanted to put the first Date: entry above From: (to make it easier to understand/read/etc.) that'd be fine.
     
  14. jerrm

    jerrm Network Guru Member

    Koitsu is right. My guess is date -R was always working and kthaddock didn't see it because of the missing end-of-header newline. I would be curious to see his original tmp file output.
     
  15. RMerlin

    RMerlin Network Guru Member

    Doesn't the Busybox sendmail applet take care of inserting the SMTP headers? That's why I only inserted the body entries (Date/From/Subject) when I wrote the original sample script. Unless the sendmail applet merely accts like a straight MTA, expecting you to provide all the headers.
     
  16. koitsu

    koitsu Network Guru Member

    Code:
    root@gw:/tmp/home/root# /usr/sbin/sendmail -f jdc@icarus.home.lan -S icarus.home.lan jdc@icarus.home.lan
    From: bob@jackass.com
    Subject: balls
     
    Does this work?  I sure hope so.
    root@gw:/tmp/home/root#
    
    Mail itself:

    Code:
    From jdc@icarus.home.lan  Wed Dec 12 08:23:29 2012
    Return-Path: <jdc@icarus.home.lan>
    X-Original-To: jdc@icarus.home.lan
    Delivered-To: jdc@icarus.home.lan
    Received: from home.lan (gw.home.lan [192.168.1.1])
            by icarus.home.lan (Postfix) with ESMTP id EE6DF73A1B
            for <jdc@icarus.home.lan>; Wed, 12 Dec 2012 08:23:15 -0800 (PST)
    From: bob@jackass.com
    Subject: balls
    To: jdc@icarus.home.lan
     
    Does this work?  I sure hope so.
    
    So it appears to add the To: SMTP header itself, but the rest of the SMTP headers are up to the user to provide via stdin.

    Be sure to understand that the -f argument is what defines the SMTP MAIL FROM envelope header (the first line you see, re: "From ... " -- note lack of colon), which does not have to be the same thing as what's in the From: SMTP header. SMTP envelope != SMTP header.

    Basically the above would translate to the following SMTP conversation:

    Code:
    HELO gw.home.lan
    MAIL FROM:<jdc@icarus.home.lan>
    RCPT TO:<jdc@icarus.home.lan>
    DATA
    From: bob@jackass.com
    Subject: balls
    To: jdc@icarus.home.lan
     
    Does this work?  I sure hope so.
    .
    QUIT
    
    Based on what I can tell, the /usr/sbin/sendmail binary acts as an idiot middle-man at the TCP level for communicating with an SMTP server. Quite literally as you issue commands to it via stdin, it feeds those directly to the SMTP server it has a TCP connection to. It appears to have some basic understanding of SMTP status codes too. If you give it an Email address the remote SMTP server returns an SMTP 5xx status code for, it rejects it right then and there. Take a look:

    Code:
    root@gw:/tmp/home/root# /usr/sbin/sendmail -f jdc@icarus.home.lan -S icarus.home.lan blah@xxx
    From: bob@jackass.com
    To: blah@xxx
    sendmail: Bad recipient: <blah@xxx>
    Subject: balls
     
    sendmail: Bad recipient: <blah@xxx>
    root@gw:/tmp/home/root#
    
    The "bad recipient" message is coming from /usr/sbin/sendmail itself, but it's a result of my SMTP server (icarus.home.lan) returning relay access denied (because my router is not in my permitted list of IPs/hosts which can send mail through it):

    Code:
    Dec 12 08:22:55 icarus postfix/smtpd[51261]: NOQUEUE: reject: RCPT from gw.home.lan[192.168.1.1]: 554 5.7.1 <blah@xxx>: Relay access denied; from=<bob@jackass.com> to=<blah@xxx> proto=SMTP helo=<gw.home.lan>
    
    The reason there's two "bad recipient" errors -- #1 comes from issuing the To: SMTP header, which /usr/sbin/sendmail obviously converts into the RCPT TO SMTP command, so that gets rejected (relay access denied). #2 comes from after I sent EOF (Ctrl-D), which is where the SMTP server again sent back the same SMTP response (relay access denied) before the socket was closed/QUIT issued.

    So basically, there's no need to include the To: line in the script itself -- the argument on the command-line will cause /usr/sbin/sendmail to do the right thing. I didn't know that until now.

    TL;DR -- /usr/sbin/sendmail is a cheap/crappy TCP-focused MTA. "It works", but I can now see why/how people get incredibly confused by its behaviour.
     

Share This Page