javamail传输多次发送请求附件

时间:2016-02-27 18:23:22

标签: 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);
            }

我的最后一次尝试是回到二进制,但确保标题全部到位。最后一次尝试确实在电子邮件中产生了图表图像,但在所有情况下,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);
            }

好。所以我取得了一些成功。我认为这不是在服务中设置标题,而是为时已晚。我查看了创建电子邮件的代码,特别是当图像添加到其中时。我添加了代码是什么以及我改变了什么。通过这样做,它现在只调用服务两次而不是三次。

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");

提前感谢您的回复!

1 个答案:

答案 0 :(得分:1)

我希望图像可以被请求两次。 JavaMail将读取图像一次,以根据图像数据的内容确定适合的编码。然后它会再次读取它以对其进行编码并将其包含在消息中。

您可以自己阅读图像并将其保存在本地以避免多个请求,或者您可以通过为部件设置Content-Transfer-Encoding标头来告诉JavaMail使用哪种编码;这样就无需猜测要使用什么。