#!/usr/bin/perl

# Author: tomekk
# e-mail:  tomekk/@/oswiecim/./eu/./org
# home page: http://tomekk.oswiecim.eu.org/
#
# Version 0.4
#
# This file is Copyrighted under the GNU Public License.
# http://www.gnu.org/copyleft/gpl.html
##########################################################

# fixed: now script at first saves the message to temp file and later moves it (problems with uncomplete 'bigger' e-mails)

# some uses
use utf8;
use strict;
use File::Temp;
use File::Copy;
use Proc::Daemon;
use Mail::POP3Client;
use Sys::Syslog qw( :DEFAULT setlogsock);

# config path
my $config = "/etc/pimsync/pimsync.conf";

##########################################################
# spawn demon!
Proc::Daemon::Init;

# output buffering mode
$| = 1;

# farm of vars
my (@cfg_file, %conf);
my ($cfg_line, $conf_entry, $conf_entry_data);
my ($host, $ts, $tn, @host_data, $maildir_new_path, @hosts);
my ($pop, $count, $i, $mail_file, $fh);

# read config file into array
open(CONFIG, $config) or die "cannot open config file: $config";
@cfg_file = <CONFIG>;
close(CONFIG);

# parse config file
foreach $cfg_line (@cfg_file)
{
        $cfg_line =~ s/#.*//;
        $cfg_line = trim($cfg_line);

        ($conf_entry, $conf_entry_data) = split(/\s*=\s*/, $cfg_line, 2);
        $conf{$conf_entry} = $conf_entry_data;
}

# push just HOSTs definitions
foreach $host (sort keys %conf)
{
	if ($host =~ /^HOST*/)
	{
		push(@hosts, $conf{$host});
	}
}

# start msg
logit ("starting, timeout: $conf{TIMEOUT}, interval: $conf{INTERVAL}, hosts: ".  scalar(@hosts));

# main loop
while (1)
{
	# loop through each host
	foreach (@hosts)
	{
		@host_data = split(';', $_);

		# basic test of config entry
		if (scalar(@host_data) == 6)
		{
			# make file path, connect to the POP3 server and do the rest
			$maildir_new_path = $conf{BASE_DIR} . "/" . $host_data[0] . "/new";

			if( -d $maildir_new_path) 
			{
				$pop = new Mail::POP3Client(USER => $host_data[1], PASSWORD => $host_data[2], HOST => $host_data[3], PORT => $host_data[4], USESSL => $host_data[5], DEBUG => 1, TIMEOUT => $conf{TIMEOUT});
					
				$count = $pop->Count();

				# some log info (log when messages > 0 and conn problems, don't want to spam)
				if ($count >= 1)
				{
					logit ("Checking: $host_data[1] at $host_data[3] - new messages: $count");
				} elsif ($count == -1)  {
					logit ("Checking: $host_data[1] at $host_data[3] - connection problem");
				}

				# got some messages, fetch them
				if ($count > 0)
				{
					for $i (1 .. $count) 
					{
						# get some data for the new file name
		                                $ts = time;
               			                $tn = mktemp('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');

						# make random file name
						$mail_file = $ts . "." . $tn;

						# save the e-mail message (into temp_dir)
						if (open ($fh, ">" . $conf{TEMP_DIR} . "/" . $mail_file))
						{
							# if file open is ok, try to save the msg
							if ($pop->HeadAndBodyToFile($fh, $i))
							{
								# and mark it for delete
								$pop->Delete($i);
							} else {
								logit ("cannot write to file: $conf{TEMP_DIR}/$mail_file - $!");
							}
						
							# close fh
							close ($fh);

							# move the file (temp_dir to maildir)
							if(!move($conf{TEMP_DIR} . "/" . $mail_file, $maildir_new_path . "/" . $mail_file))
							{
								logit ("cannot move the file: $conf{TEMP_DIR}/$mail_file - $!");
							}
						} else {
							logit ("cannot open file for writing: $conf{TEMP_DIR}/$mail_file - $!");
						}
					}
				}
	
				$pop->Close();
			} else {
				logit ("$maildir_new_path does not exists");
			}
		} else {
			logit ("something is missing in host configuration: $conf{$host}");
		}
	}
	sleep ($conf{INTERVAL});
}

# c'mon PERL, trim!
sub trim($)
{
        my $trim = shift;
        $trim =~ s/^\s+//;
        $trim =~ s/\s+$//;
        return $trim;
}

# syslog log function
# daemon facility, info level
sub logit
{
	my ($msg) = @_;
	my $pid = $$;
        setlogsock('unix');
        openlog("pimsync[$pid]", '', 'daemon');
	syslog('info', $msg);
	closelog;
}
