如何使用 Message-ID、In-Reply-To 和 References 使已发送的电子邮件在 GMail 收件人的视图中显示为线程 [英] How to cause sent emails to appear threaded in GMail recipient's view with Message-ID, In-Reply-To and References

查看:22
本文介绍了如何使用 Message-ID、In-Reply-To 和 References 使已发送的电子邮件在 GMail 收件人的视图中显示为线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了一些很棒的在线资源,例如 http://www.jwz.org/doc/threading.html,似乎任何电子邮件都带有 Message-ID 标头,然后对它的任何回复都包括 In-Reply-To 命名该 ID 和 Refences 可以命名父消息 ID 的列表,并且电子邮件客户端在查看线程视图中的电子邮件列表时使用此信息来构建线程.

I've read some great online resources like http://www.jwz.org/doc/threading.html, and it seems that any email is send with a Message-ID header, then any replies to it include In-Reply-To naming that ID and Refences which can name a list of parent message id's, and email clients use this information to construct threads when viewing a list of emails in threaded view.

我的问题是:可以将一系列电子邮件发送给带有伪造标题的收件人,以使它们出现在线程中而收件人不回复它们吗?如果是这样,为什么我在下面的尝试不起作用?

My question is: Can a series of emails be sent to a recipient with faked headers, to make them appear in a thread without the recipient replying to them? If so, why does my attempt below not work?

我们有一个系统可以发送多封与我们系统中的特定实体相关的电子邮件.假设我们销售小部件并多次向用户发送有关每个小部件的电子邮件.我们希望特定小部件 ID 的所有电子邮件在我们用户的电子邮件客户端中显示为电子邮件线程.

We have a system that sends out several emails pertaining to a specific entity in our system. Lets say we sell widgets and email users several times about each widget. We want all emails for a specific widget ID to appear as an email thread in our user's email clients.

这里的行程似乎是通常发送电子邮件,然后回复.我们的系统只是想发送几封电子邮件,并伪造 In-Reply-To 和 References 标头,以欺骗电子邮件客户端将它们显示在树中.

The trip here seems to be that normally emails are sent, then replied to. Our system simply wants to send out several emails, and fake the In-Reply-To and References headers, to trick email clients into displaying them in a tree.

我使用的 Message-ID 格式是:'foobar' + widgetId + sequence

The Message-ID format I'm using is: 'foobar' + widgetId + sequence

  • widgetId = 每个小部件的唯一编号,例如第1234章
  • sequence = 每次发送电子邮件时递增的序列号

第一封电子邮件:

  • 消息 ID <foobar-1234-0@server.com>
  • In-Reply-To:未提供
  • 参考文献:未提供

第二封邮件:

  • 消息 ID <foobar-1234-1@server.com>
  • 回复:<foobar-1234-0@server.com>
  • 参考:<foobar-1234-0@server.com>

第三封电子邮件:

  • 消息 ID <foobar-1234-2@server.com>
  • 回复:<foobar-1234-1@server.com>
  • 参考:<foobar-1234-0@server.com><foobar-1234-1@server.com>

(顺便说一句,包含消息 ID 的 @server.com 部分似乎很重要.没有它,使用例如 foobar-123-0,我们的 SMTP 服务器只是忽略它并使用它自己的自动生成的消息 ID)

(incidentally, including the @server.com portion of a message ID appears to be vital. Without that, using e.g. foobar-123-0, our SMTP server simply ignored it and used it own autogenerated message ID)

电子邮件在 Thunderbird 中以树的形式正确显示,但在 Gmail 中却没有,它们只是在收件箱中一个接一个地列出,而其他对话则在它们旁边正确地串接在一起.我不确定我是不是弄错了,Thunderbird 在处理不良数据时已尽其所能,或者 Gmail 是否需要一些我没有提供的额外非标准糖.

Emails appear correctly in Thunderbird, as a tree, but not in Gmail, they just get listed one after the other in the Inbox while other conversations are properly threaded right next to them. I'm not sure if I'm getting it wrong and Thunderbird is doing the best it can with bad data, or if Gmail needs some extra nonstandard sugar I'm not providing.

这是我的 node.js 测试脚本:

Here is my node.js test script:

/*jshint dojo:true */
/*global console:true */
'use strict';
var Q = require('q'),
    nconf = require('nconf'),
    optimist = require('optimist'),
    nodemailer = require('nodemailer');

console.log('Started to run.');
var argv = optimist.argv,
    config = nconf.argv().env().file('conf.json'),
    smtpConfig = config.get('smtp'),
        smtpTransport = nodemailer.createTransport('SMTP', {
            service: smtpConfig.service, // 'Gmail',
            auth: {
                user: smtpConfig.user, //'blah@gmail.com',
                pass: smtpConfig.pass //'xyz'
            }
        }),
    rand = Math.floor(Math.random() * 5000), // a random enough unique id
    messageIdPrefix = 'foobar-' + rand + '-';

var promises = [],
    references = '';

for (var i = 0 ; i < 3 ; i ++) {
    // Prepare email content
    var subject = 'This is test email ' + i,
        htmlMessage = '<h1>Am I threaded? Email ' + i + '</h1><p>???</p>',
        textMessage = 'Am I threaded? Email ' + i + '

???';

    var recipients = 'recipient@server.com';

    // Each email in this sequence has a common prefix
    // In Reply To should be the single immediate parent message id
    // References should list all parents, top most first
    var messageId = messageIdPrefix + i + '@server.com',
        inReplyTo = (i > 0) ? ('<' + (messageIdPrefix + (i-1)) + '@server.com>') : false;

    // setup e-mail data with unicode symbols
    var mailOptions = {
        from: config.get('ourEmail'),
        to: recipients,
        subject: subject,
        text: textMessage,
        html: htmlMessage,
        messageId: messageId,
        inReplyTo: inReplyTo,
        references: references,
        headers: {
            // 'in-Reply-To': inReplyTo
        }
    };

    // send mail with defined transport object
    var q = Q.defer();
    promises.push(q.promise);
    smtpTransport.sendMail(mailOptions, function (error, response) {
        if (error) {
            console.error(error);
            q.reject('error');
        } else {
            console.log('Message sent: ' + response.message);
            q.resolve('yay!');
        }
    });

    // next time round loop, if any, includes this id in the references list
    references = (references ? (references + ' ') : '') + messageId;
}

Q.all(promises).then(function (results) {
    console.log('All done, closing mail connection: ', results);
    smtpTransport.close(); // shut down the connection pool, no more messages
});

需要一个 conf 文件,例如:

Requires a conf file like:

{
    "ourEmail": "me@server.com",
    "smtp": {
        "service": "Gmail",
        "user": "me@server.com",
        "pass": "ilikecheese"
    }
}

对于奖励积分,请提示为什么我尝试使用 Q.all 似乎没有触发并且脚本没有干净地退出,尽管正确发送了所有电子邮件:)

For bonus points, please hint why my attempt to use Q.all doesn't seem to fire and the script does not exit cleanly, despite sending all emails correctly :)

推荐答案

Gmail 中没有线程化的原因是因为 Gmail 的线程化是根据邮件的主题进行的(不是基于in-标题中的回复"或参考"字段).

The answer to why they are not threaded in Gmail is because Gmail's threading is done according to the subject of the messages (it is not based on the "in-reply-to" or "references" field in the header).

有关 Gmail 如何处理线程的更多详细信息,请参阅 stackexchange 上此问题的答案:https://webapps.stackexchange.com/questions/965/how-does-gmail-decide-to-thread-email-messages..

See the answers to this question on stackexchange for more details on how Gmail does threading: https://webapps.stackexchange.com/questions/965/how-does-gmail-decide-to-thread-email-messages..

您的案例中的主题是这是测试电子邮件 1"、这是测试电子邮件 2"和这是测试电子邮件 3",这不会导致 Gmail 使用的规则线程化.

The subjects in your case are "This is test email 1", "This is test email 2" and "This is test email 3" which will not cause threading by the rules Gmail use.

这篇关于如何使用 Message-ID、In-Reply-To 和 References 使已发送的电子邮件在 GMail 收件人的视图中显示为线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆