1

I'm trying to send emails into one thread so it looks as similar as possible as sending via Gmail web UI.

According to the Gmail documentation, I wrote the next code on Kotlin that works correctly, but not completely

val DEFAULT_CHARSET: String = Charsets.UTF_8.name()

// get headers from original email
val messageId = originalMessage.payload.headers.find { it.name.equals("Message-ID", true) }?.value
val subject = originalMessage.payload.headers.find { it.name.equals("Subject", true) }?.value

// creating message
val message = MimeMessage(Session.getDefaultInstance(Properties()))

message.setFrom(InternetAddress(emailFrom, senderNameFrom, DEFAULT_CHARSET))
message.addRecipient(javax.mail.Message.RecipientType.TO, InternetAddress(emailTo))

message.setSubject(subject, DEFAULT_CHARSET)

// this headers are required accoring to [RFC 2822][1] standard
message.setHeader("In-Reply-To", messageId)
message.setHeader("References", messageId)
message.setHeader("Subject", "Re:$subject")

// creates message part
val messageBodyPart = MimeBodyPart()
messageBodyPart.setContent(content, "text/html; charset=UTF-8")

// creates multi-part
val multipart = MimeMultipart()
multipart.addBodyPart(messageBodyPart)


// sets the multi-part as e-mail's content
message.setContent(multipart)

val buffer = ByteArrayOutputStream()
emailMessage.writeTo(buffer)
val requestMessage = Message()
requestMessage.raw = Base64.encodeBase64URLSafeString(buffer.toByteArray())

// this thread ID you should collect from the original message
requestMessage.threadId = threadId

// from the result variable you can collect id, threadId, labels, etc.
val result = gmail.users().messages().send("me", requestMessage).execute()

As a result, emails send into one thread (inbox looks like this), but there are no three dots "show trimmed content" that hides the content of previous messages: What I have

Is it possible to make it looks like? What I need Other languages and libraries will also suit me.

P.S. I also tried sending emails as a Gmail draft, but this also doesn't work.

Test was done with java-libraries:

  • javax.mail:mail:1.5.0-b01
  • com.sun.mail:javax.mail:1.6.2
O.Solodovnikov
  • 99
  • 2
  • 12
  • Oh so when you say "thread" you don't mean `java.lang.Thread`. – markspace Nov 11 '19 at 17:06
  • 1
    See [Threading changes in Gmail conversation view](https://gsuiteupdates.googleblog.com/2019/03/threading-changes-in-gmail-conversation-view.html) for the conditions needed for messages to be threaded together. – Andreas Nov 11 '19 at 17:06
  • Some guy on the internet also said that you should set the reply `References:` field to the message ID as well as `In-Reply-To:` – markspace Nov 11 '19 at 17:08
  • @Andreas thanks for the article, now I'm sure that code is correct but it still doesn't work as I want. @markspace, thanks, I checked one more time, in the current example `message.setHeader("References", references ?: messageId)` references is always equals to `null` for the second email in the thread (first reply) – O.Solodovnikov Nov 11 '19 at 19:10
  • Try this lib: https://github.com/mimecast/robin/blob/master/doc/client.md (Disclosure: I'm the author) – transilvlad Dec 10 '19 at 15:20

1 Answers1

2

I know this thread is a bit old, but I stumbled myself in this same problem and managed to make it work.

First thing, you need to set a Message-ID header in the MimeMessage object, in the exact format Gmail is expecting ("<anyidyouwant@domain.com>", including the angular brackets). If you don't set this header to the proper format, Gmail will override its value with a new one and store the original value in the X-Google-Original-Message-ID header.

That being said, I also had a small issue with the MimeMessage class overriding the Message-ID header value when the message was sent, which required me to implement my own extended class, as described here.

This is how my Java implementation looks like:

public class MyMessage extends MimeMessage {

    public MyMessage(Session session) { 
        super(session);
    }

    protected void updateMessageID() throws MessagingException {
        setHeader("Message-ID", "<exampleid-myemail@gmail.com>");
    }
}