需求:通过img标签嵌入服务器图片地址的方式解决接收用户是否已读或者未读。
发送邮件的java代码:
1、使用图片链接的方式,将图片的地址放入超链接中;
2、使用java的MimeMessage类,将图片作为附件的形式发送,这样QQ网页邮箱就可以正常显示图片。
以下是java代码示例:
// 创建MimeMessage实例
MimeMessage message = new MimeMessage(session);
// 设置发件方地址
message.setFrom(new InternetAddress(from));
// 设置收件方地址
message.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
// 设置邮件主题
message.setSubject("测试邮件发送,包含图片");
// 创建邮件正文
MimeBodyPart text = new MimeBodyPart();
// 设置邮件正文
text.setContent("<html><body>这是一封包含图片的测试邮件,请注意查收!<br/><img='http://xxx.jpg' alt='test'></body></html>", "text/html;charset=UTF-8");
// 创建邮件正文部分
MimeMultipart mm = new MimeMultipart();
// 添加邮件正文
mm.addBodyPart(text);
// 设置邮件正文
message.setContent(mm);
// 保存邮件
message.saveChanges();
下载邮件的代码
import java.io.InputStream;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.jeff.utils.HttpUtils;
@RestController
public class FileController {
/**
*
* @description: 从服务器端获得图片,并输出到页面
*/
@RequestMapping("getImage")
public void getImage(HttpServletResponse resp) {
// 服务器图片url
String urlPath = "http://192.168.1.100:8080/images/jie.jpg";
// 从服务器端获得图片,并输出到页面
InputStream inputStream = HttpUtils.getInputStream(urlPath);
HttpUtils.writeFile(resp, inputStream);
}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.servlet.http.HttpServletResponse;
public class HttpUtils {
/**
* 创建测试类(FileController.java)
* @description: 从服务器获得一个输入流(本例是指从服务器获得一个image输入流)
*/
public static InputStream getInputStream(String urlPath) {
InputStream inputStream = null;
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL(urlPath);
httpURLConnection = (HttpURLConnection) url.openConnection();
// 设置网络连接超时时间
httpURLConnection.setConnectTimeout(3000);
// 设置应用程序要从网络连接读取数据
httpURLConnection.setDoInput(true);
httpURLConnection.setRequestMethod("GET");
int responseCode = httpURLConnection.getResponseCode();
System.out.println("responseCode is:" + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
// 从服务器返回一个输入流
inputStream = httpURLConnection.getInputStream();
} else {
inputStream = httpURLConnection.getErrorStream();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return inputStream;
}
/**
* 创建http工具类(HttpUtils.java)
* @description: 将输入流输出到页面
*/
public static void writeFile(HttpServletResponse resp, InputStream inputStream) {
OutputStream out = null;
try {
out = resp.getOutputStream();
int len = 0;
byte[] b = new byte[1024];
while ((len = inputStream.read(b)) != -1) {
out.write(b, 0, len);
}
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
>存在的问题:
上面的方法可以获取用户已读状态,但是在有的邮件客户端,图片无法隐藏,所以我们需要在服务URL请求结束后,真实返回一张图片,但是图片最好近乎不可见。
用java简单生成一个不可见的图片(一个近乎不可见的点),代码如下:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import jodd.util.Base64;
public class TestImage {
public String getImageBase64() {
ByteArrayOutputStream baos = null;
StringBuffer sb = null;
try {
int width = 1;
int height = 1;
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
g2d.setBackground(new Color(255, 255, 255));
g2d.setPaint(new Color(0, 0, 0));
g2d.clearRect(0, 0, width, height);
g2d.dispose();
baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
sb = new StringBuffer("data:image/png;base64,");
sb.append(Base64.encodeToString(baos.toByteArray()));
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// System.out.println(sb.toString());
return sb.toString();
}
public static void main(String[] args) {
new TestImage().getImageBase64();
}
}
>优化一下:
我们可以直接保存图片base64字符串,它本身就代表图片,无需每次生成,生成字符串如下:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4//8/AAX+Av4zEpUUAAAAAElFTkSuQmCC
我们在浏览器预览一下,效果如下:
这样我们利用image元素,成功跟踪到用户已读邮件的状态了。
注:由于现在QQ、网易等web收件箱限制访问各自服务器上的图片地址,故通过web页面访问时无法正常加载该图。该问题目前无法通过技术规避解决。
(完)