`

多种方法使用Java发送电子邮件

    博客分类:
  • Java
阅读更多

多种方法使用Java发送电子邮件

     第一件我们需要知道的事情是,通用电子邮件库实际上是包裹在JavaMail外层的API,所以无论我们选择哪种API,我们都需要JavaMail库。您可能还需要JavaBeans激活框架(JavaBeans Activation Framework (JAF)),该框架将负责处理关于邮件选项的更复杂的内容。最后一个在购物列表上的就是通用电子邮件库(Commons Email),您需要从JAF中将JavaMail库中的mail.jarJAF中的activation.jar和通用电子邮件库中的commons-email-1.0.jar添加到classpath的设置中。

     我们现在已经拥有了支持部件的工具包,让我们从使用JavaMail发送简单的电子邮件开始讲解,我们将提出所有的设置放到一个单独的静态类MailSettings当中,这样做将在比较代码的时候容易些。

     在发送电子邮件之前,您还需要知道SMTP服务器的主机名,SMTP服务器是负责将您的邮件发送到外部世界去的机器。

     JavaMail使用了Session类的概念来保存诸如SMTP主机和认证的信息,主要想法是基于会话(Sessions)在Java虚拟机中可以被隔离,这可以阻止恶意代码窃取其他用户在其他会话中的信息,这些信息可能包括用户名和密码等认证信息。但是,您可能会说,在同一时间,我只在Java 虚拟机上运行一个应用程序,而且我相信我的代码。”JavaMail的目的是开发大型的邮件系统,它有一个具有复杂性的关联层,您可以绕过没有经验的用户,我们用以下的例子来说明:

Properties props=new Properties();
props.put("mail.smtp.host",MailSettings.smtpHost);
Session session=Session.getDefaultInstance(props,null);

     此处,并没有创建新的会话,您只是从会话工厂(session factory)中得到并通过Properties的实例来进行设置,我们只对SMTP主机进行了设置和传送,在得到默认的实例的同时创建了一个共享的会话,现在我们可以使用这个会话来创建邮件消息了。

Message message=new MimeMessage(session);

     JavaMail中有一个Message类,各种各样的消息都是它的子类,如果查看了JavaMailAPI,您会发现它只有一个子类: MimeMessageJavaMail是被设计为通用的电子邮件框架的,所以显然存在冗余的抽象。总之,我们已经使用会话创建了一个 MimeMessage,现在我们需要来填充这个消息。

message.setFrom(new InternetAddress (MailSettings.fromAddress, MailSettings.fromName));

     再次利用抽象,JavaMail有一个Address(地址)类,其他所有的地址类型皆源于此,但是我们现在只关心发送国际互联网的电子邮件,所以我们制造一个InternetAddress,这个地址用来表示电子邮件的来源和一个用于显示的个人名字。现自我们来设置邮件将发向何方。

message.setRecipient(Message.RecipientType.TO, new InternetAddress(MailSettings.toAddress));

     地址的抽象将再次出现,我们设定接收器和接收器的类型,从此处开始,至少纯文本的电子邮件可以稳定地传送了,我们只需要设定邮件的标题、信文并打上时间戳。

message.setSubject(MailSettings.messageSubject);
message.setText(MailSettings.messageBody1);
message.setSentDate(new Date());

     此时,我们已经准备好发送消息了。

Transport.send(message);

     这个对Transport类的调用将会去查找适当的会话,并找出如何发送消息,尽管这样做看上去有些不直观。当我们完成这一步的时候,我们的邮件就已经发送出去了。此时,我们还需要添加代码来捕获三种JavaMail可能抛出的异常,它们是AddressException MessagingExceptionUnsupportedEncodingException. 但这就是最基本的使用JavaMail发送邮件的方法。

     现在,让我们来看看如何使用Apache的通用电子邮件软件包(参见MailCommons.java)来完成同样的工作,通用电子邮件库是一系列类的集合,它们基于您所要发送的邮件类型,其中最简单的是SimpleEmail类,不需要建立任何会话或属性列表:

SimpleEmail email=new SimpleEmail();
email.setHostName(MailSettings.smtpHost);

     以上代码创建了我们的邮件并指定它通过我们选定的SMTP服务器发送,因为通用电子邮件库只处理国际互联网的电子邮件,所以就不必在创建InternetAddress实例上浪费时间了,我们可以简单地设定来源地址:

email.setFrom(MailSettings.fromAddress,MailSettings.fromName);

     我们只需要添加一个地址到收信人列表当中,而不是发送接收器的类型:

email.addTo(MailSettings.toAddress);

     同样,设定邮件的标题和信文与发送邮件都很简单。

email.setSubject(MailSettings.messageSubject);
email.setMsg(MailSettings.messageBody1);
email.send();

     我们所需要去捕获的异常只有EmailException这一种,所以,您应该可以看出通过隐藏所有的框架和会话管理,事情变得非常简单并且代码更容易阅读。

     当然,这是我们所能发送的最简单的电子邮件,我们假设SMTP服务器不需要认证,我们发送的邮件只有一个收件人,并没有发送邮件副本。让我们先来看看认证,SMTP认证(SMTP AUTH)需要用户名和密码来发送邮件,在JavaMail中(参见MailJavaMail2.java),需要创建一个认证者(Authenticator)来返回所需的认证证书:

class ForcedAuthenticator extends Authenticator {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(MailSettings.smtpUsername,
MailSettings.smtpPassword);
}
}

     当我们创建会话的时候,就给出这个认证者的一个实例。

Session session=Session.getDefaultInstance(props,new ForcedAuthenticator());

     然而,这里有一点要注意,这种做法将默认的会话绑定到了该认证者,因此您需要一个指向它的引用(reference)以再次取得这个会话。当然,您也可以转而使用Session.getInstance(),来创建一个唯一的不共享的实例,但是这将依靠您自己来管理会话的实例。

     现在让我们来看看如果使用通用电子邮件库的方法来进行认证(参见MailCommons2.java),您将只看到一行新的语句:

email.setAuthentication(MailSettings.smtpUsername,MailSettings.smtpPassword);这就解决了认证过程的所有痛苦。

     还有另外一种认证方式,那就是使用在邮件服务中的POP-before-SMTP,它并没有实现SMTP AUTH,其实SMTP AUTHSMTP之后的一种扩展,而POP-before-SMTP的工作方式则是将受密码控制的邮件接收者和发送邮件的能力进行绑定,只有当用户经过 POP协议访问某个受密码保护的POP邮件服务器一段时间之后,此用户才能够发送邮件。在JavaMail中,为了发送邮件,你需要编写打开POP信箱的代码,这将涉及JavaMail接收端的工作,我们将在下一篇文章中讲解相关内容;而对于通用电子邮件库来讲,事情就容易得多了:

email.setPopBeforeSMTP(true,popHost,popUsername,popPassword);

     这使您可以操作与POP-before-SMTP相关的所有功能,而根本不需要考虑处理与POP相关的工作。

     让我们再来看看如何设定邮件的抄送收件人,现在JavaMailMessage类有一个setRecipients方法,该方法可以接受一个 InternetAddress的数组,但这样做并不精巧,如果您已经有了一个储存电子邮件地址的字符串数组,那就可以结束这种复杂方法的考验。

ArrayList ccs=new ArrayList();
for(String s:MailSettings.ccAddresses) ccs.add(new InternetAddress(s));
message.setRecipients(Message.RecipientType.CC,
(InternetAddress[]) ccs.toArray(new InternetAddress[ccs.size()]));

     现在让我们来看看通用电子邮件库,我们发现了两件事情:首先,setTosetCcsetBcc方法都使用了InternetAddress的集合作为它们的参数,这样做更符合Java的现行实践;其次,addToaddCcaddBcc方法将创建和添加收件人列表变得轻松。(参见 MailCommons3.java

for(String s:MailSettings.ccAddresses) email.addCc(s);

     这样的代码更加清晰。

     最后,让我们来看看如何发送包含内嵌图片的HTML格式的电子邮件,在此,JavaBeans激活框架将与JavaMail将协同工作,来协助图片的编码。在JavaMailAPI中,我们首先创建一个MimeMultipart的实例,然后创建MimeBodyParts的实例,并将它们组装到MimeMultipart的实例中,所以,嵌入单个图片,比如uk-builder-com.gif这个图片文件,并将它显示在HTML消息中,我们需要完成以下步骤(参见HtmlJavaMail.java

MimeMultipart multipart=new MimeMultipart();
BodyPart msgBodyPart=new MimeBodyPart();
msgBodyPart.setContent("
H1Hi! From HtmlJavaMail/H1
img src=\"cid:logo\"","text/html");
BodyPart embedImage=new MimeBodyPart();
DataSource ds=new URLDataSource(new URL(MailSettings.inlineImage));
embedImage.setDataHandler(new DataHandler(ds));
embedImage.setHeader("Content-ID","");
multipart.addBodyPart(msgBodyPart);
multipart.addBodyPart(embedImage);
message.setContent(multipart);

     第一个BodyPart将它的内容设置为一个字符串和“text/html”的内容类型,注意,在我们设置的HTML代码中,IMG标签指向了一个内容标识符(content-id),这就是MIME(多用途互联网邮件扩充协议)消息部分的名称,该消息将含有GIF格式的标识图文件,为了嵌入这个图片,我们创建了另一个BodyPart和一个JAF的数据源(data source),JAF类库将负责管理内容的工作;然后我们将使用这个DataSourceBodyPart上添加一个DataHandler(数据处理器),这样就可以读出我们的URL所指向的内容了。最后,我们还要在BodyPart的头部设定Content-ID,这样它就可以作为内嵌图片被访问了。我们创建的那些BodyParts将被添加到MimeMultipart的实例中,为此,我们使用setContent()方法而不是调用 setText()方法。最棘手的部分莫过于管理这些内容标识符了,我们在此只完成了嵌入一个图片的工作,但今后每添加一个图片,您都需要在HTML中加入一个BodyPart和一个内容标识符。

     现在让我们来看看使用通用电子邮件库方法的版本(参见HtmlMailCommons.java):

HtmlEmail email=new HtmlEmail();…
String cid=email.embed(new URL(MailSettings.inlineImage),"Builder AU Logo");
email.setHtmlMsg("
H1Hi! From MailJavaMail3/H1><img src=\"cid:"+cid+"\"");
email.setTextMsg("Your email client does not support HTML messages, sorry");

     这种方法简短了很多,而且这一版本拥有更多的功能:当电子邮件客户端不能处理HTML时,它将显示备用的文字。我们从创建一个SimpleEmail实例改变为创建一个HtmlEmail实例。为了嵌入一个图片,我们只需要简单地调用HtmlEmail的嵌入方法,这将返回一个字符串,该字符串含有被生成和管理的内嵌图片内容标识符的信息,我们可以直接使用这些信息来生成HTML内容。我们只需要简单地对适当的字符串调用setHtmlMsg方法来进行设定,setTextMsg将设定不支持HTML的客户端所显示的文字,然后我们就可以发送邮件了。

     但是,到目前为止,您可能正在想直接使用JavaMail的意义是什么呢?答案是,如果您的目的是发送电子邮件,那么对于大多数情况,通用电子邮件库仅仅需要少量的复杂代码就可以完成您的需求,但是它连一点控制邮件会话和接收邮件的功能都没有,如果您的应用软件不需要大规模地进行邮件转换或邮件阅读的操作,那么应该不会造成不便。当然,如果您需要进行上述操作,那您就已经在使用JavaMail库了。这里唯一的一个警告就是,在我写这篇文章之时,通用电子邮件库发布的是1.0版本,其API中可能有一些缺陷和漏洞,但它确实可以工作。现在您应该没有借口不让您的应用软件在工作的时候发送状态邮件了。

 

分享到:
评论

相关推荐

    基于SpringBoot的企业oa管理系统(源码+数据库+万字文档)300

    企业oa管理系统,系统包含两种角色:管理员、用户,主要功能如下。 管理员: 1. 个人中心:管理管理员个人信息和进行相关操作。 2. 用户管理:管理用户的基本信息和权限设置。 3. 公告信息管理:发布和管理企业内部公告信息。 4. 客户关系管理:管理客户信息、跟进记录和销售机会等。 5. 通讯录管理:管理企业内部员工通讯录信息。 6. 日程安排管理:管理个人和团队的日程安排和会议安排。 7. 车辆信息管理:管理企业车辆的基本信息和使用情况。 8. 文件信息管理:管理企业内部文件的上传、下载和共享。 9. 工作日志管理:记录和管理员工的工作日志和任务完成情况。 10. 上班考勤管理:管理员工的上班打卡和考勤记录。 11. 工资信息管理:管理员工的工资信息和薪资发放。 用户: 1. 个人中心:管理个人信息和进行相关操作。 2. 公告信息管理:查看和阅读企业内部公告信息。 3. 客户关系管理:查看和管理与自己相关的客户信息和销售机会。 4. 通讯录管理:查找和查看企业内部员工通讯录信息。 5. 日程安排管理:查看和管理个人的日程安排和会议安排。 6. 车辆信息管理:查看和申请企业车辆的使

    Autox-v7-arm64-v8a-release-v7.1.2.apk

    AutoX.js 是一个基于 JavaScript 的自动化工具,主要用于安卓设备的自动化操作。它是 Auto.js 的一个分支,提供了更多的功能和更高的兼容性。以下是关于 AutoX.js 的一些基本介绍和使用方法。

    TypeScript全面进阶指南

    1.开篇:用正确的方式学习 TypeScript 2.工欲善其事:打造最舒适的 TypeScript 开发环境 3.进入类型的世界:理解原始类型与对象类型 4.掌握字面量类型与枚举,让你的类型再精确一些 5.函数与 Class 中的类型:详解函数重载与面向对象 6.探秘内置类型:any、unknown、never 与类型断言 7.类型编程好帮手:TypeScript 类型工具(上) 8.类型编程好帮手:TypeScript 类型工具(下) 9.类型编程基石:TypeScript 中无处不在的泛型 10.结构化类型系统:类型兼容性判断的幕后 11.类型系统层级:从 Top Type 到 Bottom Type 12.类型里的逻辑运算:条件类型与 infer 13.内置工具类型基础:别再妖魔化工具类型了! 14.反方向类型推导:用好上下文相关类型 15.数类型:协变与逆变的比较 16.了解类型编程与类型体操的意义,找到平衡点 17.内置工具类型进阶:类型编程进阶 18.基础类型新成员:模板字符串类型入门 19.类型编程新范式:模板字符串工具类型进阶 20.工程层面的类型能力:类型声明、类型

    3gpp-29504-j20.docx

    本文档是3GPP组织发布的关于5G系统中统一数据仓库服务(UDR)的技术规范,旨在为第三阶段(Relase 19)提供协议和数据模型的详细定义。该规范主要针对Nudr接口,规定了通过此接口NF服务消费 限时福利!送硅基流动100w deepseek token,支持api调用:https://cloud.siliconflow.cn/i/VkH0G5VX

    西门子G120 Vf和矢量控制的区别及相关参数设置

    西门子G120 Vf和矢量控制的区别及相关参数设置

    【宝城期货-2025研报】短期降息预期落空,国债期货震荡筑底.pdf

    【宝城期货-2025研报】短期降息预期落空,国债期货震荡筑底.pdf

    基于yolov5识别算法实现的DNF自动脚本源码.zip

    基于yolov5识别算法实现的DNF自动脚本源码.zip

    HR人力资源管理系统PersonManage

    HR人力资源管理系统PersonManage

    【宝城期货-2025研报】有色日报:有色午后走强,铜增仓上行.pdf

    【宝城期货-2025研报】有色日报:有色午后走强,铜增仓上行.pdf

    商城程序电脑端手机端微信端三合一板

    商城程序电脑端手机端微信端三合一板

    基于SpringBoot的个人理财系统(源码+数据库+万字文档)292

    个人理财系统,系统包含两种角色:管理员、用户,系统分为前台和后台两大模块,主要功能如下。 【管理员】: 个人中心:管理员可以在个人中心查看和修改自己的个人信息。 用户管理:管理员可以对用户进行管理,包括添加新用户、编辑用户信息、删除用户以及查看用户列表。 账单类型管理:管理员可以管理账单类型,包括添加新的账单类型、编辑账单类型信息、删除账单类型以及查看账单类型列表。 【用户】: 个人中心:用户可以在个人中心查看和修改自己的个人信息。 收入账单管理:用户可以添加和管理收入账单,包括记录收入的金额、时间、来源等信息,查看、编辑和删除已记录的收入账单。 支出账单管理:用户可以添加和管理支出账单,包括记录支出的金额、时间、用途等信息,查看、编辑和删除已记录的支出账单。 理财计划管理:用户可以制定和管理理财计划,包括设定目标、计划时间、计划金额等信息,查看、编辑和删除已设定的理财计划。 统计分析管理:用户可以查看自己的收入和支出情况的统计分析结果。 备忘录管理:用户可以添加、编辑和删除备忘录。 二、项目技术 编程语言:Java 数据库:MySQL 项目管理工具:Maven 前端技术Vue

    51-图解分布式训练(七)—— accelerate 分布式训练 详细解析.pdf

    面试题关注有更多资源,私信免费的

    【宝城期货-2025研报】宝城期货橡胶早报.pdf

    【宝城期货-2025研报】宝城期货橡胶早报.pdf

    20210928-以面向对象思想编写单片机程序.zip

    以面向对象思想编写单片机程序

    更新!中国各区县-平均风速数据(1951-2024年)

    ## 介绍 平均风速是描述一个地区风力强弱的重要气象指标,是指空间某一点,在给定的时段内各次观测的风速之和除以观测次数,其广泛应用于气候研究、农业、风能开发等领域 本分享数据包含中国各区县的平均风速数据,涵盖了1951年至2024年之间共21w+条数据,数据按年度进行整理 ## 一、中国各区县平均风速数据的介绍 数据年份:1951-2024年 数据范围:区县 数据格式:面板数据 样本数量:21万+ ## 二、数据指标

    Delphi 12.3控件之UPX-4.2.2(压缩exe文件).rar

    UPX_4.2.2(压缩exe文件).rar

    基于Python Tkinter的智能书库管理系统代码

    基于Python Tkinter的智能书库管理系统代码

    Tutorial Design of Smart Sensors-ISSCC2010.rar

    Tutorial Design of Smart Sensors-ISSCC2010.rar

    steam_appid.txt

    steam_appid

    基于双侧骶髂关节强直性脊柱炎的swinUNet、resunet、unet分割实验对比

    基于双侧骶髂关节强直性脊柱炎的swinUNet、resunet、unet分割实验对比,包含数据集和完整代码,可以一键运行 评估指标有dice、iou、recall、precision、特异度曲线等等

Global site tag (gtag.js) - Google Analytics