java resolvemail_使用JavaMail发送邮件-从FTP读取图片并添加到邮件正文发送

记录一下,使用JavaMail发送邮件。

业务分析

最近工作需要,需要从FTP读取图片内容,添加到邮件正文发送。发送邮件正文,添加附件采用Spring的MimeMessageHelper对象来完成,添加图片也将采用MimeMessageHelper来完成。

查看博客发现MimeMessageHelper有addInline API,里面包含三个参数contentId,InputStreamSource,content-type,以下是文档里的解释:

public void addInline(java.lang.String contentId,InputStreamSource inputStreamSource,java.lang.String contentType) throws MessagingException

Add an inline element to the MimeMessage, taking the content from an org.springframework.core.InputStreamResource, and specifying the content type explicitly.

You can determine the content type for any given filename via a Java Activation Framework's FileTypeMap, for example the one held by this helper.

Note that the InputStream returned by the InputStreamSource implementation needs to be a fresh one on each call, as JavaMail will invoke getInputStream() multiple times.

NOTE: Invoke addInline after setText; else, mail readers might not be able to resolve inline references correctly.

Parameters:

contentId - the content ID to use. Will end up as "Content-ID" header in the body part, surrounded by angle brackets: e.g. "myId" -> "". Can be referenced in HTML source via src="cid:myId" expressions.

inputStreamSource - the resource to take the content from

contentType - the content type to use for the element

Throws:

MessagingException - in case of errors

See Also:

setText(java.lang.String), getFileTypeMap(), addInline(String, org.springframework.core.io.Resource), addInline(String, javax.activation.DataSource)

百度翻译过来大概意思是:

contentId:要使用的ContentId。将在正文部分以“content id”标题结尾,并用尖括号包围:例如“myid”->“”。也可以通过src=“cid:myid”表达式应用在HTML源代码中。

inputStreamSource:需要传入的图片资源。

contentType:将会被元素使用的contentType,内容类型,一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件。

所以,contentId自己命名后,需要将这个id添加到中被引,content-type在这里因为传输的是图片,需要选择image/jpeg,而inputStreamSource来源自ftp读取结果。

业务实现

接下主要问题是如何读取ftp里的图片信息,并将图片信息转换成inputStreamSource。因此分为两步来实现:

(1)连接ftp

/*** Name:get InputStream from ftp

*@authoryangchaolin*/

public static Map getDefectImageFromFtpForACCM(String sectionName) throwsException{

InputStream is=null;

FTPClient ftpClient=newFTPClient();

Map map=new HashMap();try{//创建连接

ftpClient.connect("ftp地址",端口号);

ftpClient.login("用户名", "密码");//验证用户名和密码

int reply=ftpClient.getReplyCode();if(!FTPReply.isPositiveCompletion(reply)){

log.info("连接ftp失败,用户名或密码错误!");

ftpClient.disconnect();

}else{

log.info("连接ftp成功!");

}

}catch(SocketException e){

log.info("ftp IP地址可能错误");throw new CustomException("ftp IP地址可能错误!");

}catch(IOException e){

log.info("ftp 端口错误");throw new CustomException("ftp 端口错误!");

}try{

ftpClient.setDataTimeout(60000);

ftpClient.setConnectTimeout(60000);

ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);

ftpClient.setControlEncoding("UTF-8");//支持中文

ftpClient.setBufferSize(8*1024);//获取指定文件的InputStream

ftpClient.changeWorkingDirectory("文件目录");//目录最前面不能以'/'开头,否则会读不到内容

is=ftpClient.retrieveFileStream(sectionName);

}catch(FileNotFoundException e){

log.info("没有找到文件");throw new CustomException("没有找到文件");

}catch(SocketException e){

log.info("连接ftp失败");throw new CustomException("连接ftp失败");

}catch(IOException e){

log.info("文件读取错误");throw new CustomException("文件读取错误");

}

map.put("inputStream", is);

map.put("ftpClient", ftpClient);returnmap;

}

(2)将图片信息转化成inputStreamSource

这里截取了部分代码,先将InputStream转换成字节数组,然后将字节数组作为参数传入方法ByteArrayResource()中,得到InputeStreamSource对象,InputeStreamSource对象将传入MimeMessageHelper对象中,作为添加邮件中图片使用。

//读取ftp上图片内容

try{

Map map=getDefectImageFromFtpForACCM("Mountain.jpg");

InputStream isOfImage=(InputStream) map.get("inputStream");

FTPClient ftpClient=(FTPClient) map.get("ftpClient");if(isOfImage!=null){byte[] bytes=IOUtils.toByteArray(isOfImage);//将图片输入流转化为字节数组//isOfImage.read(bytes);

issOfImage=newByteArrayResource(bytes);

log.info("图片byte数组大小为:"+bytes.length);//将inputStream关闭后才能执行completePendingCommand方法

isOfImage.close();

ftpClient.completePendingCommand();

ftpClient.disconnect();

}

}catch(Exception e1) {throw new CustomException("读取ftp图片失败!");

}

(3)将InputStreamSource传入MimeMessageHelper中发送带图片的邮件,图片显示在正文中

这里截取了部分代码,helper就是MimeMessageHelper对象,其中defectImage就是contentId,将会用在标签中,相当如一个标识符(html邮件部分代码不做展示),通过它可以找到图片资源。content-type暂时定义为image/jepg,这个需要参考具体的标准表,因为本次测试使用的是jpg格式图片,所以选择它。

//------------------------------测试用

helper.setText(message.toString(),true);//HTML邮件

//image就是InputStreamSource对象

helper.addInline("defectImage", image, "image/jpeg"); //content-type暂定义为image/jpeg,代表将已图片解码

log.info("邮件内容为:"+message.toString());//------------------------------测试用

邮件发送效果

0c420829e72e6c19fac97a6dff8f9936.png

总结

在添加邮件到邮件正文的过程中,发生了如下问题:

(1)图片只发送了一部分,没有全部发送完成。查看原因发现是代码inputStream转化成byte[]数组时,长度出现了问题,导致只传输了部分图片,使用IOUtils.toByteArray() API后,长度正常。

(2)图片在foxmail显示正常,但是在chrome浏览器显示不出图片,查看发现content-type设置为"text/html",将其修改为"image/jpeg"后显示正常。

(3)执行InputStream流关闭后,执行completePendingCommand()方法出错,发现是先关闭了ftp的连接,导致无法执行。completePendingCommand()会等FTPClient返回226 Transfer complete,但是FTPClient只有在接受到InputStream执行close方法时,才会返回。所以先要执行InputStream的close方法,再执行completePendingCommand,最后再关闭ftp连接。参考自:https://ask.csdn.net/questions/166657

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值