This works for me, yes it is very hackish. Could somebody verify it works for them?

This will allow staff to reply to any email from osTicket and expect it to be added to the ticket as a response. It only works if the first part of the email address is the same as the staff usernames.

In pipe.php

Use the first and last line for reference.

be sure to read the comments, you have to change one part for your setup.

//Allow mismatched emails?? For now hell NO.

//if(!is_object($ticket) || strcasecmp($ticket->getEmail(),$var))

// $ticket=null;

}

$errors=array();

$msgid=0;

if(!$ticket){ //New tickets...

$ticket=Ticket:($var,$errors,'email');

if(!is_object($ticket) || $errors){

api_exit(EX_DATAERR,'Create Failed '.implode("\n",$errors)."\n\n");

}

$msgid=$ticket->getLastMsgId();

}else{

$message=$var;

//Strip quoted reply...TODO: figure out how mail clients do it without special tag..

if($cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator()) && strpos($var,$tag))

list($message)=split($tag,$var);

//post message....postMessage does the cleanup.

$senderName=$var;

$senderName = substr($senderName, 0, -20); //Change this to remove the <USERMENTION username="youyrdomain.com">@youyrdomain.com</USERMENTION> from the email address

$sql1="SELECT staff_id FROM ost_staff WHERE username='$senderName'";

$almostsenderid=db_query($sql1);

while($row = mysql_fetch_array($almostsenderid)) {

$senderid = $row;

}

$sql="SELECT firstname,lastname FROM ost_staff WHERE staff_id='$senderid'";

$almostsendername=db_query($sql);

while($row = mysql_fetch_array($almostsendername)) {

$senderName = $row.' '.$row;

}

if ($senderid){

if(!($respId=$ticket->postEmailResponse($msgid,$senderid,$senderName,$message,$var,'Email'))) {

api_exit(EX_DATAERR,"post message failed \n\n $message\n");

}

}else{

if(!($msgid=$ticket->postMessage($message,$var,'Email'))) {

api_exit(EX_DATAERR,"post message failed \n\n $message\n");

}

}}

//Ticket created...save attachments if enabled.

Add this to class.ticket.php:

You can add it anywhere within the current functions

function postEmailResponse($mymsgid,$senderid,$senderName,$msg,$signature='none',$attachment=false,$ticket_status,$canalert=true){

global $cfg;

if(!$this->getId())

return 0;

//We don't really care much about the source at message level

$source=$source?$source:$_SERVER;

$mytid=db_input($this->getId());

$sql5="SELECT msg_id FROM ost_ticket_message WHERE ticket_id='$mytid' order by msg_id desc limit 1";

$result5=db_query($sql5);

while($row = mysql_fetch_array($result5)) {

$mymsgid = $row;

}

$sql= 'INSERT INTO '.TICKET_RESPONSE_TABLE.' SET created=NOW() '.

',msg_id='.db_input($mymsgid).

',ticket_id='.db_input($this->getId()).

',response='.db_input(Format:($msg)). //Tags/code stripped...meaning client can not send in code..etc

',staff_id='.db_input($senderid).

',staff_name='.db_input($senderName).

',ip_address='.db_input('10.2.1.22');

$resp_id=0;

//echo $sql;

$sql1= 'UPDATE '.TICKET_TABLE.' SET updated=NOW() WHERE ticket_id='.db_input($this->getId());

db_query($sql1);

if(db_query($sql) && ($resp_id=db_insert_id())):

if(!$canalert) //No alert/response

return $resp_id;

$dept=$this->getDept();

//Send Response to client...based on the template...

//TODO: check department level templates...if set.

$sql='SELECT ticket_reply_subj,ticket_reply_body FROM '.EMAIL_TEMPLATE_TABLE.

' WHERE cfg_id='.db_input($cfg->getId()).' AND tpl_id='.db_input($cfg->getDefaultTemplateId());

$resp=db_query($sql);

if(db_num_rows($resp) && list($subj,$body)=db_fetch_row($resp)){

if(strtolower($ticket_status)=="close"||strtolower($ticket_status)=="closed") $subj = " - Closed - Re: %subject";

$subj = str_replace("%ticket", $this->getExtId(),$subj);

$subj = str_replace("%subject", $this->getSubject(),$subj);

$body = str_replace("%ticket", $this->getExtId(),$body);

$body = str_replace("%name", $this->getName(),$body);

$body = str_replace("%email", $this->getEmail(),$body);

$body = str_replace("%url", $cfg->getBaseUrl(),$body);

$body = str_replace("%message",$msg,$body);

//Figure out the signature to use...if any.

switch(strtolower($signature)):

case 'mine';

$signature=$thisuser->getSignature();

break;

case 'dept':

$signature=$dept->isPublic()?$dept->getSignature():''; //make sure it is public

break;

case 'none';

default:

$signature='';

break;

endswitch;

$body = str_replace("%signature",$signature,$body);

//Email attachment when attached AND if emailed.

if(($attachment && is_file($attachment)) && $cfg->emailAttachments()) {

$semi_rand = md5(time());

$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";

$headers="MIME-Version: 1.0\n" .

"Content-Type: multipart/mixed;\n" .

" boundary=\"{$mime_boundary}\"";

$body = "This is a multi-part message in MIME format.\n\n" .

"--{$mime_boundary}\n" .

"Content-Type: text/plain; charset=\"iso-8859-1\"\n" .

"Content-Transfer-Encoding: 7bit\n\n".

$body . "\n\n";

$body.= "--{$mime_boundary}\n" .

"Content-Type: " . $attachment . ";\n" .

" name=\"" . $attachment . "\"\n" .

"Content-Disposition: attachment;\n" .

" filename=\"" . $attachment . "\"\n" .

"Content-Transfer-Encoding: base64\n\n" .

chunk_split(base64_encode(file_get_contents($attachment))). "\n\n" .

"--{$mime_boundary}--\n";

}

$email=$from=$fromNamenull;

if(($email=$dept->getEmail())) { //Dept email if set!

$from=$email->getEmail();

$fromName=$email->getName();

//Reply separator tag.

if($cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator()))

$body ="\n$tag\n\n".$body;

}else{//No emails means it is a noreply...

$from=$cfg->getNoReplyEmail();

}

Misc:($this->getEmail(),$subj,$body,$from,$fromName,$headers);

}else{

//We have a big problem...alert admin...

$msg='Problems fetching response template for ticket#'.$this->getId().' Possible config error';

Misc:('System Error',$msg);

}

return $resp_id;

endif;

return 0;

}

19 days later

Does it replaces the patch for email to v 1.6RC4? or...

This script its worth with v 1.6RC5 ??

How To implement the patch in the new version?

Does This work in the v1.6RC5?

a month later

It only works if the first part of the email address is the same as the staff usernames.

Can someone explain what this means? What email address is it referring to?

I think he means that:

Example:

'testname@example.com' is your e-mail adress.

The staff username in osticket has to be the same:

'testname'

Ok?

Greetings,

Torben

I think he means that:

Example:

'testname@example.com' is your e-mail adress.

The staff username in osticket has to be the same:

'testname'

Ok?

Greetings,

Torben

I still don't get it.

What address is "testname@example.com" Client? admin? staff?

Maybe if you tell me what line in the mod checks for the match, I can tell from there, assuming its part of the mod.

a month later

I still don't get it.

What address is "testname@example.com" Client? admin? staff?

Maybe if you tell me what line in the mod checks for the match, I can tell from there, assuming its part of the mod.

well, this is a mod for STAFF to be able to reply to clients via email. Clients do not have usernames to the Staff Control Panel, so the email addresses in question must be for the staff users.

if you staff members email address is joe@company.com, his username needs to be joe.

13 days later

Yes, thats right

well, this is a mod for STAFF to be able to reply to clients via email. Clients do not have usernames to the Staff Control Panel, so the email addresses in question must be for the staff users.

if you staff members email address is joe@company.com, his username needs to be joe.

Sorry for my late response, yes Skeyelab got it right.

BTW, this works on rc5 but it gives continual email cannot be delivered errors!? Anybody know why?

Basically the responses get input, they show up, everything works just fine. The only problem is the staff member then gets a bounce back from the mail server saying that the message could not be delivered.

Sorry for my late response, yes Skeyelab got it right.

BTW, this works on rc5 but it gives continual email cannot be delivered errors!? Anybody know why?

Basically the responses get input, they show up, everything works just fine. The only problem is the staff member then gets a bounce back from the mail server saying that the message could not be delivered.

I'm no osticket expert (just installed it for the first time today), but as I was reading forum threads here about email setup, I ran across this post about email bounce messages getting sent even though the message is delivered.

http://osticket.com/forums/showpost.php?p=2282&postcount=45(http://osticket.com/forums/showpost.php?p=2282&postcount=45)

Maybe by adding the code in that post it might silence the bounce emails?

mail issue:: from staff or admin replied mail not comeing to osticket panel

Hi

i am getting one problem after installation: staff or admin replied mail not comeing to osticket panel only client reply mails are comeing ,is there any body ,who can help me out

4 months later

This is how I made this work:

find this code in api/pipe.php

$ticket=null;

if(ereg ("{1,10}",$var,$regs)) {

$extid=trim(preg_replace("/", "", $regs));

$ticket= new Ticket(Ticket:($extid));

//Allow mismatched emails?? For now hell NO.

if(!is_object($ticket) || strcasecmp($ticket->getEmail(),$var)) {

$ticket=null;

}

}

From what I can see, this part of the code checks for a ticket number in the format to , and creates a ticket object using that number as the extID. The code then attempts to get the email address associated with that ticket, and checks that it matches with the email address which sent the email.

So, if we comment out the $ticket=null line, so it becomes //$ticket=null; then it will allow anyone to post a message to a ticket.

Anyone being able to post a message to a ticket is probably not a good thing. It means if someone knows your ticket number, they can send messages into the system. So what we need to do is make sure that only staff can reply in this way.

So, after commenting out the $ticket=null line, add this code below the closing brackets:

// mod by PRedmond to allow staff to reply via email

// check that email address is in the staff list.

$sql="SELECT username FROM " . STAFF_TABLE . " WHERE email='" . $var . "' ";

$query=db_query($sql);

while($row = mysql_fetch_array($query)) {

$senderUsername = $row;

}

// if username is in the staff list, then it can be a reply

// if username is not in the staff list, then it must be a new ticket

if (!$senderUsername){

$ticket=null;

}

// end mod

This checks that the incoming email address is in the staff list. If it is, then the message will be added to the original ticket as a response. If the email address is NOT in the staff list, then the email will become a new ticket.

Hope this helps!!

2 months later

I made a few changes and incorporated your ideas...

A little differently - it works without changing the ticket class.

I look up the staff id from the sender's email, and then create a staff session object from which I have the ability to call the postResponse method directly.

This method also shows some rough code I added at the bottom that allows embedding image attachments in outlook like email messages that post embedded images without specifying a disposition.

It's ugly but it works.

@@ -93,9 +96,29 @@

$extid=trim(preg_replace("/", "", $regs));

$ticket= new Ticket(Ticket:($extid));

//Allow mismatched emails?? For now hell NO.

- if(!is_object($ticket) || strcasecmp($ticket->getEmail(),$var))

- $ticket=null;

-}

+//TO ALLOW MOD BELOW TO WORK

+// if(!is_object($ticket) || strcasecmp($ticket->getEmail(),$var))

+// $ticket=null;

+}

+// mod to allow staff to reply via email

+ // check that email address is in the staff list.

+ $sql="SELECT username,staff_id FROM " . STAFF_TABLE . " WHERE email='" . $var . "' ";

+ $query=db_query($sql);

+ while($row = mysql_fetch_array($query)) {

+ $senderUsername = $row;

+ $senderStaffID = $row;

+ }

+//thisuser is a global required by postResponse

+ $thisuser = new StaffSession($senderStaffID);

+

+ // if username is in the staff list (or original client), then it can be a reply

+ // if username is not in the staff list, then it must be a new ticket

+ if ((!$senderUsername)

+ && (!is_object($ticket) || strcasecmp($ticket->getEmail(),$var))

+ $ticket=null;

+ }

+// end mod

+

$errors=array();

$msgid=0;

if(!$ticket){ //New tickets...

@@ -110,9 +133,24 @@

if($cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator()) && strpos($var,$tag))

list($message)=split($tag,$var);

//post message....postMessage does the cleanup.

+// mod to make a response from STAFF a response not a message

+if (!$senderUsername){

if(!($msgid=$ticket->postMessage($message,'Email',$var,$var))) {

api_exit(EX_DATAERR,"Unable to post message \n\n $message\n");

}

+} else {

+// function postResponse($msgid,$response,$signature='none',$attachment=false,$canalert=true){

+// function postMessage($msg,$source='',$msgid=NULL,$headers='',$newticket=false){

+$sql='SELECT MAX(msg_id) FROM '.TICKET_MESSAGE_TABLE.' WHERE ticket_id ='.$ticket->getId();

+$query=db_query($sql);

+while($row = mysql_fetch_array($query)) {

+ $Last_msg_id = $row;

+}

+ if(!($msgid=$ticket->postResponse($Last_msg_id,$message))){

+ api_exit(EX_DATAERR,"Unable to post response \n\n $message\n");

+ }

+}

+// end mod

}

//Ticket created...save attachments if enabled.

$struct=$parser->getStruct();

@@ -122,6 +160,13 @@

if($part->disposition

&& (!strcasecmp($part->disposition,'attachment') || !strcasecmp($part->disposition,'inline') || !strcasecmp($part->ctype_primary,'image'))){

$filename=$part->d_parameters;

+ if($filename && $cfg->canUploadFileType($filename)) {

+ $ticket->saveAttachment($filename,$part->body,$msgid,'M');

+ }

+//THIS PATCH ADDS THE ABILITY TO SAVE EMBEDDED IMAGES IN AN HTML EMAIL FROM OUTLOOK 2007

+ } elseif (!($part->disposition)

+ && (!strcasecmp($part->ctype_primary,'image')) ) {

+ $filename=$part->ctype_parameters;

if($filename && $cfg->canUploadFileType($filename)) {

$ticket->saveAttachment($filename,$part->body,$msgid,'M');

}

I personally don't agree with allowing staff responses via email, on the current code-base, without some safeguards and restrictions.

Email headers can be spoofed - combine that with sequential ticket IDs or known user's ticket ID and you have problem. In addition you have to worry about; more than one staff members responding, lack of ticket history and internal notes when responding, disabled staff (fired?) can still respond...etc.

The point is there are too many moving parts. Of course anyone is welcome to implement the mod - I was just pointing out why the functionality is not supported.

3 months later

How To Impliment

Hi guys im new to all this. How would i impliment this mod to allow staff to reply via email.

Thankx

5 months later

Allow threaded reply to emails.

This is a slightly different approach and would allow any one to reply to a ticket. What's needed is to track message-id(s) and match them up with in-reply-to headers.

This would involve a little more then just scrapping the subject for a ticket number. The main goal is to allow migration from an inbox style ticket system. We are currently using Mailman and are attempting to migrate to OSTicket.

I could use a few pointers.

1. Where to inject message IDs into mysql.

a. For messages sent by osticket, introduction of message ID generation.

b. The easy part of when creating a ticket from an email message... Where is this done.

2. What schema, each email message has an ID that would need to be added to a list. Another table?

From there authentication can be provided by having a message ID that's related to a ticket and optionally knowing the ticket id.

Any pointers would be helpful. I'm able to do most of the coding, I just have no idea how to safely extend the MySQL schema.

EDIT:

Ohh my, I see the message IDs in the DB already. I'll see what I can cook-up. Perhaps just a small change to perpend 'osticketid...' to the current message id on any message sent.

Untested patch for threaded messages.

# rcsdiff -u pipe.php

===================================================================

RCS file: pipe.php,v

retrieving revision 1.2

diff -u -r1.2 pipe.php

--- pipe.php 2010/10/19 21 1.2

+++ pipe.php 2010/10/21 19

@@ -91,8 +91,49 @@

$var=$parser->getHeader();

$var=$cfg->useEmailPriority()?$parser->getPriority();

+$var=$parser->getStruct();

+$var=$var->headers;

+$var=$var->headers;

+$var=trim($var);

+$var=strlen($var);

+$var=trim($var,'<>');

+if ($var===strlen($var)+2) {

+ $var=explode('> <', $var);

+} else {

+ $var=array();

+}

+$var=trim($var);

+$var=strlen($var);

+$var=trim($var,'<>');

+if ($var===strlen($var)+2) {

+ $var=explode('> <', $var);

+} else {

+ $var=array();

+}

+$var=array_unique(

+ array_merge($var, $var));

+unset($var, $var, $var,

+ $var);

+foreach($var as $k_mmestnik => $v_mmestnik){

+ $var='<'.$v_mmestnik.'>';

+}

+unset($k_mmestnik,$v_mmestnik);

+

$ticket=null;

-if(preg_match ("",$var,$regs)) {

+foreach($var as $k_mmestnik => $v_mmestnik){

+ $tickrow_mmestnik=db_query(

+ "SELECT ticket_id FROM ost_ticket_message WHERE messageId='$v_mmestnik'");

+ while($row_mmestnik = mysql_fetch_array($tickrow_mmestnik)) {

+ $tickid_mmestnik = $row_mmestnik;

+ $ticket= new Ticket(Ticket:($extid));

+ if($ticket) break 2;

+ }

+}

+# TODO: Look for more then one and handle what else is found.

+unset($var, $k_mmestnik, $v_mmestnik, $tickrow_mmestnik,

+ $row_mmestnik, $tickid_mmestnik);

+# TODO: Clean up mysql objects properly, how?

+if(!$ticket && preg_match ("",$var,$regs)) {

$extid=trim(preg_replace("/", "", $regs));

$ticket= new Ticket(Ticket:($extid));

//Allow mismatched emails?? For now hell NO.

@@ -129,4 +170,5 @@

}

}

api_exit(EX_SUCCESS);

+return NULL;

?>

I tried all mods, listed here - not working :(

Someone, who have working method, please, paste it here.

And I have one idea. If it's possible, to add reply mail (example: reply@org.com).

When Staff (staff@org.com) get's alert, he could answer via mail to reply@org.com. And we need a script, adding mails, got by reply@org.com as a comments, added to ticket. Get ticket number from mail title, using parser.

I need a little help coding this.

Something is not right. Looks like emails that match are just dropped.

Any advice on debugging this? Where/how should I log debugging messages?

Guys, I really want to make this work, but I don't know how to. I did manage to get it working, but it would fail when sending the message to the user. It did add correctly to the ticket as a staff message, but the user didn't get an email, and I got a bounce-back error:

pipe to |/.......api/pipe.php

generated by ****@*****

local delivery failed

10 days later

So when a client replies to the email it is added to the thread. I would love this. Does this mod do that.

That's the intent. To have messages that are replied to be interpreted as a response instead of a new ticket.

I believe that this line:if(preg_match ("",$var,$regs)) {

has a syntax error, it's missing two '/'s. Corrected in this patch. Other changes are the inclusion of logging, logs to maillog on my machine.

TODO: This may not function on messages sent by OST, only intended to work against the original mail messages... That is this should work to have OST follow an email list for example.

Assistance from an OST developer would be appreciated, specifically in regards to the ticket API. It seams as thought the call to postMessage below is failing in some situations... Actually I don't think it's ever worked for me.

Another patch that would complement this patch is to add VERP features the the code that OST calls to send messages. As well as inserting a referential MessageID to the email headers. A pointer to this section of the code would be better then having me hunt around for it.

# rcsdiff -ur1.1 pipe.php

===================================================================

RCS file: pipe.php,v

retrieving revision 1.1

diff -u -r1.1 pipe.php

--- pipe.php 2010/10/19 21 1.1

+++ pipe.php 2010/11/08 19

@@ -13,7 +13,7 @@

See LICENSE.TXT for details.

vim: expandtab sw=4 ts=4 sts=4:

- $Id: pipe.php,v 1.1 2010/10/19 21 root Exp $

+ $Id: pipe.php,v 1.4 2010/11/08 19 root Exp root $

**********************************************************************/

<USERMENTION username="chdir">@chdir</USERMENTION>(realpath(dirname(__FILE__)).'/'); //Change dir.

ini_set('memory_limit', '256M'); //The concern here is having enough mem for emails with attachments.

@@ -78,6 +78,7 @@

if($from->comment && $from->comment)

$name.=' ('.$from->comment.')';

$subj=utf8_encode($parser->getSubject());

+$subj=preg_replace('/^[\+/', '', $subj);

if(!($body=Format:($parser->getBody())) && $subj)

$body=$subj;

@@ -90,8 +91,54 @@

$var=$parser->getHeader();

$var=$cfg->useEmailPriority()?$parser->getPriority();

+$var=$parser->getStruct();

+$var=$var->headers;

+$var=$var->headers;

+$var=trim($var);

+$var=strlen($var);

+$var=trim($var,'<>');

+if ($var===strlen($var)+2) {

+ $var=preg_split('/>+</', $var, PREG_SPLIT_NO_EMPTY);

+} else {

+ $var=array();

+}

+$var=trim($var);

+$var=strlen($var);

+$var=trim($var,'<>');

+if ($var===strlen($var)+2) {

+ $var=preg_split('/>+</', $var, PREG_SPLIT_NO_EMPTY);

+} else {

+ $var=array();

+}

+$var=array_unique(

+ array_merge($var, $var));

+unset($var, $var, $var,

+ $var);

+foreach($var as $k_mmestnik => $v_mmestnik){

+ $var='<'.$v_mmestnik.'>';

+}

+unset($k_mmestnik,$v_mmestnik);

+

+openlog("OSTicket: Pipe", LOG_PID, LOG_MAIL);

+syslog(LOG_DEBUG, 'Starting run for msg-id: '.$var);

$ticket=null;

-if(preg_match ("",$var,$regs)) {

+foreach($var as $k_mmestnik => $v_mmestnik){

+ syslog(LOG_INFO, 'Search msg-id: '.$v_mmestnik);

+ $tickrow_mmestnik=db_query(

+ "SELECT ticket_id FROM ost_ticket_message WHERE messageId='$v_mmestnik'");

+ while($row_mmestnik = mysql_fetch_array($tickrow_mmestnik)) {

+ $tickid_mmestnik = $row_mmestnik;

+ syslog(LOG_NOTICE, 'Open ticket: '.$extid);

+ $ticket= new Ticket(Ticket:($extid));

+ if($ticket) break 2;

+ syslog(LOG_ERR, 'Open ticket '.$extid.' failed.');

+ }

+}

+# TODO: Look for more then one and handle what else is found.

+unset($var, $k_mmestnik, $v_mmestnik, $tickrow_mmestnik,

+ $row_mmestnik, $tickid_mmestnik);

+# TODO: Clean up mysql objects properly, how?

+if(!$ticket && preg_match ('/',$var,$regs)) {

$extid=trim(preg_replace("/", "", $regs));

$ticket= new Ticket(Ticket:($extid));

//Allow mismatched emails?? For now hell NO.

@@ -113,9 +160,11 @@

list($message)=split($tag,$var);

//post message....postMessage does the cleanup.

if(!($msgid=$ticket->postMessage($message,'Email',$var,$var))) {

+ syslog(LOG_CRIT,'Ticket postMessage failed.');

api_exit(EX_DATAERR,"Unable to post message \n\n $message\n");

}

}

+closelog();

//Ticket created...save attachments if enabled.

if($cfg->allowEmailAttachments()) {

if($attachments=$parser->getAttachments()){

@@ -128,4 +177,5 @@

}

}

api_exit(EX_SUCCESS);

+return NULL;

?>