#!/usr/bin/env perl
# File: runReport.pl
# Copyright (c) 2006 Solexa
# Author: A. J. Cox
# This software is covered by the "Illumina Genome Analyzer Software
# License Agreement" and the "Illumina Source Code License Agreement",
# and certain third party copyright/licenses, and any user of this
# source file is bound by the terms therein (see accompanying files
# Illumina_Genome_Analyzer_Software_License_Agreement.pdf and
# Illumina_Source_Code_License_Agreement.pdf and third party
# copyright/license notices).

# Upon completion of a run, send an email of links to "interested parties"

#Usage: runReport.pl [htmlDir|--test] 
#server[:port] domain webRoot [--strip fieldsToStrip] [--reportType GERALD|CASAVA] addressList
#
#htmlDir    : directory containing the summary html pages. Hinks to files will
#             included the email.
#             or --test to send test email (in which case webRoot is ignored)
#server     : name or IP address of SMTP server 
#port       : port number for SMTP services (usually 25 - defaults to this)
#domain     : domain name (e.g. my.organisation.org)
#webRoot    : root of URL (e.g. http://myWebServer/myWebShare/)	
#--strip    : strip fields from file path of htmlDir before appending
#             to webRoot to create URL, e.g. 2 for /mnt/mountPoint (default 2)
#addressList: list of email addresses to send report to (space separated)

# Email is sent by talking to an SMTP server via the SMTP services port, 
# which is traditionally port 25.

# You can test if port 25 of yourserver will be a willing participant in this
# escapade by either:
# telnet yourserver 25 - you should get a friendly message
# nmap -p 25 yourserver (if you have nmap installed)

# Assuming this works run:
# runReport.pl --test yourserver:25 yourdomain anything youremail@yourdomain
# to get a test email

# The protocol used here works on the several different SMTP servers at Solexa.
# However protocols may differ slightly. Try telnetting to the SMTP server and
# typing the commands sent in the 'sendMessage' subroutine manually.
# Unfortunately we can't get involved in supporting/debugging different 
# SMTP protocols - talk to your systems people! 



use warnings;
use strict;
use File::Basename;
use File::Spec;
use IO::Socket;

unless ((@ARGV>=5)||((@ARGV>=3)&&($ARGV[0] eq '--test'))) 
{
    print STDERR << "END";
Usage: $0 [htmlDir|-test] 
server[:port] domain webRoot [--strip fieldsToStrip] [--xls yes|no] addressList

htmlDir    : directory containing the summary html pages. Hinks to files will
             included the email.
             or --test to send test email (in which case webRoot is ignored)
server     : name or IP address of SMTP server 
port       : port number for SMTP services (usually 25 - defaults to this)
domain     : domain name (e.g. my.organisation.org)
webRoot    : root of URL (e.g. http://myWebServer/myWebShare/)	
--strip    : strip fields from file path of htmlDir before appending
             to webRoot to create URL, e.g. 2 for /mnt/mountPoint (default 2)
addressList: list of email addresses to send report to (space separated)
END

exit(0);
}

my @message;
my @transcript;

my @s;

my $curDir=shift(@ARGV);
my $serverName=shift(@ARGV);
my $domainName=shift(@ARGV);
my $webRoot=shift(@ARGV);

if ($webRoot !~ /\/$/)
{
    $webRoot.='/';
} # if

my $fieldsToStrip=2; # strip this many fields from file path

if (@ARGV and $ARGV[0] eq '--strip')
{
    shift (@ARGV);
    $fieldsToStrip=shift(@ARGV);
} # if

my $reportType = 'GERALD';
if (@ARGV and $ARGV[0] eq '--reportType')
{
    shift (@ARGV);
    $reportType=shift(@ARGV);
} # if


my $serverPort=25; # usual port for SMTP service
my $maxServerWait=20; # wait this long for a connection, then die

my $socket;

@s=split(':',$serverName);
($serverName,$serverPort)=@s if (@s==2);

my $host=$ENV{HOST};
$host=$ENV{HOSTNAME} unless (defined($host));
$host="unknown_host" unless (defined($host));


sub sendLine
{
    my ($lineRef)=@_;
    # The "\r\n" is vital when talking to Windows SMTP servers
    # It may be the case that Linux/UNIX SMTP servers need "\n" only
    print $socket $lineRef. "\r\n";
    push @transcript, "> $lineRef\n"; 
} # sendLine

sub getResponse
{
    my $answer=<$socket>;
    push @transcript, "< $answer";
    #  All error codes are in range 500-599
    if ($answer=~/^5[0-9][0-9]/)
    {
	print STDERR "$_" foreach (@transcript);
	warn "Error in SMTP protocol, report not sent";
	exit (0);
   } # if
} # getResponse


sub sendMessage
{
    my $answer;
    unless ($socket=IO::Socket::INET->new
	    ( PeerAddr => $serverName,
	      PeerPort => $serverPort,
	      Proto => 'tcp',
	      Type  => SOCK_STREAM,
	      Timeout => $maxServerWait)) 
    { 
	warn "Could not connect to $serverName:$serverPort - $!"; 
	exit (0); 
    } # OR

    # Some servers demand a domain name here. Those that don't don't seem
    # to mind if one is there.
    sendLine("helo ${domainName}");

    getResponse();

    # Our servers demand that domainName is our domain name. Others might
    # be less fussy.
    sendLine ("mail from: <${host}\@${domainName}>");
    
    getResponse();

    # Our main email server only allows email to be sent to addresses within
    # our domain name
    foreach (@ARGV)
    {
	sendLine("rcpt to: <${_}>");
	getResponse();
        unshift @message, "To: Gerald Reports <${_}>";
    } # foreach

    sendLine('data');

    getResponse();

    foreach (@message)
    {
	sendLine($_);
    } # foreach

    sendLine ('.');

    getResponse();

    sendLine ('quit');

    getResponse();

    print "SMTP protocol completed, transcript follows:\n";
    foreach (@transcript)
    {
	print "$_";
    } # for
} # sub sendMessage

# start of main loop

push @message, "Report sent from $host via $serverName port $serverPort at ".scalar(localtime);

if ($curDir eq '--test')
{
    unshift @message, "Subject: Test message";
    sendMessage();
    exit (0);
} # if


my $file;

#my @filesToLink=qw/Error.htm IVC.htm All.htm Perfect.htm Hist.htm Prb.htm Info.htm Summary.htm Monotemplate.htm Home.html/;
my @filesToLink = glob('Flowcell_Summary_*.htm Project_*/Summary_Stats_*/*.htm');

my $fullDirName=File::Spec->rel2abs($curDir);


# Get rid of any Windows '\' foolishness
$fullDirName=~s/\\/\//g;

my $runFolderPath;
my $runFolderURL;
my $htmlFolderURL;
my $htmlFolderPath;

my @splitHtmlFolder=split('/',$fullDirName);

# Need to do <= because the leading '/' gives an extra null field when split
for (my $i=0; $i<=$fieldsToStrip; $i++)
{
    shift @splitHtmlFolder;
} # for


$"='/';

$htmlFolderPath="@splitHtmlFolder";
$htmlFolderURL="${webRoot}@splitHtmlFolder";

# TBD Ensure only one '/' character at end of webRoot

unshift @message, "Subject: $reportType run completed in @splitHtmlFolder";

if ('GERALD' eq $reportType)
{
    my @splitRunFolder=@splitHtmlFolder;
    pop @splitRunFolder; # Bustard
    pop @splitRunFolder; # Firecrest
    pop @splitRunFolder; # Data
    pop @splitRunFolder; # Run folder
    $runFolderPath="@splitRunFolder";
    $runFolderURL="${webRoot}@splitRunFolder";
    
    my @xls=glob ("$runFolderPath/*.xls");
    
    if (@xls!=0)    
    {
        push @message , "";
        push @message, "Run folder summary spreadsheets:";
        
        foreach $file (@xls)
        {
        	$file=basename($file);
        	my $filePath="$runFolderURL/$file";
        	push @message, "";
        	push @message, "$filePath";
        } # foreach
    } # if
}

push @message, "";
push @message, "Links to output files:";


foreach $file (@filesToLink)
{
    my $filePath=File::Spec->catfile($curDir,$file);

    
    if (-e $filePath)
    {
        push @message , "";
        push @message , "${htmlFolderURL}/${file}";
        push @message , "";
    } # if


} # foreach

sendMessage() if @ARGV;

# end of runReport.pl
