<?/*
Copyright (C) 2003 Media Net Link, Inc. Danville, CA 94526 USA

This file is part of AthenaRMS.

AthenaRMS 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 2 of the License, or
(at your option) any later version.

AthenaRMS 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/?>
<?php
# Purpose: parse an incoming email message and store as a new ticket
#          or process a reply
  chdir(dirname($_SERVER['PHP_SELF']));
  ini_set('include_path', ini_get('include_path') . ':..');

  require_once 'db.php';
  require_once 'person.php';
  require_once 'ticket.php';
  require_once 'comment.php';
  require_once 'crm.php';
  require_once 'config.php';
  require_once 'crypt.php';
  require_once 'email.php';

  ## raise memory limit
  ini_set('memory_limit', '16M');

  ## set up logging
  ini_set('display_errors', 1);
  if ($error_log) {
    ini_set('log_errors', 1);
    ini_set('error_log', $error_log);
  }

  $config = new Config();
  $crypt = new Crypt();
  $email_obj = new Email();

  $crms = $config->Valid_Email_Domains ();
  if (!$crms) failed_mail($config->error);

  $stdin = fopen ('php://stdin', 'r');

  while (!feof ($stdin)) {
    $whole_msg .= fgets ($stdin, 100000);
  }

  fclose ($stdin);

  # if ($athena_admin) mail ($athena_admin, 'new ticket', $whole_msg);

  $headers = $email_obj->Parts ($whole_msg);

  foreach (array ('cc', 'delivered-to', 'to') as $hfield) {
    foreach (preg_split ('/[\s,;]+/', $headers[$hfield]) as $email) {
      ## handle virtualdomain munged addresses

      if ($mail_server == 'qmail') 
	$email = preg_replace('/[^@]+-/', '', $email);

      list($user, $domain) = 
	split('@', preg_replace('/"[^"]+"|^\s*<\s*|\s*>\s*$/', '', $email));

      if (!$user || !$domain) continue;

      $user   = strtolower($user);
      $domain = strtolower($domain);

      ## if it looks like and is a ticket
      if (preg_match('/^[0-9a-f]+$/', $user) 
	    && ($ticket_id = $crypt->decrypt($user))) break;

      foreach ($crms as $crm) {
	if ($crm[0] == $domain) {
	  if ($crm[2] == $user) {
	    $crm_id = $crm[1];
	    break;
	  }
	  $dom_crm_id = $crm[1];
	}
      }

      if ($crm_id || $ticket_id) break;
    }

    if ($crm_id || $ticket_id) break;
  }

  function failed_mail ($err='') {
    global $to_email;
    global $fwd_mail;
    global $error_log;
    global $athena_admin;

    if ($athena_admin)
	mail ($athena_admin, "Failed Redirect ($err)", 
	    "Message:\n\nError: $err\n\n$fwd_mail\n");

    ## just in case email is broken
    if ($error_log)
      error_log("handle_email.php: $err");

    return (0);
  }

  if (!$crm_id) $crm_id = $dom_crm_id;

  if (!$crm_id && !$ticket_id) 
    return failed_mail("couldn't find ticket or crm ID");

  ## Message is a Reply to an Open Ticket
  if ($ticket_id) {
    if (preg_match ('/^(\d+)\|(\d+)$/', $ticket_id, $matches)) {
      $ticket_id = $matches[1];
      $msg_creator_pid = $matches[2];
    } elseif (!preg_match('/^\d+$/', $ticket_id)) {
      return failed_mail("invalid ticket_id format: '$ticket_id'");
    }

    $ticket_p = new Ticket ();
    $person_p = new Person ();

    $ticket = $ticket_p->Info_by_Ticket_ID ($ticket_id);

    $crm_id = $ticket->Get ('crm_id');

    if (!$crm_id) return failed_mail ($ticket->error);

    list ($msg, $attachments) = $email_obj->Msg_Bodies ($headers);

    if ($ticket->Get ('status') != 'Open') {
      $ticket->Set ('status', 'ReOpen');
      $ticket->Update ();
    }

    $support_pid = $ticket->Get ('support_person_id');
    $user_pid = $ticket->Get ('user_person_id');
    $person = $person_p->Info_by_Person_ID ($support_pid);
    $email = $person->Get ('email');

    require_once 'crm_view.php';
    $crmv = new CRM_View ();
    $crm_list = $crmv->List_All ($support_pid);
    if (count($crm_list) > 1) {
      $rms_msg = '(you may need to use the "change RMS" link to switch to the proper RMS before the below link works)'."\n";
    }

    $commit = 1;
    $comment_id = '';

    if ($msg_creator_pid) {
      $internal = 'Y';

      if ($msg_creator_pid == $user_pid) $internal = 'N';

      require_once 'comment.php';
      $comment = new Comment ();

      $ary = split($email_obj->Make_Eyecatch(),$msg);

      $msg = $ary[0];

      $comment_id = $comment->Add (array (
	'comments' => $msg,
	'person_id' => $msg_creator_pid,
	'ticket_id' => $ticket_id,
	'updated_by' => "reply autoinsert",
	'internal' => $internal,
      ));

      foreach ($attachments as $a) {
	$attach_id = $comment->Save_Attachment (
		       $comment_id,
		       $a[name],
		       $a[type],
		       "reply autoinsert - $msg_creator_pid",
		       $a[data]
		     );
    
	if (!$attach_id) $commit = 0;
      }
    }

    ##if ($commit) $type = 'commit';

    #### ROLLBACK CODE COMMITS OR ROLLS BACK HERE
    ## But why?  We weren't in a transaction in the first place...

    if ($msg_creator_pid and $commit and $comment_id) {

      $url = $config->CRM_URL($crm_id)
	   . "support/ticket/edit_comment?ticket_id=$ticket_id&comment_id=$comment_id";

      $out_msg = "
  Ticket $ticket_id was updated with a reply, please trim any data from the reply that shouldn't have been entered into the system.
  $rms_msg
  $url

  ";

    } else {

      $url = $config->CRM_URL($crm_id) 
	   . "support/ticket/edit_ticket?ticket_id=$ticket_id";

      # forward the message on, need to make sure attachments look ok
      $out_msg = "
  Enter this as a user or escalated reply on the edit ticket page:
  $rms_msg
  $url

  Message received:

  $fwd_mail
  ";

    }

    # error_log("handle_email: out_msg => [$out_msg]",0);

    $out_headers = "From: $email\nReturn-Path: $email\nReply-To: $email\n";

    ## save everything for now

    if (0 && $error_log)
      error_log("\n___EOF___\n$to_email\n$fwd_mail\n",0);

    #if (!mail ($email, "Reply to $ticket_id", $out_msg, $out_headers)) return failed_mail ('cant send message');

  } else {  ## Message is a New Ticket to Open

    ## extract email address and first and last names

    ## here are some samples:

    ## <person_with_stuff@example.com>
    ## someone+else@example.com
    ## Joe Person - My Org <joe-person@your.com>
    ## "PERRY,NANCY (Her-ORG,ex1)" <nancy.perry@my.com>
    ## Feedback to Webmaster <feedback_webmaster3@am.exch.my.com>
    ## Laurette Flynn <lflynn@cminet.com> (by way of Jane Doe - ORG)

    ## step 1: match any of the above; capture the email and name sections
    if (preg_match('/^\s*(("?([^"]+)"?\s*)?<)?([\w+.-]+@[\w+.-]+)/', 
	  $headers['from'], $m)) {

      $email = $m[4];

      ## step 2: throw away name sections like " - Company" and " (notes)"
      $from = preg_replace('/\s+((-\s|\().+)?$/', '', $m[3]);

      if (strpos($from, ',')) {   ## if Last, First (Middle)?
	  $names = preg_split('/\s*,\s*/', $from);

	  ## stick the last name onto the end
	  array_push($names, array_shift($names));
      } elseif ($from) {    ## otherwise split on space
	  $names = preg_split('/\s+/', $from);
      }

      if ($names) {
	  $c = count($names);

	  $last = $names[$c-1];

	  if ($c > 1 && preg_match('/^(mc|van|de)$/i', $names[$c-2])) {
	      $last = $names[$c-2] . " $last";
	      $c--;
	  }

	  if ($c > 1) $first = $names[0];
      } else {
	  $first = $last = '';
      }
    } else {
      echo "not a valid email address\n";
      if ($athena_admin) mail ($athena_admin, 'no email_address', $whole_msg);
      print "no email from address!";
      return (0);
    }

    $subject = $headers[subject];

    ## filter off unsubscribe text for hp users?

    list ($msg, $attachments) = $email_obj->Msg_Bodies ($headers);

    $person = new Person ();
    $ticket = new Ticket ();
    $comment = new Comment ();
    $crm = new CRM ();

    if (!$crm_id) {
      if ($athena_admin) mail ($athena_admin, 'no crm_id', $whole_msg);
      if ($error_log) error_log('handle_email: No crm_id!');
      return;
    }

    $crm_r = $crm->Select_by_CRM_ID ($crm_id);
    if (!$crm_r) {
	if ($error_log) error_log('handle_email: ' . $crm->error);
	return;
    }
    
    #### ROLLBACK CODE STARTS HERE

    $person_id = $person->Add (array(
      'email' => $email,
      'last_name' => $last,
      'first_name' => $first,
      'updated_by' => 'direct support email',
    ));
    if (!$person_id) {
	if ($error_log) error_log('handle_email: ' . $person->error);
	return;
    }

    list ($r, $ticket_id, $tm_id) = $ticket->Add_Both (array (
      'updated_by' => 'direct support email',
      'user_person_id' => $person_id,
      'crm_id' => $crm_id,
      'source_id' => $crm_r->Get ('email_source_id'),
      'subject' => $subject,
    ));
    if (!$r) {
	if ($error_log) error_log('handle_email: ' . $ticket->error);
	$person->Delete($person_id);
	return;
    }

    $comment_id = $comment->Add (array (
      'comments' => $msg,
      'person_id' => $person_id,
      'ticket_id' => $ticket_id,
      'updated_by' => 'direct support email',
    ));
    if (!$comment_id) {
	if ($error_log) error_log('handle_email: ' . $comment->error);
	$ticket->Delete($ticket_id,$crm_id);
	$person->Delete($person_id);
	return;
    }

    foreach ($attachments as $a) {
      $attach_id = $comment->Save_Attachment (
		     $comment_id,
		     $a[name],
		     $a[type],
		     $person_id,
		     $a[data]
		   );

      if (!$attach_id) {
	## On failed attachment, skip to next one
	print "Failed to save attachment $a[name]\n";
      }
    }

    if (!$comment_id or !$ticket_id or !$person_id) {
      if ($error_log) error_log("handle_email: error: comment_id: "
	. "'$comment_id', ticket_id: '$ticket_id', person_id: '$person_id'");

      # without transactions, we will have to delete the parts that do exist.
      # assuming there is a reasonable function to do this.
      # \_ There isn't. -geordan

      $comment->Delete($comment_id);
      $ticket->Delete($ticket_id, $crm_id);
      $person->Delete($person_id);
      
      if (!$athena_admin || 
		  !mail ($athena_admin, 'failed auto insert', $whole_msg)) {
	$save = fopen ('/tmp/athena_email_to_db_errs.txt', 'a');
	fputs($save, "\n___EOF___\n$whole_msg\n");
	fclose ($save);
      }
    } else {

      if ($email and !$config->Value('no_new_ticket_user_confirmation',$crm_id)) {
	$emailo = new Email ();

	if ($emailo->Valid($email)) {

	  $enc_ticket = $crypt->encrypt ($ticket_id);

	  $enc_ticket_person = $crypt->encrypt ($ticket_id.'|'.$person_id);

	  if (!$enc_ticket_person) return failed_mail($crypt->error);

	  $domain = $config->Get ('email_domain',$crm_id);

	  $from_enc = $enc_ticket_person.'@'.$domain;
	  $from_enc = '"'.$config->Get ('Email Sig',$crm_id)."\" <$from_enc>";

	  $url = $config->Users_URL($enc_ticket, $crm_id);

	  require_once 'template.php';
	  $template = new Template ();

	  include $template->load ('user_new_ticket_email_confirmation.php',$crm_id);

	  $ok = $emailo->Send_Msg ($email, $subject, $mail_msg, $from_enc);

	  if (!$ok) return failed_mail($emailo->error);
	}
      }
    }
  }
?>
