Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save replies to existing ticket? #691

Open
patriotaki opened this issue Dec 7, 2022 · 17 comments
Open

Save replies to existing ticket? #691

patriotaki opened this issue Dec 7, 2022 · 17 comments

Comments

@patriotaki
Copy link

Environment (please complete the following information):

  • PHP IMAP version: [latest?not sure]
  • PHP Version: [7.4.33]
  • Type of execution: [Apache]

Your Text
Hello,

How can I map a reply with an existing email? I am trying to create a basic support ticketing system, lets say for example an email is sent to test@example.com, when the cron job executes a new ticket is being created in my web app and I reply through my system. If the user replies back through his email client, how can I detect it and add it as a reply and not as a new ticket?

@Sebbo94BY
Copy link
Collaborator

Hello @patriotaki,
I had the same use-case and question a few years ago. 😅

Each email has an unique Message-ID. Those must be referenced in all related emails of the same email thread/conversation. So your ticket system needs to store each single Message-ID to be able to reply to them in order to build the email thread/conversation.

I've shared my solution on Stackoverflow in the past. It also includes an example based on Laravel. You might want to check it out: https://stackoverflow.com/a/50768215/2966991

@patriotaki
Copy link
Author

Hello @Sebi94nbg
thank you for the reply.
From what I see the messageId is only present in replies? and not in the first email that is being sent?

@Sebbo94BY
Copy link
Collaborator

@patriotaki Usually, every email has a Message-ID.

However, RFC 2822 3.6.4 Identification fields specifies, that every email (message) SHOULD have it:

Though optional, every message SHOULD have a "Message-ID:" field.

So if an email has a Message-ID or not, depends on the software, which sent the email.

I personally don't know any case, where this header is not set / available. In my cases it was always available / set.

In worst case, your ticket system should be able to handle incoming emails without this header field.

@patriotaki
Copy link
Author

@Sebi94nbg hmm thats weird, emails that are sent from gmail do not have a message ID in my tests

I am trying to find the correct logic of how ticket system should work. I guess that everytime that a ticket is created (either by form or by email) a unique message id must be generated by the software (me) that should be included in the reply-email (when a staff/admin replies). This way when the user replies through the email client ill be able to "detect" that its a reply to that specific email.

So in conclusion all emails that are sent by the software (me) should have a unique message id generated by the software (me), even if the initial sender does not have a message id?

Is my understanding correct?

@Sebbo94BY
Copy link
Collaborator

Are you sure? I've just sent an email from a Gmail business account to myself and it had a Message-ID. The private Gmail stuff usually behaves identical. I've found an old email from a private Gmail account and I also could find it there.

As written: The Message-IDs are the way to go. That's a RFC standard and usually also used by email clients for building the email threads/conversations. Also Gmail uses those therefore.

Yes, your ticket system needs to set for each sending email the header field Message-ID with an unique value.

Additional, if its a reply to an existing email thread/conversation, you also need to set ALL Message-IDs of the previous emails in the References header field.

Just as my $this->withSwiftMessage(function ($swiftmessage) { ... } on Stackoverflow shows it: https://stackoverflow.com/a/50768215/2966991 :)

@patriotaki
Copy link
Author

@Sebi94nbg Yes, i've tried multiple times, message id is always empty, unless i am not using the correct code.
This is the output
Image: https://monosnap.com/file/yHXbdxfEZUn8OwyvMh3FJ8C9moBArz

code:
echo 'from-name: '.(string) ($email->fromName ?? $email->fromAddress)."\n"; echo 'from-email: '.(string) $email->fromAddress."\n"; echo 'to: '.(string) $email->toString."\n"; echo 'subject: '.(string) $email->subject."\n"; echo 'message_id: '.(string) $email->messageId."\n";

@Sebbo94BY
Copy link
Collaborator

Sebbo94BY commented Dec 8, 2022

Ah, using this library, ok. But in a mail client, you should see it.

Can you find it in $email->headersRaw? If yes: Can you please provide your censored headers, so that I can debug and fix it, if necessary?

@patriotaki
Copy link
Author

patriotaki commented Dec 9, 2022

@Sebi94nbg Message id is still empty in headersRaw

h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to;
followed by a long string, unless the values are encoded in that long string?

@Sebbo94BY
Copy link
Collaborator

headersRaw should return you a huge text block with all available headers. It should simply contain the headers in the raw format. Unchanged from this library.

See

If you don't even get this, then you probably have a different problem. How does your code look like?

Did you also check the email headers in Gmail? There you should see a Message-ID. Click on "Show original" at the three dots on the right side within an open email.

@patriotaki
Copy link
Author

patriotaki commented Dec 9, 2022

The message id is visible in the gmail when clicking show original
code sample below:

`

            $user = $department_value["email"];
	$host = $department_value["imap_host"];
	$port = $department_value["imap_port"];
	$pass = $department_value["imap_password"];
	$auth = $department_value["imap_secure"];

	if($user!="" && $host!="" && $pass!="" && $port!="" && $auth!="")
	{
		$host_splitted = explode($host, ".");
		$host_s = "";
		if(count($host_splitted)>2){
			$host_s = "{".$host;
		}
		else
		{
			$host_s = "{mail.".$host;
		}
		
		$auth_s = "";
		if($auth=="ssl")
		{
			$auth_s = "/ssl/novalidate-cert";
		}
		else
		{
			$auth_s = "";
		}
		
		$mailbox = new PhpImap\Mailbox(
			$host_s.':'.$port.$auth_s.'}INBOX', // IMAP server and mailbox folder
			$user, // Username for the before configured mailbox
			$pass, // Password for the before configured username
		);
					
		try {
    $mail_ids = $mailbox->searchMailbox('ALL');
	} catch (ConnectionException $ex) {
		echo $ex->getErrors('first');
		continue;

	} catch (Exception $ex) {
		echo $ex->getMessage();
		continue;

	}

		foreach ($mail_ids as $mail_id)
		{
    echo "+------ P A R S I N G ------+<br>";

    $email = $mailbox->getMail(
        $mail_id, // ID of the email, you want to get
        false // Do NOT mark emails as seen (optional)
    );
    echo 'from-name: '.(string) ($email->fromName ?? $email->fromAddress)."<br>";
    echo 'from-email: '.(string) $email->fromAddress."<br>";
    echo 'to: '.(string) $email->toString."<br>";
    echo 'subject: '.(string) $email->subject."<br>";
    echo 'message_id: '.(string) $email->messageId."<br>";`

@Sebbo94BY
Copy link
Collaborator

Mhmm, looks good in general. I can't see anything, what could cause the issue. But I also can't see your full code, so the issue might be somewhere else. You're using continue within the try-catch block, but this will only work in loops, which I can't see there.

Also checking the variables, if they are empty or not is not really necessary - the connection attempt would throw either a connection exception or authentication failure, which can be catched. If you really want to check them, you may also rather want to use something like !empty(trim($user)) to be sure, that it's empty or not.

When you add a echo 'headers_raw: '.(string) $email->headersRaw."<br>"; under your PARSING code, you should see the respective headers as they are fetched by the PHP IMAP function(s). If the Message-ID is already missing there, then this is probably an issue of your specific used PHP version or your code.

Please also ensure, that you're using the latest version https://github.com/barbushin/php-imap/releases/tag/5.0.1 of this library and try it again. This also works with PHP 7.4, which you use.

@patriotaki
Copy link
Author

patriotaki commented Dec 9, 2022

@Sebi94nbg
Yes, the process is in a loop thus the keyword continue

this is the a partial result of headersRaw() , as far as I can see there is no message-id, I've tried other email clients but again no message-id. I haven't included the whole header because no where else the word message-id was present.
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=B4CVInUWzAN/Ra9i2OOtLCnYKxsQpMggMCNQN6FAjAs=; b=A3K7rCwbDUUBYWzlVgDf8cxLVZ3opsJcsrJp5uXMeTd+Px+vAFfXO4IdQ+fS2yrVK Idddt/B3sYZI6qL6MBIWFCA2mwlqDXb0sc9cveEANwfwAFMPkQzBqxqNw3fOTKC0Plc5 XCG0aONdp6Dbr9gDde0imyhhzbNxXPd4u0uckA9Ci1h7nPRic+Zr6gyEpqAwKmE1APg cgulkDaC0aw9XZdpnUfRbEXVNw55C4D1TRwYLzSRFbaxm0OngFlPlxjPXsp5arITD8Vm r4aSYcDBKyrrJTnQvJg1viWH+nI5QDg4mMtBX4zhJvXRXp0pAfODrLZMxolVq+5JS/D NP/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=B4CVInUWzAN/Ra9i2OOtLCnYKxsQpMggMCNQN6FAjAs=; b=HhSa+ouevUgP3ub/nkX/dg0s3HlKwh9dRTOPfVOt6O7cFwJI5KVke9prz8QxkoKIa kT0J73hAssvsOKIdKE+C0lBJdhQmD4fo+6KXmGz5hl2teK6q8/PGEeI0KMj4NxSlLVot W99jnBsFPQ/lwonzTpklrduQDic5BOeaNXyc+SlF5QGXAmk2PHXXFNy+E5lKK7GR0g uOK3EY4+3tVLRBOgszmGsnZz2TfaeQ+hGwfgngGLjqTJwcdI7GshPtplx9JnTL1LtiVh cFIE6YadsQkYFKwQK9qhvmF61zBzsJ6AkqFcTXc31IKciEfVUStYkvrV1ucalVPLQlj tcvg==

@patriotaki
Copy link
Author

@Sebi94nbg
PS: I tried Outlook email, and still no message ID

@patriotaki
Copy link
Author

@Sebi94nbg sorry for bumping, just want to know if this is a "global" issue or is isolated to my code only?
I haven't figured it out yet, messageID is always empty

@Sebbo94BY
Copy link
Collaborator

Sebbo94BY commented Dec 15, 2022 via email

@patriotaki
Copy link
Author

Great, let me know once you have more information.
Enjoy your holidays.

I‘ve also asked this myself. I need to test it. But due to christmas and my main work, I had no time to test it yet.

@patriotaki
Copy link
Author

Hi @Sebi94nbg ,

Happy new year!

from what I can see I am not the only one with an empty message id in header response (see headers from issue #698)
seems like a bug, is there any ETA of when this will be fixed? It's kinda urgent for me so if there are there any workarounds that I can do to get the message id please let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants