JavaMail邮件发送解析

  电子邮件的应用非常广泛,例如在某网站注册了一个账户,自动发送一封欢迎邮件,通过邮件找回密码,自动批量发送活动信息等。电子邮件在网络中传输和网页一样需要遵从特定的协议,常用的电子邮件协议包括 SMTP,POP3,IMAP。其中邮件的创建和发送只需要用到 SMTP协议,所有本文也只会涉及到SMTP协议。SMTP 是 Simple Mail Transfer Protocol 的简称,即简单邮件传输协议。在邮件寄送方面,Java EE的解决方案是JavaMail,本文简要介绍JavaMail的使用。

   要使用JavaMail进行邮件传送,首先必须创建代表当次邮件会话的javax.mail.Session对象,Session中包括了SMTP邮件服务器地址、连接端口、用户名、密码等信息。以连接163邮件为例,可以创建Session对象:

properties = new Properties();
// 设置发送邮件的邮件服务器的属性(这里使用网易的smtp服务器)
properties.put("mail.smtp.host", "smtp.163.com");
properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.smtp.socketFactory.fallback", "false");
properties.setProperty("mail.smtp.port", "465");
properties.setProperty("mail.smtp.socketFactory.port", "465");
// 需要经过授权,也就是有户名和密码的校验,这样才能通过验证
properties.setProperty("mail.smtp.auth", "true");
Session session = Session.getDefaultInstance(properties,
    new Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
    });

  其中username必须是163邮箱的用户名,password必须是163邮件的授权码,所以163邮箱必须开启POP3/SMTP服务和IMAP/SMTP服务,因为程序属于第三方登录(类似于Foxmail这样的第三方邮件客户端),所以登录密码必须使用163的授权码。

  在取得代表当次邮件传送会话的Session对象之后,接着要创建邮件信息,设定发信人、收信人、主题、传送日期与邮件本文:

Message message = new MimeMessage(session);
// 加载发件人地址
message.setFrom(new InternetAddress(from));
// 加载收件人地址
message.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
// 加载标题
message.setSubject(subject);
message.setSentDate(new Date());
message.setText(text);

  最后再以javax.mail.Transport的静态send()方法传送信息:

Transport.send(message);

1、设置实验邮箱

  登录自己的163邮箱,进入设置菜单,开启 POP3/SMTP服务和IMAP/SMTP服务的结果如图所示。

  点击左侧导航栏里的客户端授权密码,可以设置授权码。

2、发送纯文字邮件

  首先创建一个Dynamic Web Project,把下载好的mail.jar 作为类库加入工程,这里不多说。

  简单的邮件发送网页:

  Servlet代码:

package cc.openhome;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(
        urlPatterns = { "/mail.do" }, 
        initParams = { 
                @WebInitParam(name = "mailHost", value = "smtp.163.com"), 
                @WebInitParam(name = "mailPort", value = "465"), 
                @WebInitParam(name = "username", value = "xxxx@163.com"), 
                @WebInitParam(name = "password", value = "xxxxx")
        })
public class MailServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private String mailHost;
    private String mailPort;
    private String username;
    private String password;
    private Properties properties;

    @Override
    public void init() {
        mailHost = getServletConfig().getInitParameter("mailHost");
        mailPort = getServletConfig().getInitParameter("mailPort");
        username = getServletConfig().getInitParameter("username");
        password = getServletConfig().getInitParameter("password");
        properties = new Properties();
        // 设置发送邮件的邮件服务器的属性(这里使用网易的smtp服务器)
        properties.put("mail.smtp.host", mailHost);
        properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        properties.setProperty("mail.smtp.socketFactory.fallback", "false");
        properties.setProperty("mail.smtp.port", mailPort);
        properties.setProperty("mail.smtp.socketFactory.port", mailPort);
         // 需要经过授权,也就是有户名和密码的校验,这样才能通过验证(一定要有这一条)
        properties.setProperty("mail.smtp.auth", "true");
    }

    public MailServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        String from = request.getParameter("from");
        String to = request.getParameter("to");
        String subject = request.getParameter("subject");
        String text = request.getParameter("text");

        try {
            Message message = getMessage(from, to, subject, text);
            Transport.send(message);
            response.getWriter().println("<h1>邮件发送成功</h1>");
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }

    private Message getMessage(String from, String to, String subject, String text) throws AddressException, MessagingException {
        // PS_02: 连接失败的原因通常为以下几点, 仔细检查代码:
        // (1) 邮箱没有开启 SMTP 服务;
        // (2) 邮箱密码错误, 例如某些邮箱开启了独立密码;
        // (3) 邮箱服务器要求必须要使用 SSL 安全连接;
        // (4) 请求过于频繁或其他原因, 被邮件服务器拒绝服务;
        // (5) 如果以上几点都确定无误, 到邮件服务器网站查找帮助。
        Session session = Session.getDefaultInstance(properties,new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        });
         // 设置为debug模式,  可以在控制台上看到发送邮件的过程
        session.setDebug(true);   
        Message message = new MimeMessage(session);
        // 加载发件人地址
        message.setFrom(new InternetAddress(from));
         // 加载收件人地址
        message.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
        // 加载标题
        message.setSubject(subject);
        message.setSentDate(new Date());
        message.setText(text);
        return message;
    }
}

  在这个Servlet中,将连接SMTP基本信息设定为Servlet初始参数,并且在init()方法中,设定好创建Session对象的必要属性。

  发送邮件成功的网页如图所示:

  收到的测试邮件如图所示:

3、发送多重内容邮件

  如果邮件可以包括HTML或附加文件等多重内容,则必须要有javax.mail.Multipart对象,并在这个对象中增加代表多重内容的javax.mail.internet.MimeBodyPart对象。举个例子来说,如果要让邮件内容包括HTML内容,则可以如下:

// 处理HTML内容
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(text, "text/html;charset=UTF-8");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(htmlPart);
message.setContent(multipart);

  如果邮件要附加文件,则可以创建MimeBodyPart,设定文件名与内容之后,再加入MultiPart中:

byte [] file=...;
MimeBodyPart filePart = new MimeBodyPart();
filePart.setFileName(MimeUtility.encodeText(filename, "UTF-8", "B"));
filePart.setContent(file,part.getContentType());

  在使用MimeBodyPart的setFileName()设定附件名称时,必须做Mime编码,所以借助MimeUtility.encodeText()方法,在使用setContent()设定内容时,还需指定内容类型。

  简单的多重内容邮件发送网页:

  Servlet代码:

package cc.openhome;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
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;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeUtility;


@MultipartConfig
@WebServlet(
        urlPatterns = { "/multipart.do" }, 
        initParams = { 
            @WebInitParam(name = "mailHost", value = "smtp.163.com"), 
            @WebInitParam(name = "mailPort", value = "465"), 
            @WebInitParam(name = "username", value = "xxxx@163.com"), 
            @WebInitParam(name = "password", value = "xxxxx")
        })
public class MultiPartMailServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private String mailHost;
    private String mailPort;
    private String username;
    private String password;
    private Properties properties;

    @Override
    public void init() {
        mailHost = getServletConfig().getInitParameter("mailHost");
        mailPort = getServletConfig().getInitParameter("mailPort");
        username = getServletConfig().getInitParameter("username");
        password = getServletConfig().getInitParameter("password");

        properties = new Properties();
        // 设置发送邮件的邮件服务器的属性(这里使用网易的smtp服务器)
        properties.put("mail.smtp.host", mailHost);
        properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        properties.setProperty("mail.smtp.socketFactory.fallback", "false");
        properties.setProperty("mail.smtp.port", mailPort);
        properties.setProperty("mail.smtp.socketFactory.port", mailPort);
         // 需要经过授权,也就是有户名和密码的校验,这样才能通过验证(一定要有这一条)
        properties.setProperty("mail.smtp.auth", "true");
    }

    public MultiPartMailServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        String from = request.getParameter("from");
        String to = request.getParameter("to");
        String subject = request.getParameter("subject");
        String text = request.getParameter("text");
        Part part = request.getPart("file");

        try {
            Message message = getMessage(from, to, subject, text, part);
            Transport.send(message);
            response.getWriter().println("<h1>邮件发送成功</h1>");
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }

    private Message getMessage(String from, String to, String subject, String text, Part part) throws AddressException, MessagingException, IOException {
        Session session = Session.getDefaultInstance(properties,new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        });
         // 设置为debug模式,  可以在控制台上看到发送邮件的过程
        session.setDebug(true);   
        Message message = new MimeMessage(session);
        // 加载发件人地址
        message.setFrom(new InternetAddress(from));
         // 加载收件人地址
        message.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
        // 加载标题
        message.setSubject(subject);
        message.setSentDate(new Date());
        // 处理HTML内容
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(text, "text/html;charset=UTF-8");
        Multipart multipart = new MimeMultipart();
        multipart.addBodyPart(htmlPart);
        //如果有上传文件,就可以取得文件名,处理文件内容
        String filename = getFilename(part);
        if(!"".equals(filename)) {
            MimeBodyPart filePart = new MimeBodyPart();
            filePart.setFileName(MimeUtility.encodeText(filename, "UTF-8", "B"));
            filePart.setContent(getBytes(part), part.getContentType());
            multipart.addBodyPart(filePart);
        }
        message.setContent(multipart);

        return message;
    }

    private String getFilename(Part part) {
        String header = part.getHeader("Content-Disposition");
        String filename = header.substring(header.indexOf("filename=\"") + 10, header.lastIndexOf("\""));
        return filename;
    }

    private byte[] getBytes(Part part) throws IOException {
        InputStream in = part.getInputStream();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length = -1;
        while((length = in.read(buffer)) != -1) {
            out.write(buffer, 0, length);
        }
        in.close();
        out.close();
        return out.toByteArray();
    }
}

  成功收到的邮件如图所示:

  由于窗体会以multipart/form-data类型送出,在Servlet3.0中,如果要使用HttpServletRequest的getPart()等方法,必须加注@MultipartConfig。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值