【问题标题】:Setting message Id using smtp may be reset after that?使用 smtp 设置消息 ID 之后可能会重置?
【发布时间】:2018-11-30 20:29:58
【问题描述】:

我有使用 smtp 协议发送电子邮件的客户端,但我需要为我发送的每封电子邮件保存消息 ID,我搜索了很多关于获取消息 ID 但我没有找到方法所以我必须自己设置它在代码中。 我的问题是邮件服务器是否保证我设置的header的message id在发送邮件后不会被邮件服务器替换或重置?

我尝试了我的代码,当我向 Gmail 发送电子邮件时它正在工作,并且在发送电子邮件后仍然保留我设置的消息 ID。 但我不确定它是否总是适用于所有电子邮件?

设置消息 id 的原因因为我需要将此消息 id 保存在数据库中因为之后我将检索每封已发送电子邮件的回复,我发现将这封电子邮件与其回复相关联的唯一方法是消息 id。

提前感谢,我希望在这里找到回复

 Guid id = Guid.NewGuid();  
 mail.Headers.Add("Message-Id", String.Format("<{0}@{1}>", id.tostring(), "mail.example.com"));

【问题讨论】:

    标签: c# email smtp smtpclient pop3


    【解决方案1】:

    本身没有“保证”,但 SMTP(或其他)邮件服务器很少会替换您的 Message-ID 标头。

    也就是说,虽然在技术上使用 Guid 是可行的,但它是一个非常长的字符串,可用作Message-ID。以下是我在MailKit 中生成Message-Id 的方法:

    const string base36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
    static void GetRandomBytes (byte[] buffer)
    {
        using (var random = RandomNumberGenerator.Create ())
            random.GetBytes (buffer);
    }
    
    /// <summary>
    /// Generates a Message-Id.
    /// </summary>
    /// <remarks>
    /// Generates a new Message-Id using the supplied domain.
    /// </remarks>
    /// <returns>The message identifier.</returns>
    /// <param name="domain">A domain to use.</param>
    /// <exception cref="System.ArgumentNullException">
    /// <paramref name="domain"/> is <c>null</c>.
    /// </exception>
    /// <exception cref="System.ArgumentException">
    /// <paramref name="domain"/> is invalid.
    /// </exception>
    public static string GenerateMessageId (string domain)
    {
        if (domain == null)
            throw new ArgumentNullException (nameof (domain));
    
        if (domain.Length == 0)
            throw new ArgumentException ("The domain is invalid.", nameof (domain));
    
        ulong value = (ulong) DateTime.Now.Ticks;
        var id = new StringBuilder ();
        var block = new byte[8];
    
        GetRandomBytes (block);
    
        do {
            id.Append (base36[(int) (value % 36)]);
            value /= 36;
        } while (value != 0);
    
        id.Append ('.');
    
        value = 0;
        for (int i = 0; i < 8; i++)
            value = (value << 8) | (ulong) block[i];
    
        do {
            id.Append (base36[(int) (value % 36)]);
            value /= 36;
        } while (value != 0);
    
        id.Append ('@').Append (domain);
    
        return id.ToString ();
    }
    

    【讨论】:

    • 感谢@jstedfast 的回复,我使用GUID 来确保这个ID 永远不会重复,但是使用长消息ID 有什么问题吗??特别是如果我没有默认设置消息 id 将设置为长 id
    • 嗯,标题行应该适合 78 个字符,所以理想情况下 Message-Id 应该适合其中(包括“Message-ID:”字符串)。我上面的解决方案也将产生一个唯一的字符串,并且是推荐的(来自规范)的方式。
    • Guid 工作得很好,不过,如果你愿意这样做的话。
    猜你喜欢
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    • 2011-10-05
    • 2011-06-12
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多