mirror of https://github.com/itflow-org/itflow
Introduce subject-based automatic ticket merging/reply detection where e-mail is sent from a known contact or domain and the subject is a 95% match for a ticket opened in the last 7 days for that client
This commit is contained in:
parent
b0724f5b66
commit
b991f787a2
|
|
@ -598,16 +598,65 @@ foreach ($messages as $message) {
|
|||
}
|
||||
}
|
||||
|
||||
// Decide whether it's a reply to an existing ticket or a new ticket
|
||||
// 1. Reply to existing ticket with the number in subject
|
||||
if (preg_match("/\[$config_ticket_prefix(\d+)\]/", $subject, $ticket_number_matches)) {
|
||||
$ticket_number = intval($ticket_number_matches[1]);
|
||||
if (addReply($from_email, $date, $subject, $ticket_number, $message_body, $attachments)) {
|
||||
$email_processed = true;
|
||||
}
|
||||
} else {
|
||||
// Known contact?
|
||||
$email_processed = addReply($from_email, $date, $subject, $ticket_number, $message_body, $attachments);
|
||||
}
|
||||
|
||||
// 2. Fuzzy duplicate check using a known contact/domain and similar_text subject
|
||||
if (!$email_processed && strlen(trim($subject)) > 10) {
|
||||
$contact_id = 0;
|
||||
$client_id = 0;
|
||||
|
||||
// First: check if sender is a registered contact
|
||||
$from_email_esc = mysqli_real_escape_string($mysqli, $from_email);
|
||||
$any_contact_sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_email = '$from_email_esc' LIMIT 1");
|
||||
$contact_sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_email = '$from_email_esc' AND contact_archived_at IS NULL LIMIT 1");
|
||||
$contact_row = mysqli_fetch_array($contact_sql);
|
||||
|
||||
if ($contact_row) {
|
||||
$contact_id = intval($contact_row['contact_id']);
|
||||
$client_id = intval($contact_row['contact_client_id']);
|
||||
} else {
|
||||
// Else: check if sender domain is registered
|
||||
$from_domain_esc = mysqli_real_escape_string($mysqli, $from_domain);
|
||||
$domain_sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_name = '$from_domain_esc' AND domain_archived_at IS NULL LIMIT 1");
|
||||
$domain_row = mysqli_fetch_assoc($domain_sql);
|
||||
|
||||
if ($domain_row && $from_domain == $domain_row['domain_name']) {
|
||||
$client_id = intval($domain_row['domain_client_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// If we found either a contact or a domain, check recent tickets for a matching subject
|
||||
if ($client_id) {
|
||||
$recent_tickets_sql = mysqli_query($mysqli,
|
||||
"SELECT ticket_id, ticket_number, ticket_subject
|
||||
FROM tickets
|
||||
WHERE ticket_client_id = $client_id AND ticket_resolved_at IS NULL
|
||||
AND ticket_created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)"
|
||||
);
|
||||
|
||||
while ($rowt = mysqli_fetch_assoc($recent_tickets_sql)) {
|
||||
$ticket_number = intval($rowt['ticket_number']);
|
||||
$existing_subject = $rowt['ticket_subject'];
|
||||
|
||||
// Calculate similarity percentage
|
||||
similar_text(strtolower($subject), strtolower($existing_subject), $percent);
|
||||
|
||||
if ($percent >= 95) {
|
||||
// Treat as a reply/duplicate
|
||||
$email_processed = addReply($from_email, $date, $subject, $ticket_number, $message_body, $attachments);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. A known, registered contact?
|
||||
if (!$email_processed) {
|
||||
$from_email_esc = mysqli_real_escape_string($mysqli, $from_email);
|
||||
$any_contact_sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_email = '$from_email_esc' AND contact_archived_at IS NULL LIMIT 1");
|
||||
$rowc = mysqli_fetch_array($any_contact_sql);
|
||||
|
||||
if ($rowc) {
|
||||
|
|
@ -616,43 +665,41 @@ foreach ($messages as $message) {
|
|||
$contact_email = sanitizeInput($rowc['contact_email']);
|
||||
$client_id = intval($rowc['contact_client_id']);
|
||||
|
||||
if (addTicket($contact_id, $contact_name, $contact_email, $client_id, $date, $subject, $message_body, $attachments, $original_message_file)) {
|
||||
$email_processed = true;
|
||||
}
|
||||
} else {
|
||||
// Known domain?
|
||||
$from_domain_esc = mysqli_real_escape_string($mysqli, $from_domain);
|
||||
$domain_sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_name = '$from_domain_esc' LIMIT 1");
|
||||
$rowd = mysqli_fetch_assoc($domain_sql);
|
||||
|
||||
if ($rowd && $from_domain == $rowd['domain_name']) {
|
||||
$client_id = intval($rowd['domain_client_id']);
|
||||
|
||||
// Create a new contact
|
||||
$contact_name = $from_name;
|
||||
$contact_email = $from_email;
|
||||
mysqli_query($mysqli, "INSERT INTO contacts SET contact_name = '".mysqli_real_escape_string($mysqli, $contact_name)."', contact_email = '".mysqli_real_escape_string($mysqli, $contact_email)."', contact_notes = 'Added automatically via email parsing.', contact_client_id = $client_id");
|
||||
$contact_id = mysqli_insert_id($mysqli);
|
||||
|
||||
// Logging
|
||||
logAction("Contact", "Create", "Email parser: created contact " . mysqli_real_escape_string($mysqli, $contact_name) . "", $client_id, $contact_id);
|
||||
customAction('contact_create', $contact_id);
|
||||
|
||||
if (addTicket($contact_id, $contact_name, $contact_email, $client_id, $date, $subject, $message_body, $attachments, $original_message_file)) {
|
||||
$email_processed = true;
|
||||
}
|
||||
} elseif ($config_ticket_email_parse_unknown_senders) {
|
||||
// Unknown sender allowed?
|
||||
$bad_from_pattern = "/daemon|postmaster/i";
|
||||
if (!(preg_match($bad_from_pattern, $from_email))) {
|
||||
if (addTicket(0, $from_name, $from_email, 0, $date, $subject, $message_body, $attachments, $original_message_file)) {
|
||||
$email_processed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$email_processed = addTicket($contact_id, $contact_name, $contact_email, $client_id, $date, $subject, $message_body, $attachments, $original_message_file);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. A known domain?
|
||||
if (!$email_processed) {
|
||||
$from_domain_esc = mysqli_real_escape_string($mysqli, $from_domain);
|
||||
$domain_sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_name = '$from_domain_esc' AND domain_archived_at IS NULL LIMIT 1");
|
||||
$rowd = mysqli_fetch_assoc($domain_sql);
|
||||
|
||||
if ($rowd && $from_domain == $rowd['domain_name']) {
|
||||
$client_id = intval($rowd['domain_client_id']);
|
||||
|
||||
// Create a new contact
|
||||
$contact_name = $from_name;
|
||||
$contact_email = $from_email;
|
||||
mysqli_query($mysqli, "INSERT INTO contacts SET contact_name = '".mysqli_real_escape_string($mysqli, $contact_name)."', contact_email = '".mysqli_real_escape_string($mysqli, $contact_email)."', contact_notes = 'Added automatically via email parsing.', contact_client_id = $client_id");
|
||||
$contact_id = mysqli_insert_id($mysqli);
|
||||
|
||||
logAction("Contact", "Create", "Email parser: created contact " . mysqli_real_escape_string($mysqli, $contact_name), $client_id, $contact_id);
|
||||
customAction('contact_create', $contact_id);
|
||||
|
||||
$email_processed = addTicket($contact_id, $contact_name, $contact_email, $client_id, $date, $subject, $message_body, $attachments, $original_message_file);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Unknown sender allowed?
|
||||
if (!$email_processed && $config_ticket_email_parse_unknown_senders) {
|
||||
$bad_from_pattern = "/daemon|postmaster/i";
|
||||
if (!preg_match($bad_from_pattern, $from_email)) {
|
||||
$email_processed = addTicket(0, $from_name, $from_email, 0, $date, $subject, $message_body, $attachments, $original_message_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Flag/move based on processing result
|
||||
if ($email_processed) {
|
||||
$processed_count++; // increment first so a move failure doesn't hide the success
|
||||
|
|
|
|||
Loading…
Reference in New Issue