明天要做关于发送邮件的接口,虽然我之前已用Java Mail做过许多关于邮件的发送。但同事说有点难点,虽我还不知难点在哪,还是要复习下。凡事预则立,不预则废嘛~

所需的包:

Java Mail : 目前,可从如下地址下载:JavaMail API

Activation : 目前,可从如下地址下载:JavaBeans Activation Framework (JAF)

参考的好文章:

JavaMail发送和接收邮件

JavaMail:用Authenticator的子类进行身份验证及策略模式

Java发送邮件(带附件)

Java 基于JavaMail实现向QQ邮箱发送邮件

代码托管于:https://github.com/nicchagil/multi-project的MailSender文件夹。

基于SMTP发送一个简单的邮件

首先,需要一个认证器:

package No001_基于SMTP的文本邮件;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication; public class SimpleAuthenticator extends Authenticator { private String username;
private String password; public SimpleAuthenticator(String username, String password) {
super();
this.username = username;
this.password = password;
} protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
} }

然后,书写简单的发送邮件程序:

package No001_基于SMTP的文本邮件;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage; public class SMTPSimpleMail { public static void main(String[] args) throws AddressException, MessagingException {
/* 必需的信息 */
String SMTP_MAIL_HOST = "smtp.163.com"; // 此邮件服务器地址,自行去所属邮件查询
String EMAIL_USERNAME = "example_email@163.com";
String EMAIL_PASSWORD = "mypassword";
String TO_EMAIL_ADDRESS = "example_email_too@qq.com"; /* 服务器信息 */
Properties props = new Properties();
props.put("mail.smtp.host", SMTP_MAIL_HOST);
props.put("mail.smtp.auth", "true"); /* 创建Session */
Session session = Session.getDefaultInstance(props, new SimpleAuthenticator(EMAIL_USERNAME, EMAIL_PASSWORD)); /* 邮件信息 */
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(EMAIL_USERNAME));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(TO_EMAIL_ADDRESS));
message.setSubject("how to use java mail to send email.(Title)(001)");
message.setText("how to use java mail to send email.(Content)"); // 发送
Transport.send(message);
System.out.println("不是特别倒霉,你可以去查收邮件了。");
} }

各种收件人、抄送人、秘密抄送人,怎么办

认证器沿用,略。

其实就是设置、追加多个收件人、抄送人、秘密抄送人:

package No002_各种发件人收件人抄送人怎么办;

import java.io.UnsupportedEncodingException;
import java.util.Properties; import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage; public class SendMailWithMultiPeople { public static void main(String[] args) throws AddressException, MessagingException, UnsupportedEncodingException {
/* 必需的信息 */
String SMTP_MAIL_HOST = "smtp.163.com"; // 此邮件服务器地址,自行去所属邮件查询
String EMAIL_USERNAME = "example@163.com";
String EMAIL_PASSWORD = "mypassword";
String TO_EMAIL_ADDRESS_1 = "example@163.com";
String CC_EMAIL_ADDRESS_1 = "example@163.com";
String BCC_EMAIL_ADDRESS_1 = "example@163.com"; /* 服务器信息 */
Properties props = new Properties();
props.put("mail.smtp.host", SMTP_MAIL_HOST);
props.put("mail.smtp.auth", "true"); /* 创建Session */
Session session = Session.getDefaultInstance(props, new SimpleAuthenticator(EMAIL_USERNAME, EMAIL_PASSWORD)); /* 发件人 */
Address[] senderArray = new Address[1];
senderArray[0] = new InternetAddress("example@163.com", "Nick Huang"); /* 邮件信息 */
MimeMessage message = new MimeMessage(session);
message.addFrom(senderArray);
message.addRecipient(Message.RecipientType.TO, new InternetAddress(TO_EMAIL_ADDRESS_1));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(CC_EMAIL_ADDRESS_1));
message.addRecipient(Message.RecipientType.CC, new InternetAddress(CC_EMAIL_ADDRESS_1));
message.addRecipient(Message.RecipientType.CC, new InternetAddress(TO_EMAIL_ADDRESS_1));
message.addRecipient(Message.RecipientType.BCC, new InternetAddress(BCC_EMAIL_ADDRESS_1));
message.setSubject("我是一封学习Java Mail的邮件");
message.setText("我是一封学习Java Mail的邮件的内容,请邮件过滤器高抬贵手。"); // 发送
Transport.send(message);
System.out.println("不是特别倒霉,你可以去查收邮件了。");
} }

发送附件怎么办

认证器沿用,略。

发送附件demo:

package No003_发送附件怎么办;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.Properties; import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
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; public class SendMailWithAttachment { public static void main(String[] args) throws AddressException, MessagingException, UnsupportedEncodingException {
/* 必需的信息 */
String SMTP_MAIL_HOST = "smtp.163.com"; // 此邮件服务器地址,自行去所属邮件查询
String EMAIL_USERNAME = "example@163.com";
String EMAIL_PASSWORD = "password";
String TO_EMAIL_ADDRESS_1 = "example@163.com"; /* 服务器信息 */
Properties props = new Properties();
props.put("mail.smtp.host", SMTP_MAIL_HOST);
props.put("mail.smtp.auth", "true"); /* 创建Session */
Session session = Session.getDefaultInstance(props, new SimpleAuthenticator(EMAIL_USERNAME, EMAIL_PASSWORD)); /* 发件人 */
Address[] senderArray = new Address[1];
senderArray[0] = new InternetAddress(EMAIL_USERNAME); /* 邮件信息 */
MimeMessage message = new MimeMessage(session);
message.addFrom(senderArray);
message.addRecipient(Message.RecipientType.TO, new InternetAddress(TO_EMAIL_ADDRESS_1));
message.setSubject("我是一封学习Java Mail的邮件"); BodyPart bodyPart = new MimeBodyPart();
bodyPart.setText("这是一封学习Java Mail的邮件的内容,请邮件过滤器高抬贵手。"); /* 附件 */
BodyPart attachmentPart1 = new MimeBodyPart();
DataSource source = new FileDataSource(new File("D:/文件壹.txt"));
attachmentPart1.setDataHandler(new DataHandler(source));
attachmentPart1.setFileName("=?GBK?B?" + new sun.misc.BASE64Encoder().encode("文件壹.txt".getBytes()) + "?="); BodyPart attachmentPart2 = new MimeBodyPart();
source = new FileDataSource(new File("D:/文件贰.txt"));
attachmentPart2.setDataHandler(new DataHandler(source));
attachmentPart2.setFileName("=?GBK?B?" + new sun.misc.BASE64Encoder().encode("文件贰.txt".getBytes()) + "?="); Multipart multipart = new MimeMultipart();
multipart.addBodyPart(bodyPart);
multipart.addBodyPart(attachmentPart1);
multipart.addBodyPart(attachmentPart2);
message.setContent(multipart); // 发送
Transport.send(message);
System.out.println("不是特别倒霉,你可以去查收邮件了。");
} }

还有,发送HTML邮件

认证器沿用,略。

其实就是告诉收件客户端用HTML解析渲染:

package No004_发送HTML邮件;

import java.io.UnsupportedEncodingException;
import java.util.Properties; import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
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; public class HowToSendHTMLMail { public static void main(String[] args) throws AddressException, MessagingException, UnsupportedEncodingException {
/* 必需的信息 */
String SMTP_MAIL_HOST = "smtp.163.com"; // 此邮件服务器地址,自行去所属邮件查询
String EMAIL_USERNAME = "example@163.com";
String EMAIL_PASSWORD = "password";
String TO_EMAIL_ADDRESS_1 = "example@163.com"; /* 服务器信息 */
Properties props = new Properties();
props.put("mail.smtp.host", SMTP_MAIL_HOST);
props.put("mail.smtp.auth", "true"); /* 创建Session */
Session session = Session.getDefaultInstance(props, new SimpleAuthenticator(EMAIL_USERNAME, EMAIL_PASSWORD)); /* 发件人 */
Address[] senderArray = new Address[1];
senderArray[0] = new InternetAddress(EMAIL_USERNAME); /* 邮件信息 */
MimeMessage message = new MimeMessage(session);
message.addFrom(senderArray);
message.addRecipient(Message.RecipientType.TO, new InternetAddress(TO_EMAIL_ADDRESS_1));
message.setSubject("如何发送HTML的邮件"); /* 正文 */
MimeBodyPart bodyPart = new MimeBodyPart();
bodyPart.setContent("<h1>loving you...</h2>", "text/html;charset=gb2312"); /* 封装邮件各部分信息 */
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(bodyPart);
message.setContent(multipart); // 发送
Transport.send(message);
System.out.println("不是特别倒霉,你可以去查收邮件了。");
} }

要不,来个工具类?

认证器是一定的,沿用,略。

由于需要设置的属性多且繁杂,用个自己人简单易用的属性命名,所以来一个配置类

package No005_来一个工具类;

import java.io.File;
import java.util.ArrayList;
import java.util.List; public class MailSenderConfig {
private String SMTPMailHost; // 支持SMTP协议的邮件服务器地址 /* 用于登录邮件服务器 */
private String username;
private String password; private String subject; // 标题
private String content; // 内容 private String fromMail; // 显示从此邮箱发出邮件
private List<String> toMails; // 收件人
private List<String> ccMails; // 抄送人
private List<String> bccMails; // 秘密抄送人
private List<File> attachments; // 附件 public MailSenderConfig(String sMTPMailHost, String subject,
String content, String fromMail) {
super();
SMTPMailHost = sMTPMailHost;
this.subject = subject;
this.content = content;
this.fromMail = fromMail;
} public String getSMTPMailHost() {
return SMTPMailHost;
} public void setSMTPMailHost(String sMTPMailHost) {
SMTPMailHost = sMTPMailHost;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public String getFromMail() {
return fromMail;
} public void setFromMail(String fromMail) {
this.fromMail = fromMail;
} public List<String> getToMails() {
return toMails;
} public void setToMails(List<String> toMails) {
this.toMails = toMails;
} public List<String> getCcMails() {
return ccMails;
} public void setCcMails(List<String> ccMails) {
this.ccMails = ccMails;
} public List<String> getBccMails() {
return bccMails;
} public void setBccMails(List<String> bccMails) {
this.bccMails = bccMails;
} public List<File> getAttachments() {
return attachments;
} public void setAttachments(List<File> attachments) {
this.attachments = attachments;
} public String getSubject() {
return subject;
} public void setSubject(String subject) {
this.subject = subject;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} public void addToMail (String mail) {
if (this.toMails == null) {
this.toMails = new ArrayList<String>();
}
this.toMails.add(mail);
} public void addCcMail (String mail) {
if (this.ccMails == null) {
this.ccMails = new ArrayList<String>();
}
this.ccMails.add(mail);
} public void addBccMail (String mail) {
if (this.bccMails == null) {
this.bccMails = new ArrayList<String>();
}
this.bccMails.add(mail);
} public void addAttachment (File f) {
if (this.attachments == null) {
this.attachments = new ArrayList<File>();
}
this.attachments.add(f);
} }

最后,就是工具类的部分,主要负责几个事情:按照Java Mail规则作些初始化动作、将自定义的属性配置类翻译并以Java Mail规则设置、发送邮件。

还有,需要提下的是,因为工具类所提供的代替设置的属性有限,更多的情况可能不满足需要,所以暴露出MimeMessage,在不满足需求的情况开发者可自行加工配置,而其他部分仍可沿用工具类。

package No005_来一个工具类;

import java.io.File;
import java.util.Properties; import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
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 No002_各种发件人收件人抄送人怎么办.SimpleAuthenticator; public class MailSender { private MailSenderConfig c;
private MimeMessage message; public MailSender(MailSenderConfig config) throws Exception {
super();
this.c = config;
this.setConfig();
} /**
* 初始化
* @return
*/
private Session initSession() {
Properties props = new Properties();
if (c.getSMTPMailHost() != null && c.getSMTPMailHost().length() > 0) {
props.put("mail.smtp.host", c.getSMTPMailHost());
} if (c.getUsername() != null && c.getUsername().length() > 0 &&
c.getPassword() != null && c.getPassword().length() > 0) {
props.put("mail.smtp.auth", "true");
return Session.getDefaultInstance(props, new SimpleAuthenticator(c.getUsername(), c.getPassword()));
} else {
props.put("mail.smtp.auth", "false");
return Session.getDefaultInstance(props);
}
} /**
* 设置Java Mail属性
* @throws Exception
*/
private void setConfig() throws Exception {
this.configValid(); Session s = this.initSession();
message = new MimeMessage(s); /* 发件人 */
Address[] fromMailArray = new Address[1];
fromMailArray[0] = new InternetAddress(c.getFromMail());
message.addFrom(fromMailArray); if (c.getToMails() != null && c.getToMails().size() > 0) {
for (String mail : c.getToMails()) {
message.addRecipient(Message.RecipientType.TO, new InternetAddress(mail));
}
}
if (c.getCcMails() != null && c.getCcMails().size() > 0) {
for (String mail : c.getCcMails()) {
message.addRecipient(Message.RecipientType.CC, new InternetAddress(mail));
}
}
if (c.getToMails() != null && c.getToMails().size() > 0) {
for (String mail : c.getToMails()) {
message.addRecipient(Message.RecipientType.BCC, new InternetAddress(mail));
}
} // 邮件标题
message.setSubject(c.getSubject()); /* 正文 */
MimeBodyPart bodyPart = new MimeBodyPart();
bodyPart.setContent(c.getContent(), "text/html;charset=gb2312"); /* 封装邮件各部分信息 */
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(bodyPart);
message.setContent(multipart); BodyPart attachmentPart = null;
DataSource ds = null;
if (c.getAttachments() != null && c.getAttachments().size() > 0) {
for (File f : c.getAttachments()) {
attachmentPart = new MimeBodyPart();
ds = new FileDataSource(f);
attachmentPart.setDataHandler(new DataHandler(ds));
attachmentPart.setFileName("=?GBK?B?" + new sun.misc.BASE64Encoder().encode(f.getName().getBytes()) + "?="); multipart.addBodyPart(attachmentPart);
}
} message.setContent(multipart);
} /**
* 配置校验
* @throws Exception
*/
private void configValid() throws Exception {
if (c == null) {
throw new Exception("配置对象为空");
} if (c.getSMTPMailHost() == null || c.getSMTPMailHost().length() == 0) {
throw new Exception("SMTP服务器为空");
} if (c.getFromMail() == null && c.getFromMail().length() == 0) {
throw new Exception("发件人邮件为空");
} if (c.getToMails() == null || c.getToMails().size() < 1) {
throw new Exception("收件人邮件为空");
} if (c.getSubject() == null || c.getSubject().length() == 0) {
throw new Exception("邮件标题为空");
} if (c.getContent() == null || c.getContent().length() == 0) {
throw new Exception("邮件内容为空");
}
} /**
* 发送邮件
* @throws MessagingException
*/
public void send() throws MessagingException {
Transport.send(message);
} /**
* 设置MimeMessage,暴露此对象以便于开发者自行设置个性化的属性
* @return
*/
public MimeMessage getMessage() {
return message;
} /**
* 设置MimeMessage,暴露此对象以便于开发者自行设置个性化的属性
* @return
*/
public void setMessage(MimeMessage message) {
this.message = message;
} }

提供一个简单的测试类

package No005_来一个工具类;

import java.io.File;

import javax.mail.internet.MimeMessage;

public class TestCall {

    public static void main(String[] args) throws Exception {
/* 必需的信息 */
String SMTP_MAIL_HOST = "smtp.163.com"; // 此邮件服务器地址,自行去所属邮件查询
String EMAIL_USERNAME = "example@163.com";
String EMAIL_PASSWORD = "password";
String TO_EMAIL_ADDRESS_1 = "example@163.com";
String TO_EMAIL_ADDRESS_2 = "example@163.com"; /* 使用情况一,正常使用 */
/*
MailSenderConfig c = new MailSenderConfig(SMTP_MAIL_HOST,
"this is test mail for test java mail framework 3.", "this is content 3.", EMAIL_USERNAME);
c.setUsername(EMAIL_USERNAME);
c.setPassword(EMAIL_PASSWORD);
c.addToMail(TO_EMAIL_ADDRESS_1);
c.addToMail(TO_EMAIL_ADDRESS_2);
c.addCcMail(TO_EMAIL_ADDRESS_2);
c.addCcMail(TO_EMAIL_ADDRESS_1);
c.addAttachment(new File("d:/1.txt")); MailSender ms = new MailSender(c);
ms.send();
System.out.println("sent...");
*/ /* 使用情况二,在更多情况下,工具类所作的设置并不满足需求,故将MimeMessage暴露并 */
MailSenderConfig c = new MailSenderConfig(SMTP_MAIL_HOST,
"this is test mail for test java mail framework 4.", "this is content 4.", EMAIL_USERNAME);
c.setUsername(EMAIL_USERNAME);
c.setPassword(EMAIL_PASSWORD);
c.addToMail(TO_EMAIL_ADDRESS_1);
c.addToMail(TO_EMAIL_ADDRESS_2);
c.addCcMail(TO_EMAIL_ADDRESS_2);
c.addCcMail(TO_EMAIL_ADDRESS_1);
c.addAttachment(new File("d:/1.txt")); MailSender ms = new MailSender(c); MimeMessage message = ms.getMessage();
message.setContent("this is the replaced content by MimeMessage 4.", "text/html;charset=utf-8");
ms.setMessage(message); ms.send();
System.out.println("sent...");
} }

升级下工具类

在实际使用中,发现在批量发送邮件情况下,工具类的支持不好,比如发送100封邮件,按照上述工具类的逻辑,每发送一封邮件就建立一个连接,那么,100封不就100次了吗?这样严重浪费啊。

于是,针对此点作些升级:

认证器是一定的,沿用,略。

配置类

import java.util.ArrayList;
import java.util.List; public class MailSenderConfig { private String SMTPMailHost; // 支持SMTP协议的邮件服务器地址 /* 用于登录邮件服务器 */
private String username;
private String password; private String subject; // 标题
private String content; // 内容 private String fromMail; // 显示从此邮箱发出邮件
private List<String> toMails; // 收件人
private List<String> ccMails; // 抄送人
private List<String> bccMails; // 秘密抄送人
private List<Attachment> attachments; // 附件
private String contentType = "text/html;charset=utf-8"; /**
* 构造器
* @param sMTPMailHost SMTP服务器
* @param subject 标题
* @param content 内容(默认以“text/html;charset=utf-8”形式发送)
* @param fromMail 发送人地址
*/
public MailSenderConfig(String sMTPMailHost, String subject,
String content, String fromMail) {
super();
SMTPMailHost = sMTPMailHost;
this.subject = subject;
this.content = content;
this.fromMail = fromMail;
} /**
* 构造器
* @param sMTPMailHost SMTP服务器
* @param username 邮件服务器用户名
* @param password 邮件服务器密码
* @param subject 标题
* @param content 内容(默认以“text/html;charset=utf-8”形式发送)
* @param fromMail 发送人地址
*/
public MailSenderConfig(String sMTPMailHost, String username,
String password, String subject, String content, String fromMail) {
super();
SMTPMailHost = sMTPMailHost;
this.username = username;
this.password = password;
this.subject = subject;
this.content = content;
this.fromMail = fromMail;
} public void addToMail (String mail) {
if (this.toMails == null) {
this.toMails = new ArrayList<String>();
}
this.toMails.add(mail);
} public void addCcMail (String mail) {
if (this.ccMails == null) {
this.ccMails = new ArrayList<String>();
}
this.ccMails.add(mail);
} public void addBccMail (String mail) {
if (this.bccMails == null) {
this.bccMails = new ArrayList<String>();
}
this.bccMails.add(mail);
} public void addAttachment (Attachment a) {
if (this.attachments == null) {
this.attachments = new ArrayList<Attachment>();
}
this.attachments.add(a);
} /*
* Getter and Setter
*/ public String getSMTPMailHost() {
return SMTPMailHost;
} public void setSMTPMailHost(String sMTPMailHost) {
SMTPMailHost = sMTPMailHost;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public String getFromMail() {
return fromMail;
} public void setFromMail(String fromMail) {
this.fromMail = fromMail;
} public List<String> getToMails() {
return toMails;
} public void setToMails(List<String> toMails) {
this.toMails = toMails;
} public List<String> getCcMails() {
return ccMails;
} public void setCcMails(List<String> ccMails) {
this.ccMails = ccMails;
} public List<String> getBccMails() {
return bccMails;
} public void setBccMails(List<String> bccMails) {
this.bccMails = bccMails;
} public List<Attachment> getAttachments() {
return attachments;
} public void setAttachments(List<Attachment> attachments) {
this.attachments = attachments;
} public String getSubject() {
return subject;
} public void setSubject(String subject) {
this.subject = subject;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} public String getContentType() {
return contentType;
} public void setContentType(String contentType) {
this.contentType = contentType;
}
}

附件实体类

import java.io.File;

/**
* 邮件附件实体类
*/
public class Attachment { private File file;
private String filename; public File getFile() {
return file;
} public void setFile(File file) {
this.file = file;
} public String getFilename() {
if (filename == null || filename.trim().length() == 0) {
return file.getName();
} return filename;
} public void setFilename(String filename) {
this.filename = filename;
} public Attachment(File file, String filename) {
super();
this.file = file;
this.filename = filename;
} public Attachment(File file) {
super();
this.file = file;
} }

抽象发送类

import java.util.Properties;

import javax.mail.Session;

public abstract class AbstractSessionMailSender {

    protected Session session;

    /**
* 初始化Session
* @return
*/
public static Session initSession(MailSenderConfig c) {
Properties props = new Properties();
if (c.getSMTPMailHost() != null && c.getSMTPMailHost().length() > 0) {
props.put("mail.smtp.host", c.getSMTPMailHost());
} if (c.getUsername() != null && c.getUsername().length() > 0 &&
c.getPassword() != null && c.getPassword().length() > 0) {
props.put("mail.smtp.auth", "true");
return Session.getDefaultInstance(props, new SimpleAuthenticator(c.getUsername(), c.getPassword()));
} else {
props.put("mail.smtp.auth", "false");
return Session.getDefaultInstance(props);
}
} /**
* 暴露Getter、Setter提供Session的可设置性,以支持批量发送邮件/发送多次邮件时,可缓存Session
* @return
*/
public Session getSession() {
return session;
} public void setSession(Session session) {
this.session = session;
} }

发送类

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
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; public class MailSender extends AbstractSessionMailSender { private MailSenderConfig c;
private MimeMessage message; public MailSender(MailSenderConfig config) throws Exception {
super();
this.c = config;
this.setConfig();
} public MailSender(MailSenderConfig config, Session session) throws Exception {
super();
this.c = config;
this.setConfig();
super.setSession(session);
} /**
* 发送邮件
* @throws MessagingException
*/
public void send() throws MessagingException {
Transport.send(message);
} /**
* 获取MimeMessage,暴露此对象以便于开发者自行设置个性化的属性(此工具类不支持的方法可由开发人员自行设置,设置完毕设置回来)
* @return
*/
public MimeMessage getMessage() {
return message;
} /**
* 设置MimeMessage,暴露此对象以便于开发者自行设置个性化的属性(此工具类不支持的方法可由开发人员自行设置,设置完毕设置回来)
* @return
*/
public void setMessage(MimeMessage message) {
this.message = message;
} /**
* 设置Java Mail属性
* @throws Exception
*/
private void setConfig() throws Exception {
this.configValid(); if (session == null) {
session = initSession(c);
}
message = new MimeMessage(session); /* 发件人 */
Address[] fromMailArray = new Address[1];
fromMailArray[0] = new InternetAddress(c.getFromMail());
message.addFrom(fromMailArray); if (c.getToMails() != null && c.getToMails().size() > 0) {
for (String mail : c.getToMails()) {
message.addRecipient(Message.RecipientType.TO, new InternetAddress(mail));
}
}
if (c.getCcMails() != null && c.getCcMails().size() > 0) {
for (String mail : c.getCcMails()) {
message.addRecipient(Message.RecipientType.CC, new InternetAddress(mail));
}
}
if (c.getToMails() != null && c.getToMails().size() > 0) {
for (String mail : c.getToMails()) {
message.addRecipient(Message.RecipientType.BCC, new InternetAddress(mail));
}
} // 邮件标题
message.setSubject(c.getSubject()); /* 正文 */
MimeBodyPart bodyPart = new MimeBodyPart();
bodyPart.setContent(c.getContent(), c.getContentType()); /* 封装邮件各部分信息 */
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(bodyPart);
message.setContent(multipart); /* 附件 */
BodyPart attachmentPart = null;
DataSource ds = null;
if (c.getAttachments() != null && c.getAttachments().size() > 0) {
for (Attachment a : c.getAttachments()) {
attachmentPart = new MimeBodyPart();
ds = new FileDataSource(a.getFile());
attachmentPart.setDataHandler(new DataHandler(ds));
attachmentPart.setFileName(MimeUtility.encodeText(a.getFilename())); multipart.addBodyPart(attachmentPart);
}
} message.setContent(multipart);
} /**
* 配置校验
* @throws Exception
*/
private void configValid() throws Exception {
if (c == null) {
throw new Exception("配置对象为空");
} if (c.getSMTPMailHost() == null || c.getSMTPMailHost().length() == 0) {
throw new Exception("SMTP服务器为空");
} if (c.getFromMail() == null && c.getFromMail().length() == 0) {
throw new Exception("发件人邮件为空");
} if (c.getToMails() == null || c.getToMails().size() < 1) {
throw new Exception("收件人邮件为空");
} if (c.getSubject() == null || c.getSubject().length() == 0) {
throw new Exception("邮件标题为空");
} if (c.getContent() == null || c.getContent().length() == 0) {
throw new Exception("邮件内容为空");
}
} }

一个Junit的测试类

import java.io.File;

import javax.mail.Session;
import javax.mail.internet.MimeMessage; import org.junit.Test; public class ReadMe { /* 必需的信息 */
String SMTP_MAIL_HOST = "smtp.163.com"; // 此邮件服务器地址,自行去所属邮件服务器描述页查询
String EMAIL_USERNAME = "example@163.com";
String EMAIL_PASSWORD = "password";
String TO_EMAIL_ADDRESS_1 = "example@163.com";
/* 选填的信息 */
String TO_EMAIL_ADDRESS_2 = "example@163.com"; @Test
public void case1() throws Exception {
/* 使用情况一,正常使用 */
MailSenderConfig c = new MailSenderConfig(SMTP_MAIL_HOST,
"this is a mail for test java mail framework in case1.", "this is content.", EMAIL_USERNAME);
c.setUsername(EMAIL_USERNAME);
c.setPassword(EMAIL_PASSWORD);
c.addToMail(TO_EMAIL_ADDRESS_1);
c.addToMail(TO_EMAIL_ADDRESS_2);
c.addCcMail(TO_EMAIL_ADDRESS_2);
c.addCcMail(TO_EMAIL_ADDRESS_1);
c.addAttachment(new Attachment(new File("d:/1.txt"))); MailSender ms = new MailSender(c);
ms.send();
System.out.println("sent...");
} @Test
public void case2() throws Exception {
/* 使用情况二,在更多情况下,工具类所作的设置并不满足需求,故将MimeMessage暴露以便于开发者自行设置个性化的属性 */
MailSenderConfig c = new MailSenderConfig(SMTP_MAIL_HOST,
"this is a mail for test java mail framework in case2.", "this is content.", EMAIL_USERNAME);
c.setUsername(EMAIL_USERNAME);
c.setPassword(EMAIL_PASSWORD);
c.addToMail(TO_EMAIL_ADDRESS_1);
c.addToMail(TO_EMAIL_ADDRESS_2);
c.addCcMail(TO_EMAIL_ADDRESS_2);
c.addCcMail(TO_EMAIL_ADDRESS_1);
c.addAttachment(new Attachment(new File("d:/1.txt"))); MailSender ms = new MailSender(c); MimeMessage message = ms.getMessage();
message.setContent("this is the replaced content by MimeMessage in case2.", "text/html;charset=utf-8");
ms.setMessage(message); ms.send();
System.out.println("sent...");
} @Test
public void case3() throws Exception {
/* 使用情况三,多次发送邮件,可缓存Session,使多次发送邮件均共享此Session,以减少重复创建Session
* 同时需注意缓存的Session的时效性
*/
MailSenderConfig c = new MailSenderConfig(SMTP_MAIL_HOST,
"this is the first mail for test java mail framework to share session in case3.", "this is content.", EMAIL_USERNAME);
c.setUsername(EMAIL_USERNAME);
c.setPassword(EMAIL_PASSWORD);
c.addToMail(TO_EMAIL_ADDRESS_1);
c.addToMail(TO_EMAIL_ADDRESS_2);
c.addCcMail(TO_EMAIL_ADDRESS_2);
c.addCcMail(TO_EMAIL_ADDRESS_1);
c.addAttachment(new Attachment(new File("d:/1.txt"))); Session session = MailSender.initSession(c); MailSender ms = new MailSender(c, session);
ms.send(); c.setSubject("this is the second mail for test java mail framework to share session in case3.");
c.setContent("this is content 2.");
ms = new MailSender(c, session);
ms.send();
System.out.println("sent...");
} }

关于QQ邮箱不能成功发送的解决方法

有网友发现用本程序不能使用QQ邮箱发送邮件,本人试了后确认不行。主要原因有两个:1、QQ邮箱需要SSL;2、QQ邮箱需要先开通SMTP服务,再获取授权码当作密码使用(见《什么是授权码,它又是如何设置?》,点击进入)。

既然找出了问题,那么解决问题相对容易:

1、设置SSL,代码如下:

props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
props.put("mail.smtp.port", "465");

2、然后到自己的邮箱中开启SMTP服务后获取授权码当作密码使用。

如无意外,就OK了。

关于使用Java Mail通过QQ邮箱发送邮件,这篇文章写得很好:《Java 基于JavaMail实现向QQ邮箱发送邮件》,点击进入

总结

目前,我遇到的需求就是这么多,如日后遇见其他常见的需求并有时间,会进一步添加。

Java发送邮件,所遇到的常见需求的更多相关文章

  1. Java发送邮件初窥

    一.背景 最近朋友的公司有用到这个功能,之前对这一块也不是很熟悉,就和他一起解决出现的异常的同时,也初窥一下使用Apache Common Email组件进行邮件发送. 二.Java发送邮件的注意事项 ...

  2. 用java发送邮件(黄海已测试通过)

    /** * java发送带附件的邮件 * 周枫 * 2013.8.10 */ package com.dsideal.Util; import javax.mail.*; import javax.m ...

  3. Java发送邮件(带附件)

    实现java发送邮件的过程大体有以下几步: 准备一个properties文件,该文件中存放SMTP服务器地址等参数. 利用properties创建一个Session对象 利用Session创建Mess ...

  4. 用Java发送邮件

    要用Java发送邮件,除过JDK本身的jar包之外,还需要两个额外的jar包:JavaMail和JAF.当然,如果你使用的JavaEE的JDK,那就不用单独去网上下载了,因为JavaEE的JDK中已经 ...

  5. Java中字符串的一些常见方法

    1.Java中字符串的一些常见方法 /** * */ package com.you.model; /** * @author Administrator * @date 2014-02-24 */ ...

  6. Java发送邮件时标题和发件人乱码

    最近碰到一个问题,Java发送邮件时,查看邮箱结果,发件人及邮件标题正文全部乱码 通过翻阅资料,原因及解决方法如下: // Set Subject: 头字段 message.setSubject(Mi ...

  7. Java - 31 Java 发送邮件

    Java 发送邮件 使用Java应用程序发送E-mail十分简单,但是首先你应该在你的机器上安装JavaMail API 和Java Activation Framework (JAF) . 你可以在 ...

  8. Java-Runoob-高级教程:Java 发送邮件

    ylbtech-Java-Runoob-高级教程:Java 发送邮件 1.返回顶部 1. Java 发送邮件 使用Java应用程序发送 E-mail 十分简单,但是首先你应该在你的机器上安装 Java ...

  9. Java发送邮件--web.xml配置,Java代码配置

    前言:我目前总结的使用java发送邮件的方式有两种,分别是在spring框架xml配置文件使用bean标签,另一种方法是把发送功能封装成一个对象,废话不多说上代码, 边看代码边讲解,希望对需要的人能有 ...

随机推荐

  1. web server与app server有什么不同

    简单来说,web服务器提供页面给浏览器,而app服务器提供客户端可以调用的接口.具体而言,我们可以说: Web服务器处理HTTP请求,而app服务器基于多种不同的协议,处理应用程序的逻辑问题. 以下将 ...

  2. Oracle中游标返回多条数据的情况

    DECLARE -- 定义类型. TYPE test_type IS TABLE OF test_main%ROWTYPE; test_data test_type; -- 定义游标. CURSOR ...

  3. JSON讲解和“弹窗”

    json定义形式{key1:value1, key2:value2, key3:value3.....} 例: title>JSON讲解</title> <script src ...

  4. [Ubuntu] Linux下使用google app engine,无法打开https网站的解决方法

    为什么这里写的是 google app engine?原因我就不解释了.步骤如下: 1)安装证书导入工具:$ sudo apt-get install libnss3-tools 2)导入CA.crt ...

  5. MyEclipse启动失败

    日志的一部分: !SESSION 2014-09-24 11:47:03.156 -----------------------------------------------eclipse.buil ...

  6. 【crunch bang】安装firefox,删除iceweasel

    首先,移除iceweasel: apt-get remove iceweasel Then, download the latest Linux build of Firefox directly f ...

  7. 解决ultravnc在win2008 R2下CTRL+ALT+DELETEA组合键发送失败的问题

    首先,请google “ultravnc ctrl+alt+delete”,得到的解决方法是,更改UAC.进入组策略-计算机配置-管理模板-windows登陆选项,“禁用或启用软件注意序列”,更改成“ ...

  8. 三层架构和MVC模式

    目录[-] 1.三层架构 2.MVC 2.1 标准的MVC(Model-View-Controller) 2.2 Web MVC 3.三层架构和MVC的区别与联系 1.三层架构 三层架构(3-tier ...

  9. sp_executesql的执行计划会被重用(转载)

    前一段时间,给一位朋友公司做咨询,看到他们的很多的存储过程都存在动态sql语句执行,sp_executesql,即使在没有动态表名,动态字段名的情况下仍然使用sp_executesql,这个做法是不太 ...

  10. android拨打电话

    1.要使用Android系统中的电话拨号功能,首先必须在AndroidManifest.xml功能清单中加入允许拨打电话的权限: <uses-permission android:name=&q ...