常用框架(JavaMail)

JavaMail

1、JavaMail初步

1.1、导入相应的jar包

1.2、创建相应的session,通过session来设置邮件发送的配置信息

			Properties props = new Properties();
			/**
			 * 设置邮件发送的协议,一般都是SMTP协议
			 */
			props.setProperty("mail.transport.protocol", "smtp");
			/**
			 * 设置发送邮件的服务器,不同的邮箱服务器不一致,可以在邮箱的帮助中查询
			 */
			props.setProperty("mail.host", "smtp.163.com");
			/**
			 * 设置发送服务器验证,一些邮箱需要增加这个验证才能发送邮件
			 */
			props.setProperty("mail.smtp.auth", "true");
			/**
			 * 创建session
			 */
			Session session = Session.getInstance(props);
			//打开邮件发送的调试功能,可以看到邮件的发送过程
			session.setDebug(true);

1.3、创建message来设定相应的邮件信息

			/*
			 * 创建Message对象,通过这个对象来设置邮件的发送信息
			 */
			Message msg = new MimeMessage(session);
			/*
			 * 设置邮件的标题
			 */
			msg.setSubject("javamail");
			/*
			 * 设置邮件的内容,使用setText()是设置纯文本内容
			 */
			msg.setText("java send mail!");
			/*
			 * 设置邮件从什么地方发送的
			 */
			msg.setFrom(new InternetAddress("xxxxx@163.com"));
			/*
			 * 设置邮件的发送人,此时表示的发送人
			 */
			msg.setRecipients(RecipientType.TO, InternetAddress.parse("5858588@qq.com,xxx@xxx.com.cn"));
			/*
			 * 设置邮件的抄送人
			 */
			msg.setRecipients(RecipientType.CC, InternetAddress.parse("5858588@qq.com,xxx@xxx.com.cn"));

1.4、创建transport对象来完成邮件的发送

			/**
			 * 创建Transport来完成邮件的发送
			 */
			tran = session.getTransport();
			/**
			 * 连接用户名和密码
			 */
			tran.connect("username", "password");
			/**
			 * 发送邮件,此时如果msg中设置了收件人,但是在sendMessage()的第二个参数中
			 * 没有设置的话也不会发送,所以使用sendMessage()来发送邮件不是一种推荐的方式
			 * 应该使用:Transport.send(msg);来发送邮件,如果使用Transport.send(msg);
			 * 来发送邮件,需要在其它地方设置用户名和密码
			 * 特别注意:
			 * 发送邮件报错:com.sun.mail.smtp.SMTPSendFailedException: 554 DT:SPM 163 smtp13,
			 * EcCowADnHUj2sU9Yx_D3EQ--.12S2 1481617913,
			 * please see http://mail.163.com/help/help_spam_16.htm?ip=121.57.11.39&hostid=smtp13&time=1481617913
			 * 导致报错原因:邮件标题或内容被系统识别为垃圾邮件
			 * 
			 */
			tran.sendMessage(msg, new InternetAddress[]{new InternetAddress("xxx@xxx.com.cn")});

    使用了transport对象之后一定要transport:

		} finally {
			try {
				if(tran!=null) tran.close();
			} catch (MessagingException e) {
				e.printStackTrace();
			}
		}

2、JavaMail的第二种方式

		try {
			Properties props = new Properties();
			//设置邮件发送的协议,一般都是SMTP协议
			props.setProperty("mail.transport.protocol", "smtp");
			//设置发送邮件的服务器,不同的邮箱服务器不一致,可以在邮箱的设置中查询
			props.setProperty("mail.host", "smtp.163.com");
			//设置发送服务器验证,一些邮箱需要增加这个验证才能发送邮件
			props.setProperty("mail.smtp.auth", "true");
			//当需要使用Transport.send()发送邮件时,需要将用户名和密码设置到session中
			//在实际的开发中会创建一个类来继承Authenticator类,以此动态的设置用户名和密码
			Session session = Session.getInstance(props,new Authenticator(){
				//通过Authenticator中的getPasswordAuthentication()的方法来设置邮箱的用户名和密码
				@Override
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication("username", "password");
				}
			});
			session.setDebug(true);
			Message msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress("xxxxx@163.com"));
			msg.setRecipient(RecipientType.TO, new InternetAddress("5858588@qq.com"));
			msg.setSubject("a mail");
			//通过以下方式可以创建一个html的文档
			msg.setContent("<h1 style='color:red'>This is a mail.</h1>", "text/html;charset=utf-8");
			//使用Transport的static方法send()发送邮件需要在session创建时来确定访问的用户名和密码
			Transport.send(msg);
		} catch (AddressException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		}

    使用Session.getDefaultInstance()方法获取session

try {
			Properties props = new Properties();
			//设置邮件发送的协议,一般都是SMTP协议
			props.setProperty("mail.transport.protocol", "smtp");
			//设置发送邮件的服务器,不同的邮箱服务器不一致,可以在邮箱的设置中查询
			props.setProperty("mail.host", "smtp.163.com");
			//设置发送服务器验证,一些邮箱需要增加这个验证才能发送邮件
			props.setProperty("mail.smtp.auth", "true");
			//当需要使用Transport.send()发送邮件时,需要将用户名和密码设置到session中
			Session session = Session.getDefaultInstance(props,new Authenticator(){
				//通过Authenticator中的getPasswordAuthentication()的方法来设置邮箱的用户名和密码
				@Override
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication("username", "password");
				}
			});
			
			session.setDebug(true);
			
			Message msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress("xxxxx@163.com"));
			msg.setRecipient(RecipientType.TO, new InternetAddress("5858588@qq.com"));
			msg.setSubject("mail1");
			//通过以下方式可以创建一个html的文档
			msg.setContent("<h1 style='color:red'>mail1.</h1>", "text/html;charset=utf-8");
			//使用Transport的static方法send()发送邮件需要在session创建时来确定访问的用户名和密码
			Transport.send(msg);
			
			System.out.println("-----------------------");
			
			Properties props2 = new Properties();
			props2.setProperty("mail.transport.protocol", "smtp");
			//设置发送邮件的服务器,不同的邮箱服务器不一致,可以在邮箱的设置中查询
			props2.setProperty("mail.host", "smtp.163.com");
			//设置发送服务器验证,一些邮箱需要增加这个验证才能发送邮件
			props2.setProperty("mail.smtp.auth", "true");
			/**
			 * 当使用getDefaultInstance()[单例模式]的时候,会查找session是否在内存中
			 * 已经存在,如果存在就不会再去读取新的properties中的配置,而是直接使用内存
			 * 中已经存在的配置信息,所以此时可以不设置props都可以访问。
			 * 所以如果在一个项目中可能会涉及到使用多个邮箱发送邮件,就不要使用getDefaultInstance()来处理
			 * 在一些特殊的情况:如果邮箱验证此时只会通过一个邮箱发出邮件,就可以使用getDefaultInstance()来处理
			 */
			Session s2 = Session.getInstance(props2,new Authenticator() {
				@Override
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication("username", "password");
				}
			});
			
			Message msg2 = new MimeMessage(s2);
			msg2.setFrom(new InternetAddress("xxxxx@163.com"));
			msg2.setRecipient(RecipientType.TO, new InternetAddress("5858588@qq.com"));
			msg2.setSubject("mail2");
			//通过以下方式可以创建一个html的文档
			msg2.setContent("<h1 style='color:red'>mail2.</h1>", "text/html;charset=utf-8");
			//使用Transport的static方法send()发送邮件需要在session创建时来确定访问的用户名和密码
			Transport.send(msg2);
		} catch (AddressException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		}

1.3、复杂格式的JavaMail

    实现代码:

try {
			Properties props = new Properties();
			//设置邮件发送的协议,一般都是SMTP协议
			props.setProperty("mail.transport.protocol", "smtp");
			//设置发送邮件的服务器,不同的邮箱服务器不一致,可以在邮箱的设置中查询
			props.setProperty("mail.host", "smtp.163.com");
			//设置发送服务器验证,一些邮箱需要增加这个验证才能发送邮件
			props.setProperty("mail.smtp.auth", "true");
			//当需要使用Transport.send()发送邮件时,需要将用户名和密码设置到session中
			//在实际的开发中会创建一个类来继承Authenticator类,以此动态的设置用户名和密码
			Session session = Session.getInstance(props,new Authenticator(){
				//通过Authenticator中的getPasswordAuthentication()的方法来设置邮箱的用户名和密码
				@Override
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication("username", "password");
				}
			});
			session.setDebug(true);
			Message msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress("xxxxx@163.com"));
			msg.setRecipient(RecipientType.TO, new InternetAddress("xxx@xxx.com.cn"));
			msg.setSubject("什么情况");
			
			/**
			 * 创建整个邮件的Multipart,因为邮件的内容已经不仅仅只是纯文本或者纯html文本,
			 * 而需要添加相应的附件,此时就得通过Multipart来创建
			 */
			Multipart emailPart = new MimeMultipart();
			/**
			 * Multipart不能直接加入内容,需要通过BodyPart来加入内容,假设有两个附件就
			 * 需要三个BodyPart,两个用来存储附件,一个用来存储邮件的正文
			 */
			MimeBodyPart att1 = new MimeBodyPart();
			
			att1.setDataHandler(new DataHandler(new FileDataSource("d:/OS/kj.pptx")));
			att1.setFileName("kj.pptx");
			MimeBodyPart att2 = new MimeBodyPart();
			//创建第二个附件
			att2.setDataHandler(new DataHandler(new FileDataSource("d:/OS/项目经理.docx")));
			//要解决中文乱码的问题需要通过一个MimeUtility这个类来编码中文
			att2.setFileName(MimeUtility.encodeText("项目经理.docx"));
			
			MimeBodyPart content = new MimeBodyPart();
			//由于文件的正文还有图片和内容,所以也需要通过Multipart来创建
			MimeMultipart contentMultipart = new MimeMultipart();
			//然后再创建相应的BodyPart来设置内容
			MimeBodyPart imgBody = new MimeBodyPart();
			//创建了正文中的图片内容
			imgBody.setDataHandler(new DataHandler(new FileDataSource("d:/OS/01.jpg")));
			//为这张图片设置一个id,在正文中可以通过cid:xxx来访问
			imgBody.setContentID("smile");
			
			MimeBodyPart htmlBody = new MimeBodyPart();
			htmlBody.setContent("<h1>报错啊</h1><img src='cid:smile'/>", "text/html;charset=utf-8");
			
			contentMultipart.addBodyPart(imgBody);
			contentMultipart.addBodyPart(htmlBody);
			//完成了邮件正文的设置
			content.setContent(contentMultipart);
			
			/**
			 * 设置邮件的信息
			 */
			//添加第一个附件
			emailPart.addBodyPart(att1);
			//添加第二个附件
			emailPart.addBodyPart(att2);
			//添加邮件正文
			emailPart.addBodyPart(content);
			//设置邮件的信息
			msg.setContent(emailPart);
			
			//使用Transport的static方法send()发送邮件需要在session创建时来确定访问的用户名和密码
			Transport.send(msg);
		} catch (AddressException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

1.4、整合Spring

    1、beans.xml设置

	<!-- Spring整合JavaMail发送邮件,并设置相应的属性 -->
	<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
	   	<!-- 设置发送邮件的服务器,不同的邮箱服务器不一致,可以在邮箱的设置中查询 -->
	    <property name="host" value="smtp.163.com"/>
	    <!-- 设置邮件发送的协议,一般都是SMTP协议 -->
	    <property name="protocol" value="smtp"/>
	    <!-- 设置发送邮箱的用户名和密码 -->
	    <property name="username" value="username"/>
		<property name="password" value="password"/>
		<!-- 设置mail的私有属性 -->
		<property name="javaMailProperties">
			<props>
				<!-- 设置发送服务器验证,一些邮箱需要增加这个验证才能发送邮件 -->
				<prop key="mail.smtp.auth">true</prop>
				<!-- 设置是否开启调试 -->
				<prop key="mail.debug">true</prop>
			</props>
		</property>	    
	</bean>

    2、直接使用mailSender创建MimeMessage

	@Resource(name="mailSender")
	JavaMailSender mailSender;
	
	@Test
	public void test01() {
		try {
			//创建MimeMessage
			MimeMessage msg = mailSender.createMimeMessage();
			//通过MimeMessageHelper来完成对邮件信息的创建
			MimeMessageHelper helper = new MimeMessageHelper(msg, true, "utf-8");
			helper.setFrom("xxxxx@163.com");
			helper.setTo("xxx@xxx.com.cn");
			helper.setSubject("spring整合javamail");
			//设置邮件的正文
			helper.setText("<div style='color:red;font-size:15px'>通过spring发送</div><img src='cid:sss'/>",true);
			//添加附件
			helper.addAttachment(MimeUtility.encodeText("科技.pptx"), new FileSystemResource("d:/OS/kj.pptx"));
			//添加邮件内容中的信息
			FileSystemResource fsr = new FileSystemResource("d:/OS/01.jpg");
			helper.addInline("sss", fsr);
			//发送邮件
			mailSender.send(msg);
		} catch (MailException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		}

    3、异步发送邮件

    beans.xml中添加多线程:

	<!-- 正常的情况如果要发送邮件,需要异步发送,否则会把大量的时间浪费在发送邮件上面,
		此时可能会造成用户重复刷新,使用spring的ThreadPoolTaskExecutor可以方便实现多线程的程序 -->
	<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
	    <property name="corePoolSize" value="5" />
	    <property name="maxPoolSize" value="10" />
	    <property name="queueCapacity" value="25" />
	</bean>

    将发送邮件放到单独的一个线程中:

	private class sendMailThread implements Runnable {
		private Message msg;
		private Integer[] userIds;
		private AttachDto ad;
		private String[] newNames;
		
		public sendMailThread(Message msg, Integer[] userIds, AttachDto ad,String[] newNames) {
			super();
			this.msg = msg;
			this.userIds = userIds;
			this.ad = ad;
			this.newNames = newNames;
		}
		
		public void run() {
			sendMail(msg,userIds,ad,newNames);
		}
	}
	
	private void sendMail(Message msg, Integer[] userIds, AttachDto ad,String[] newNames) {
		try {
			System.out.println("-----------开始发送邮件-------------");
			MimeMessage email = mailSender.createMimeMessage();
			MimeMessageHelper helper = new MimeMessageHelper(email, true, "utf-8");
			helper.setFrom("xxxxx@163.com");
			helper.setTo("xxx@xxx.com.cn");
			helper.setSubject(msg.getTitle());
			String uploadPath = ad.getUploadPath();
			if(ad.isHasAttache()) {
				File[] atts = ad.getAtts();
				String[] fns = ad.getAttsFileName();
				for(int i=0;i<atts.length;i++) {
					String fn = fns[i];
					helper.addAttachment(MimeUtility.encodeText(fn), new FileSystemResource(uploadPath+"/"+newNames[i]));
				}
			}
			helper.setText(msg.getContent(),true);
			mailSender.send(email);
			System.out.println("--------------邮件发送成功!---------------");
		} catch (MailException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		}
	}

    发送邮件:

		/**
		 * 特别注意:如果Hibernate5使用extends HibernateDaoSupport中的getHibernateTemplate()异步发送会报错:
		 * Write operations are not allowed in read-only mode (FlushMode.MANUAL): 
		 * Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
		 */
		//将发送邮件放置到一个线程中,这样就是实现了异步处理
		taskExecutor.execute(new sendMailThread(msg, userIds, ad,newNames));

    BaseDao获取session方法:

	private SessionFactory sessionFactory;

	@Resource
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
    //获取被Spring所管理的Session
	public Session getSession(){
		return this.sessionFactory.getCurrentSession();
	}

 

转载于:https://my.oschina.net/pmos/blog/806823

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值