Rev 23 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
<?php
/*
* getBackupMail.php
*
* Author: R. W. Rodolico
* Copyright: 20160218, Daily Data, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
* Read messages from mail server. If they are YAML or XML sysinfo reports
* save them to local drive, then remove them from mail server.
* Files will be named with the following values, separated by underscores
* report date (YYYY-MM-DD)
* report time (HH:MM:SS) (CONTAINS COLONS)
* client name (MAY CONTAIN SPACES)
* device name
* serial number (default to 00000 if it is not in the report)
*
* Requires php5-imap
* apt-get install php5-imap
*
* Good information taken from
* http://docstore.mik.ua/orelly/webprog/pcook/ch17_04.htm
*
* V0.1 201602018 RWR
* copied from getSysinfoMail.php
*
*
*
*/
$VERSION = '0.1';
$MAXDOWNLOAD = 10000; // maximum number of e-mails to download at one time
$LOGGING = 1;
$CLI = isset( $_SERVER["TERM"]); // only set if we are not in a cron job
// where to load the configuration file from
$confFileName = "rsbackupRead.conf.yaml";
$searchPaths = array( '/etc/camp', '/opt/camp', '/opt/camp/backups', $_SERVER['SCRIPT_FILENAME'], getcwd() );
/*
* function loadConfig
* Parameters $confFileName - the name of the configuration file
* $searchPaths - an array of paths to be searched
* Returns An array containing the configuration
* will search for a configuration file in $searchPaths for $confFileName
* in order (so as to give priorities). The configuration file is
* assumed to be a YAML file
*/
function loadConfig ( $confFileName, $searchPaths ) {
/*
* we don't know where the configuration file will be, so we have a list
* below (searchPaths) to look for it. It will load the first one it
* finds, then exit. THUS, you could have multiple configuration files
* but only the first one in the list will be used
*/
$configuration = array();
foreach ( $searchPaths as $path ) {
if ( file_exists( "$path/$confFileName" ) ) {
print "Found $path/$confFileName\n";
$configuration = yaml_parse_file( "$path/$confFileName" );
#require "$path/$confFileName";
break; // exit out of the loop; we don't try to load it more than once
} // if
} // foreach
return $configuration;
}
/*
* function OpenMailbox
* Parameters: $username
* $password
* $server
* $ssl=true
* $port=null
* $mailbox='INBOX'
*
* Returns: The IMAP instance handle
* The server string (used by some functions)
*/
function OpenMailbox ( $username, $password, $server, $ssl = true, $port=null, $mailbox = 'INBOX' ) {
if ( $port == null )
if ( $ssl ) $port = 993; else $port = 143;
$server = gethostbyname( $server );
$serverString = "$server:$port/imap";
if ( $ssl ) $serverString .= '/ssl';
$serverString .= '/novalidate-cert';
$serverString = '{' . $serverString . '}' . $mailbox;
$server = imap_open( $serverString, $username, $password );
return array($server, $serverString);
}
/*
* function getContents
* Paramters $mail - handle to the connection
* $n - the # of the message to get
* Returns An array containing all attachments
*
*/
function getContents( $mail, $n ) {
$header = imap_header( $mail, $n );
$structure = imap_fetchstructure( $mail, $n );
$attachments = array();
if(isset($structure->parts) && count($structure->parts)) {
for($i = 0; $i < count($structure->parts); $i++) {
$attachments[$i] = array(
'is_attachment' => false,
'filename' => '',
'name' => '',
'attachment' => ''
);
if($structure->parts[$i]->ifdparameters) {
foreach($structure->parts[$i]->dparameters as $object) {
if(strtolower($object->attribute) == 'filename') {
$attachments[$i]['is_attachment'] = true;
$attachments[$i]['filename'] = $object->value;
}
}
}
if($structure->parts[$i]->ifparameters) {
foreach($structure->parts[$i]->parameters as $object) {
if(strtolower($object->attribute) == 'name') {
$attachments[$i]['is_attachment'] = true;
$attachments[$i]['name'] = $object->value;
}
}
}
if($attachments[$i]['is_attachment']) {
$attachments[$i]['attachment'] = imap_fetchbody($mail, $n, $i+1);
if($structure->parts[$i]->encoding == 3) { // 3 = BASE64
$attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
}
elseif($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
$attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
}
} else {
$attachments[$i]['attachment'] = imap_fetchbody( $mail, $n, $i+1 );
}
}
}
return array( $header, $attachments );
}
function saveAttachments ( $attachments, $mailDate ) {
$body = '';
$saved = false;
foreach ( $attachments as $thisOne ) {
if ( $thisOne['is_attachment'] ) {
saveFile( makeFileName( $thisOne['filename'] ), $thisOne['attachment'], $mailDate );
$saved = true;
} else {
$body .= $thisOne['attachment'];
}
}
return array( $saved, $body );
}
/* function makeFileName
* Parameter $data
* $type - the type of the file
* Returns properly formatted file name for saving
*
* The file name is created as a combination of the report date
* client name, hostname and serial number, separated by the underscore
* character. The type of the file is appended, and the configuration
* value for outpath is prepended
*/
function makeFileName ( $body ) {
global $configuration;
$outpath = $configuration['outpath'];
return $outpath . '/' . $body;
}
/*
* function saveFile
* parameter $filename
* $contents
* $timestamp
* returns Number of bytes written
*
* Saves $contents to file $filename, then sets the timestamp to
* $timestamp. It is assumed $filename was created by makeFileName
* and $contents is the content of a report. $timestamp is the actual
* report timestamp
*/
function saveFile( $filename, $contents, $timestamp ) {
$bytesWritten = file_put_contents( $filename, $contents );
if ( $bytesWritten ) {
if ( ! touch( $filename, $timestamp ) ) logError( "could not set timestamp of $filename to $timestamp" );
}
return $bytesWritten;
}
function logError ( $message ) {
global $configuration;
error_log( "$message\n", 3, $configuration['logFile'] );
}
/**************************************************************************************************************
* Begin Main Program
**************************************************************************************************************/
// get the configuration
$configuration = loadConfig( $confFileName, $searchPaths );
#print_r( $configuration ) ; die;
// ensure the path we want to write to exists
if ( ! is_dir( $configuration['outpath'] ) ) {
if ( ! mkdir( $configuration['outpath'], 0777, true ) ) {
die( "Could not create path " . $configuration['outpath'] . "\n" );
}
}
$listMailboxes = isset( $argv[1] ) ; // anything passed on cli results in a list of mailboxes instead of the job
foreach ( $configuration['servers'] as $thisServer ) {
if ($MAXDOWNLOAD <= 0 ) break;
if ( ! $thisServer['enabled'] ) continue; // ignore anything that is not enabled
print "Working on " . $thisServer['servername'] . "\n";
$messagesToDelete = array(); // trap the UID's of messages to delete, more accurate than using message number
print "Opening " . $thisServer['servername'] . "\n";
// open the mail server connection. NOTE: the $connectString is used in other functions, so we need to preserve it
list( $server, $connectString ) = OpenMailbox( $thisServer['username'],
$thisServer['password'],
$thisServer['servername'] ,
$thisServer['ssl'],
$thisServer['port'],
$listMailboxes ? '' : $thisServer['mailbox']
);
print "Success with $connectString\n";
if ( $listMailboxes ) {
$list = imap_list($server, $connectString, "*");
print_r( $list ); print "\n";
continue;
}
$count = 0;
$lookedAt = 0;
if ( $server ) {
$folderCount = imap_num_msg( $server );
for ( $num = 1; ($num <= $folderCount) && $MAXDOWNLOAD; $num++ ) {
list( $header, $attachments ) = getContents( $server, $num );
$lookedAt++;
# $mailDate = getMailDate( $header );
list($saved,$body) = saveAttachments( $attachments, strtotime($header->date) );
if ( $saved ) {
$messagesToDelete[] = imap_uid( $server, $num );
$count++;
$MAXDOWNLOAD--;
}
if ( $CLI ) print '.'; // only do this if interactive session
} // for
if ( $thisServer['deleteProcessed'] ) {
foreach ( $messagesToDelete as $uid ) {
imap_delete( $server, $uid, FT_UID ) or logError( "Can't delete [$uid]: imap_last_error()" );
}
imap_expunge( $server );
} // if delete
imap_close( $server );
} else {
print "Could not open server " . $thisServer['servername'] . "\n";
} // if..else
print "\nLooked at $lookedAt messages, Processed $count\n\n";
} // outer for
?>