Daily Email Report plugin

Discuss Scalix Management Services ( formerly Scalix Admin Console )

Moderator: ScalixSupport

jmason1182
Posts: 55
Joined: Wed Jul 11, 2007 4:11 pm

Daily Email Report plugin

Postby jmason1182 » Wed Aug 22, 2007 12:40 pm

First off, let me say that I haven't really had any problems with scalix. In the grand scheme of things, my Scalix experience has been pleasant. Yeah, I've had lots of frustration... times when I couldn't get any help.... even times when I thought I'd have to ditch Scalix.... but the amount of time that it has been up and running without problems FAR outweighs the bad times. Plus, I have my Scalix server backing up via lvm AND via individual mailstore backups.... so I don't worry about losing anything.

SO, I decided to turn my little script that I had written to send myself our local weather forecast into a plugin and post it so other people can use it. This script is a plugin that can be added and maintained via the SAC tools so you can daily email any html document to users or groups. It works by using wget to download the page, store it temporarily, then attach it to an email using mutt. It can work (and has been tested with) a few (2) restricted html pages, several html pages from ftp, and even a few text files from ftp. Also, LOTS and i mean LOTS of general web pages have been done as well. For instance, daily I get a forecast from accuweather.com via this plugin. Secondly, I download several text status & error logs from our ftp servers. And lastly I daily get emails outlining changes in the discover channel's website ( I like watching their videos).

So I know it works....but I still have to say "use at your own risk". So far this hasn't caused any problems whatsoever.

Pay attention to the setup and the notes comments in the script. (Yes, I use bash.... why not!? :D )

Each report is called a "program".... think of it like a newsletter or magazine but you control where it's content comes from. Basically, once installed as a plugin, you can add, delete, list, or run the "programs". I would recommend following the setup exactly. Then, when you run the plugin, select the action from add, del, list, or run. Warning.... if you run it.... it will send email!!!

The only requirements are you have to have wget and mutt..... but seeing as how they are so common (I run fedora 5 with Scalix 11 and used "yum install mutt" to add the mutt program and viola.... oh and wget is almost 99.9% always there on linux... anyway)
that shouldn't be a problem.

Enjoy!

/opt/scalix/daily

Code: Select all

#!/bin/bash
#
# Daily Email Report Scalix Plugin
# Copyright (C) 2007 John A. Mason
#
#
# Requirements:
#       wget - command-line tool to retrieve html documents
#       mutt - command-line tool to send email with attachments
#
#
# Setup:
#
# 1) Copy this file into (for instance) /opt/scalix/
#
# 2) Set the file as executable. (chmod +x /opt/scalix/daily)
#
# 3) Run sxcfgplugin.py --deploy -l daily -i {instance | all} -u sxadmin
#
# 4) Modify the crontab for the following:
#
#  4a) Either use the direct path for the instance to run every morning
#       (ie "30 5 * * 1,2,3,4,5 /var/opt/scalix/##/s/plugin/daily -a run")
#               where ## is the instance
#
#  4b) Or use omrealpath to figure it out.
#       (ie "30 5 * * 1,2,3,4,5 $(/opt/scalix/bin/omrealpath "~/plugin/daily") -a run"
#
#
# 5) Use the SAC to utilize the plugin. Enjoy!
#
# For more help, use man crontab on parameters for crontab.
#
#
#
# Copyright (C) 2007 John A. Mason
#
######################################################################################3
# NOTES: DO NOT EDIT THIS FILE>...... this file edits itself!!
#      - Yes, this is a somewhat security risk... but minimal.
#      - Ensure this file can be writable by using a test run. (I use chmod 755)
#      - It's either this file edits itself.... or we have to
#        do fun stuff with a database to keep the attributes!
#        (the manual says you can't add or delete files... so
#        let's just edit ourself and we aren't doing that!)
#
######################################################################################3

help() {
        echo ""
        echo ""
        echo "VERSION:"
        echo "1.0"
        echo ""
        echo "NAME:"
        echo "Daily Email Report"
        echo ""
        echo "DESCRIPTION:"
        echo ""
        echo "Allows for wget to retrieve an HTML page (including images) to send using mutt each day."
        echo "For example, go to accuweather.com and lookup your local forecast. Then, copy the url "
        echo "and use it to send your local forecast to a new group called weather@your.domain.com!! "
        echo "Then your users can receive their local forecast just by their membership in that group!"
        echo "PARAMETERS:"
        echo "-a        Action          string  single  'add', 'del', 'list', 'run'"
        echo "-n        Name (No SPACES)                string  single  Unique name for this report __NO SPACES__"
        echo "-e        Email Address           string  single  Email address to receive report"
        echo "-u        Target URL              string  single  URL of html page to send"
        echo "-s        Subject         string  single  Subject line of email"
        echo "--help    Help    \"\"    \"\"    \"\"    Usage Information"
        echo ""
        echo "OUTPUT:"
        echo ""
        echo "text/plain"
}

headme() {
        tmpstart=$(grep -E -n "#func\) ${name}$" ${myself} | awk -F: '{print $1}')
        head -$(echo "${tmpstart} - 1" | bc) ${myself}
}
headme2() {
        tmpstart=$(grep -E -n "#call\) ${name}$" ${myself} | awk -F: '{print $1}')
        head -$(echo "${tmpstart} - 1" | bc) ${myself}
}
headme3() {
        runner=runSystem
        tmpstart=$(grep -E -n "#calls\) ${runner}$" ${myself} | awk -F: '{print $1}')
        head -$(echo "${tmpstart} - 1" | bc) ${myself}
}
headme4() {
        runner=runSystem
        tmpstart=$(grep -E -n "#calls\) ${runner}$" ${myself} | awk -F: '{print $1}')
        head -$(echo "${tmpstart} + 2" | bc) ${myself}
}

tailme() {
        tmplen=$(cat ${myself} | wc -l)
        tmpend=$(grep -E -n "#endfunc\) ${name}$" ${myself} | awk -F: '{print $1}')
        tmpstart=$(grep -E -n "#func\) ${name}$" ${myself} | awk -F: '{print $1}')
        tail -$(echo "${tmplen} - ${tmpstart} - (${tmpend} - ${tmpstart})" | bc) ${myself}
}
tailme2() {
        tmplen=$(cat ${myself} | wc -l)
        tmpend=$(grep -E -n "#endcall\) ${name}$" ${myself} | awk -F: '{print $1}')
        tmpstart=$(grep -E -n "#call\) ${name}$" ${myself} | awk -F: '{print $1}')
        tail -$(echo "${tmplen} - ${tmpstart} - (${tmpend} - ${tmpstart})" | bc) ${myself}
}
tailme3() {
        runner=runSystem
        tmplen=$(cat ${myself} | wc -l)
        tmpstart=$(grep -E -n "#calls\) ${runner}$" ${myself} | awk -F: '{print $1}')
        tail -$(echo "${tmplen} - ${tmpstart} + 1" | bc) ${myself}
}
tailme4() {
        runner=runSystem
        tmplen=$(cat ${myself} | wc -l)
        tmpstart=$(grep -E -n "#calls\) ${runner}$" ${myself} | awk -F: '{print $1}')
        tail -$(echo "${tmplen} - ${tmpstart} - 2" | bc) ${myself}
}

add() {
        if [ -z "$name" ] || [ -z "$emailaddress" ] || [ -z "$subject" ] || [ -z "$url" ]; then
                echo "Error: Missing parameter. All fields must be present (name, email, subject, url)" 1>&2;
                echo "Error: Missing parameter. All fields must be present (name, email, subject, url)";
                exit 10
        fi
        grep -E "^#func\) ${name}$" ${myself} > /dev/null 2>&1
        if [ $? -eq 0 ] || [ "${name}" = "runSystem" ]; then
                echo "Error: Name already exists. Names must be unique." 1>&2
                echo "Error: Name already exists. Names must be unique."
                exit 20
        fi
echo "$(headme3)

#func) ${name}
${name}() {
        NAME=\"${name}\"
        SUBJECT=\"${subject}\"
        EMAIL=\"${emailaddress}\"
        URL=\"${url}\"
        wget \"\${URL}\" -o /dev/null -O /tmp/\${NAME}.html
        echo \"\" | mutt -s \"\${SUBJECT}\" -a /tmp/\${NAME}.html \${EMAIL}
        rm -f /tmp/\${NAME}.html
}
#endfunc) ${name}

$(tailme3)" > ${myself}

echo "$(headme4)
#call) ${name}
${name};
#endcall) ${name}
$(tailme4)" > ${myself}

echo "${name} added successfully."

}

list() {
        echo "Current Daily Programs:"
        grep -e "^#func)" ${myself} | grep -v "runSystem" | grep -v "\${name}" | awk '{print "     "$2}'
        echo ""
        exit 0
}
del() {
        if [ -z "$name" ]; then
                echo "Error: Missing parameter. Name is required." 1>&2;
                echo "Error: Missing parameter. Name is required.";
                exit 10
        fi
        grep -E "^#func\) ${name}$" ${myself} > /dev/null 2>&1
        if [ $? -eq 1 ] || [ "${name}" = "runSystem" ]; then
                echo "Error: Name does not exist. Use the list action to see available programs." 1>&2
                echo "Error: Name does not exist. Use the list action to see available programs."
                exit 40
        fi
        echo "$(headme)
$(tailme)" > ${myself}
        echo "$(headme2)
$(tailme2)" > ${myself}
        echo "${name} removed successfully."
}


###########################FUNCTIONS###############################################
#
#  To remove a daily option, just delete the function call in the run function.
#  You can, but don't have to delete the function itself
#
###################################################################################

#func) Google
Google() {
        NAME="Google"
        SUBJECT="Your Daily Google Forecast"
        EMAIL="sxadmin@mydomain.com"
        URL="http://www.google.com"
        wget "${URL}" -o /dev/null -O /tmp/${NAME}.html
        echo "" | mutt -s "${SUBJECT}" -a /tmp/${NAME}.html ${EMAIL}
        rm -f /tmp/${NAME}.html
}
#endfunc) Google

#calls) runSystem
run() {
        echo "Running.... be patient...";
#call) Google
Google;
#endcall) Google
        echo "Completed...";
}

#
# main script
#
declare myself
declare action
declare name
declare emailaddress
declare subject
declare url
myself=$0
action=""
name=""
subject=""
emailaddress=""
url=""

while [ "$1" != "" ]; do
        case "$1" in
                --help) help;
                        exit 0
                        shift;;
                -a) action="$2";
                   shift;;
                -e) emailaddress="$2";
                   shift;;
                -s) subject="$2";
                   shift;;
                -u) url="$2";
                   shift;;
                -n) name="$2";
                   shift;;
                *) echo "Error: Invalid parameter" 1>&2;
                   echo "Error: Invalid parameter";
                   help;
                   exit 10
                   shift;;
        esac
        shift
done


case "$action" in
        add) add;
             exit 0;;
        del) del;
             exit 0;;
        list) list;
             exit 0;;
        run) run;
             exit 0;;
        *) echo "Error: no action given" 1>&2;
           echo "Error: no action given";
           help;
           exit 30;;
esac
exit 0



If you want an explanation of what is going on (to verify agains malicious code, etc...) then read further:

First off, the help outlines the options. The action option determines what to do with the others. For instance, 'list' doesn't need any options... it lists the names of the programs that are currently in the script.

Next, 'add' will add a new program. First, it makes sure that you have a name, email address, subject line, and a url. If those requirements are met (and the name isn't a duplicate of another) then it literally looks for the "runSystem" tags. It then replaces it's script code with what's before the runSystem tags, then adds a new function with the same name as the name provided, and then puts the rest of the script back together. In other words, it just inserts a new function in the right spot that has the same name as the name you provide so it can then add a function call into the run function.

You'll notice the "-a run" parameters in the crontab setup.... that's because the 'run' action will just run the "run" function... which calls the other functions (called programs) and boom.... it works!

The 'del' action will of course delete the program with the same name you provide. Other than that the only complicated thing is the headme and tailme functions.

So here's how they work.... using the utilities head and tail of course! (and bc - the basic calculator... hopefully people have that... and I haven't ever NOT seen it on a unix/linux system... so here's hoping)

Basically, i grep to find the line I need, then use awk to get the line number from the grep command. THEN, i feed that into bc to compute how many lines from the top to output or how many lines from the bottom to output. When I get the output I want from head or tail, I can use echo to insert more program code... OR just make sure i head and tail with a gap to delete code. It's really simple even though it looks really complicated.

Again, I just read in the manual (pg 80 in Scalix Administration Guide v. 11.0.2) where "Plugins cannot remove or delete anything from the Scalix system's file system".... so i figured since it doesn't mention 'editing' that I would just use the script file I'm already in!!! Then a cronjob can have direct access to wget and then attach an html document to send via email!!!

Oh... and don't ask.... if you want to access restricted content with this you are crazy!!! FTP files can be done via: ftp://username:password@url.url.com as the url. Same thing with some restricted http locations. BUT if it is a server-script (like PHP) that is securing the url... then good luck. You just have to deal with some weird parameters and hope you can pass the username and password via normal http request parameters!

Good luck!

jmason1182
Posts: 55
Joined: Wed Jul 11, 2007 4:11 pm

Postby jmason1182 » Thu Sep 13, 2007 9:04 am

September 13, 2007 - I have been using my plugin now for quite some time... and it works great!


Return to “Scalix Management Services”



Who is online

Users browsing this forum: No registered users and 2 guests