本文主要解决以下问题:
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 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(); // 发送! } }
<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不到的情况再来补充。