2013-08-09 23:46:21 +00:00
< ? php
2013-08-10 11:59:36 +00:00
class Mail_Handler {
private $db ;
2013-08-12 03:14:00 +00:00
public function mail_fork () {
//Start a new child process and return the process id!
2013-08-10 11:59:36 +00:00
$pid = pcntl_fork ();
return $pid ;
2013-08-09 23:46:21 +00:00
}
2013-08-10 11:59:36 +00:00
2013-08-13 15:16:43 +00:00
public static function send_ticketing_mail ( $ticketObj , $content , $type , $author ) {
global $TICKET_MAILING_SUPPORT ;
if ( $TICKET_MAILING_SUPPORT ){
$txt = " " ;
$subject = " " ;
if ( $type == " REPLY " ){
$txt = " ---------- Ticket # " . $ticketObj -> getTId () . " ---------- \n You received a new reply on your ticket: " . $ticketObj -> getTitle () .
" \n -------------------- \n \n " ;
$subject = " New reply on [Ticket # " . $ticketObj -> getTId () . " ] " ;
$endTxt = " \n \n ---------- \n You can reply on this message to answer directly on the ticket! " ;
$txt = $txt . $content . $endTxt ;
self :: send_mail ( $ticketObj -> getAuthor (), $subject , $txt , $ticketObj -> getTId (), $author );
} else if ( $type == " NEW " ){
$txt = " ---------- Ticket # " . $ticketObj -> getTId () . " ---------- \n Your ticket: " . $ticketObj -> getTitle () . " is newly created " ;
if ( $ticketObj -> getAuthor () != $author ){
$txt = $txt . " by " . Ticket_User :: get_username_from_id ( $author );
} else {
$author = $ticketObj -> getAuthor ();
}
$txt = $txt . " \n -------------------- \n \n " ;
$subject = " New ticket created [Ticket # " . $ticketObj -> getTId () . " ] " ;
$endTxt = " \n \n ---------- \n You can reply on this message to answer directly on the ticket! " ;
$txt = $txt . $content . $endTxt ;
self :: send_mail ( $ticketObj -> getAuthor (), $subject , $txt , $ticketObj -> getTId ());
}
}
}
2013-08-12 03:14:00 +00:00
2013-08-10 11:59:36 +00:00
2013-08-17 01:06:22 +00:00
public static function send_mail ( $recipient , $subject , $body , $ticket_id = 0 , $from = NULL ) {
2013-08-10 11:59:36 +00:00
if ( is_numeric ( $recipient )) {
$id_user = $recipient ;
$recipient = NULL ;
}
2013-08-13 15:16:43 +00:00
$query = " INSERT INTO email (Recipient,Subject,Body,Status,Attempts,Sender,UserId,MessageId,TicketId) VALUES (:recipient, :subject, :body, :status, :attempts, :sender, :id_user, :messageId, :ticketId) " ;
$values = array ( 'recipient' => $recipient , 'subject' => $subject , 'body' => $body , 'status' => 'NEW' , 'attempts' => 0 , 'sender' => $from , 'id_user' => $id_user , 'messageId' => 0 , 'ticketId' => $ticket_id );
2013-08-12 03:14:00 +00:00
$db = new DBLayer ( " lib " );
$db -> execute ( $query , $values );
2013-08-10 11:59:36 +00:00
}
2013-08-12 03:14:00 +00:00
//the main function
2013-08-11 01:55:07 +00:00
function cron () {
2013-08-10 11:59:36 +00:00
global $cfg ;
2013-08-16 19:43:39 +00:00
$default_groupemail = $cfg [ 'mail' ][ 'default_groupemail' ];
$default_groupname = $cfg [ 'mail' ][ 'default_groupname' ];
2013-08-16 20:24:11 +00:00
/*
2013-08-10 11:59:36 +00:00
$inbox_host = $cfg [ 'mail' ][ 'host' ];
2013-08-13 15:16:43 +00:00
$oms_reply_to = " Ryzom Ticketing Support <ticketing@ " . $inbox_host . " > " ;
2013-08-16 19:43:39 +00:00
global $MAIL_DIR ; */
2013-08-10 11:59:36 +00:00
// Deliver new mail
echo ( " mail cron \n " );
2013-08-11 00:29:31 +00:00
//creates child process
2013-08-11 01:55:07 +00:00
$pid = self :: mail_fork ();
2013-08-12 03:14:00 +00:00
$pidfile = '/tmp/ams_cron_email_pid' ;
2013-08-11 00:29:31 +00:00
2013-08-10 11:59:36 +00:00
if ( $pid ) {
2013-08-11 00:29:31 +00:00
2013-08-11 23:11:48 +00:00
// We're the parent process, do nothing!
2013-08-16 19:43:39 +00:00
//INFO: if $pid =
//-1: "Could not fork!\n";
// 0: "In child!\n";
//>0: "In parent!\n";
2013-08-11 23:11:48 +00:00
2013-08-10 11:59:36 +00:00
} else {
2013-08-11 01:55:07 +00:00
//make db connection here because the children have to make the connection.
$this -> db = new DBLayer ( " lib " );
2013-08-11 00:29:31 +00:00
//if $pidfile doesn't exist yet, then start sending the mails that are in the db.
2013-08-10 11:59:36 +00:00
if ( ! file_exists ( $pidfile )) {
2013-08-16 19:43:39 +00:00
2013-08-11 00:29:31 +00:00
//create the file and write the child processes id in it!
2013-08-10 11:59:36 +00:00
$pid = getmypid ();
$file = fopen ( $pidfile , 'w' );
fwrite ( $file , $pid );
fclose ( $file );
//select all new & failed emails & try to send them
2013-08-11 00:29:31 +00:00
//$emails = db_query("select * from email where status = 'NEW' or status = 'FAILED'");
$statement = $this -> db -> executeWithoutParams ( " select * from email where Status = 'NEW' or Status = 'FAILED' " );
$emails = $statement -> fetchAll ();
2013-08-10 11:59:36 +00:00
foreach ( $emails as $email ) {
2013-08-12 21:56:58 +00:00
$message_id = self :: new_message_id ( $email [ 'TicketId' ]);
2013-08-11 00:29:31 +00:00
//if recipient isn't given, then use the email of the id_user instead!
echo ( " Emailing { $email [ 'Recipient' ] } \n " );
if ( ! $email [ 'Recipient' ]) {
2013-08-13 15:16:43 +00:00
$email [ 'Recipient' ] = Ticket_User :: get_email_by_user_id ( $email [ 'UserId' ]);
2013-08-10 11:59:36 +00:00
}
2013-08-16 19:43:39 +00:00
//create sending email adres based on the $sender id which refers to the department id
if ( $email [ 'Sender' ] == NULL ) {
$from = $default_groupname . " < " . $default_groupemail . " > " ;
2013-08-10 11:59:36 +00:00
} else {
2013-08-16 19:43:39 +00:00
$group = Support_Group :: getGroup ( $email [ 'Sender' ]);
$from = $group -> getName () . " < " . $group -> getGroupEmail () . " > " ;
2013-08-10 11:59:36 +00:00
}
2013-08-16 19:43:39 +00:00
2013-08-12 21:56:58 +00:00
$headers = " From: $from\r\n " . " Message-ID: " . $message_id ;
2013-08-16 19:43:39 +00:00
2013-08-11 00:29:31 +00:00
if ( mail ( $email [ 'Recipient' ], $email [ 'Subject' ], $email [ 'Body' ], $headers )) {
2013-08-10 11:59:36 +00:00
$status = " DELIVERED " ;
2013-08-11 00:29:31 +00:00
echo ( " Emailed { $email [ 'Recipient' ] } \n " );
2013-08-10 11:59:36 +00:00
} else {
$status = " FAILED " ;
2013-08-11 00:29:31 +00:00
echo ( " Email to { $email [ 'Recipient' ] } failed \n " );
2013-08-10 11:59:36 +00:00
}
//change the status of the emails.
2013-08-11 00:29:31 +00:00
$this -> db -> execute ( 'update email set Status = ?, MessageId = ?, Attempts = Attempts + 1 where MailId = ?' , array ( $status , $message_id , $email [ 'MailId' ]));
2013-08-16 19:43:39 +00:00
2013-08-09 23:46:21 +00:00
}
2013-08-10 11:59:36 +00:00
unlink ( $pidfile );
2013-08-09 23:46:21 +00:00
}
2013-08-10 11:59:36 +00:00
// Check mail
2013-08-16 20:24:11 +00:00
$sGroups = Support_Group :: getGroups ();
$defaultGroup = new Support_Group ();
2013-08-17 01:06:22 +00:00
$defaultGroup -> setSGroupId ( 0 );
2013-08-16 20:24:11 +00:00
$defaultGroup -> setGroupEmail ( $default_groupemail );
$defaultGroup -> setIMAP_MailServer ( $cfg [ 'mail' ][ 'default_mailserver' ]);
$defaultGroup -> setIMAP_Username ( $cfg [ 'mail' ][ 'default_username' ]);
$defaultGroup -> setIMAP_Password ( $cfg [ 'mail' ][ 'default_password' ]);
$sGroups [] = $defaultGroup ;
2013-08-11 23:11:48 +00:00
2013-08-16 20:24:11 +00:00
foreach ( $sGroups as $group ){
$mbox = imap_open ( $group -> getIMAP_MailServer (), $group -> getIMAP_Username (), $group -> getIMAP_Password ()) or die ( 'Cannot connect to mail server: ' . imap_last_error ());
$message_count = imap_num_msg ( $mbox );
for ( $i = 1 ; $i <= $message_count ; ++ $i ) {
//return task ID
2013-08-17 17:07:00 +00:00
$tid = self :: incoming_mail_handler ( $mbox , $i , $group );
2013-08-16 20:24:11 +00:00
if ( $tid ) {
2013-08-17 17:07:00 +00:00
//TODO: base file on Ticket + timestamp
$file = fopen ( $MAIL_DIR . " /mail/ticket " . $tid . " . " . time (), 'w' );
2013-08-16 20:24:11 +00:00
fwrite ( $file , $entire_email );
2013-08-17 17:07:00 +00:00
fclose ( $file );
//mark message $i of $mbox for deletion!
imap_delete ( $mbox , $i );
2013-08-16 20:24:11 +00:00
}
2013-08-17 17:07:00 +00:00
2013-08-11 23:11:48 +00:00
}
2013-08-16 20:24:11 +00:00
//delete marked messages
imap_expunge ( $mbox );
imap_close ( $mbox );
2013-08-10 11:59:36 +00:00
}
2013-08-09 23:46:21 +00:00
}
2013-08-10 11:59:36 +00:00
}
2013-08-12 21:56:58 +00:00
function new_message_id ( $ticketId ) {
2013-08-10 11:59:36 +00:00
$time = time ();
$pid = getmypid ();
2013-08-11 00:29:31 +00:00
global $cfg ;
global $ams_mail_count ;
$ams_mail_count = ( $ams_mail_count == '' ) ? 1 : $ams_mail_count + 1 ;
2013-08-12 21:56:58 +00:00
return " <ams.message " . " . " . $ticketId . " . " . $pid . $ams_mail_count . " . " . $time . " @ " . $cfg [ 'mail' ][ 'host' ] . " > " ;
2013-08-10 11:59:36 +00:00
}
2013-08-12 21:56:58 +00:00
function get_ticket_id_from_subject ( $subject ){
$startpos = strpos ( $subject , " [Ticket # " );
2013-08-17 01:06:22 +00:00
if ( $startpos ){
$tempString = substr ( $subject , $startpos + 9 );
$endpos = strpos ( $tempString , " ] " );
if ( $endpos ){
$ticket_id = substr ( $tempString , 0 , $endpos );
} else {
$ticket_id = 0 ;
}
} else {
$ticket_id = 0 ;
}
2013-08-12 21:56:58 +00:00
return $ticket_id ;
}
2013-08-10 11:59:36 +00:00
2013-08-12 21:56:58 +00:00
2013-08-17 01:06:22 +00:00
function incoming_mail_handler ( $mbox , $i , $group ){
2013-08-12 21:56:58 +00:00
$header = imap_header ( $mbox , $i );
$subject = self :: decode_utf8 ( $header -> subject );
2013-08-17 01:06:22 +00:00
$entire_email = imap_fetchheader ( $mbox , $i ) . imap_body ( $mbox , $i );
$subject = self :: decode_utf8 ( $header -> subject );
$to = $header -> to [ 0 ] -> mailbox ;
$from = $header -> from [ 0 ] -> mailbox . '@' . $header -> from [ 0 ] -> host ;
$txt = self :: get_part ( $mbox , $i , " TEXT/PLAIN " );
//$html = self::get_part($mbox, $i, "TEXT/HTML");
2013-08-12 21:56:58 +00:00
2013-08-17 01:06:22 +00:00
//get the id out of the email address of the person sending the email.
if ( $from !== NULL && ! is_numeric ( $from )){
$from = Ticket_User :: get_id_from_email ( $from );
}
2013-08-12 21:56:58 +00:00
//get ticket_id out of the message-id or else out of the subject line
$ticket_id = 0 ;
if ( isset ( $header -> references )){
$pieces = explode ( " . " , $header -> references );
if ( $pieces [ 0 ] == " <ams " ){
$ticket_id = $pieces [ 2 ];
} else {
$ticket_id = self :: get_ticket_id_from_subject ( $subject );
}
} else {
$ticket_id = self :: get_ticket_id_from_subject ( $subject );
}
2013-08-17 01:06:22 +00:00
//if ticket id is found, that means it is a reply on an existing ticket
2013-08-12 21:56:58 +00:00
if ( $ticket_id ){
2013-08-13 15:16:43 +00:00
//use the line ---------- Ticket # to make a distincton between the old message and the reply
$endpos = strpos ( $txt , " >---------- Ticket # " );
if ( $endpos ){
$txt = substr ( $txt , 0 , $endpos );
} else {
$endpos = strpos ( $txt , " ---------- Ticket # " );
if ( $endpos ){
$txt = substr ( $txt , 0 , $endpos );
}
}
2013-08-17 01:06:22 +00:00
//if email is sent from an existing email address in the db (else it will give an error while loading the user object)
if ( $from != " FALSE " ){
$user = new Ticket_User ();
$user -> load_With_TUserId ( $from );
$ticket = new Ticket ();
$ticket -> load_With_TId ( $ticket_id );
//if user has access to it!
if (( Ticket_User :: isMod ( $user ) or ( $ticket -> getAuthor () == $user -> getTUserId ())) and $txt != " " ){
Ticket :: createReply ( $txt , $user -> getTUserId (), $ticket -> getTId (), 0 );
}
2013-08-17 17:07:00 +00:00
2013-08-17 01:06:22 +00:00
}
2013-08-17 17:07:00 +00:00
print ( " \n Email found that is a reply to a ticket! \n " );
return $ticket_id ;
2013-08-12 21:56:58 +00:00
2013-08-17 17:07:00 +00:00
} else if ( $from != " FALSE " ){
2013-08-12 21:56:58 +00:00
2013-08-17 01:06:22 +00:00
//if ticket_id isn't found, create a new ticket!
//if an existing email address mailed the ticket
2013-08-17 17:07:00 +00:00
$newTicketId = Ticket :: create_Ticket ( $subject , $txt , 1 , $from , $from );
//if not default group, then forward it!
if ( $group -> getSGroupId ()){
Ticket :: forwardTicket ( 0 , $newTicketId , $group -> getSGroupId ());
2013-08-12 21:56:58 +00:00
}
2013-08-17 17:07:00 +00:00
print ( " \n Email found that is a new ticket! \n " );
return $newTicketId ;
2013-08-13 15:16:43 +00:00
2013-08-17 17:07:00 +00:00
} else {
//if it's a email that has nothing to do with ticketing, return 0;
print ( " \n Email found that isn't a reply or new ticket! \n " );
return 0 ;
2013-08-12 21:56:58 +00:00
}
}
/* function ams_create_email ( $from , $subject , $body , $html , $recipient = 0 , $sender = NULL ) {
2013-08-10 11:59:36 +00:00
2013-08-12 03:14:00 +00:00
//TODO:
2013-08-12 21:56:58 +00:00
if ( $recipient == 0 && ! is_string ( $recipient )) {
2013-08-10 11:59:36 +00:00
global $user ;
$recipient = $user -> uid ;
2013-08-12 21:56:58 +00:00
}
2013-08-10 11:59:36 +00:00
2013-08-12 03:14:00 +00:00
if ( $sender !== NULL && ! is_numeric ( $sender )) $sender = self :: get_id_from_username ( $sender );
if ( ! is_numeric ( $recipient )) $recipient = self :: get_id_from_username ( $recipient );
2013-08-10 11:59:36 +00:00
$message = array (
'creator' => $sender ,
'owner' => $recipient ,
'type' => 'email' ,
'summary' => $subject ,
'data' => array (
'subject' => $subject ,
'body' => $body ,
'html' => $html ,
'sender' => oms_get_username_from_id ( $sender ),
'from' => $from ,
'recipient' => oms_get_username_from_id ( $recipient ),
'time' => time (),
),
);
//TO ASK:
oms_task_create ( $message );
oms_task_index ( $message , array ( 'subject' , 'body' , 'sender' , 'recipient' ));
//---------------------------
return $message [ 'id_task' ];
2013-08-12 21:56:58 +00:00
} */
2013-08-10 11:59:36 +00:00
2013-08-12 03:14:00 +00:00
/* function oms_get_email ( $id ) {
2013-08-10 11:59:36 +00:00
$message = oms_task_load ( $id );
if ( $message ) {
oms_prepare_email ( $message );
return $message ;
} else {
return FALSE ;
}
2013-08-12 03:14:00 +00:00
} */
2013-08-10 11:59:36 +00:00
2013-08-12 03:14:00 +00:00
/* function oms_prepare_email ( & $message ) {
2013-08-10 11:59:36 +00:00
$data = $message [ 'data' ];
$data [ 'id_message' ] = $message [ 'id_task' ];
$data [ 'read' ] = ( $message [ 'status' ] != 'NEW' && $message [ 'status' ] != 'UNREAD' );
$message = $data ;
2013-08-12 03:14:00 +00:00
} */
2013-08-10 11:59:36 +00:00
2013-08-12 03:14:00 +00:00
/* function oms_email_mark_read ( $mid ) {
2013-08-10 11:59:36 +00:00
db_exec ( " update task set status = 'READ' where id_task = ? and type = 'email' and module = 'email' " , array ( $mid ));
2013-08-12 03:14:00 +00:00
} */
2013-08-10 11:59:36 +00:00
function decode_utf8 ( $str ) {
preg_match_all ( " /= \ ?UTF-8 \ ?B \ ?([^ \ ?]+) \ ?=/i " , $str , $arr );
for ( $i = 0 ; $i < count ( $arr [ 1 ]); $i ++ ){
$str = ereg_replace ( ereg_replace ( " \ ? " , " \ ? " ,
$arr [ 0 ][ $i ]), base64_decode ( $arr [ 1 ][ $i ]), $str );
}
return $str ;
2013-08-09 23:46:21 +00:00
}
2013-08-10 11:59:36 +00:00
function get_mime_type ( & $structure ) {
$primary_mime_type = array ( " TEXT " , " MULTIPART " , " MESSAGE " , " APPLICATION " , " AUDIO " , " IMAGE " , " VIDEO " , " OTHER " );
if ( $structure -> subtype ) {
return $primary_mime_type [( int ) $structure -> type ] . '/' . $structure -> subtype ;
}
return " TEXT/PLAIN " ;
2013-08-09 23:46:21 +00:00
}
2013-08-10 11:59:36 +00:00
function get_part ( $stream , $msg_number , $mime_type , $structure = false , $part_number = false ) {
if ( ! $structure ) {
$structure = imap_fetchstructure ( $stream , $msg_number );
2013-08-09 23:46:21 +00:00
}
2013-08-10 11:59:36 +00:00
if ( $structure ) {
2013-08-12 03:14:00 +00:00
if ( $mime_type == self :: get_mime_type ( $structure )) {
2013-08-10 11:59:36 +00:00
if ( ! $part_number ) {
$part_number = " 1 " ;
2013-08-09 23:46:21 +00:00
}
2013-08-10 11:59:36 +00:00
$text = imap_fetchbody ( $stream , $msg_number , $part_number );
if ( $structure -> encoding == 3 ) {
return imap_base64 ( $text );
} else if ( $structure -> encoding == 4 ) {
return imap_qprint ( $text );
} else {
return $text ;
2013-08-09 23:46:21 +00:00
}
2013-08-10 11:59:36 +00:00
}
if ( $structure -> type == 1 ) /* multipart */ {
while ( list ( $index , $sub_structure ) = each ( $structure -> parts )) {
if ( $part_number ) {
$prefix = $part_number . '.' ;
} else {
$prefix = '' ;
}
2013-08-12 03:14:00 +00:00
$data = self :: get_part ( $stream , $msg_number , $mime_type , $sub_structure , $prefix . ( $index + 1 ));
2013-08-10 11:59:36 +00:00
if ( $data ) {
return $data ;
}
} // END OF WHILE
} // END OF MULTIPART
} // END OF STRUTURE
return false ;
} // END OF FUNCTION
}