我通过Gmail API发送电子邮件,想知道邮件何时反弹。我怎么能这样做?
根据我的理解,退回的电子邮件通常包含某种标题,表示反弹,例如:
X-Failed-Recipients: zzzzzzzzzasdfasdfadfa@gmail.com
然而,似乎并不总是一个标题,表明它被弹回的原始消息ID。
我在想下面的计划,但是我认为我必须接近这个错误的洞。
问题
我还有其他一些想法:
答案 0 :(得分:13)
通过Gmail API发送时被退回的邮件会收到邮件守护程序(mailer-daemon@googlemail.com
)的回复。您可以不断检查用户的消息,以查看是否已收到来自守护程序的新消息。
确保自上次检查后以秒为单位存储时间戳,因此下次不会收到任何令人讨厌的副本。
query = from:mailer-daemon@googlemail.com after:<TIME_SINCE_EPOCH_IN_SECONDS>
GET https://www.googleapis.com/gmail/v1/users/me/messages?q=from%3Amailer-daemon%40googlemail.com+after%3A1437055051&access_token={YOUR_API_KEY}
<强>响应:强>
{
"messages": [
{
"id": "14e97f7ed03b7e88",
"threadId": "14e97f7ea9b794a4"
},
]
}
我反弹了!让我们获取整个邮件并对其进行解码并获取您正在暗示的消息ID。
GET https://www.googleapis.com/gmail/v1/users/me/messages/14e97f7ed03b7e88?fields=payload%2Fbody%2Fdata&access_token={YOUR_API_KEY}
<强>响应:强>
{
"payload": {
"body": {
"data": "RGVsA0K..."
}
}
}
将邮件从其URL安全版本转换为常规base64(替换所有&#34; - &#34;使用&#34; +&#34;和&#34; _&#34;替换为&#34; /&#34;),以及我们得到的base64解码:
atob("RGVsA0K...".replace(/\-/g, '+').replace(/\_/g, '/'));
已解码的邮件:
"Delivery to the following recipient failed permanently:
sadsadsadas@sadsads.asdsad
Technical details of permanent failure:
DNS Error: Address resolution of sadsads.asdsad. failed: Domain name not found
----- Original message -----
.
.
.
Received: from 292824132082.apps.googleusercontent.com named unknown by
gmailapi.google.com with HTTPREST; Thu, 16 Jul 2015 13:44:43 -0400
from: example@gmail.com
Date: Thu, 16 Jul 2015 13:44:43 -0400
Message-ID: <this_is_it@mail.gmail.com>
Subject: Subject Text
To: sadsadsadas@sadsads.asdsad
Content-Type: text/plain; charset=UTF-8
The actual message text goes here
这里我们有Message-ID!让我们收到退回的电子邮件!
query = rfc822msgid:<this_is_it@mail.gmail.com>;
GET https://www.googleapis.com/gmail/v1/users/me/messages?q=rfc822msgid%3A%3CCADsZLRzOs1wT4B5pgR7oHHdbjkQhuaCQQs8CEckhLwVw73QFEQ%40mail.gmail.com%3E&key={YOUR_API_KEY}
<强>响应:强>
{
"messages": [
{
"id": "14e97f7ea9b794a4", // <-- Here is the message that bounced!
"threadId": "14e97f7ea9b794a4"
}
],
}
答案 1 :(得分:1)
通过
发送消息时service.users().messages().send(userId, message).execute();
它将返回Message
。您可以使用其threadId
来检查您是否收到该邮件的任何回复。
这是一种检查它是否反弹的简单方法(发送后延迟1秒):
public static boolean isBounced(Gmail service, String threadId) throws IOException {
List<Message> list = service.users().messages().list("me")
.setQ("from=mailer-daemon@googlemail.com")
.execute().getMessages();
return list.stream().anyMatch(msg -> msg.getThreadId().equals(threadId));
}
答案 2 :(得分:0)
这是使用后端技术并尝试遵循当前文档指南的方法。由于它出现在:之前:之前:标签仅支持日期而非日期+时间。因此,虽然EPOCH时间可能已经在早期的代码上工作,但是在当前的API中需要更多的工作。下面的一些内容尚未添加到github上的测试项目中。但是要提出一个想法:
我们要求它回顾任何超过一天的退回邮件,然后解析标题以查找收到的日期 - 将字符串转换为实际日期,并将-20分钟之前的结果与未添加到列表中的旧结果进行比较
List verifyBounceList (Gmail service) {
List foundResults=[]
Date date = new Date()
use (groovy.time.TimeCategory) {
date= date -20.minute
}
Date yesterday = new Date()-1
def bounceRecords = listMessagesMatchingQuery(service,'me','from:mailer-daemon@googlemail.com after:'+yesterday.format('YYYY/MM/dd'))
bounceRecords?.each {
Message message = getMessage(service,'me',it.id)
String receivedDateString = message.getPayload().headers?.find{it.name=='Received'}.value.split(';')[1].trim()
SimpleDateFormat df = new SimpleDateFormat('EEE, dd MMM yyyy HH:mm:ss z (Z)')
Date receivedDate=df.parse(receivedDateString)
if (receivedDate>date) {
foundResults<<[bouncedRecord:it,mapRecord:message]
}
}
return foundResults
}
Message getMessage(Gmail service, String userId, String messageId) throws IOException {
Message message = service.users().messages().get(userId, messageId).execute()
///System.out.println("Message snippet: " + message.getSnippet())
return message
}
/**
* Simply does a query in given mailbox
* used to query for mail failures
* @param service
* @param userId
* @param query
* @return
* @throws IOException
*/
List<Message> listMessagesMatchingQuery(Gmail service, String userId, String query) throws IOException {
ListMessagesResponse response = service.users().messages().list(userId).setQ(query).execute()
List<Message> messages = new ArrayList<Message>()
while (response.getMessages() != null) {
messages.addAll(response.getMessages())
if (response.getNextPageToken() != null) {
String pageToken = response.getNextPageToken()
response = service.users().messages().list(userId).setQ(query).setPageToken(pageToken).execute()
} else {
break;
}
}
for (Message message : messages) {
//System.out.println(message.toPrettyString());
}
return messages;
}
上面以迭代返回结果的列表的形式返回:
<g:if test="${instance.size()>0}">
<h2>Bounces found : ${instance.size()}</h2><br/>
<div class="errors">
<g:each in="${instance}" var="failed">
${failed.bouncedRecord} --> ${failed.mapRecord?.id} ${failed.mapRecord?.getSnippet()} ${ }<br/>
<g:each in="${failed.mapRecord.getPayload().headers}" var="a">
${a }<br/>---
</g:each>
</g:each>