【JAVA】使用javax.mail发送邮件


本文主要解决以下问题:

1、如何用java实现邮件发送功能?

2、如何发送给多个人、抄送给多个人?

3、如何发送携带附件的邮件?


开始说正文。

首先,发送邮件肯定要有个发件人,所有要有发件人的用户名和密码;然后得有服务器给中转吧,不同的邮箱对应的服务器也不一样,所以有邮件服务器的概念;再然后就是邮件本身,要有主题、收件人、抄送、正文、附件等等。


发件人的邮箱好说,随随便便就能申请到,可是邮件服务器呢?这里列出一些常用的邮件服务器(感谢数据的整理者):


sina.com:
POP3服务器地址:pop3.sina.com.cn(端口:110)
SMTP服务器地址:smtp.sina.com.cn(端口:25) 

sinaVIP:
POP3服务器:pop3.vip.sina.com (端口:110)
SMTP服务器:smtp.vip.sina.com (端口:25)

sohu.com:
POP3服务器地址:pop3.sohu.com(端口:110)
SMTP服务器地址:smtp.sohu.com(端口:25)

126邮箱:
POP3服务器地址:pop.126.com(端口:110)
SMTP服务器地址:smtp.126.com(端口:25)

139邮箱:
POP3服务器地址:POP.139.com(端口:110)
SMTP服务器地址:SMTP.139.com(端口:25)

163.com:
POP3服务器地址:pop.163.com(端口:110)
SMTP服务器地址:smtp.163.com(端口:25)

QQ邮箱 
POP3服务器地址:pop.qq.com(端口:110)
SMTP服务器地址:smtp.qq.com (端口:25)

QQ企业邮箱
POP3服务器地址:pop.exmail.qq.com (SSL启用 端口:995)
SMTP服务器地址:smtp.exmail.qq.com(SSL启用 端口:587/465)

yahoo.com:
POP3服务器地址:pop.mail.yahoo.com
SMTP服务器地址:smtp.mail.yahoo.com

yahoo.com.cn:
POP3服务器地址:pop.mail.yahoo.com.cn(端口:995)
SMTP服务器地址:smtp.mail.yahoo.com.cn(端口:587

HotMail
POP3服务器地址:pop3.live.com (端口:995)
SMTP服务器地址:smtp.live.com (端口:587)

gmail(google.com)
POP3服务器地址:pop.gmail.com(SSL启用 端口:995)
SMTP服务器地址:smtp.gmail.com(SSL启用 端口:587)

263.net:
POP3服务器地址:pop3.263.net(端口:110)
SMTP服务器地址:smtp.263.net(端口:25)

263.net.cn:
POP3服务器地址:pop.263.net.cn(端口:110)
SMTP服务器地址:smtp.263.net.cn(端口:25)

x263.net:
POP3服务器地址:pop.x263.net(端口:110)
SMTP服务器地址:smtp.x263.net(端口:25)

21cn.com:
POP3服务器地址:pop.21cn.com(端口:110)
SMTP服务器地址:smtp.21cn.com(端口:25)

Foxmail:
POP3服务器地址:POP.foxmail.com(端口:110)
SMTP服务器地址:SMTP.foxmail.com(端口:25)

china.com:
POP3服务器地址:pop.china.com(端口:110)
SMTP服务器地址:smtp.china.com(端口:25)

tom.com:
POP3服务器地址:pop.tom.com(端口:110)
SMTP服务器地址:smtp.tom.com(端口:25)

etang.com:
POP3服务器地址:pop.etang.com
SMTP服务器地址:smtp.etang.com

好嘞,有了这个之后就开始今天的正事,讲讲怎么用java发送邮件,首先上原理( 原文在此)。

JAVA MAIL是利用现有的邮件账户发送邮件的工具,比如说,我在网易注册一个邮箱账户,通过JAVA Mail的操控,我可以不亲自登录网易邮箱,让程序自动的使用网易邮箱发送邮件。这一机制被广泛的用在注册激活和垃圾邮件的发送等方面。

JavaMail可以到http://www.oracle.com/technetwork/java/javamail/index-138643.html进行下载,并将mail.jar添加到classpath即可。如果你使用的是JAVA EE SDK,则可以在C:\glassfishv3\glassfish\modules\mail.jar找到所需的jar包,同样需要添加的classpath。

JAVA邮件发送的大致过程是这样的的:

1、构建一个继承自javax.mail.Authenticator的具体类,并重写里面的getPasswordAuthentication()方法。此类是用作登录校验的,以确保你对该邮箱有发送邮件的权利。
2、构建一个properties文件,该文件中存放SMTP服务器地址等参数。
3、通过构建的properties文件和javax.mail.Authenticator具体类来创建一个javax.mail.Session。Session的创建,就相当于登录邮箱一样。剩下的自然就是新建邮件。
4、构建邮件内容,一般是javax.mail.internet.MimeMessage对象,并指定发送人,收信人,主题,内容等等。
5、使用javax.mail.Transport工具类发送邮件。


接下来上干货

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
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 Email {
	private static String defaultSenderName = "";// 默认的发件人用户名,defaultEntity用得到
	private static String defaultSenderPass = "";// 默认的发件人密码,defaultEntity用得到
	private static String defaultSmtpHost = "";// 默认的邮件服务器地址,defaultEntity用得到

	private String smtpHost; // 邮件服务器地址
	private String sendUserName; // 发件人的用户名
	private String sendUserPass; // 发件人密码

	private MimeMessage mimeMsg; // 邮件对象
	private Session session;
	private Properties props;
	private Multipart mp;// 附件添加的组件
	private List<FileDataSource> files = new LinkedList<FileDataSource>();// 存放附件文件

	private void init() {
		if (props == null) {
			props = System.getProperties();
		}
		props.put("mail.smtp.host", smtpHost);
		props.put("mail.smtp.auth", "true"); // 需要身份验证
		session = Session.getDefaultInstance(props, null);
		// 置true可以在控制台(console)上看到发送邮件的过程
		session.setDebug(true);
		// 用session对象来创建并初始化邮件对象
		mimeMsg = new MimeMessage(session);
		// 生成附件组件的实例
		mp = new MimeMultipart();
	}

	private Email(String smtpHost, String sendUserName, String sendUserPass, String to, String cc, String mailSubject, String mailBody,
			List<String> attachments) {
		this.smtpHost = smtpHost;
		this.sendUserName = sendUserName;
		this.sendUserPass = sendUserPass;

		init();
		setFrom(sendUserName);
		setTo(to);
		setCC(cc);
		setBody(mailBody);
		setSubject(mailSubject);
		if (attachments != null) {
			for (String attachment : attachments) {
				addFileAffix(attachment);
			}
		}

	}

	/**
	 * 邮件实体
	 * 
	 * @param smtpHost
	 *            邮件服务器地址
	 * @param sendUserName
	 *            发件邮件地址
	 * @param sendUserPass
	 *            发件邮箱密码
	 * @param to
	 *            收件人,多个邮箱地址以半角逗号分隔
	 * @param cc
	 *            抄送,多个邮箱地址以半角逗号分隔
	 * @param mailSubject
	 *            邮件主题
	 * @param mailBody
	 *            邮件正文
	 * @param attachmentPath
	 *            附件路径
	 * @return
	 */
	public static Email entity(String smtpHost, String sendUserName, String sendUserPass, String to, String cc, String mailSubject, String mailBody,
			List<String> attachments) {
		return new Email(smtpHost, sendUserName, sendUserPass, to, cc, mailSubject, mailBody, attachments);
	}

	/**
	 * 默认邮件实体,用了默认的发送帐号和邮件服务器
	 * 
	 * @param to
	 *            收件人,多个邮箱地址以半角逗号分隔
	 * @param cc
	 *            抄送,多个邮箱地址以半角逗号分隔
	 * @param subject
	 *            邮件主题
	 * @param body
	 *            邮件正文
	 * @param attachment
	 *            附件全路径
	 * @return
	 */
	public static Email defaultEntity(String to, String cc, String subject, String body, List<String> attachments) {
		return new Email(defaultSmtpHost, defaultSenderName, defaultSenderPass, to, cc, subject, body, attachments);
	}

	/**
	 * 设置邮件主题
	 * 
	 * @param mailSubject
	 * @return
	 */
	private boolean setSubject(String mailSubject) {
		try {
			mimeMsg.setSubject(mailSubject);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/**
	 * 设置邮件内容,并设置其为文本格式或HTML文件格式,编码方式为UTF-8
	 * 
	 * @param mailBody
	 * @return
	 */
	private boolean setBody(String mailBody) {
		try {
			BodyPart bp = new MimeBodyPart();
			bp.setContent("<meta http-equiv=Content-Type content=text/html; charset=UTF-8>" + mailBody, "text/html;charset=UTF-8");
			// 在组件上添加邮件文本
			mp.addBodyPart(bp);
		} catch (Exception e) {
			System.err.println("设置邮件正文时发生错误!" + e);
			return false;
		}
		return true;
	}

	/**
	 * 添加一个附件
	 * 
	 * @param filename
	 *            邮件附件的地址,只能是本机地址而不能是网络地址,否则抛出异常
	 * @return
	 */
	public boolean addFileAffix(String filename) {
		try {
			if (filename != null && filename.length() > 0) {
				BodyPart bp = new MimeBodyPart();
				FileDataSource fileds = new FileDataSource(filename);
				bp.setDataHandler(new DataHandler(fileds));
				bp.setFileName(MimeUtility.encodeText(fileds.getName(), "utf-8", null)); // 解决附件名称乱码
				mp.addBodyPart(bp);// 添加附件
				files.add(fileds);
			}
		} catch (Exception e) {
			System.err.println("增加邮件附件:" + filename + "发生错误!" + e);
			return false;
		}
		return true;
	}

	/**
	 * 删除所有附件
	 * 
	 * @return
	 */
	public boolean delFileAffix() {
		try {
			FileDataSource fileds = null;
			for (Iterator<FileDataSource> it = files.iterator(); it.hasNext();) {
				fileds = it.next();
				if (fileds != null && fileds.getFile() != null) {
					fileds.getFile().delete();
				}
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/**
	 * 设置发件人地址
	 * 
	 * @param from
	 *            发件人地址
	 * @return
	 */
	private boolean setFrom(String from) {
		try {
			mimeMsg.setFrom(new InternetAddress(from));
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/**
	 * 设置收件人地址
	 * 
	 * @param to收件人的地址
	 * @return
	 */
	private boolean setTo(String to) {
		if (to == null)
			return false;
		try {
			mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/**
	 * 设置抄送
	 * 
	 * @param cc
	 * @return
	 */
	private boolean setCC(String cc) {
		if (cc == null) {
			return false;
		}
		try {
			mimeMsg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc));
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/**
	 * 发送邮件
	 * 
	 * @return
	 */
	public boolean send() throws Exception {
		mimeMsg.setContent(mp);
		mimeMsg.saveChanges();
		System.out.println("正在发送邮件....");
		Transport transport = session.getTransport("smtp");
		// 连接邮件服务器并进行身份验证
		transport.connect(smtpHost, sendUserName, sendUserPass);
		// 发送邮件
		transport.sendMessage(mimeMsg, mimeMsg.getRecipients(Message.RecipientType.TO));
		System.out.println("发送邮件成功!");
		transport.close();
		return true;
	}
}



我自己写的一个封装的Email类,提供了两个静态的方法获取实体,send方法用来发送邮件,附上测试代码

import java.util.Arrays;
import java.util.List;

import org.junit.Test;

import smok.springmvc.model.Email;

public class EmailTest {

	@Test
	public void sendEmail() throws Exception {
		String userName = "[email protected]"; // 发件人邮箱
		String password = "********"; // 发件人密码
		String smtpHost = "smtp.qq.com"; // 邮件服务器

		String to = "[email protected]"; // 收件人,多个收件人以半角逗号分隔
		String cc = "[email protected]"; // 抄送,多个抄送以半角逗号分隔
		String subject = "这是邮件的主题"; // 主题
		String body = "这是邮件的正文"; // 正文,可以用html格式的哟
		List<String> attachments = Arrays.asList("D:\\tmp\\1.png", "D:\\tmp\\2.png"); // 附件的路径,多个附件也不怕

		Email email = Email.entity(smtpHost, userName, password, to, cc, subject, body, attachments);

		email.send(); // 发送!
	}

}

直接粘代码可是会报错的,这里边依赖了几个包,我把pom也放上来

	<span style="white-space:pre">	</span><dependency>
			<groupId>javax.mail</groupId>
			<artifactId>javax.mail-api</artifactId>
			<version>1.5.2</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>com.sun.mail</groupId>
			<artifactId>smtp</artifactId>
			<version>1.5.2</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>com.sun.mail</groupId>
			<artifactId>mailapi</artifactId>
			<version>1.5.2</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.9</version>
			<scope>test</scope>
		</dependency>


到这里应该已经解决了开头提到的三个问题了

1、发送邮件,ok

2、发送给多个人,只有以半角逗号分隔收件人就可以了,抄送也是一样的方式

3、发送附件,只要有文件的全路径,发送多个文件也没问题呀~


总算是把发邮件这个事情搞定了,以后遇到cover不到的情况再来补充。


你可能感兴趣的:(java)