javamail发送带附件的邮件,发件速度快_java 发送邮件 拉取附件速度很慢-程序员宅基地

技术标签: 发送邮件  发件快  java  附件时间长  javamail  带附件  

     使用javamail发送邮件,准备工作

1.如果使用的是qq邮箱,则需要登录QQ邮箱,找到“设置--账户”找到如下图,将POP3/SMTP服务和IMAP/SMTP服务开启,然后生成授权码,这里的授权码,就是你要用来发邮件时,自己QQ邮箱的密码(注意:QQ邮箱用javamail发邮件,用的是授权码,而不是QQ邮箱的密码)

2.如果使用的是163邮箱,则需要登录163邮箱,找到“设置--POP3/SMTP/IMAP”,将其勾选上。对于163邮箱,有的邮箱能用163邮箱号和密码就能发邮件,但是有的163邮箱就必须得使用授权码,这个是因邮箱而异吧。。。我的163邮箱就得用授权码才能通过javamail发邮件,但是我一个朋友的邮箱用登录密码就可以通过javamail发邮件

我写的demo里,附件是由前端先上传到文件服务器(文件服务器以下简称“OSS”),然后前端将附件的信息(包含存储在OSS上的地址)再传给我,然后我再把附件添加到邮件体里。代码如下:

发件工具类:

import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.URLDataSource;
import javax.mail.Flags;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

import com.xhl.leads.leadsmail.sendmail.entity.MailAttachment;

public class SendMailUtil {
	public static void sendMail() throws Exception {
		int draft = 0;//默认不是草稿
		int priority = 3;//默认是普通邮件  优先级(1:紧急 3:普通 5:低)
		int receiptFlag = 0;//是否需要回执  默认是0,不需要回执
		String host = "smtp.163.com";
		Properties props = new Properties();
		props.setProperty("mail.transport.protocol", "smtp");// "smtp"
		props.setProperty("mail.smtp.host", host);// smtp.qq.com
		props.setProperty("mail.smtp.port", "465");// 465
		props.setProperty("mail.smtp.auth", "true");// "true"
//	    props.setProperty("mail.debug", "true");// "true"  注释掉后,控制台将不会再打印发送邮件主题内容的日志
		props.setProperty("mail.smtp.socketFactory.class",     
                         "javax.net.ssl.SSLSocketFactory"); 
		props.setProperty("mail.smtp.socketFactory.fallback", "false"); 
		System.setProperty("mail.mime.splitlongparameters", "false");//设置了附件名过长问题,从而导致附件名显示带bin的错误,造成附件异常
		Session session = Session.getDefaultInstance(props);
		String from = "****@163.com";//发件人邮箱
		String passWord = "*****";
		String content = "您好:邮件!!!";
		Message message = new MimeMessage(session);
		message.setSentDate(new Date());
		// 设置发件人地址
		message.setFrom(new InternetAddress(from));
		// 设置主题
		message.setSubject("这是一封邮件");
		// 设置收件人
		message.addRecipients(Message.RecipientType.TO, 
        InternetAddress.parse(MimeUtility.encodeText("*****@qq.com")));
		// 设置抄送人
		message.addRecipients(Message.RecipientType.CC, 
        InternetAddress.parse(MimeUtility.encodeText("")));//选填
		// 设置密送人
		message.addRecipients(Message.RecipientType.BCC, 
        InternetAddress.parse(MimeUtility.encodeText("")));//选填
		if (draft == 1) { // 如果是草稿
			message.setFlag(Flags.Flag.DRAFT, true);
		}
		// 设置优先级(1:紧急 3:普通 5:低)
		if (priority == 1)
			message.setHeader("X-Priority", "1");
		// 如果receiptFlag=1 代表需要回执
		if (receiptFlag == 1)
			message.setHeader("Disposition-Notification-To", from);
		// 设置邮件内容
		Multipart multipart = new MimeMultipart();
		MimeBodyPart txtPart = new MimeBodyPart();
		txtPart.setContent(content, "text/html;charset=utf-8");
		multipart.addBodyPart(txtPart);
		
		List<MailAttachment> mailAttachmentList = new ArrayList<MailAttachment>(); //获取当前邮件附件集合
		String attachmentUrl = "";
		String fileName = "";
		if (mailAttachmentList != null && mailAttachmentList.size() > 0) {
			for (MailAttachment attachment : mailAttachmentList) {
				attachmentUrl = attachment.getFilePath();
				fileName = attachment.getFileName();
				MimeBodyPart part = new MimeBodyPart();
				URL url = new URL(attachmentUrl);
	            DataSource dataSource=new URLDataSource(url);
				part.setDataHandler(new DataHandler(dataSource));
				part.setFileName(MimeUtility.encodeText(fileName));
				multipart.addBodyPart(part);
			}
		}
		message.setContent(multipart);
		message.setFlag(Flags.Flag.RECENT, true);
		message.saveChanges();
		if (draft == 0) {
			Transport transport = session.getTransport("smtp");
			transport.connect(host, from, passWord);
			transport.sendMessage(message, message.getAllRecipients());
			transport.close();
		}
	}
	public static void main(String[] args) {
		
		try {
			sendMail();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

附件对象:

import lombok.Data;

@Data
public class MailAttachment {
	private int id;
	private String filePath;//附件在文件服务器上的路径
	private String fileName;//附件的名字
	private String fileSize;//附件的大小
	private int fileOrder;//附件的顺序
	private String fileType;//附件类型
}

网上的很多javamail发送邮件,在将附件添加到邮件体时,都是用的File文件的形式,但是经过实践,我发现用这种方式去将附件保存到邮件体中,对于我们这种先将附件存储在OOS上,然后再从OSS上取下附件,速度很慢;找了很多资料,终于找到了以url的形式将附件添加到邮件体中

1)网上最常用的保存附件到邮件体中的方法:以File的方式

FileDataSource fds = new FileDataSource(file); // 得到数据源  
part.setDataHandler(new DataHandler(fds)); // 得到附件本身并至入BodyPart  将附件以文件的形式添加到javamail中

利用这种方法,我先将存储到文件服务器上的文件得到,然后在本地生成临时文件,将文件添加到邮件体中,待邮件发送成功后,将临时文件在删除,我发现速度很慢,尤其是附件好几兆的时候,发一封邮件都得用时六七分钟;

2)第二种保存附件到邮件体中的方法:以流的方式

DataSource dataSource= new ByteArrayDataSource(inputStream,"application/octet-stream");//将附件改为以流的形式添加到javamail中
part.setDataHandler(new DataHandler(dataSource));

针对1)的现象,我想是不是我可以不生成临时文件,而只是把附件从OSS上拿到这个文件的流,然后将流保存到邮件体中,发现这种方法会减少时间,但是也没有减少很多

3)第三种保存附件到邮件体中的方法:以url的方式-----最佳方案

URL url = new URL(attachmentUrl);
DataSource dataSource=new URLDataSource(url);
part.setDataHandler(new DataHandler(dataSource));

使用3)的方法,添加附件到邮件体中,既未生成临时文件,而且速度还极快。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_26797239/article/details/84138992

智能推荐

安装cx_Oracle库,在Windows中安装Python cx_Oracle模块并连接到Oracle数据库-程序员宅基地

文章浏览阅读394次。我一直试图安装和设置这个,尽管有几个链接描述如何做到这一点,我只是没有得到这个工作。我将首先描述设置:我的电脑:Windows 8.1 Enterprise(62位)远程服务器:Oracle DB 12.1.0.2版C:\Users\Pymat\Oracle\instantclient_12_1这里是oraocci12.dll所在的位置,以及其他文件夹和文件C:\Users\Pymat\AppDa...

PS选框工具详解_选框工具的意义是什么-程序员宅基地

文章浏览阅读7.4k次,点赞2次,收藏2次。PS选框工具详解选框工具:是一个选择工具,可以在图片上任意选取一个矩形或者圆形等形状的面积,进行剪切、填色、修改颜色等处理。工具和工具属性:工具有矩形选框工具、椭圆选框工具、单行选框工具、单列选框工具工具属性有:选区方式(新建选区、添加到选区、从选区减去,与选区交叉)、羽化(软化选区的边)、样式(正常、固定比例、固定大小)、消除锯齿、调整边缘。,3.快捷键:Alt: 按下A..._选框工具的意义是什么

html js字符串超出截取,js最实用string(字符串)类型的使用及截取与拼接详解_冷君聊大片的博客-程序员宅基地

文章浏览阅读204次。var a = '世界上最远的距离不是天涯海角';一、通过字符获取位置或通过位置获取字符://指定位置返回字符console.log(str.charAt(1));console.log(str[1]);//指定位置返回字符编码console.log(str.charCodeAt(1));//返回字符串位置console.log(str.indexOf("o"));//不存在返回-1console..._js 字符串超出取前

springboot学习笔记:全局捕获异常不生效_springboot全局异常处理没起作用-程序员宅基地

文章浏览阅读4.4k次,点赞2次,收藏2次。全局捕获异常,很明显的错误404返回给客户,很不好呀。整个web请求项目全局捕获异常,比如空指针直接返回给客户啊,那多操蛋呀~看这几个常用的注解:@ExceptionHandler 表示拦截异常@ControllerAdvice 是 controller 的一个辅助类,最常用的就是作为全局异常处理的切面类 @ControllerAdvice 可以指定扫描范围 @Control..._springboot全局异常处理没起作用

ppt倒计时3分钟_3款超好用的万能PPT效率插件!轻松5分钟搞定20页PPT-程序员宅基地

文章浏览阅读1.5k次。先问大家一个问题,你做一个20页的PPT大约需要多久呢?可能很多人,听到这个问题,第一反应是回答:估计要做1天!搞不好还要加班但其实,您的新同事,或者新来的实习生,可能只需要1个小时就能搞定!甚至有的人只需要5分钟!别不信,使用好插件,你也能轻松搞定!今天就跟大家推荐3款大神都在偷用的PPT插件!01 PPT美化大师一款超级方便的PPT小插件!支持在WPS和OFFICE上使用!PPT 美化大师拥有..._wps在ppt中5分钟倒计时插件

oracle修改NLS_CHARACTERSET字符集_alter system set nls_characterset-程序员宅基地

文章浏览阅读590次。sqlplus "/ as sysdba"SQL> SHUTDOWN IMMEDIATE;SQL> STARTUP MOUNT;SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;SQL> ALTER SYSTEM SET AQ_TM_PROCESSES=0;SQL> ALTER DATABASE OPEN;SQL> AL..._alter system set nls_characterset

随便推点

线段树进阶-程序员宅基地

文章浏览阅读173次。zkw线段树zkw线段树由清华大学张昆玮(zkw)发明,相较于普通线段树,其优点有:非递归,时间常数小使用二进制思想,代码短,方便书写建树我们强制要求叶子节点(即区间大小为1的节点)排列在最后一行,并且还是一颗满二叉树(多余的节点不用)。这样我们就可以写出建树的代码,此时只更新了叶子节点的信息,我们没有更新非叶子节点的信息。void build(int n){ // 寻找最后一行的大小,也是非叶子节点的大小 for (M = 1; M < n + 2; M <_线段树进阶

netty——协议+聊天室案例+空闲检测+优化+rpc+底层源码透析_rpc 空闲_胡尚的博客-程序员宅基地

文章浏览阅读236次。关于netty相关的基础知识可以点击此链接知识来源:netty学习视频文章目录协议设计与解析了解协议http协议自定义协议编解码@Sharable聊天室实例业务介绍登录单聊群聊退出空闲检测优化扩展序列化算法参数CONNECT_TIMEOUT_MILLISSO_BACKLOGulimit -nTCP_NODELAYSO_SNDBUF和SO_RCVBUFALLOCATORRCVBUF_ALLOCATORrpc搭建rpc简单框架获取channel客户端——代理获取返回值异常调用总结探究源码启动流程nio启动流_rpc 空闲

python scipy找不到lena-程序员宅基地

文章浏览阅读3.4k次,点赞4次,收藏2次。python scipy找不到lenascipy.misc.lena AttributeError: ‘module’ object has no attribute ‘lena’在数据可视化的那本书上看到的demo,不过运行不通过,然后出现上面的那个错误,lena函数看起来被移除了。 123456 import scipy.misclena..._scipy.misc.lena

最全的前端程序员常用英语词汇都在这了~-程序员宅基地

文章浏览阅读839次,点赞3次,收藏19次。Aalign 对齐active 激活absolute 绝对alpha 图像通道animate 动画animation 动画片alert 提醒add 加append 添加after 之后Bback 超过范围的三次方缓动bounce 指数衰减的反弹缓动before 在…之前blur 当输入框失焦的时候触发BOM 全称Browser Object Model 浏览器对象模型blur 失焦bind 绑定background 背景border 边框banner 页面上的一个

小林求职记(一):面试官:什么是大事务?小林哥:就是 很大...的...事务??-程序员宅基地

文章浏览阅读569次。最近疫情期间跳槽不易,在外包公司工作了5年的小林在某直聘软件上边投递了好几家互联网公司的java工程师岗位。在经历了快半年的无人问津之后,终于被一家公司的技术leader叫去了面试。到了南山科技园的某栋大楼地下,看了下时间,距离面试约定时间还有大概15分钟。小王慢慢悠悠地步入了这栋科技大楼,在前台坐下后,过了不久,面试官便赶来了。面试官你好,请自我介绍一下吧。小林你好,我是xxxxx面试官扫了下我的简历,发现了简历上的一点:熟悉mysql数据库。这时候面试官笑了笑,仿佛心里头在盘算着后边该怎么问

Android 进程和线程-程序员宅基地

文章浏览阅读127次。默认情况下,Android 系统中同一应用的所有组件均运行在相同的进程和线程(称为主线程)中,新启动的应用组件会创建进程或者在已存在的进程中启动并使用相同的执行线程。 但是,也可以安排应用中的组件在单独的进程中运行,并为任何进程创建额外的线程一、进程如果需要控制某个组件所属的进程,则可在清单文件中执行以下...