Java-mail发送邮件

1、调用工具类发射邮件*

@SuppressWarnings(“null”)
private void getSendEmailStartus(RequestInfo requestInfo) throws Exception {
String account = xxxxx;// 登录账户
String password =xxxxxxx;// 登录密码
// 抄送者账号
String csz = xxxxx;
String requestid = requestInfo.getRequestid();
FormtableMain19 find = DB.conn().find(FormtableMain19.class, “REQUESTID=?”, requestid);
// 附件名称
String[] fileName = null;
// 附件地址
String[] fileSrc = null;
if (null != find) {
String[] fjsc = new String[] { “123456C1”, “123456C2”, “123456C3” };
if (fjsc.length > 0) {
fileSrc = new String[fjsc.length];
fileName = new String[fjsc.length];
for (int i = 0; i < fjsc.length; i++) {
EmailPDF find2 = DB.conn().find(EmailPDF.class, “fileuniqueidentifier=?”, fjsc[i]);
fileName[i] = find2.getImagefilename();
fileSrc[i] = find2.getFilerealpath();
}
}
if (CustomUtil.isBlank(find.getYjll())) {
throw new RuntimeException(“邮件内容不能为空,requestId为:” + requestid);
}
if (CustomUtil.isBlank(find.getYxdz())) {
throw new RuntimeException(“邮件地址不能为空 ,requestId为:” + requestid);
}
if (!SendEmailUtil.isMailAddr(find.getYxdz())) {
throw new RuntimeException(“邮箱地址输入不合法 ,requestId为:” + requestid);
}
new SendEmailUtil().send(account, “xxx:” + find.getXm(), find.getYjll(), find.getYxdz() + “,” + csz,
fileSrc, account, password, fileName);
}

}

配置文件*

#邮箱服务配置
email.host = xxxxx.xxx.163.com #域民
email.prot = *** #端口
email.protocol = imap #协议
#邮箱账户、密码
devEmail.ACCOUNT = ************
devEmail.PWSSWORD = *************

邮件工具类*

private static Logger logger = Logger.getLogger(SendEmailUtil.class);
private static byte[] ZIP_HEADER_1 = new byte[] { 80, 75, 3, 4 };
private static byte[] ZIP_HEADER_2 = new byte[] { 80, 75, 5, 6 };
static {
System.setProperty(“mail.mime.splitlongparameters”, “false”);
System.setProperty(“mail.mime.charset”, “UTF-8”);
}

public static Session initProperties(String account, String password) {
	Properties properties = new Properties();
	properties.setProperty("mail.transport.protocol", PropUtil.getStringCK("ecustom", "email.protocol"));
	properties.setProperty("mail.smtp.host", PropUtil.getStringCK("ecustom", "email.host"));
	properties.setProperty("mail.smtp.port", PropUtil.getStringCK("ecustom", "email.prot"));
	properties.put("mail.smtp.auth", "true");
	MailSSLSocketFactory mailSSLSocketFactory = null;
	try {
		mailSSLSocketFactory = new MailSSLSocketFactory();
		mailSSLSocketFactory.setTrustAllHosts(true);
	} catch (GeneralSecurityException e) {
		e.printStackTrace();
	}
	properties.put("mail.smtp.enable", "true");
	properties.put("mail.smtp.ssl.socketFactory", mailSSLSocketFactory);
	properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
	properties.put("mail.smtp.socketFactory.fallback", "false");
	properties.put("mail.smtp.socketFactory.port", PropUtil.getStringCK("ecustom", "email.prot"));
	存在session问题:
	Session session = Session.getDefaultInstance(properties, new Authenticator() {
		@Override
		protected PasswordAuthentication getPasswordAuthentication() {
			return new PasswordAuthentication(account, password);
		}
	});
	第二种:
	Session session = Session.getInstance(properties, new Authenticator() {
		@Override
		protected PasswordAuthentication getPasswordAuthentication() {
			return new PasswordAuthentication(account, password);
		}
	});
	session.setDebug(true);
	return session;
}

拓展知识:

问题解决,
将 Session session = Session.getDefaultInstance(props, myauth);
改成
Session session = Session.getInstance(props, myauth);
即可
我就按照他的方法把代码里的方法替换了一下,重新运行,输入第一个邮箱账号和密码,成功发送,第二次输入其他的邮箱账号和密码,点发送,ok,成功了。
好了,到这里问题也解决了,但是还不明白Session.getDefaultInstance和 Session.getInstance有什么区别呢?又找了一下资料,结果找到了也是遇到过553异常的人写的一篇blog,他的blog标题居然是:
”JavaMail中Session.getDefaultInstance的应用“,
不是吧,这样太难找了,一般都是搜索问题名称,谁会搜索这个。如果发帖者能把标题改成问题,那我也就不用找这么就了。不过还是要感谢这个人,他在这篇帖子里详细的说明了为什么用Session.getDefaultInstance方法会出现在第二次输入其他邮箱账号登录时出现553异常。
以下内容都这摘自这个帖子:
http://muder2007.blog.163.com/blog/static/45933070200872025130613/

何谓getDefaultInstance?
从处理流程中可以看出,首先是从缓存中查找是否有properties存在
如果存在,则加载默认的properties
如果不存在才加载用户自己定义的properties,
所以当一个应用为每个用户独立创建properties的时候,还是应该调用getInstance,
除非你希望有一个默认的properties让用户使用

问题找到了,因为它会首先去内存和系统文件中去找properties,所以不管我在页面改几次数据,其实在后台中生成session时都和系统启动时的一样,所以在MailUtil.sendTextMessage(mailSession,RptTaskMailConfig.Sender,
receiver,null,mail_subject,mail_content,“GB2312”,null);时session里的sender和传入的sender不一致,因此出错,修改Session.getDefaultInstance(props, authentic);为Session.getInstance(props, authentic);后,可以正确发送修改帐号,密码等资料后的邮件.OK

最后再补充一下,session.getdefaultinstance和getinstance的区别 :

如果想要同时使用两个帐号发送javamail,比如使用[email protected]发送1#邮件,使用[email protected]发送2#邮件,这时候,你就需要同时创建两个java.mail.Session对象。但是如果你仍然使用Session.getDefaultInstance创建session对象的话,你会发现,第二个username:[email protected]创建的session永远都和第一个一样,这是为什么呢?因为,getDefaultInstance是真正单例模式,而且,里面的username和password属性是final型的,无法更改。所以,你会发现两封email都是由[email protected]发出来的。所以这个时候你要使用javax.mail.Session.getInstance()方法来创建session对象。

/**
 * @Description: 发送邮件
 * @Title: send
 * @date 2019-10-08 17:12
 * @param @param sender发件人别名
 * @param @param subject邮件主题
 * @param @param content接收者列表,多个接收者之间用","隔开
 * @param @param receiverList :内容
 * @param @param fileSrc []附件地址
 * @return void 返回类型 fileName:[]附件名称 account: 发送者账户 password :发送者密码
 * @throws @return void
 * @param sender
 * @param subject
 * @param content
 * @param receiverList
 * @param fileSrc
 * @throws Exception 
 */
public void send(String sender, String subject, String content, String receiverList, String[] fileSrc,
		String account, String password, String[] fileName) throws Exception {

	Session session = initProperties(account, password);
	MimeMessage mimeMessage = new MimeMessage(session);
	mimeMessage.setFrom(new InternetAddress(account, sender));// 发件人,可以设置发件人的别名
	InternetAddress[] internetAddressTo = new InternetAddress().parse(receiverList);
	mimeMessage.setRecipients(Message.RecipientType.TO, internetAddressTo);
	mimeMessage.setSubject(subject);
	mimeMessage.setSentDate(new Date());
	Multipart mainParth = new MimeMultipart();
	BodyPart html = new MimeBodyPart();
	html.setContent(content, "text/html; charset=UTF-8");
	mainParth.addBodyPart(html);
	MimeBodyPart bodyPart = new MimeBodyPart();
	if (fileSrc != null && fileSrc.length > 0) {
		logger.info("附件数量:" + fileSrc.length);
		URL url;
		for (int i = 0; i < fileSrc.length; i++) {
			String devAgreement =http;
			if (fileSrc[i].startsWith(devAgreement)) {
				logger.info("在线附件文件发送");
				bodyPart = new MimeBodyPart();
				url = new URL(fileSrc[i]);
				DataSource dataSource = new URLDataSource(url);
				DataHandler dataHandler = new DataHandler(dataSource);
				bodyPart.setDataHandler(dataHandler);
				mainParth.addBodyPart(bodyPart);
			} else {
				logger.info("附件文件发送含压缩文件");
				bodyPart = new MimeBodyPart();
				MimeBodyPart bodyPart2 = fileDecompression(bodyPart, fileSrc[i], fileName[i]);
				mainParth.addBodyPart(bodyPart2);
				logger.info("》》》退出");
			}

		}
	}
	logger.info("》》》内容进入");
	mimeMessage.setContent(mainParth);
	//mimeMessage.saveChanges();
	logger.info("》》》发射");
	Transport.send(mimeMessage);
	logger.info("邮件发送结束");
}

/**
 * @Description:解压服务器文件 不同服务器文件解压读取未解决
 * @Title: fileDecompression
 * @date 2019-11-01
 * @param @param string 参数
 * @return void 返回类型
 * @throws @return void
 * @param string
 * @throws IOException
 * @throws MessagingException
 */
private MimeBodyPart fileDecompression(MimeBodyPart bodyPart, String filePath, String fileName)
		throws IOException, MessagingException {
	logger.info("文件地址:" + filePath);
	logger.info("文件名称:" + fileName);
	File file = new File(filePath);
	if (!file.exists()) {
		fileError(file);
	}
	boolean archiveFile = isArchiveFile(file);
	if (archiveFile) {//zip压缩包
		logger.info("压缩包邮件解析发送");
		DataSource ds = new FileDataSource(file);
		bodyPart.setDataHandler(new DataHandler(ds));
		bodyPart.setFileName(MimeUtility.encodeWord(fileName, "UTF-8", "Q"));
		logger.info("压缩包邮件解析结束");
		return bodyPart;
	} else {// 文件
		logger.info("文件发送");
		DataSource ds = new FileDataSource(file);
		bodyPart.setDataHandler(new DataHandler(ds));
		bodyPart.setFileName(MimeUtility.encodeWord(fileName, "UTF-8", "Q"));
		return bodyPart;
	}
}

/**
 * @Description: 抛出异常
 * @Title: fileError
 * @date 2019-11-05 17:48
 * @param @param file 参数
 * @return void 返回类型
 * @throws @return void
 * @param file
 */
private void fileError(File file) {
	throw new RuntimeException("文件路径不正确");
}

/**
 * 判断文件是否为一个压缩文件
 * 
 * @param file
 * @return
 */
public static boolean isArchiveFile(File file) {

	if (file == null) {
		return false;
	}

	if (file.isDirectory()) {
		return false;
	}

	boolean isArchive = false;
	InputStream input = null;
	try {
		input = new FileInputStream(file);
		byte[] buffer = new byte[4];
		int length = input.read(buffer, 0, 4);
		if (length == 4) {
			isArchive = (Arrays.equals(ZIP_HEADER_1, buffer)) || (Arrays.equals(ZIP_HEADER_2, buffer));
		}
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		if (input != null) {
			try {
				input.close();
			} catch (IOException e) {
			}
		}
	}

	return isArchive;
}

/**
 * 
 * @param mailString 待判断的mail邮件地址
 * @return boolean 是否匹配成功
 */
public static boolean isMailAddr(String mailString) {
	String pattenString = "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$";
	Pattern pattern = Pattern.compile(pattenString);
	Matcher matcher = pattern.matcher(mailString);
	return matcher.matches();
}

知识拓展:

multipart/form-data:

1、既可以提交普通键值对,也可以提交(多个)文件键值对。

2、HTTP规范中的Content-Type不包含此类型,只能用在POST提交方式下,属于http客户端(浏览器、java httpclient)的扩展

3、通常在浏览器表单中,或者http客户端(java httpclient)中使用。

application/octet-stream:

1、只能提交二进制,而且只能提交一个二进制,如果提交文件的话,只能提交一个文件,后台接收参数只能有一个,而且只能是流(或者字节数组)

2、属于HTTP规范中Content-Type的一种

3、很少使用

application/x-www-form-urlencoded

1、不属于http content-type规范,通常用于浏览器表单提交,数据组织格式:name1=value1&name2=value2,post时会放入http body,get时,显示在在地址栏。

2、所有键与值,都会被urlencoded,请查看urlencoder

解压压缩文件转换成字节流数组导入email容器中*

/**
* 根据文件路径获取ZIP字节流。
* @param zipFilePath
* @return
* @throws IOException
*/
public static byte[] getBytesByZip(String zipFilePath) throws IOException{
InputStream inputStream;
byte[] fileByte = null;
ZipFile zipFile = null;
try{
zipFile = new ZipFile(zipFilePath);
Enumeration<?> entries = zipFile.getEntries();
while (entries.hasMoreElements()){
ZipEntry entry = (ZipEntry)entries.nextElement();
inputStream = zipFile.getInputStream(entry);
fileByte = inputStreamToByte(inputStream);
inputStream.close();
}
} finally {
if (zipFile != null) {
zipFile.close();
}
}
return fileByte;
}

/**
 * InputStream文件流转换成字节数组。
 * @param in	文件流
 * @return
 * @throws IOException
 */
public static byte[] inputStreamToByte(InputStream in)
		throws IOException{
	ByteArrayOutputStream outStream = new ByteArrayOutputStream();
	byte[] data = new byte[1024];
	int count = -1;
	while((count = in.read(data, 0, 1024)) != -1) {
		outStream.write(data, 0, count);
	}
	outStream.close();
	data = null;
	return outStream.toByteArray();
}

发送附件的不同方式:

/**
* 发送邮件以及通过byte[]流或base64编码字符串发送邮件附件
* @param Notice
* @return void
*/
public void sendEmailByFlow(Notice notice) throws Exception {
boolean sessionDebug = false;
InternetAddress[] address = null;
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd hh:mm:ss”);
try {

		SiteConfig  config = new SiteConfig();                    	//配置信息
		String mailServer = config.getSendEmailSmtp();              //服务器地址
		String mailAuth = config.getMailSmtpAuth();                 //验证
		String mailAddress = config.getSendEmailAddress();          //邮箱
		String mailUser = config.getSendEmailAddress();             //用户名
		String mailPassword = config.getSendEmailPassword();        //密码
		String mailSmtpPort = config.getMailSmtpPort();             //端口
		
		Properties props = System.getProperties();
		props.put("mail.smtp.host", mailServer);
		props.put("mail.smtp.auth", mailAuth);

		Session mailSession = Session.getDefaultInstance(props, null);
		mailSession.setDebug(sessionDebug);

		Message msg = new MimeMessage(mailSession);
		msg.setFrom(new InternetAddress(mailAddress));
		if (notice.getToAddress() != null && !"".equals(notice.getToAddress())) {
			address = InternetAddress.parse(notice.getToAddress(), false);
			for (InternetAddress addr:address) {
				if (this.isEmail(addr.getAddress()) == false) {
					log.info(sdf.format(new Date() + notice.getScene() + addr.getAddress() + "地址格式不正确。"));
				}
			}
			msg.setRecipients(Message.RecipientType.TO, address);
		}
		if (notice.getCcAddress() != null && !"".equals(notice.getCcAddress())) {
			address = InternetAddress.parse(notice.getCcAddress(), false);
			for (InternetAddress addr:address) {
				if (this.isEmail(addr.getAddress()) == false) {
					log.info(sdf.format(new Date() + notice.getScene() + addr.getAddress() + "地址格式不正确。"));
				}
			}
			msg.setRecipients(Message.RecipientType.CC, address);
		}
		if (notice.getBccAddress() != null && !"".equals(notice.getBccAddress())) {
			address = InternetAddress.parse(notice.getBccAddress(), false);
			for (InternetAddress addr:address) {
				if (this.isEmail(addr.getAddress()) == false) {
					log.info(sdf.format(new Date() + notice.getScene() + addr.getAddress() + "地址格式不正确。"));
				}
			}
			msg.setRecipients(Message.RecipientType.BCC, address);
		}
		
        String message = notice.getContent();
		msg.setSubject(notice.getTitle());
		msg.setSentDate(new Date());

		msg.setText(message);
		Multipart mm = new MimeMultipart();
		BodyPart mdp = new MimeBodyPart();                 //新建一个存放信件内容的BodyPart对象
		mdp.setContent(message, "text/html;charset=UTF-8");
		mm.addBodyPart(mdp);                               //将含有信件内容的BodyPart加入到MimeMultipart对象中

		String[] fname = notice.getAttachFileName();
		byte[] data = null;
        String[] file64Str = notice.getFile64Str();
        if (file64Str != null && file64Str.length > 0) {
    		BASE64Decoder base = new BASE64Decoder();
			for (int i=0; i<fname.length; i++) {
				data = base.decodeBuffer(file64Str[i]);
				mdp = new MimeBodyPart();
				DataSource obj = new ByteArrayDataSource(data, "application/octet-stream");
				DataHandler dh = new DataHandler(obj);
				mdp.setDataHandler(dh);
				mdp.setFileName(MimeUtility.encodeWord(fname[i],"UTF-8","Q")); 
				mdp.setHeader("content-id", fname[i]); 
				mm.addBodyPart(mdp);
			}
        } else {
        	data = notice.getFileFlow();
			mdp = new MimeBodyPart();
			DataSource obj = new ByteArrayDataSource(data, "application/octet-stream");
			DataHandler dh = new DataHandler(obj);
			mdp.setDataHandler(dh);
			mdp.setFileName(MimeUtility.encodeWord(fname[0],"UTF-8","Q")); 
			mdp.setHeader("content-id", fname[0]); 
			mm.addBodyPart(mdp);
        }


		msg.setContent(mm);
		msg.saveChanges();

		Transport transport = mailSession.getTransport("smtp");
		transport.connect(mailServer, Integer.parseInt(mailSmtpPort), mailUser, mailPassword);
		transport.sendMessage(msg, msg.getAllRecipients());
		transport.close();
		

	} catch (MessagingException e) {
		e.printStackTrace();
		log.error(sdf.format(new Date() + notice.getScene() + "异常错误,邮件发送失败。"));
		throw e;
	}
}

private boolean isEmail(String str) {
	String regex = "^([\\w-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([\\w-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$";
	return match(regex, str);
}

private boolean match(String regex, String str) {
	Pattern pattern = Pattern.compile(regex);
	Matcher matcher = pattern.matcher(str);
	return matcher.matches();
}

/**
 *  根据byte数组,生成文件。
 * @param filePath	目标文件路径
 * @return
 * @throws IOException 
 */
public static void toRealFile(byte[] bfile, String filePath)
		throws IOException {
	BufferedOutputStream bos = null;
	FileOutputStream fos = null;
	File file = null;
	try {
		file = new File(filePath);
		fos = new FileOutputStream(file);
		bos = new BufferedOutputStream(fos);
		bos.write(bfile);
	} finally {
		if (bos != null) {
			bos.close();
		}
		if (fos != null) {
			fos.close();
		}
	}
}
发布了26 篇原创文章 · 获赞 0 · 访问量 718

猜你喜欢

转载自blog.csdn.net/YHM_MM/article/details/102888643