JavaMail发送邮件和附件(源码)-程序员宅基地

技术标签: 邮件服务器  string  session  javamail  javaEE  user  properties  

JavaMail是Sun发布的处理电子邮件的应用程序接口,它预置了一些最常用的邮件传送协议的实现方法,并且提供了很容易的方法去调用它们。JavaMail是Sun发布的应用程序接口,所以目前它还没有被JDK包含。因此你需要从Sun的官方网站上下载到JavaMail类文件包。除此之外还需要Sun的JAF(JavaBeans Activation Framework ),否则JavaMail将不能运行。

核心JavaMail API 由七个类组成:Session 、Message 、Address 、Authenticator 、Transport 、Store 及 Folder ,它们都来自javax.mail 、即JavaMail API 顶级包。可以用这些类完成大量常见的电子邮件任务,包括发送消息、检索消息、删除消息、认证、回复消息、转发消息、管理附件、处理基于HTML文件格式的消息以及搜索或过滤邮件列表。有关JavaMail 的更多信息,请参考JavaMail 指南。

 

JavaMail的基础知识

使用JavaMail是发送电子邮件所需要的组件 。

JavaMail的机构使处理电子邮件非常容易。下面列出了一些我们需要的类:

1.Properties

JavaMail需要Properties来创建一个session对象。它将寻找字符串"mail.smtp.host",属性值就是发送邮件的主机,如:

Properties props = new Properties ();

props.put("mail.smtp.host", "smtp.sina.com"); // 可以换上你的smtp主机名。

props.put("mail.smtp.auth", "true"); // 身份验证,目前免费邮件服务器都需要这一项

2.Session

这个Session类代表JavaMail中的一个邮件会话。每一个基于JavaMail的应用程序至少有一个Session(可以有任意多的Session)。在这个例子中,Session对象需要知道用来处理邮件的SMTP服务器。为了做到这一点,你可以参照下面的例子用Properties 来创建一个Session 对象

Session session = Session.getDefaultInstance(props, null);

3.Transport

邮件是既可以被发送也可以被受到。JavaMail使用了两个不同的类来完成这两个功能:Transport 和 Store。 Transport 是用来发送信息的,而Store用来收信。对于这的教程我们只需要用到Transport对象。Store的用法请参看Sun的JavaMail文档。

用法:Transport transport = session.getTransport("smtp");

用JavaMail Session对象的getTransport 方法来初始化Transport。传过去的字符串申明了对象所要使用的协议,如"smtp"。这将为我们省了很多时间。因为JavaMail已经内置了很多协议的实现方法。

注意: JavaMail并不是绝对支持每一个协议,目前支持IMAP、 SMTP和 POP3。

4.Message

Message对象将存储我们实际发送的电子邮件信息,Message对象被作为一个MimeMessage对象来创建并且需要知道应当选择哪一个JavaMail session。

使用方法是:Message message = new MimeMessage(session);

 

邮件乱码问题:

JavaMail中的邮件主题需要进行BASE64编码,格式形如:=?GBK?B?xPq1xMPcwuvS0b6t1tjWw6Osx+u+ob/stcfCvKOssqLQ3rjEw9zC66Oh?=

所以,直接使用message.setSubject("中文主题"),或者message.setSubject("中文主题".getBytes ("ISO-8859-1"), "GBK"))都一样会出现乱码。在设置邮件主题前需要将主题字串的字节编码为BASE64格式,并添加编码头,示例代码如下:

sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();

msg.setSubject("=?GBK?B?"+enc.encode(subject.getBytes())+"?=");

 

邮件发送源码:

 

SendMail.java

package com.lzw.mail;

 

import java.util.Arrays;

import java.util.Date;

import java.util.Properties;

 

import javax.activation.DataHandler;

import javax.activation.DataSource;

import javax.activation.FileDataSource;

import javax.mail.Address;

import javax.mail.Authenticator;

import javax.mail.BodyPart;

import javax.mail.Message;

import javax.mail.MessagingException;

import javax.mail.Multipart;

import javax.mail.NoSuchProviderException;

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 com.lzw.io.Out;

/**

 * 邮件发送程序

 * @author 李赵伟 Create: 2007-12-19

 */

public class SendMail {

    private Session session;        //会话

    private Transport transport;    //发送邮件

 

    private User user;                 //邮件相关的帐户信息

    private MailAddress mailAddress;   //收件人地址

    private MailBody mailBody;         //邮件内容

    private final String MAIL_SMTP_HOST = "mail.smtp.host";

    private final String MAIL_SMTP_AUTH = "mail.smtp.auth";

 

    public SendMail(User user) {

       this.user = user;

       init();

    }

 

    /**

     * 初始化<code> Session, Transport </code>

     */

    private void init() {

       Authenticator auth = new Authenticator() {

           protected PasswordAuthentication getPasswordAuthentication() {

              return new PasswordAuthentication(user.getUsername(), user

                     .getPassword());

           }

       };

 

       Properties props = new Properties();

       // 设置发送邮件的邮件服务器的属性(这里使用网易的smtp服务器)

       props.put(MAIL_SMTP_HOST, user.getHost());

       // 需要经过授权,也就是有户名和密码的校验,这样才能通过验证(一定要有这一条)

       props.put(MAIL_SMTP_AUTH, "true");

       // 用刚刚设置好的props对象构建一个session

       session = Session.getDefaultInstance(props, auth);

       try {

           // 发送邮件

           transport = session.getTransport("smtp");

           // 连接服务器的邮箱

           transport.connect(user.getHost(), user.getUsername(), user

                  .getPassword());

       } catch (NoSuchProviderException e) {

           e.printStackTrace();

       } catch (MessagingException e) {

           e.printStackTrace();

       }

       Out.pln("与 " + user.getHost() + " 成功建立会话");

    }

 

    /**

     * 设置收件人地址

     *

     * @param mailAddress

     */

    public void setAddress(MailAddress mailAddress) {

       this.mailAddress = mailAddress;

    }

 

    /**

     * 设置邮件内容

     *

     * @param mailBody

     */

    public void setMailBody(MailBody mailBody) {

       this.mailBody = mailBody;

    }

 

    /**

     * 构造邮件的内容

     *

     * @return

     * @throws AddressException

     * @throws MessagingException

     */

    private Message createMessage() throws AddressException, MessagingException {

       // 用session为参数定义消息对象

       MimeMessage message = new MimeMessage(session);

       // 加载发件人地址

       message.setFrom(new InternetAddress(user.getFrom()));

       message.setSentDate(new Date());

       // 加载收件人地址

       message.addRecipients(Message.RecipientType.TO, getAddress(mailAddress

              .getTo()));

       if (mailAddress.isHasCC())

           message.addRecipients(Message.RecipientType.CC,

                  getAddress(mailAddress.getCc()));

 

       // 加载标题

       message.setSubject(mailBody.getSubject());

 

       if (mailBody.isContentFlag() || mailBody.isAffixFlag()) {

           // 向multipart对象中添加邮件的各个部分内容,包括文本内容和附件

           Multipart multipart = new MimeMultipart();

 

           if (mailBody.isContentFlag()) {

              // 设置邮件的文本内容

              MimeBodyPart contentPart = new MimeBodyPart();

              if (mailBody.isMimeContent())

                  contentPart.setContent(mailBody.getContent(),

                         "text/html;charset=GBK");

              else

                  contentPart.setText(mailBody.getContent());

              multipart.addBodyPart(contentPart);

           }

 

           if (mailBody.isAffixFlag()) {

              // 添加附件

              BodyPart affixBody = new MimeBodyPart();

              DataSource source = new FileDataSource(mailBody.getAffix());

              // 添加附件的内容

              affixBody.setDataHandler(new DataHandler(source));

              // 添加附件的标题这里很重要,通过下面的Base64编码的转换可以保证你的

              // 中文附件标题名在发送时不会变成乱码

              sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();

              String fileName = "=?GBK?B?"

                     + enc.encode(mailBody.getAffixName().getBytes()) + "?=";

              affixBody.setFileName(fileName);

              multipart.addBodyPart(affixBody);

           }

 

           // 将multipart对象放到message中

           message.setContent(multipart);

       }

       // 保存邮件

       message.saveChanges();

       return message;

    }

 

    /**

     * 发送邮件,包含:邮件正文、(1个附件)

     *

     * @param debug

     *            调试设置

     */

    public void send(boolean debug) {

       // 有了这句便可以在发送邮件的过程中在console处显示过程信息,供调试使

       // 用(你可以在控制台(console)上看到发送邮件的过程)

       session.setDebug(debug);

       try {

           Message message = createMessage();

           transport.sendMessage(message, message.getAllRecipients());

       } catch (AddressException e) {

           e.printStackTrace();

       } catch (MessagingException e) {

           e.printStackTrace();

       }

 

       Out.pln("/n----------------------------------------------------------");

       Out.pln("- 邮件成功发送!");

       Out.pln("- TO : " + Arrays.toString(mailAddress.getTo()));

       if (mailAddress.isHasCC())

           Out.pln("- CC : " + Arrays.toString(mailAddress.getCc()));

       Out.pln("----------------------------------------------------------/n");

    }

 

    /**

     * 关闭资源

     *

     * @throws MessagingException

     */

    public void close() throws MessagingException {

       if (null != transport)

           transport.close();

    }

 

    public Address[] getAddress(String[] address) throws AddressException {

       Address[] addrs = new InternetAddress[address.length];

       for (int i = 0; i < address.length; i++)

           addrs[i] = new InternetAddress(address[i]);

       return addrs;

    }

 

    /**

     * 测试

     */

    public static void main(String[] args) {

       String host = "smtp.sina.com";

       String username = "";

       String password = "";

       // String from = "";

       String to = "";

       // String cc = null;

       String subject = "测试";

       String content = "<a href=http://www.baidu.com>baidu</a>";

       boolean mimeContent = true;

       String affix = "d:/temp/temp.txt";

       String affixName = "temp.txt";

       boolean debug = false;

       // String userFile = "user.properties";

       // String addressFile = "mailaddress.properties";

 

       SendMail mail = null;

       try {

           try {

              User user = new User(host, username, password);

              MailAddress mailAddress = new MailAddress(to);

 

              // User user = new User(userFile);

              // MailAddress mailAddress = new MailAddress(SendMail.class

              // .getResourceAsStream(addressFile));

 

              MailBody mailBody = new MailBody(subject, content, mimeContent,

                     affix, affixName);

              mail = new SendMail(user);

              // for (int i = 0; i < 5; i++) {

              // 设置发件人地址、收件人地址和邮件标题

              mail.setAddress(mailAddress);

 

              // 设置要发送附件的位置和标题

              mail.setMailBody(mailBody);

              // 设置smtp服务器以及邮箱的帐号和密码

              mail.send(debug);

 

              // try {

              // Thread.sleep(1 * 1000);

              // } catch (InterruptedException e) {

              // e.printStackTrace();

              // }

              // mailBody = new MailBody(subject + "_" + (i + 1), content);

              // }

 

           } finally {

              if (null != mail)

                  mail.close();

           }

       } catch (AddressException e) {

           e.printStackTrace();

       } catch (MessagingException e) {

           e.printStackTrace();

           // } catch (IOException e) {

           // e.printStackTrace();

       }

    }

}


使用JavaMail发送邮件需要注意的地方:

使用免费的邮件服务器发送邮件时,需要对用户的身份做验证;而进行身份验证的过程又比较消耗时间,当用户需要发送多封邮件时如果每次都做身份验证的话时间的消耗是非常大的;

在整个邮件发送过程中Session(会话)的建立只需要一次,也就是说身份验证也只做一次就可以了,即Session session = Session. getDefaultInstance(props, auth);

发送邮件的过程相对比较简单,有一个需要注意的地方就是连接邮件服务器时transport.connect(user.getHost(), user.getUsername(), user.getPassword());也只需要执行一次即可,这个过程和身份验证一样都需要消耗大量时间。

该程序只允许发送带有一个附件的邮件;

文章出处:http://www.diybl.com/course/3_program/java/javajs/20071226/95325.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lenolong/article/details/3958201

智能推荐

VLAN以及三层交换机_核心交换机如何查询vlan-程序员宅基地

文章浏览阅读2k次,点赞2次,收藏7次。VLAN以及三层交换机1、VLAN概述与优势1.1vlan概述1.2vlan优势1.3VLAN的分类Trunk概述三层交换技术1、VLAN概述与优势1.1vlan概述VLAN(Virtual Local Area Network),中文称为虚拟局城网。是一组逻辑上隔离的设备和用户。这些设备和用户不受物理位置限制,可根据部门成组等进行灵活划分,保障信息安全。同时隔绝广播信息,提升网络效能,防止广播风暴的产生。1.2vlan优势1. 限制广播域。广播域被限制在一个VLAN内,提高了网络处理能力。 2_核心交换机如何查询vlan

clearTimeout无效_cleartimeout不生效-程序员宅基地

文章浏览阅读7.3k次。如图所示clearTimeout接受id作为参数,所以检查一下是否传入的不是id因为默认情况下setTimeout方法是会返回id但有时候会返回一个setTimeout对象比如使用vsCode 开发的同学在使用setTimeout时会自动引入timer对象,此时setTimeout就会返回Timeout对象,此时只需要将对应的id传入即可或者直接将引用注掉..._cleartimeout不生效

安卓发送post请求_android post-程序员宅基地

文章浏览阅读1.6k次。在HTTP通信中使用最多的就是GET和POST了,GET请求可以获取静态页面,也可以把参数放在URL字符串的后面,传递给服务器。本文将使用标准Java接口HttpURLConnection,以一个实例演示如何使用POST方式向服务器提交数据,并将服务器的响应结果显示在Android客户端。在Android中,提供了标准Java接口HttpURLConnection和Apache接口HttpClient,为客户端HTTP编程提供了丰富的支持。将提交的数据写入Log\Log.php文件中。_android post

中科大-凸优化 笔记(lec28)-多目标优化问题_如何用凸函数求解多目标问题-程序员宅基地

文章浏览阅读1.2k次。全部笔记的汇总贴(视频也有传送门):中科大-凸优化min⁡ts.t.AT(x)A(x)−t2I≤0t≥0  ⇔min⁡ts.t.  [tIA(x)AT(x)tI]⪰0t≥0  ⇔min⁡ts.t.    Y=[tIA(x)AT(x)tI](线性)Y⪰0(半正定)t≥0(线性)\min t\\s.t. A^T(x)A(x)-t^2I\le0\\t\ge0\\\;\\\Leftrightarrow \\\min t\\s.t.\;\left[ \begin{matrix}tI& A(x) \\A^_如何用凸函数求解多目标问题

【ROS进阶】常用函数——ros::ok(),ros::Rate,ros::spin()和ros::spinOnce()-程序员宅基地

文章浏览阅读8k次,点赞33次,收藏117次。(一)ros::ok()用于检查系统状态,适用于Publisher程序无限循环语法:while(ros::ok()){ //...}ros::ok()在以下几种情况下会返回false:1、按下Ctrl-C时。2、我们被一个同名同姓的节点从网络中踢出。3、ros::shutdown()被应用程序的另一部分调用。4、所有的ros::NodeHandles都被销毁了。5、一旦ros::ok()返回false,所有的ROS调用都会失败(二)ros::Rate用于设置循环频率,适用于P_ros::ok()

Java代码注释加入图片和表格_java注释里面如何用表格-程序员宅基地

文章浏览阅读4.2k次,点赞2次,收藏6次。注释中加入图片/** * <img width="宽度" height="高度" src="图片url" alt=""> */图片URL自行挑选。我这里使用了某开源库的图片url:/** * The following is the design idea of this class: * <img width="640" height="320" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx_java注释里面如何用表格

随便推点

快速上手JDBC_jdbc url用于标识一个被注册的驱动程序,驱动程序管理器通过与这个url选择正确-程序员宅基地

文章浏览阅读793次。目录一、步骤二、ORM思想三、如何获取连接1.Driver接口实现类2.URL3.用户名和密码4.代码示例四、如何实现CRUD操作1.PreparedStatement 与 Statement ​2.ResultSet与ResultSetMetaData3.增删改代码示例(通用)4.查询代码示例(通用)一、步骤1.导入所需数据库的jar包,(这里以mysql为例)2.获取连接3.连接后进行CRUD操作二、ORM思想..._jdbc url用于标识一个被注册的驱动程序,驱动程序管理器通过与这个url选择正确

【安卓学习之第三方库】 Rxpay学习:支付宝微信支付-程序员宅基地

文章浏览阅读990次。█ 【安卓学习之第三方库】 Rxpay学习:支付宝微信支付█ 相关文章:【安卓学习之第三方库】库的使用2-jar类库的使用(以dom4j为例)和升级(以极光推送为例)【安卓学习之第三方库】 消息推送之极光推送【安卓学习之第三方库】 消息推送之阿里云推送 █ 读前说明:本文通过学习别人写demo,学习一些课件,参考一些博客,’学习相关知识,如果涉及侵权请告知本文只简单罗列相关的代码实现过程涉及到的逻辑以及说明也只是简单介绍,主要当做笔记,了解过程而已下载demo█ 在An_rxpay

#671. 优美!最长上升子序列、#736. 上帝的集合_优美!最长上升子序列-程序员宅基地

这篇文章是关于一个优美的问题:如何找出给定数组中最长的递增子序列。文章提出了解决这个问题的方法,并给出了相应的代码实现。

访谈:腾讯高级交互设计师C7210的十年设计路(上)-程序员宅基地

文章浏览阅读360次。人物专访介绍:艺名C7210,2005年毕业于东华大学信息管理与信息系统专业;2006至2008年于博客大巴(blogbus.com)任网页设计师;2009至2010年于Tom集团任前端工程师;2010至2013于大众点评网(dianping.com)任重构工程师后转岗交互设计师;2014年初加入腾讯ISUX任高级交互设计师至今。1,能聊聊您从网页设计师变成前端工程_c7210

fl2440模块学习——3G拨号上网_fl2440资料-程序员宅基地

文章浏览阅读1.8k次。本篇学习在fl2440开发板上添加3G无线拨号上网模块,实现上网。 所使用的3G模块为:SIMCOM的 SIM5360E,可以支持WCDMA/GSM,即联通2G/3G,移动2G。测试用的是联通卡。 先了解一下: WCDMA 是英文Wideband Code Division Multiple Access(宽带码分多址)的英文简称,是一种第三代无线通讯技术。目前是由国内的联通在做; GSM(_fl2440资料

ssm配置双数据源mysql,sqlserver_ssm sqlserver 数据源-程序员宅基地

文章浏览阅读972次,点赞2次,收藏7次。记录说明:项目使用Spring+SpringMVC+Mybatis框架,项目之前一直在使用mysql数据库,后因项目对接需要,配置多数据源增加sqlserver数据库。梳理一下相关的文件:1、pom.xml文件(使用的是maven管理工具)2、DataSource 接口注解文件3、DataSourceAspect 类文件4、DynamicDataSourceHolder 类文件5、Mu..._ssm sqlserver 数据源