Вопрос

I'm using PHPMailer to send emails to support when our server is pinged with updates (usually related to payments).

I'm trying to get related emails to display as a Gmail conversation to make it easier to support staff to follow previous updates/replies. I had originally assumed that it was based on subject, but that doesn't seem to make a difference.

My mailer code:

$mail               = new PHPMailer;                        // create a new instance
$mail->isSMTP();                                            // set that we're using stmp
$mail->CharSet      = 'UTF-8';                              // make sure it's utf-8 encoded
$mail->Host         = 'smtp.gmail.com';                     // the hostname of the mail server
$mail->Port         = 587;                                  // set the smtp port number (587 for authenticated TLS)
$mail->SMTPSecure   = 'tls';                                // set the encryption to use, ssl (deprecated) or tls
$mail->SMTPAuth     = true;                                 // should we use smtp authentication?
$mail->Username     = MY_EMAIL_LOGIN;                       // the user name for the smtp authentication
$mail->Password     = MY_EMAIL_PASSWORD;                    // the password for smtp authentication
$mail->wordWrap     = 70;                                   // make sure we've no lines longer than 70 chars
$mail->Subject      = "[Payment] - Player {$payment->user->name} ({$payment->user->id}) - Payment ID {$payment->id}";
$mail->Body         = $htmlBody;                            // our html body
$mail->AltBody      = $plainBody;                           // our fallback, plain-text body
$mail->setFrom( SUPPORT_EMAIL, 'Support' );                 // who this is from
$mail->addReplyTo( SUPPORT_EMAIL, 'Support' );              // who we can reply to
$mail->addAddress( SUPPORT_EMAIL );                         // who we're sending it to
$mail->isHTML( true );                                      // is this a html formatted email?
if( !$mail->send() )
    error_log( "Can't send an email to support about payment {$payment->id} for user {$payment->user->id}" );

If I get 2 emails from the same user relating to the same payment (so the same subject), what I want it to come in as:

+-----------------------------------------------------------------------------+
| Support (2)       | [Payment] Player foo (123456789) - Payment ID 123456789 |
+-----------------------------------------------------------------------------+

What it's actually coming in as:

+-----------------------------------------------------------------------------+
| Support           | [Payment] Player foo (123456789) - Payment ID 123456789 |
+-----------------------------------------------------------------------------+
| Support           | [Payment] Player foo (123456789) - Payment ID 123456789 |
+-----------------------------------------------------------------------------+

Am I missing something simple?

Это было полезно?

Решение

For anybody looking for what worked: following the link left by @ErikNedwidek will lead you to this blog post: http://www.sensefulsolutions.com/2010/08/how-does-email-threading-work-in-gmail.html

Two rules are specified:

  • The subject must be similar.
  • The sender must be a part of the thread OR in-reply-to must be used.

The first one is covered, as the subjects are identical, and the first part of the second should be covered as the sender is the same as the receiver.

There was also this part:

One interesting thing to note is that if you send email messages from Gmail they will also be threaded. The rules are exactly the same as when you receive them, except for one minor detail. If you send the same exact message twice with no subject prefix (e.g. subject is test not re: test) it does get threaded on the receiving end, but not on sending end. Conversely, if it does contain a prefix (e.g. re: test) it will be threaded in both cases.

I figured it wasn't getting threaded because the sender and receiver addresses are the same. Changing the receiver address to another test address meant that messages were threaded properly when received. Keeping the sender and receiver address the same, but adding another receiver address also meant that they got threaded properly. Just having one receiver address that matches the sender address wouldn't work though.

I tried adding a 're:' to the start of the subject, but that didn't make any difference. What did work however, was adding the 'In-Reply-To' header using:

$mail->addCustomHeader( 'In-Reply-To', '<' . SUPPORT_EMAIL . '>' );

Note that the < and > are important, as without it seemed to be ignored.

So to summarise:

  • foo@domain.com sending to foo@domain.com = no threading
  • foo@domain.com sending to bar@domain.com = threading
  • foo@domain.com sending to foo@domain.com and bar@domain.com = threading on both
  • foo@domain.com sending to foo@domain.com with re: pre-pended to the subject = no threading
  • foo@domain.com sending to foo@domain.com with header In-Reply-To set to foo@domain.com = no threading
  • foo@domain.com sending to foo@domain.com with header In-Reply-To set to <foo@domain.com> = threading

Full PHPMailer code:

$mail               = new PHPMailer;                                // create a new instance
$mail->isSMTP();                                                    // set that we're using stmp
$mail->CharSet      = 'UTF-8';                                      // make sure it's utf-8 encoded
$mail->Host         = 'smtp.gmail.com';                             // the hostname of the mail server
$mail->Port         = 587;                                          // set the smtp port number (587 for authenticated TLS)
$mail->SMTPSecure   = 'tls';                                        // set the encryption to use, ssl (deprecated) or tls
$mail->SMTPAuth     = true;                                         // should we use smtp authentication?
$mail->Username     = MY_EMAIL_LOGIN;                               // the user name for the smtp authentication
$mail->Password     = MY_EMAIL_PASSWORD;                            // the password for smtp authentication
$mail->wordWrap     = 70;                                           // make sure we've no lines longer than 70 chars
$mail->Subject      = "[Payment] Player {$payment->user->name} ({$payment->user->id}) - Payment ID {$payment->id}";
$mail->Body         = $htmlBody;                                    // our html body
$mail->AltBody      = $plainBody;                                   // our fallback, plain-text body
$mail->setFrom( SUPPORT_EMAIL, 'Support' );                         // who this is from
$mail->addReplyTo( SUPPORT_EMAIL, 'Support' );                      // who we can reply to
$mail->addAddress( SUPPORT_EMAIL );                                 // who we're sending it to
$mail->addCustomHeader( 'In-Reply-To', '<' . SUPPORT_EMAIL . '>' ); // so we get threading on gmail (needed as to and from are the same address)
$mail->isHTML( true );                                              // is this a html formatted email?
if( !$mail->send() )
    error_log( "[paymentsRealtimeUpdates] Can't send an email to support about payment {$payment->id} for user {$payment->user->id}" );

Unrelated small point - whatever address you set for the setFrom seemed to be ignored - Gmail would take whatever address is behind the MY_EMAIL_LOGIN login.

Другие советы

Check out the accepted answer here:

https://webapps.stackexchange.com/questions/965/how-does-gmail-decide-to-thread-email-messages

The author also has more information in a blog post. It's 3 years old, but hopefully the information still holds.

Well, this doesn't really have anything to do with PHP. This has to do with the way Gmail nests emails together in a "conversation"

You might want to have a look at questions like https://webapps.stackexchange.com/questions/16651/gmail-not-grouping-messages-with-the-same-subject-from-google-groups

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top