javamail transport多次发送请求附件
javamail transport send requests attachment multiple times
我目前有一个功能齐全的电子邮件通知系统。一切正常,但注意到其中一个内联图像(通过休息服务附加到电子邮件)被请求了三次。
它似乎在调用 transport.send 后发生。我假设当 javamail 发送电子邮件时,它会调用所有引用的内联图像并生成 base64 图像并将其放在外发电子邮件中。
我的问题是...
以上假设是否正确,为什么在原始电子邮件中验证它只包含一次图像时会多次调用该服务。
下面是原始电子邮件的副本,地址已更改,base64 图像,text/plain 和 text/html 版本已删除。
原始电子邮件
Date: Thu, 25 Feb 2016 20:40:04 -0800 (PST)
From: something.news.noreply@something.org
To: user.email@something.org
Message-ID: <56557433.31456461613977.JavaMail.something.news.noreply@something.orgh>
Subject: Business News for 02/26/2016
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_Part_6_670038123.1456461604268"
X-Priority: 3
------=_Part_6_670038123.1456461604268
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
TEXT VERSION OF EMAIL
------=_Part_6_670038123.1456461604268
Content-Type: multipart/related;
boundary="----=_Part_7_2073972040.1456461604268"
------=_Part_7_2073972040.1456461604268
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
HTML VERSION OF EMAIL
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="840da574-a395-4fb8-8f33-bcbb1837220e?t=1452039853427"
Content-Transfer-Encoding: base64
Content-ID: <@9dc060f2-84ec-4344-8871-68d4e4885b70_840da574-a395-4fb8-8f33-bcbb1837220e?t=1452039853427>
Content-Disposition: inline;
filename="840da574-a395-4fb8-8f33-bcbb1837220e?t=1452039853427"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="21ae1010-9675-4daa-8ac8-659052b943e8?t=1450724912940"
Content-Transfer-Encoding: base64
Content-ID: <@17ab1018-2bc5-44f5-9934-fb7b0f1a860b_21ae1010-9675-4daa-8ac8-659052b943e8?t=1450724912940>
Content-Disposition: inline;
filename="21ae1010-9675-4daa-8ac8-659052b943e8?t=1450724912940"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="a96af9b6-9093-4086-bf91-e5677bef533f?t=1450966405365"
Content-Transfer-Encoding: base64
Content-ID: <@15a682c9-95e8-42ee-880b-f52a47396341_a96af9b6-9093-4086-bf91-e5677bef533f?t=1450966405365>
Content-Disposition: inline;
filename="a96af9b6-9093-4086-bf91-e5677bef533f?t=1450966405365"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="25caf361-80a9-44c2-9ae6-97c19709becf?t=1450966427231"
Content-Transfer-Encoding: base64
Content-ID: <@2e9839ae-9c10-4c8f-9c4a-bc9e1a934fc3_25caf361-80a9-44c2-9ae6-97c19709becf?t=1450966427231>
Content-Disposition: inline;
filename="25caf361-80a9-44c2-9ae6-97c19709becf?t=1450966427231"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268
Content-Type: image/png; name=upChart
Content-Transfer-Encoding: base64
Content-ID: <@6ca90a68-1d24-4414-ac8a-8c84b50bb663_upChart>
Content-Disposition: inline; filename=upChart
BASE 64 IMAGE
THIS IS THE IMAGE THAT IS RETRIEVED VIA A WEB SERVICE CALL. IT CREATES A CHART
IMAGE THAT GET ATTACHED TO EMAIL.
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="10739ce0-c979-4e47-8cee-666304b9a92e?t=1451426510519"
Content-Transfer-Encoding: base64
Content-ID: <@14227419-3db7-444b-a704-7abaccd1e380_10739ce0-c979-4e47-8cee-666304b9a92e?t=1451426510519>
Content-Disposition: inline;
filename="10739ce0-c979-4e47-8cee-666304b9a92e?t=1451426510519"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="995344fa-765f-4a27-848c-d36d26c593f3?t=1451426553685"
Content-Transfer-Encoding: base64
Content-ID: <@f17f0535-a2a3-47a8-aca4-9ed883542de8_995344fa-765f-4a27-848c-d36d26c593f3?t=1451426553685>
Content-Disposition: inline;
filename="995344fa-765f-4a27-848c-d36d26c593f3?t=1451426553685"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268--
------=_Part_6_670038123.1456461604268--
我已经添加了我相信相关的代码。代码从一开始的样子开始,然后我根据建议做了两处更改。
开始于:
try {
// Get a REST client so we can call the Highcharts service.
hcClient = new RestClient(hcServer, hcResource);
// Create a client response object.
ClientResponse cr = null;
// Initialize tries counter and loop a maximum of 3 tries
// if highcharts export server doesn't respond with a 200.
int tries = 0;
do {
// Increase tries count.
tries++;
// Call the service and place response data into our data object.
cr = hcClient.getWebResource().post(ClientResponse.class, params);
// Pull the response status from client.
upChartRespStatus = cr.getStatus();
// Determine if we received a 200 code or not.
if(upChartRespStatus == 200) {
// Obtain entity and build response.
response = Response
.ok(new ByteArrayInputStream(cr.getEntity(cbChart.getClass())))
.build();
} else {
// Log warning that chart was not received, what the response
// status was and what try we are on.
logger.warn("Unable to get requested chart, response code was "+upChartRespStatus+".");
logger.warn("Reattempting to get chart. The current count of retries is: "+tries);
}
} while (tries <= 3 && upChartRespStatus != 200);
} catch(Exception e) {
logger.error(e.getMessage());
} finally {
hcClient.destroy();
}
我想也许我会尝试发送 base64 编码的图像。我什至没有收到电子邮件中的图片。
// Determine if we received a 200 code or not.
if(upChartRespStatus == 200) {
// Get entity from client request.
ByteArrayInputStream bais = new ByteArrayInputStream(cr.getEntity(cbChart.getClass()));
String b64Image = new String(Base64.encode(read(bais)));
// Obtain entity and build response.
response = Response
.ok(b64Image)
.header("Content-Type", "image/png")
.header("Content-Length", b64Image.length())
.header("Content-Transfer-Encoding", "BASE64")
.build();
} else {
// Log warning that chart was not received, what the response
// status was and what try we are on.
logger.warn("Unable to get requested chart, response code was "+upChartRespStatus+".");
logger.warn("Reattempting to get chart. The current count of retries is: "+tries);
}
我最后一次尝试是回到二进制,但要确保 headers 都已到位。最后一次尝试确实在电子邮件中生成了图表图像,但在所有情况下,transport.send 在实际发送之前仍会调用该服务三次。
// Determine if we received a 200 code or not.
if(upChartRespStatus == 200) {
// Get entity from client request.
ByteArrayInputStream bais = new ByteArrayInputStream(cr.getEntity(cbChart.getClass()));
// Obtain entity and build response.
response = Response
.ok(bais)
.header("Content-Type", "image/png")
.header("Content-Length", bais.available())
.header("Content-Transfer-Encoding", "BINARY")
.build();
} else {
// Log warning that chart was not received, what the response
// status was and what try we are on.
logger.warn("Unable to get requested chart, response code was "+upChartRespStatus+".");
logger.warn("Reattempting to get chart. The current count of retries is: "+tries);
}
好的。所以我取得了一些成功。我认为没有在服务中设置 headers,而是为时已晚。我查看了创建电子邮件的代码,特别是当图像被添加到其部分时。我已经添加了代码是什么以及我改变了什么。通过这样做,它现在只调用服务两次而不是三次。
private void addImagesInline(Multipart parent, List<URL> embeded, HashMap<String,String> cids) throws MessagingException {
if (embeded != null) {
for (URL img : embeded) {
final MimeBodyPart htmlPartImg = new MimeBodyPart();
DataSource htmlPartImgDs = new URLDataSource(img);
htmlPartImg.setDataHandler(new DataHandler(htmlPartImgDs));
String fileName = img.getFile();
fileName = getFileName(fileName);
String newFileName = cids.get(fileName);
boolean imageNotReferencedInHtml = newFileName == null;
if (imageNotReferencedInHtml) continue;
htmlPartImg.setHeader("Content-ID", "<"+newFileName+">");
htmlPartImg.setDisposition(BodyPart.INLINE);
htmlPartImg.setFileName(fileName);
parent.addBodyPart(htmlPartImg);
}
}
}
我将这些添加到代码行中。
htmlPartImg.setHeader("Content-Type", "image/png");
htmlPartImg.setHeader("Content-Transfer-Encoding", "BASE64");
提前感谢您的任何回复!
我希望图像被请求两次。 JavaMail 将读取图像一次,以根据图像数据的内容确定合适的编码。然后它将再次读取它以对其进行编码并将其包含在消息中。
你可以自己读取图片并保存在本地,避免多次请求,也可以通过设置该部分的Content-Transfer-Encoding头来告诉JavaMail使用什么编码;这样它就不必猜测要使用什么。
我目前有一个功能齐全的电子邮件通知系统。一切正常,但注意到其中一个内联图像(通过休息服务附加到电子邮件)被请求了三次。
它似乎在调用 transport.send 后发生。我假设当 javamail 发送电子邮件时,它会调用所有引用的内联图像并生成 base64 图像并将其放在外发电子邮件中。
我的问题是... 以上假设是否正确,为什么在原始电子邮件中验证它只包含一次图像时会多次调用该服务。
下面是原始电子邮件的副本,地址已更改,base64 图像,text/plain 和 text/html 版本已删除。
原始电子邮件
Date: Thu, 25 Feb 2016 20:40:04 -0800 (PST)
From: something.news.noreply@something.org
To: user.email@something.org
Message-ID: <56557433.31456461613977.JavaMail.something.news.noreply@something.orgh>
Subject: Business News for 02/26/2016
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_Part_6_670038123.1456461604268"
X-Priority: 3
------=_Part_6_670038123.1456461604268
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
TEXT VERSION OF EMAIL
------=_Part_6_670038123.1456461604268
Content-Type: multipart/related;
boundary="----=_Part_7_2073972040.1456461604268"
------=_Part_7_2073972040.1456461604268
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
HTML VERSION OF EMAIL
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="840da574-a395-4fb8-8f33-bcbb1837220e?t=1452039853427"
Content-Transfer-Encoding: base64
Content-ID: <@9dc060f2-84ec-4344-8871-68d4e4885b70_840da574-a395-4fb8-8f33-bcbb1837220e?t=1452039853427>
Content-Disposition: inline;
filename="840da574-a395-4fb8-8f33-bcbb1837220e?t=1452039853427"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="21ae1010-9675-4daa-8ac8-659052b943e8?t=1450724912940"
Content-Transfer-Encoding: base64
Content-ID: <@17ab1018-2bc5-44f5-9934-fb7b0f1a860b_21ae1010-9675-4daa-8ac8-659052b943e8?t=1450724912940>
Content-Disposition: inline;
filename="21ae1010-9675-4daa-8ac8-659052b943e8?t=1450724912940"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="a96af9b6-9093-4086-bf91-e5677bef533f?t=1450966405365"
Content-Transfer-Encoding: base64
Content-ID: <@15a682c9-95e8-42ee-880b-f52a47396341_a96af9b6-9093-4086-bf91-e5677bef533f?t=1450966405365>
Content-Disposition: inline;
filename="a96af9b6-9093-4086-bf91-e5677bef533f?t=1450966405365"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="25caf361-80a9-44c2-9ae6-97c19709becf?t=1450966427231"
Content-Transfer-Encoding: base64
Content-ID: <@2e9839ae-9c10-4c8f-9c4a-bc9e1a934fc3_25caf361-80a9-44c2-9ae6-97c19709becf?t=1450966427231>
Content-Disposition: inline;
filename="25caf361-80a9-44c2-9ae6-97c19709becf?t=1450966427231"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268
Content-Type: image/png; name=upChart
Content-Transfer-Encoding: base64
Content-ID: <@6ca90a68-1d24-4414-ac8a-8c84b50bb663_upChart>
Content-Disposition: inline; filename=upChart
BASE 64 IMAGE
THIS IS THE IMAGE THAT IS RETRIEVED VIA A WEB SERVICE CALL. IT CREATES A CHART
IMAGE THAT GET ATTACHED TO EMAIL.
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="10739ce0-c979-4e47-8cee-666304b9a92e?t=1451426510519"
Content-Transfer-Encoding: base64
Content-ID: <@14227419-3db7-444b-a704-7abaccd1e380_10739ce0-c979-4e47-8cee-666304b9a92e?t=1451426510519>
Content-Disposition: inline;
filename="10739ce0-c979-4e47-8cee-666304b9a92e?t=1451426510519"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268
Content-Type: image/png;
name="995344fa-765f-4a27-848c-d36d26c593f3?t=1451426553685"
Content-Transfer-Encoding: base64
Content-ID: <@f17f0535-a2a3-47a8-aca4-9ed883542de8_995344fa-765f-4a27-848c-d36d26c593f3?t=1451426553685>
Content-Disposition: inline;
filename="995344fa-765f-4a27-848c-d36d26c593f3?t=1451426553685"
BASE 64 IMAGE
------=_Part_7_2073972040.1456461604268--
------=_Part_6_670038123.1456461604268--
我已经添加了我相信相关的代码。代码从一开始的样子开始,然后我根据建议做了两处更改。
开始于:
try {
// Get a REST client so we can call the Highcharts service.
hcClient = new RestClient(hcServer, hcResource);
// Create a client response object.
ClientResponse cr = null;
// Initialize tries counter and loop a maximum of 3 tries
// if highcharts export server doesn't respond with a 200.
int tries = 0;
do {
// Increase tries count.
tries++;
// Call the service and place response data into our data object.
cr = hcClient.getWebResource().post(ClientResponse.class, params);
// Pull the response status from client.
upChartRespStatus = cr.getStatus();
// Determine if we received a 200 code or not.
if(upChartRespStatus == 200) {
// Obtain entity and build response.
response = Response
.ok(new ByteArrayInputStream(cr.getEntity(cbChart.getClass())))
.build();
} else {
// Log warning that chart was not received, what the response
// status was and what try we are on.
logger.warn("Unable to get requested chart, response code was "+upChartRespStatus+".");
logger.warn("Reattempting to get chart. The current count of retries is: "+tries);
}
} while (tries <= 3 && upChartRespStatus != 200);
} catch(Exception e) {
logger.error(e.getMessage());
} finally {
hcClient.destroy();
}
我想也许我会尝试发送 base64 编码的图像。我什至没有收到电子邮件中的图片。
// Determine if we received a 200 code or not.
if(upChartRespStatus == 200) {
// Get entity from client request.
ByteArrayInputStream bais = new ByteArrayInputStream(cr.getEntity(cbChart.getClass()));
String b64Image = new String(Base64.encode(read(bais)));
// Obtain entity and build response.
response = Response
.ok(b64Image)
.header("Content-Type", "image/png")
.header("Content-Length", b64Image.length())
.header("Content-Transfer-Encoding", "BASE64")
.build();
} else {
// Log warning that chart was not received, what the response
// status was and what try we are on.
logger.warn("Unable to get requested chart, response code was "+upChartRespStatus+".");
logger.warn("Reattempting to get chart. The current count of retries is: "+tries);
}
我最后一次尝试是回到二进制,但要确保 headers 都已到位。最后一次尝试确实在电子邮件中生成了图表图像,但在所有情况下,transport.send 在实际发送之前仍会调用该服务三次。
// Determine if we received a 200 code or not.
if(upChartRespStatus == 200) {
// Get entity from client request.
ByteArrayInputStream bais = new ByteArrayInputStream(cr.getEntity(cbChart.getClass()));
// Obtain entity and build response.
response = Response
.ok(bais)
.header("Content-Type", "image/png")
.header("Content-Length", bais.available())
.header("Content-Transfer-Encoding", "BINARY")
.build();
} else {
// Log warning that chart was not received, what the response
// status was and what try we are on.
logger.warn("Unable to get requested chart, response code was "+upChartRespStatus+".");
logger.warn("Reattempting to get chart. The current count of retries is: "+tries);
}
好的。所以我取得了一些成功。我认为没有在服务中设置 headers,而是为时已晚。我查看了创建电子邮件的代码,特别是当图像被添加到其部分时。我已经添加了代码是什么以及我改变了什么。通过这样做,它现在只调用服务两次而不是三次。
private void addImagesInline(Multipart parent, List<URL> embeded, HashMap<String,String> cids) throws MessagingException {
if (embeded != null) {
for (URL img : embeded) {
final MimeBodyPart htmlPartImg = new MimeBodyPart();
DataSource htmlPartImgDs = new URLDataSource(img);
htmlPartImg.setDataHandler(new DataHandler(htmlPartImgDs));
String fileName = img.getFile();
fileName = getFileName(fileName);
String newFileName = cids.get(fileName);
boolean imageNotReferencedInHtml = newFileName == null;
if (imageNotReferencedInHtml) continue;
htmlPartImg.setHeader("Content-ID", "<"+newFileName+">");
htmlPartImg.setDisposition(BodyPart.INLINE);
htmlPartImg.setFileName(fileName);
parent.addBodyPart(htmlPartImg);
}
}
}
我将这些添加到代码行中。
htmlPartImg.setHeader("Content-Type", "image/png");
htmlPartImg.setHeader("Content-Transfer-Encoding", "BASE64");
提前感谢您的任何回复!
我希望图像被请求两次。 JavaMail 将读取图像一次,以根据图像数据的内容确定合适的编码。然后它将再次读取它以对其进行编码并将其包含在消息中。
你可以自己读取图片并保存在本地,避免多次请求,也可以通过设置该部分的Content-Transfer-Encoding头来告诉JavaMail使用什么编码;这样它就不必猜测要使用什么。