`

javax.mail.Message发送Email,带附件,异步

阅读更多
package 

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
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 org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class TestMailSender {
	private static final Logger log = LoggerFactory.getLogger(MailSender.class);
	
	/* 邮箱配置详情 */
	private static final String MAIL_SMTP_AUTH = "true";
	private static final String MAIL_HOST = "";
	private static final String MAIL_TRANSPORT_PROTOCOL = "smtp";
	private static final String MAIL_SMTP_PORT = "25";
	private static final String MAIL_AUTH_NAME = "";
	private static final String MAIL_AUTH_PASSWORD = "";
	private static final String MAIL_DISPLAY_SENDNAME = "发件人";
	private static final String MAIL_DISPLAY_SENDMAIL = "";
	private static final String MAIL_SEND_CHARSET = "UTF-8";
	private static final boolean MAIL_IS_DEBUG = true;
	
	/* 邮箱逻辑配置 */
	private static final int MAIL_FAILED_RESEND_TIMES = 3; 								// 同步、异步发送邮件失败,尝试发送次数
	private static final long MAIL_FAILED_ASYN_RESEND_WAITING_MILLISECONDS = 10000; 	// 异步多线程发送邮件失败,重试间隔时间
	private static final long MAIL_FAILED_SYNC_RESEND_WAITING_MILLISECONDS = 3000;  	// 同步发送邮件失败,线程等待时间
	public static final long MAIL_ASYN_SEND_SPACING_MILLISECONDS = 2000;
	public static final long MAIL_SYNC_SEND_SPACING_MILLISECONDS = 1000;
	
	private static final Message message = initMessage();
	
	// 初始化邮箱配置
	private static final Message initMessage() {
		// 基本配置
		Properties props = new Properties();
		props.setProperty("mail.smtp.auth", MAIL_SMTP_AUTH);
		props.setProperty("mail.host", MAIL_HOST);
		props.setProperty("mail.transport.protocol", MAIL_TRANSPORT_PROTOCOL);
		props.setProperty("mail.smtp.port", MAIL_SMTP_PORT);

		Session session = Session.getInstance(props, new Authenticator() {
			@Override
			protected PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(MAIL_AUTH_NAME,
						MAIL_AUTH_PASSWORD);
			}
		});

		session.setDebug(MAIL_IS_DEBUG);
		Message message = new MimeMessage(session);

		try {
			message.setFrom(new InternetAddress(MimeUtility
					.encodeText(MAIL_DISPLAY_SENDNAME)
					+ "<"
					+ MAIL_DISPLAY_SENDMAIL + ">"));
		} catch (AddressException e) {
			log.error("初始化邮箱配置失败", e);
			throw new RuntimeException(e.getMessage());
		} catch (UnsupportedEncodingException e) {
			log.error("初始化邮箱配置失败", e);
			throw new RuntimeException(e.getMessage());
		} catch (MessagingException e) {
			log.error("初始化邮箱配置失败", e);
			throw new RuntimeException(e.getMessage());
		}
		return message;
	}
	
	/**
	 * 异步根据主题和内容发送邮件
	 * 
	 * @param subject 邮件主题
	 * @param content 邮件内容
	 * @param beSentMails 接收邮件的邮箱地址,不合法的邮箱会自动过滤,如果没有合法邮箱不会发送任何邮件
	 */
	public static void asynMail(String subject, String content, String... beSentMails) {
		Thread thread = new MailSenderByContentDetailThread(subject, content, beSentMails);
		thread.start();
	}
	
	/**
	 * 异步根据主题和内容发送邮件(带附件)
	 * 
	 * @param subject 邮件主题
	 * @param content 邮件内容
	 * @param attachmentName 附件文件名
	 * @param attachmentFile 附件地址
	 * @param beSentMails 接收邮件的邮箱地址,不合法的邮箱会自动过滤,如果没有合法邮箱不会发送任何邮件
	 */
	public static void asynMultiMail(String subject, String content, String attachmentName, String attachmentFile, String... beSentMails) {
		Thread thread = new MailSenderByContentDetailThread(subject, content, attachmentName, attachmentFile,beSentMails);
		thread.start();
	}
	
	/**
	 * 内部包装,根据主题和内容发送邮件
	 * 
	 * @param subject 邮件主题
	 * @param content 邮件内容
	 * @param beSentMails 接收邮件的邮箱地址,不合法的邮箱会自动过滤,如果没有合法邮箱不会发送任何邮件
	 */
	private static final synchronized void sendMail(String subject, String content, String... beSentMails) {
		// 过滤不合法邮箱
		beSentMails = validBeSentMails(beSentMails);

		// 检验过滤结果
		if (ArrayUtils.isEmpty(beSentMails)) {
			return;
		}
		
		try {
			message.setSubject(subject);
			message.setContent(content,"text/html;charset=" + MAIL_SEND_CHARSET );
			
			Address[] addresses = new Address[beSentMails.length];
			for (int i = 0; i < beSentMails.length; i++) {
				addresses[i] = new InternetAddress(beSentMails[i]);
			}
			message.setRecipients(Message.RecipientType.TO, addresses);
			Transport.send(message);
		} catch (Exception e) {
			log.error("根据主题和内容发送邮失败", e);
			throw new RuntimeException("resend" + e.getMessage());
		}
		
	}
	
	/**
	 * 内部包装,根据主题和内容发送邮件(带附件)
	 * 
	 * @param subject 邮件主题
	 * @param content 邮件内容
	 * @param attachmentName 附件文件名
	 * @param attachmentFile 附件地址
	 * @param beSentMails 接收邮件的邮箱地址,不合法的邮箱会自动过滤,如果没有合法邮箱不会发送任何邮件
	 */
	private static final synchronized void sendMultiMail(String subject, String content, String attachmentName, String attachmentFile, String... beSentMails) {
		// 过滤不合法邮箱
		beSentMails = validBeSentMails(beSentMails);

		// 检验过滤结果
		if (ArrayUtils.isEmpty(beSentMails)) {
			return;
		}
		
		try {
			//邮件标题
			message.setSubject(subject);
			//message.setContent(content,"text/html;charset=" + MAIL_SEND_CHARSET );
			
			Multipart multipart = new MimeMultipart();
			
			//设置邮件的文本内容
	        BodyPart contentPart = new MimeBodyPart();
	        contentPart.setText(content);
	        multipart.addBodyPart(contentPart);
	        
	        //添加附件
	        BodyPart messageBodyPart= new MimeBodyPart();
	        DataSource source = new FileDataSource(attachmentFile);
	        //添加附件的内容
	        messageBodyPart.setDataHandler(new DataHandler(source));
	        //添加附件的标题
	        messageBodyPart.setFileName(attachmentName);
	        
	        multipart.addBodyPart(messageBodyPart);
	        
	        //将multipart对象放到message中
            message.setContent(multipart);
            //保存邮件
            message.saveChanges();
			
			Address[] addresses = new Address[beSentMails.length];
			for (int i = 0; i < beSentMails.length; i++) {
				addresses[i] = new InternetAddress(beSentMails[i]);
			}
			message.setRecipients(Message.RecipientType.TO, addresses);
			Transport.send(message);
		} catch (Exception e) {
			log.error("根据主题和内容发送邮失败", e);
			throw new RuntimeException("resend" + e.getMessage());
		}
		
	}
	
	// 返回所有合法的邮箱,都不合法则返回空
	private static String[] validBeSentMails(String... beSentMails) {
		// 没有任何接收邮箱
		if (ArrayUtils.isEmpty(beSentMails)) {
			return null;
		}

		// 验证邮箱格式合法性
		Pattern pattern = Pattern.compile("^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$");
		List<String> finalBeSentMails = new ArrayList<String>();
		for (String tmp : beSentMails) {
			if (StringUtils.isEmpty(tmp)) {
				continue;
			}

			Matcher matcher = pattern.matcher(tmp);
			if (matcher.matches()) {
				finalBeSentMails.add(tmp);
			}
		}

		// 只给合法的地址发送邮件
		if (finalBeSentMails.size() != beSentMails.length) {
			if (finalBeSentMails.size() == 0) {
				return null;
			}
			return finalBeSentMails.toArray(new String[finalBeSentMails.size()]);
		}
		
		// 所有邮箱均合法
		return beSentMails;
	}
	
	// 根据详情发送邮件线程类
	static final class MailSenderByContentDetailThread extends Thread {
		private String subject;
		private String content;
		private String[] beSentMails;
		private String attachmentName;//附件文件名
		private String attachmentFile;//附件文件位置
		
		MailSenderByContentDetailThread(String subject, String content, String[] beSentMails) {
			this.subject = subject;
			this.content = content;
			this.beSentMails = beSentMails;
			this.attachmentName = null;
			this.attachmentFile = null;
		}
		
		MailSenderByContentDetailThread(String subject, String content, String attachmentName, String attachmentFile, String[] beSentMails) {
			this.subject = subject;
			this.content = content;
			this.beSentMails = beSentMails;
			this.attachmentName = attachmentName;
			this.attachmentFile = attachmentFile;
		}
		
		@Override
		public void run() {
			int sendTimes = 0;
			int i = 0;
			// 发送次数在允许尝试范围内
			do {
				try {
					// 发送邮件
					for (; i < beSentMails.length; i++) {
						if(StringUtils.isNotBlank(attachmentName) && StringUtils.isNotBlank(attachmentFile)){
							TestMailSender.sendMultiMail(subject, content, attachmentName, attachmentFile, beSentMails[i]);
						}else{
							TestMailSender.sendMail(subject, content, beSentMails[i]);
						}
						if (i < beSentMails.length - 1) {
							Thread.sleep(MAIL_ASYN_SEND_SPACING_MILLISECONDS);
						}
					}
					break;
				} catch(Exception e) {
					// 不是邮件发送的异常,直接输出错误信息并跳出
					if (!e.getMessage().startsWith("resend")) {
						log.error("邮件发送失败", e);
						break;
					}
					
					// 发送次数已到达允许尝试范围,记录错误信息
					if (sendTimes == MAIL_FAILED_RESEND_TIMES) {
						log.error("邮件发送失败,错误原因:{}" , e.getMessage().substring(6, e.getMessage().length() - 1));
						log.error("发送主题为:{}" ,subject);
						log.error("发送内容为:{}" , content);
						log.error("接收邮箱有:{}" , Arrays.toString(beSentMails));
						log.error("为<{}>发送邮件时出错,后续邮件均未发送。",beSentMails[i]);
						break;
					}
					
					
					// 线程休眠后重试
					try {
						Thread.sleep(MAIL_FAILED_ASYN_RESEND_WAITING_MILLISECONDS);
					} catch (InterruptedException e1) {
						log.error("线程休眠后重试失败", e1);
					}
				}
			} while (sendTimes++ < MAIL_FAILED_RESEND_TIMES);
		}
	}
	
	
}

 

分享到:
评论

相关推荐

    javamail的jdk打包

    JavaMail 是一个开源的 Java API,它允许开发者在 Java 应用程序中发送和接收电子邮件。这个API提供了全面的电子邮件处理功能,包括SMTP、POP3和IMAP协议的支持。在JavaMail的使用过程中,通常会涉及到两个核心的JAR...

    java email 发送带附件的邮件

    在本文中,我们将深入探讨如何使用JavaMail API来发送带有附件的电子邮件。 首先,我们需要理解JavaMail的基本组件。`javax.mail.Session`是JavaMail的核心,用于管理邮件会话和配置邮件服务器信息。`Message`对象...

    java 发送邮件+附件.rar

    在Java编程中,发送带有附件的电子邮件是一项常见的任务,尤其在自动化报告、系统通知或数据共享等场景下。本文将详细讲解如何使用Java发送带有附件的邮件,主要涉及以下知识点: 1. JavaMail API:JavaMail是Java...

    java邮件开发jar包

    在描述中提到的"email",通常是指这个压缩包包含的JavaMail相关jar文件,可能包括了`javax.mail.jar`、`javax.mail-api.jar`、`activation.jar`等。`activation.jar`是JavaBeans Activation Framework (JAF) 的一...

    Java通过Exchange协议发送和接收邮件

    4. 设置附件:如果需要发送附件,可以通过EmailMessage的addAttachment方法添加。 5. 发送邮件:使用EmailMessage的send方法将邮件发送出去。 接收邮件部分,主要涉及到查询和处理邮箱中的邮件: 1. 获取Folder对象...

    java 发送email 邮件

    本教程将深入探讨如何使用Java发送带有附件、支持多接收者且解决乱码问题的电子邮件。 首先,我们需要导入JavaMail API,这是一个用于处理电子邮件的开放源代码库。在Java项目中,可以通过以下Maven依赖引入: ```...

    用java发邮件代码

    Java发送邮件是软件开发...在实际项目中,可能还需要考虑错误处理、日志记录、异步发送等复杂情况。对于更复杂的邮件服务,可以使用开源库如JavaMailSenderImpl(Spring框架)进行封装,以简化代码并提供更强大的功能。

    <邮件自动发送>例子-Java实现

    此外,如果你需要发送大量邮件,考虑使用线程池或者异步处理以提高效率。 对于提供的文档"java实现邮件自动发送的功能例子.doc",它应该详细阐述了上述步骤,包括代码示例和可能遇到的问题。通过阅读该文档,你将...

    java程序发送邮件

    此外,如果你的应用需要大量发送邮件,还应考虑使用线程池或异步处理来提高效率。 总之,`TestEmail.java`代码应该是一个简单的Java程序,演示了如何使用JavaMail API向指定收件人发送邮件。确保正确配置邮件服务器...

    java 邮件发送

    为了发送带有附件的邮件,我们可以使用 `Multipart` 和 `BodyPart` 类: ```java Multipart multipart = new MimeMultipart(); BodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setText("邮件正文...

    java发送Email_群发email.rar

    1. **JavaMail API**: 这是Java发送邮件的基础,包括`javax.mail`和`javax.mail.internet`两个包。你需要导入这些包来使用相关的类和方法。 2. **Session对象**: 这是JavaMail的核心,用于配置邮件服务器的连接参数...

    strust2发送邮件

    Struts2是一个非常流行的Java Web框架,用于构建和维护可扩展且易于管理的企业级应用程序。在Struts2中,发送邮件是一项常见的...此外,考虑到并发性和性能,可能还需要对邮件发送进行适当的异步处理和错误重试机制。

    java email 发送邮件

    在Java中发送邮件主要涉及到 javax.mail 和 javax.mail.internet 这两个包中的类。 以下是一个简单的JavaMail发送邮件的步骤和相关知识点: 1. **导入必要的库**:首先,你需要在项目中引入JavaMail相关的jar包。...

    java email 发送文档

    如果你需要发送带有附件的邮件,可以使用MIME类型处理。例如,如果附件是`incident_email.mp4`,可以这样操作: ```java MimeBodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setText("邮件正文...

    Android应用源码之AndroidEmail(邮件收发)-IT计算机-毕业设计.zip

    - `javax.mail.Message`用于创建邮件内容,包括主题、正文、附件等。可以设置各种属性,如发件人、收件人、抄送人、密送人等。 6. **Transport类**: - `javax.mail.Transport`负责实际的邮件发送,调用`...

    程序实现发送邮件

    它包括了`javax.mail`和`javax.mail.internet`两个主要包,提供了一系列的类和接口,如`Session`、`Message`、`MimeMessage`等。 3. **Session对象**:这是JavaMail API的入口点,用于设置SMTP服务器信息、认证信息...

    Java调用SMTP命令发邮件,实现抄送,附件--无需邮件搭建邮件服务器直接发送

    下面是一个简单的JavaMail示例,演示了如何发送带有抄送和附件的邮件: ```java Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); ...

    javamail邮件发送

    在实际项目中,你可能还需要考虑使用异步发送、错误重试、日志记录以及更复杂的邮件格式(如嵌入式图像、CSS样式等)。JavaMail提供了一套完整的API来应对这些需求,使其成为Java开发中处理邮件任务的强大工具。

    java发送邮件的包email.jar

    5. **添加附件**:如果需要发送带有附件的邮件,可以使用`MimeBodyPart`和`MimeMultipart`类。`MimeBodyPart`用于创建单个部分,如文本或附件,`MimeMultipart`则用于组合多个部分。 6. **发送邮件**:最后,使用`...

    java 工具类-----email

    JavaMail API提供了`javax.mail`和`javax.mail.internet`这两个主要包,包含了创建、发送和接收邮件所需的所有类。发送电子邮件的基本步骤如下: 1. **配置属性**:设置邮件服务器的相关参数,如SMTP服务器地址、...

Global site tag (gtag.js) - Google Analytics