|
|
|
|
|
|
| |
Hi All.
This code opens a pop3 mailbox and reads in the messages stored there one at a time. Each messages is taken and the subject line and body are built and passed to a create_incident function which would process it according to the needs of your application (you get to write this part!).
Each message is read and checked for some kind of validity (I checked the subject line for certain items) and if its spam, it flagged for deletion. Regular allowable messages are then separated into a subject and a full body line (handles base64 encoded messages as well). Once the message was processed, its flagged for deletion, which happens when the server closes the connection to the mailbox.
The intent of this code was not to emulate a mail system, its design goal was to read emails, and produce database records based on that email's data. It does not make full use of the POP3 functionaility, but then it didn't need to.
Enjoy...
Bastien
| <?php
require("email_functions.php");
global $timeout, $error, $buffer;
// Date in the past
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
// always modified
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// HTTP/1.1
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
// HTTP/1.0
header("Pragma: no-cache");
ob_start();
//-----------------------------------------------------------------------------
// Declarations
//-----------------------------------------------------------------------------
$error = ""; // Error string.
$timeout = 90; // Default timeout before giving
up on a network operation.
$Count = -1; // Mailbox msg count
$buffer = 512; // Socket buffer for socket
fgets() calls, max per RFC 1939 the returned line a POP3
// server can send is 512 bytes.
$server = "mail.yourdomain.com"; // Set this to hard code
the server name
$RFC1939 = true; // Set by noop(). See
rfc1939.txt
$msg_list_array = array(); // List of messages from server
$login = 'email_login';
$pass = 'email_password';
$KeyUserID = 'me'; // for the db record to id the program
as the user
//-----------------------------------------------------------------------------
// Control Code
//-----------------------------------------------------------------------------
//echo "<h2>Starting Program</h2><br>";
set_time_limit($timeout);
$fp = connect ($server, $port = 110);
$Count = login($login,$pass, $fp);
if( (!$Count) or ($Count == -1) )
{
do_log("TIRS", "Check for new messages",'', "No Messages");
exit;
}// end if
// ONLY USE THIS IF YOUR PHP VERSION SUPPORTS IT!
// register_shutdown_function(quit());
if ($Count < 1)
{
die();
} else {
//echo "Login OK: Inbox contains [$Count] messages<BR>\n";
do_log("TIRS", "Check for new messages",'', "$Count Messages");
$msg_list_array = uidl("", $fp);
set_time_limit($timeout);
}// end if
// loop thru the array to get each message
for ($i=1; $i <= $Count; $i++){
set_time_limit($timeout);
$MsgOne = get($i, $fp);
if( (!$MsgOne) or (gettype($MsgOne) != "array") )
{
//echo "oops, Message not returned by the server.<BR>\n";
exit;
}// end if
/*
call the function to read the message
returns true if access, breakdown and insertion
in to db are completed sucessfully
*/
message_details($MsgOne, $i, $fp);
}// end for loop
//close the email box and delete all messages marked for deletion
quit($fp);
//close the application
//echo "<br>Finished</b>";
exit;
//-----------------------------------------------------------------------------
// Function Listing
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Get the Message Details
//-----------------------------------------------------------------------------
function message_details($MsgOne, $msgNo, $fp)
{
/*
Function to read the message and extract :
a. subject
b. date
c. split the body line by line
*/
$body = ''; // get the body of the message into 1 variable
$subjects = ''; // get the subject of the email
$dates = ''; // get the date of the email
$body_start_key = false; // body starts at blank line, blank line is
separator for from headers to body
$TIRSFlag = false; // flag for seeing if the email is really to
be processed by the app
$base64Flag = false; // flag to handle base 64 encoding by
email systems.
foreach ($MsgOne as $key => $value)
{
if (trim($value) == "Content-Transfer-Encoding: base64"){
$base64Flag = true;
}//end if
//get the subject line of the email
if (strlen(stristr($value, "Subject"))>1){
$subjects = trim(stristr($value, " "));
//look for IncidentNo in the subject to see if we need to attempt to process the email
if (strlen(stristr($subjects, "IncidentNo:"))>1){
$TIRSFlag = true;
}// end if
}// end if
//get the date of the email
if (strlen(stristr($value, "Date"))>1){
$dates = trim(stristr($value, " "));
$date_key = $key;
}// end if
//the body
if (strlen(trim($value))==0){
if ($body_start_key == false){ $body_start_key = true; } //set the start key for the body
}//end if
if ($body_start_key == true){
$body .= trim($value);
if ($base64Flag == false){ $body .="<br />"; }
}// end if
}// end foreach
// only create incident if the subject line contains the word incident
if ($TIRSFlag == false){
//delete the message
delete($msgNo, $fp);
}else{
//decode the message if its base64 encoded
if ($base64Flag == true) {
$body = base64_decode($body);
}//end if
// call the function that does the sql inserts
create_incident($subjects, $body, $msgNo, $fp);
}// end if
}// end function
//-----------------------------------------------------------------------------
// Create the incident
//-----------------------------------------------------------------------------
function create_incident($subject, $message_body, $msgNo, $fp)
{
//process the body of the email and take it apart and find stuff in it...do whatever processing you need to here
//the code below is simply a hint and probably not relevant to your situation
//its strictly here as a guide as to what can be done with the body of the email
//my application takes the subject and body apart and creates a record in our web-based
//application's database (the code for this has been removed...)
// declarations for function
$inc_sec_off = '';
$inc_site = '';
$inc_type = '';
$inc_issue = '';
$inc_co_id = '';
$inc_http = '';
$options = '';
// take the subject apart to get the individual elements
$sub_details = stristr($subject, ":"); // get
rest of subject line from the first ':'
$split_subject = explode (" ", $sub_details); //
split on space
$incident_no = trim($split_subject[1]); //
incident number from email
$incident_type = trim($split_subject[3]); //
incident type from email
$inc_date = trim($split_subject[5]); // incident date
from email
$inc_dates = explode("/",$inc_date);
if (count($inc_dates)>1){
$inc_date = $inc_dates[2]."-".$inc_dates[0]."-".$inc_dates[1];
//proper date format (Damned Americans)
}//end if
$weekday = date( "l", $inc_date); // get the weekday
$time = strtotime($inc_date . " ". trim($split_subject[6]));
$inc_time = date("H:i:s", strftime($time) ); // incident
time from email
//convert the body crlf to <br> tags if not done when the message was built
if (strlen(stristr($message_body,"<br>"))==0){
$message_body = nl2br($message_body);
}
// take the body apart to get the individual elements
$body = explode("<br />", $message_body);
for ($x=0; $x<count($body); $x++){
if (strlen(stristr($body[$x], "Security Officer"))>1) {
$inc_sec_off = substr(stristr($body[$x], ":"),1); }
if (strlen(stristr($body[$x], "client_number"))>1) { $inc_site
= substr(stristr($body[$x], ":"),1); }
if (strlen(stristr($body[$x], "Company ID"))>1) { $inc_co_id
= substr(stristr($body[$x], ":"),1); }
if (strlen(stristr($body[$x], "Are"))>1) { $inc_issue
= substr(stristr($body[$x], ":"),1); }
if (strlen(stristr($body[$x], "http"))>1) { $inc_https
= explode("//",$body[$x]); }
}// end for loop
//echo $message_body;
//delete the email if the insertion was succesful
if ($result && $result1){
delete ($msgNo, $fp);
}// end if
}// end function
?> | |
email_functions.php
| <?php
/*
<!-- Version=2.30 Date=11/05/04 Name=email_functions.php --> */
function connect ($server, $port)
{
global $buffer;
// Opens a socket to the specified server. Unless overridden,
// port defaults to 110. Returns true on success, false on fail
// If MAILSERVER is set, override $server with it's value
$e_server = $server;
if(!$fp = fsockopen($e_server, $port, &$errno, &$errstr))
{
$error = "POP3 connect: Error [$errno] [$errstr]";
return false;
}
stream_set_blocking($fp,true);
update_timer();
$reply = fgets($fp,$buffer);
$reply = strip_clf($reply);
if(!is_ok($reply))
{
$error = "POP3 connect: Error [$reply]";
return false;
}
$BANNER = parse_banner($reply);
$RFC1939 = noop($fp);
if($RFC1939)
{
$error = "POP3: premature NOOP OK, NOT an RFC 1939 Compliant server";
quit($fp);
return false;
}
return $fp;
}// end function
function noop ($fp)
{
$cmd = "NOOP";
$reply = send_cmd($cmd, $fp);
if(!is_ok($reply))
{
return false;
}
return true;
}// end function
function user ($user, $fp)
{
// Sends the USER command, returns true or false
if(empty($user))
{
$error = "POP3 user: no user id submitted";
return false;
}
$reply = send_cmd("USER $user", $fp);
if(!is_ok($reply))
{
$error = "POP3 user: Error [$reply]";
return false;
}
return true;
}// end function
function pass ($pass, $fp)
{
// Sends the PASS command, returns # of msgs in mailbox,
// returns false (undef) on Auth failure
if(empty($pass))
{
$error = "POP3 pass: no password submitted";
return false;
}
$reply = send_cmd("PASS $pass", $fp);
if(!is_ok($reply))
{
$error = "POP3 pass: authentication failed [$reply]";
quit($fp);
return false;
}
// Auth successful.
//echo "<br>User Authenticated<br>";
$count = last("count", $fp);
$COUNT = $count;
$RFC1939 = noop($fp);
if(!$RFC1939)
{
$error = "POP3 pass: NOOP failed. Server not RFC 1939 compliant";
quit($fp);
return false;
}
return $count;
}// end function
function login ($login = "", $pass = "", $fp)
{
// Sends both user and pass. Returns # of msgs in mailbox or
// false on failure (or -1, if the error occurs while getting
// the number of messages.)
if(!user($login, $fp))
{
// Preserve the error generated by user()
return false;
}
$count = pass($pass, $fp);
if( (!$count) or ($count == -1) )
{
// Preserve the error generated by last() and pass()
return "-1";
}
return $count;
}// end function
function top ($msgNum, $numLines = "0", $fp)
{
// Gets the header and first $numLines of the msg body
// returns data in an array with each returned line being
// an array element. If $numLines is empty, returns
// only the header information, and none of the body.
update_timer();
$buffer = $buffer;
$cmd = "TOP $msgNum $numLines";
fwrite($fp, "TOP $msgNum $numLines\r\n");
$reply = fgets($fp, $buffer);
$reply = $strip_clf($reply);
if($DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
if(!is_ok($reply))
{
$error = "POP3 top: Error [$reply]";
return false;
}
$count = 0;
$MsgArray = array();
$line = fgets($fp,$buffer);
while ( !ereg("^\.\r\n",$line))
{
$MsgArray[$count] = $line;
$count++;
$line = fgets($fp,$buffer);
if(empty($line)) { break; }
}
return $MsgArray;
}// end function
function pop_list ($msgNum = "", $fp)
{
// If called with an argument, returns that msgs' size in octets
// No argument returns an associative array of undeleted
// msg numbers and their sizes in octets
global $buffer;
$Total = $Count;
if( (!$Total) or ($Total == -1) )
{
return false;
}
if($Total == 0)
{
return array("0","0");
// return -1; // mailbox empty
}
$update_timer();
if(!empty($msgNum))
{
$cmd = "LIST $msgNum";
fwrite($fp,"$cmd\r\n");
$reply = fgets($fp,$buffer);
$reply = $strip_clf($reply);
if(!is_ok($reply))
{
$error = "POP3 pop_list: Error [$reply]";
return false;
}
list($junk,$num,$size) = explode(" ",$reply);
return $size;
}
$cmd = "LIST";
$reply = $send_cmd($cmd, $fp);
if(!is_ok($reply))
{
$reply = $strip_clf($reply);
$error = "POP3 pop_list: Error [$reply]";
return false;
}
$MsgArray = array();
$MsgArray[0] = $Total;
for($msgC=1;$msgC <= $Total; $msgC++)
{
if($msgC > $Total) { break; }
$line = fgets($fp,$buffer);
$line = $strip_clf($line);
if(ereg("^\.",$line))
{
$error = "POP3 pop_list: Premature end of list";
return false;
}
list($thisMsg,$msgSize) = explode(" ",$line);
settype($thisMsg,"integer");
if($thisMsg != $msgC)
{
$MsgArray[$msgC] = "deleted";
}
else
{
$MsgArray[$msgC] = $msgSize;
}
}
return $MsgArray;
}// end function
function get ($msgNum, $fp)
{
// Retrieve the specified msg number. Returns an array
// where each line of the msg is an array element.
global $buffer;
update_timer();
$buffer = $buffer;
$cmd = "RETR $msgNum";
$reply = send_cmd($cmd, $fp);
if(!is_ok($reply))
{
$error = "POP3 get: Error [$reply]";
return false;
}
$count = 0;
$MsgArray = array();
$line = fgets($fp,$buffer);
while ( !ereg("^\.\r\n",$line))
{
$MsgArray[$count] = $line;
$count++;
$line = fgets($fp,$buffer);
if(empty($line)) { break; }
}
return $MsgArray;
}// end function
function last ( $type = "count", $fp )
{
// Returns the highest msg number in the mailbox.
// returns -1 on error, 0+ on success, if type != count
// results in a popstat() call (2 element array returned)
$last = -1;
$reply = send_cmd("STAT", $fp);
if(!is_ok($reply))
{
$error = "POP3 last: error [$reply]";
return $last;
}
$Vars = explode(" ",$reply);
$count = $Vars[1];
$size = $Vars[2];
settype($count,"integer");
settype($size,"integer");
if($type != "count")
{
return array($count,$size);
}
return $count;
}// end function
function resets($fp)
{
// Resets the status of the remote server. This includes
// resetting the status of ALL msgs to not be deleted.
// This method automatically closes the connection to the server.
$reply = $send_cmd("RSET", $fp);
if(!is_ok($reply))
{
// The POP3 RSET command -never- gives a -ERR
// response - if it ever does, something truely
// wild is going on.
$error = "POP3 reset: Error [$reply]";
}
quit($fp);
return true;
}// end function
function send_cmd ( $cmd, $fp )
{
// Sends a user defined command string to the
// POP server and returns the results. Useful for
// non-compliant or custom POP servers.
// Do NOT include the \r\n as part of your command
// string - it will be appended automatically.
// The return value is a standard fgets() call, which
// will read up to $buffer bytes of data, until it
// encounters a new line, or EOF, whichever happens first.
// This method works best if $cmd responds with only
// one line of data.
global $buffer;
if(!isset($fp))
{
$error = "POP3 send_cmd: No connection to server";
return false;
}
if(empty($cmd))
{
$error = "POP3 send_cmd: Empty command string";
return "";
}
$buffer = $buffer;
update_timer();
fwrite($fp,"$cmd\r\n");
$reply = fgets($fp,$buffer);
$reply = strip_clf($reply);
return $reply;
}// end function
function quit($fp)
{
// Closes the connection to the POP3 server, deleting
// any msgs marked as deleted.
global $buffer;
$cmd = "QUIT";
fwrite($fp,"$cmd\r\n");
$reply = fgets($fp,$buffer);
$reply = strip_clf($reply);
fclose($fp);
return true;
}// end function
< |
| |