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

智能推荐

【JZOJ5262】【GDOI2018模拟8.12】树(DP,性质题)_gdoi2018省选模拟树-程序员宅基地

文章浏览阅读460次。DescriptionSolution首先我们可以知道两个性质:1、路径u-v和路径v-w可以合并为路径u-w;2、路径u1-v1加路径u2-v2和路径u1-v2加路径u2-v1是等价的(就是起始点和终点可以互换) 那么知道这些性质之后就很好做了。我们只用知道每个点多少次做起点和多少次做终点。 我们设f[i]表示满足i子树的需求i上的值要是多少。 那么枚举i的所有儿子,判断a[i]-f[i],_gdoi2018省选模拟树

[PTA]7-65 字符串替换 (15 分)含思路_字符串替换pta-程序员宅基地

文章浏览阅读2.8k次,点赞4次,收藏28次。我们进行简单的运算即可实现倒序。_字符串替换pta

linux网络设置_linux如何开启网络连接-程序员宅基地

文章浏览阅读4k次,点赞5次,收藏22次。traceroute 180.101.50.188————————测试到180.101.50.188有多少个网关。vim /etc/sysconfig/static-routes——————————修改。netstat -antp | grep 22———————查看端口号22的相关信息。systemctl restart network————————————重启。systemctl restart network————————重新启动。_linux如何开启网络连接

pr中,视频导入后,视频画面大小显示不完整应该如何解决?_avi视频到pr里会放大-程序员宅基地

文章浏览阅读4w次,点赞23次,收藏6次。本人pr小白,今天编辑视频时候遇到了问题,也解决了,所以分享记录一下。问题一视频下面原来有字幕的,可是导入的视频变大了,现在看不到了怎么办?还有就是,频导入之后画质好像变糊了又是为什么?解决:将箭头放到要编辑的视频那里,右击,然后点击设为帧大小这样完整的视频就出来了。问题二如果视频模糊,就是序列设置的不对 要先新建序列一般的都是1920×1080本人博客:https://blog.csdn.net/weixin_46654114本人b站求关注:https://space.bi_avi视频到pr里会放大

apollo中配置map,list_apollo list-程序员宅基地

文章浏览阅读1.8k次。注:key可以不用引号,value使用单引号,但key中存在_或-等一些特殊字符时,需要加上引号,避免出错。注:key可以不用引号,value也不用引号,但key中存在_或-等一些特殊字符时,需要加上引号,避免出错。注:使用@Value注解获取,apollo中未配置时默认为null。注:使用@Value注解获取,apollo中未配置时默认为null。2.apollo中的Map配置。1.apollo中的Map配置。注:使用逗号分隔,不用引号。..._apollo list

比最快的超级计算机快一百万亿倍!中国科学家实现“量子计算优越性”里程碑_中国科学院比马普所强-程序员宅基地

文章浏览阅读4.4k次,点赞22次,收藏12次。本文来自:中国科学技术大学公众号北京时间12月4日国际顶尖杂志《Science》刊发了中国科学技术大学潘建伟、陆朝阳等组成的研究团队的一项重磅研究成果让我们一起来看看吧!中国科学家实现“量子计算优越性”里程碑中国科学技术大学潘建伟、陆朝阳等组成的研究团队与中科院上海微系统所、国家并行计算机工程技术研究中心合作,构建了76个光子100个模式的量子计算原型机“九章”,实现了具有实用前景的“高斯玻色取样”任务的快速求解。根据现有理论该量子计算系统处理高斯玻色取样的速度比目前最快的超级计算机快一百万._中国科学院比马普所强

随便推点

java汉字拼音简码_java生成首字母拼音简码的总结-程序员宅基地

文章浏览阅读306次。百度找到了某论坛高人写的java(具体论坛记不清了),直接用来调用,再次非常感谢,基本上实现了我的需求package MD5;import java.util.Scanner;public class ChineseToPinYin {/*** 汉字转拼音缩写** @param str* 要转换的汉字字符串* @return String 拼音缩写*/public Strin..._java生成拼音码

C++ 数据结构——堆排序_数据结构堆排序c++-程序员宅基地

文章浏览阅读93次。/* 堆排序 */#include <iostream>using namespace std;int *data;void Sift(int k,int last){ int i,j,temp; i=k;j=2*i+1; while (j<=last) { if(j<last&&data[j]<data[j+1]) j++; if(data[i]>data[j]) _数据结构堆排序c++

debian 11 还不能进入命令行界面,按照网上的改也不行。_debian 无法打开命令行窗口-程序员宅基地

文章浏览阅读952次。再查查资料,有没有DEBIAN问题解答中心呢?_debian 无法打开命令行窗口

2345王牌输入法的卸载_89e1d5c2-a068-44b6-b820-f8406c8a4706-程序员宅基地

文章浏览阅读2.3k次,点赞3次,收藏10次。2345王牌输入法的卸载输入法卸载了也还有2345这个流氓输入法,研究3个小时找到了2345输入法在语言栏的根源所在,希望能帮到你windows键加R键打开运行,输入regedit 然后ctrl+F键 搜索下面路径,打开后就会看见语言栏里的输入法了,直接删除加粗这个文件夹,就删除了HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\CTF\TIP{0055AAB0-EACB-46DB-9BB4-1B97FC046D02}\LanguageProfile\0x00000804\ _89e1d5c2-a068-44b6-b820-f8406c8a4706

Android R setenforce 实现_android setenforce-程序员宅基地

文章浏览阅读2.2k次。1、开机启动system/core/init/main.cppint main(int argc, char** argv) {#if __has_feature(address_sanitizer) __asan_set_error_report_callback(AsanReportCallback);#endif if (!strcmp(basename(argv[0]), "ueventd")) { return ueventd_main(argc,._android setenforce

app_process: zygote启动(3)_app_process zygote-程序员宅基地

文章浏览阅读485次。涉及源码android-8.0.0_r1\system\core\rootdir\init.rcandroid-8.0.0_r1\system\core\rootdir\init.*.rcandroid-8.0.0_r1\frameworks\base\core\java\com\android\internal\os\Zygote.javaandroid-8.0.0_r1\frameworks\base\core\java\com\android\internal\os\ZygoteInit.ja_app_process zygote

推荐文章

热门文章

相关标签