Gmail API 在发送电子邮件时覆盖自定义 Message-ID header
Gmail API is overriding the custom Message-ID header while sending emails
我们在使用 Java MimeMessage 发送电子邮件时手动设置自定义 Message-ID header。 Message-ID 格式遵循 RFC822 标准。然而,在通过 Gmail API 发送邮件时,Message-ID header 被来自 gmail 的新邮件覆盖。
相反,如果我们 Java 通过 SMTP 发送电子邮件,自定义 Message-ID 将由 Gmail 保留。
有没有办法在通过 Gmail API 发送电子邮件时自定义 Message-ID?
我检查了以下问题,但我不确定是否仍然如此。 (RFC822 Message-Id in new Gmail API)
[更新]
EmailMimeMessage.scala
package utils.email
import javax.mail._
import javax.mail.internet._
import play.api.Logger
class EmailMimeMessage(session: Session, messageId: String) extends MimeMessage(session) {
@throws(classOf[MessagingException])
override def updateMessageID(): Unit = {
Logger.info(s"[EmailMimeMessage] before sending add message id: $messageId")
setHeader("Message-ID", messageId)
}
}
GmailApiService.scala
package utils.email
import java.io.ByteArrayOutputStream
import java.util.Properties
import javax.mail.Session
import javax.mail.internet.{InternetAddress, MimeMessage}
import com.google.api.client.auth.oauth2.{BearerToken, Credential}
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
import com.google.api.client.http.HttpTransport
import com.google.api.client.json.JsonFactory
import com.google.api.client.json.jackson2.JacksonFactory
import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64
import com.google.api.services.gmail.Gmail
import scala.util.Try
case class EmailToBeSent(
to_email: String,
from_email: String,
from_name: String,
reply_to_email: String,
subject: String,
textBody: String,
htmlBody: String,
message_id: String
)
object GmailApiService {
private val APPLICATION_NAME: String = "Gmail API Java Quickstart"
private val JSON_FACTORY: JsonFactory = JacksonFactory.getDefaultInstance
private val HTTP_TRANSPORT: HttpTransport = GoogleNetHttpTransport.newTrustedTransport()
def createEmail(emailToBeSent: EmailToBeSent): Try[MimeMessage] = Try {
val props = new Properties()
val session = Session.getDefaultInstance(props, null)
val email = new EmailMimeMessage(session, emailToBeSent.message_id)
email.setFrom(new InternetAddress(emailToBeSent.from_email))
email.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(emailToBeSent.to_email))
email.setSubject(emailToBeSent.subject)
email.setText(emailToBeSent.textBody)
email
}
def createMessageWithEmail(email: MimeMessage) = Try {
val baos = new ByteArrayOutputStream
email.writeTo(baos)
val encodedEmail = Base64.encodeBase64URLSafeString(baos.toByteArray)
val message = new com.google.api.services.gmail.model.Message()
message.setRaw(encodedEmail)
message
}
def sendGmailService(emailToBeSent: EmailToBeSent, accessToken: String) = Try {
val credential = new Credential(BearerToken.authorizationHeaderAccessMethod)
.setAccessToken(accessToken)
val service = new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME).build
val user = "me"
val message = createEmail(emailToBeSent) flatMap { email => createMessageWithEmail(email) }
val sentMessage = service.users().messages().send(user, message.get).execute()
sentMessage
}
}
按如下方式调用 GmailApiService.sendGmailService(使用 Message-ID:“<1495728783999.123.456.local@examplegmail.com>”),在发送的电子邮件中 Message-ID 被 GMail 覆盖为 "YYfdasCAN=-fdas432HFD43FD_THD@mail.gmail.com":
val emailToBeSent = EmailToBeSent(
to_email = "mary_to@gmail.com",
from_email = "john_from@examplegmail.com",
from_name = "John Doe",
reply_to_email = "john_from@gmail.com",
subject = "How are you ?",
textBody = "Hey, how are you ?",
htmlBody = "<strong>Hey, how are you ?</strong>",
message_id ="<1495728783999.123.456.local@examplegmail.com>",
in_reply_to_id = None,
sender_email_settings_id = 0
)
val sentMsg = GmailApiService.sendGmailService(emailToBeSent, GOOGLE_OAUTH_ACCESS_TOKEN).get
我 2014 年的回答仍然正确:RFC822 Message-Id in new Gmail API
Gmail 始终在外发电子邮件上设置 RFC822 Message-Id header。
我们在使用 Java MimeMessage 发送电子邮件时手动设置自定义 Message-ID header。 Message-ID 格式遵循 RFC822 标准。然而,在通过 Gmail API 发送邮件时,Message-ID header 被来自 gmail 的新邮件覆盖。
相反,如果我们 Java 通过 SMTP 发送电子邮件,自定义 Message-ID 将由 Gmail 保留。
有没有办法在通过 Gmail API 发送电子邮件时自定义 Message-ID?
我检查了以下问题,但我不确定是否仍然如此。 (RFC822 Message-Id in new Gmail API)
[更新]
EmailMimeMessage.scala
package utils.email
import javax.mail._
import javax.mail.internet._
import play.api.Logger
class EmailMimeMessage(session: Session, messageId: String) extends MimeMessage(session) {
@throws(classOf[MessagingException])
override def updateMessageID(): Unit = {
Logger.info(s"[EmailMimeMessage] before sending add message id: $messageId")
setHeader("Message-ID", messageId)
}
}
GmailApiService.scala
package utils.email
import java.io.ByteArrayOutputStream
import java.util.Properties
import javax.mail.Session
import javax.mail.internet.{InternetAddress, MimeMessage}
import com.google.api.client.auth.oauth2.{BearerToken, Credential}
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
import com.google.api.client.http.HttpTransport
import com.google.api.client.json.JsonFactory
import com.google.api.client.json.jackson2.JacksonFactory
import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64
import com.google.api.services.gmail.Gmail
import scala.util.Try
case class EmailToBeSent(
to_email: String,
from_email: String,
from_name: String,
reply_to_email: String,
subject: String,
textBody: String,
htmlBody: String,
message_id: String
)
object GmailApiService {
private val APPLICATION_NAME: String = "Gmail API Java Quickstart"
private val JSON_FACTORY: JsonFactory = JacksonFactory.getDefaultInstance
private val HTTP_TRANSPORT: HttpTransport = GoogleNetHttpTransport.newTrustedTransport()
def createEmail(emailToBeSent: EmailToBeSent): Try[MimeMessage] = Try {
val props = new Properties()
val session = Session.getDefaultInstance(props, null)
val email = new EmailMimeMessage(session, emailToBeSent.message_id)
email.setFrom(new InternetAddress(emailToBeSent.from_email))
email.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(emailToBeSent.to_email))
email.setSubject(emailToBeSent.subject)
email.setText(emailToBeSent.textBody)
email
}
def createMessageWithEmail(email: MimeMessage) = Try {
val baos = new ByteArrayOutputStream
email.writeTo(baos)
val encodedEmail = Base64.encodeBase64URLSafeString(baos.toByteArray)
val message = new com.google.api.services.gmail.model.Message()
message.setRaw(encodedEmail)
message
}
def sendGmailService(emailToBeSent: EmailToBeSent, accessToken: String) = Try {
val credential = new Credential(BearerToken.authorizationHeaderAccessMethod)
.setAccessToken(accessToken)
val service = new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME).build
val user = "me"
val message = createEmail(emailToBeSent) flatMap { email => createMessageWithEmail(email) }
val sentMessage = service.users().messages().send(user, message.get).execute()
sentMessage
}
}
按如下方式调用 GmailApiService.sendGmailService(使用 Message-ID:“<1495728783999.123.456.local@examplegmail.com>”),在发送的电子邮件中 Message-ID 被 GMail 覆盖为 "YYfdasCAN=-fdas432HFD43FD_THD@mail.gmail.com":
val emailToBeSent = EmailToBeSent(
to_email = "mary_to@gmail.com",
from_email = "john_from@examplegmail.com",
from_name = "John Doe",
reply_to_email = "john_from@gmail.com",
subject = "How are you ?",
textBody = "Hey, how are you ?",
htmlBody = "<strong>Hey, how are you ?</strong>",
message_id ="<1495728783999.123.456.local@examplegmail.com>",
in_reply_to_id = None,
sender_email_settings_id = 0
)
val sentMsg = GmailApiService.sendGmailService(emailToBeSent, GOOGLE_OAUTH_ACCESS_TOKEN).get
我 2014 年的回答仍然正确:RFC822 Message-Id in new Gmail API
Gmail 始终在外发电子邮件上设置 RFC822 Message-Id header。