发送邮件
本项目源码在:https://coding.net/u/pruidong/p/SpringEmailDemo/git
之前简单使用过Java Email发送邮件,但最近接触了Spring Mail组件之后,发现在之前的基础上更加方便了.本文的内容参照了:Spring Mail官方文档,以及Thymeleaf官方示例.但对部分内容进行了修改和优化,也使得发送邮件变得更加简单.
有两点需要说明的是:
- 本文不会贴完所有的资源,可以前往[项目地址]获取所有源码;
- 项目基于Maven构建,并且不需要Spring Web MVC(也就是不需要在Tomcat中运行),配置相关邮箱信息之后,直接在控制台运行即可
部分源码
直接使用下面的源码无法构建出完整项目,因为有部分图片、模板文件(HTML,txt)未贴出,贴出下面的代码,仅作为参考依据.完整源码可以访问项目地址
Maven依赖文件(pom.xml):
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>xyz.suancaiyu</groupId> <artifactId>SpringMail19Demo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.6.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.11.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.11.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.11.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.11.RELEASE</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>3.0.7.RELEASE</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring4</artifactId> <version>3.0.7.RELEASE</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> </dependencies> </project>
配置邮箱地址、邮箱服务器信息(base.properties):
xyz.suancaiyu.smtpServer=SMTP服务器地址(smtp.qq.com) xyz.suancaiyu.smtpServerPort=SMTP服务器端口 xyz.suancaiyu.smtpUserName=邮箱登录名 xyz.suancaiyu.smtpUserPassword=邮箱登录密码(QQ邮箱要使用授权码) xyz.suancaiyu.smtpFromEmail=发件人邮箱地址 xyz.suancaiyu.smtpToEmail=收件人邮箱地址
Spring的配置文件(AppInitial.java):
package xyz.suancaiyu.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.thymeleaf.TemplateEngine; import org.thymeleaf.spring4.SpringTemplateEngine; import org.thymeleaf.templatemode.TemplateMode; import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; import org.thymeleaf.templateresolver.ITemplateResolver; import org.thymeleaf.templateresolver.StringTemplateResolver; import xyz.suancaiyu.Constat; import java.util.Collections; import java.util.Properties; /** * Spring 配置文件. * * Created by puruidong on 2017/9/15. */ @Configuration @ComponentScan(basePackages = "xyz.suancaiyu.*") public class AppInitial { @Bean public SimpleMailMessage templateMessage() { SimpleMailMessage msg = new SimpleMailMessage(); msg.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL)); msg.setTo(Constat.getValue(Constat.SMTPTOEMAIL)); return msg; } @Bean public JavaMailSenderImpl mailSender() { JavaMailSenderImpl jmsl = new JavaMailSenderImpl(); jmsl.setHost(Constat.getValue(Constat.SMTPSERVER)); jmsl.setPort(Integer.valueOf(Constat.getValue(Constat.SMTPSERVERPORT))); jmsl.setUsername(Constat.getValue(Constat.SMTPUSERNAME)); jmsl.setPassword(Constat.getValue(Constat.SMTPPASSWORD)); Properties properties = new Properties(); properties.setProperty("mail.smtp.auth", "true"); properties.setProperty("mail.smtp.ssl.enable", "true"); properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); jmsl.setJavaMailProperties(properties); return jmsl; } /********* Thymeleaf Email Template **************/ @Bean public ResourceBundleMessageSource emailMessageSource() { final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("mail/MailMessages"); return messageSource; } @Bean public TemplateEngine emailTemplateEngine() { final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); // Resolver for TEXT emails templateEngine.addTemplateResolver(textTemplateResolver()); // Resolver for HTML emails (except the editable one) templateEngine.addTemplateResolver(htmlTemplateResolver()); // Resolver for HTML editable emails (which will be treated as a String) templateEngine.addTemplateResolver(stringTemplateResolver()); // Message source, internationalization specific to emails templateEngine.setTemplateEngineMessageSource(emailMessageSource()); return templateEngine; } private ITemplateResolver textTemplateResolver() { final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); templateResolver.setOrder(Integer.valueOf(1)); templateResolver.setResolvablePatterns(Collections.singleton("text/*")); templateResolver.setPrefix("/mail/"); templateResolver.setSuffix(".txt"); templateResolver.setTemplateMode(TemplateMode.TEXT); templateResolver.setCharacterEncoding(Constat.EMAIL_TEMPLATE_ENCODING); templateResolver.setCacheable(false); return templateResolver; } private ITemplateResolver htmlTemplateResolver() { final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); templateResolver.setOrder(Integer.valueOf(2)); templateResolver.setResolvablePatterns(Collections.singleton("html/*")); templateResolver.setPrefix("/mail/"); templateResolver.setSuffix(".html"); templateResolver.setTemplateMode(TemplateMode.HTML); templateResolver.setCharacterEncoding(Constat.EMAIL_TEMPLATE_ENCODING); templateResolver.setCacheable(false); return templateResolver; } private ITemplateResolver stringTemplateResolver() { final StringTemplateResolver templateResolver = new StringTemplateResolver(); templateResolver.setOrder(Integer.valueOf(3)); // No resolvable pattern, will simply process as a String template everything not previously matched templateResolver.setTemplateMode("HTML5"); templateResolver.setCacheable(false); return templateResolver; } /********* Thymeleaf Email Template END **************/ }
发送纯文本邮件(未使用模板,SendTextEmail.java):
package xyz.suancaiyu.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.MailSender; import org.springframework.mail.SimpleMailMessage; import org.springframework.stereotype.Component; import java.time.LocalDate; /** * 发送纯文本邮件. * <p> * <p> * Created by puruidong on 2017/9/15. */ @Component public class SendTextEmail { @Autowired private SimpleMailMessage templateMessage; @Autowired private MailSender mailSender; public void sendEmail() { System.out.println("发送纯文本邮件:"); templateMessage.setSubject("订单信息-" + LocalDate.now().toString()); templateMessage.setText("你好,email测试. "); mailSender.send(templateMessage); System.out.println("发送成功.."); } }
发送带附件的邮件(SendFileEmail.java):
package xyz.suancaiyu.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Component; import xyz.suancaiyu.Constat; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import static xyz.suancaiyu.Constat.PNG_MIME; /** * 发送邮件-带附件. * <p> * Created by puruidong on 2017/9/15. */ @Component public class SendFileEmail { @Autowired private JavaMailSenderImpl mailSender; public void sendEmail() { System.out.println("发送邮件,携带附件:"); MimeMessage message = mailSender.createMimeMessage(); try { MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setTo(Constat.getValue(Constat.SMTPTOEMAIL)); helper.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL)); helper.setText("订单消息-详情请查看附件"); helper.setSubject("订单消息"); helper.addAttachment("detail.jpg", new ClassPathResource(Constat.THYMELEAF_LOGO_IMAGE), PNG_MIME); mailSender.send(message); System.out.println("发送成功!"); } catch (MessagingException e) { e.printStackTrace(); } } public void sendHTMLEmail() { System.out.println("发送HTML邮件:"); MimeMessage message = mailSender.createMimeMessage(); try { MimeMessageHelper helper = new MimeMessageHelper(message, true, "GBK"); helper.setTo(Constat.getValue(Constat.SMTPTOEMAIL)); helper.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL)); helper.setText("<mail.html><head><META http-equiv=Content-Type content='text/mail.html; charset=GBK'> <meta charset='utf-8'/><head><body><img src='cid:identifier1234'><b>测试一个文本.</b><p style='color:red'>重要提示.</p></body></mail.html>", true); helper.setSubject("订单消息"); helper.addInline("identifier1234", new ClassPathResource(Constat.THYMELEAF_LOGO_IMAGE), PNG_MIME); mailSender.send(message); System.out.println("发送成功!"); } catch (MessagingException e) { e.printStackTrace(); } } }
使用Thymeleaf发送模板邮件(参照了Thymeleaf官方示例,有部分改动):
package xyz.suancaiyu.service.thymeleaf; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Component; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.Context; import xyz.suancaiyu.Constat; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.util.Arrays; import java.util.Date; /** * 使用Thymeleaf发送模板邮件. * * Created by puruidong on 2017/9/15. */ @Component public class EmailService { @Autowired private JavaMailSenderImpl mailSender; @Autowired private TemplateEngine emailTemplateEngine; private static final String EMAIL_TEXT_TEMPLATE_NAME = "text/email-text"; private static final String EMAIL_SIMPLE_TEMPLATE_NAME = "html/email-simple"; private static final String EMAIL_WITHATTACHMENT_TEMPLATE_NAME = "html/email-withattachment"; private static final String EMAIL_INLINEIMAGE_TEMPLATE_NAME = "html/email-inlineimage"; private static final String EMAIL_EDITABLE_TEMPLATE_CLASSPATH_RES = "html/email-editable"; public void sendTextMail() { // Prepare the evaluation context final Context ctx = new Context(); ctx.setVariable("name", "test123"); ctx.setVariable("subscriptionDate", new Date()); ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music")); // Prepare message using a Spring helper final MimeMessage mimeMessage = this.mailSender.createMimeMessage(); final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "UTF-8"); try { message.setSubject("Example plain TEXT email"); message.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL)); message.setTo(Constat.getValue(Constat.SMTPTOEMAIL)); // Create the plain TEXT body using Thymeleaf final String textContent = emailTemplateEngine.process(EMAIL_TEXT_TEMPLATE_NAME, ctx); message.setText(textContent); // Send email mailSender.send(mimeMessage); } catch (MessagingException e) { e.printStackTrace(); } } /* * Send HTML mail (simple) */ public void sendSimpleMail() { // Prepare the evaluation context final Context ctx = new Context(); ctx.setVariable("name", "13343sdsxvbn"); ctx.setVariable("subscriptionDate", new Date()); ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music")); // Prepare message using a Spring helper final MimeMessage mimeMessage = this.mailSender.createMimeMessage(); final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "UTF-8"); try { message.setSubject("Example HTML email (simple)"); message.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL)); message.setTo(Constat.getValue(Constat.SMTPTOEMAIL)); // Create the HTML body using Thymeleaf final String htmlContent = emailTemplateEngine.process(EMAIL_SIMPLE_TEMPLATE_NAME, ctx); message.setText(htmlContent, true /* isHtml */); // Send email this.mailSender.send(mimeMessage); } catch (MessagingException e) { e.printStackTrace(); } } public void sendMailWithInline() { final Context ctx = new Context(); ctx.setVariable("name", "testlocal"); ctx.setVariable("subscriptionDate", new Date()); ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music")); ctx.setVariable("imageResourceName", "identifier1234"); // so that we can reference it from HTML final MimeMessage mimeMessage = mailSender.createMimeMessage(); try { final MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); helper.setSubject("Thymeleaf模板邮件"); helper.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL)); helper.setTo(Constat.getValue(Constat.SMTPTOEMAIL)); final String htmlContent = emailTemplateEngine.process(EMAIL_INLINEIMAGE_TEMPLATE_NAME, ctx); helper.setText(htmlContent, true); helper.addInline("identifier1234", new ClassPathResource(Constat.THYMELEAF_LOGO_IMAGE), Constat.PNG_MIME); mailSender.send(mimeMessage); } catch (MessagingException e) { e.printStackTrace(); } } /* * Send HTML mail with inline image */ public void sendEditableMail() { try { // Prepare message using a Spring helper final MimeMessage mimeMessage = mailSender.createMimeMessage(); final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true /* multipart */, "UTF-8"); message.setSubject("Example editable HTML email"); message.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL)); message.setTo(Constat.getValue(Constat.SMTPTOEMAIL)); // Prepare the evaluation context final Context ctx = new Context(); ctx.setVariable("name", "fdsafdsadsaork11233"); ctx.setVariable("subscriptionDate", new Date()); ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music")); // Create the HTML body using Thymeleaf final String output = emailTemplateEngine.process(EMAIL_EDITABLE_TEMPLATE_CLASSPATH_RES, ctx); message.setText(output, true /* isHtml */); // Add the inline images, referenced from the HTML code as "cid:image-name" message.addInline("background", new ClassPathResource(Constat.BACKGROUND_IMAGE), Constat.PNG_MIME); message.addInline("logo-background", new ClassPathResource(Constat.LOGO_BACKGROUND_IMAGE), Constat.PNG_MIME); message.addInline("thymeleaf-banner", new ClassPathResource(Constat.THYMELEAF_BANNER_IMAGE), Constat.PNG_MIME); message.addInline("thymeleaf-logo", new ClassPathResource(Constat.THYMELEAF_LOGO_IMAGE), Constat.PNG_MIME); // Send mail mailSender.send(mimeMessage); } catch (Exception e) { e.printStackTrace(); } } }
运行测试类(Main.java):
package xyz.suancaiyu.main; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import xyz.suancaiyu.config.AppInitial; import xyz.suancaiyu.service.SendFileEmail; import xyz.suancaiyu.service.SendTextEmail; import xyz.suancaiyu.service.thymeleaf.EmailService; /** * 使用Spring mail发送邮件. * <p> * <p> * <p> * 可能出现的问题: * <p> * <p> * 1.增加验证,否则会报:553 authentication is required 的错误信息 * Properties prop = new Properties(); * prop.setProperty("mail.smtp.auth", "true"); * JavaMailSenderImpl.setJavaMailProperties(prop); * <p> * 2.当邮件内容是HTML语言时的中文问题: * 初始化MimeMessageHelper辅助类时,设置"GBK" encoding!如: * MimeMessageHelper messageHelp = new MimeMessageHelper(message,true,"GBK"); * 同时在设置:<META http-equiv=Content-Type content='text/mail.html; charset=GBK'> * 如果都设置为"UTF-8",在某些邮件客户端标题不能正常显示! * <p> * 3.邮件附件的中文问题! * spring的文档里面说MimeMessageHelper设置了encoding,同时对title,text,attach产生作用,但还是会出问题: * 解决方法:MimeUtility.encodeWord(file.getName());就OK了! * <p> * Created by puruidong on 2017/9/15. */ public class Main { private static final ApplicationContext ctx = new AnnotationConfigApplicationContext(AppInitial.class); /** * 发送文本邮件. */ private static void sendTextEmail() { SendTextEmail send = ctx.getBean(SendTextEmail.class); send.sendEmail(); } /** * 发送文件邮件. */ private static void sendFileEmail() { SendFileEmail send = ctx.getBean(SendFileEmail.class); send.sendEmail(); send.sendHTMLEmail(); } /** * 使用Thymeleaf模板发送模板邮件. * <p> * 参考:https://github.com/thymeleaf/thymeleafexamples-springmail */ private static void sendThymeleafEmail() { EmailService emailService = ctx.getBean(EmailService.class); emailService.sendMailWithInline(); emailService.sendTextMail(); emailService.sendSimpleMail(); emailService.sendEditableMail(); } public static void main(String[] args) { System.out.println("先配置base.properties"); System.exit(1); sendThymeleafEmail(); } }
到此.