一个java发送邮件的示例

简介

    前一段时间因为在项目中要实现一个用java发送邮件的功能,针对具体的实现情况,包含有专门搭建邮件服务器和配置邮件发送信息以及模板组织等若干个步骤。整个的功能实现比较简单,不过对于怎么在工程中用好他们,还是有必要的好好总结一下。

 

邮件发送基础

    在讨论发送具体邮件信息之前,我们先讨论一下邮件发送的一些基本概念。在很多情况下,我们发送邮件的时候,都是通过手动配置邮件客户端让它们连接到邮件服务器或者直接登录到一些网站查看邮件。实际上,他们无非是对应两种连接邮件服务器的客户端而已,一种是单机版的,一种是web版的。他们的本质还是所有发送的邮件消息提交给邮件服务器,再由邮件服务器转发到目的地。

    结合我们发送邮件的步骤,我们连接到邮件服务器并发送邮件的过程无非是以下几个步骤:

1. 连接邮件服务器,身份验证。

2. 选择或者设置收件人,主题和邮件内容等。

3. 选择发送邮件,邮件服务器将内容转发。

    另外一个就是,我们发送的邮件有多种协议,它们还分别对应不同的端口。比如如下是几个典型的邮件协议和对应的端口:

协议名端口号
POP3110
SMTP25
NNTP119

    在实际的应用中,它们的端口可能会根据需要进行调整。

    在我们的很多实际应用中,一般很少会需要直接配置邮件服务器,而是直接使用这些邮件服务器。尤其是对于许多免费的服务器来说,针对他们开放的端口和协议我们可以通过使用程序来实现和它们的交互,实现收发邮件。在讨论具体怎么配置邮件服务器之前,我们先讨论一下邮件发送的几种方式。

 

邮件发送的几种方式

    我们需要发送邮件的程序一般引用了javax.mail.jar包,这个包可以在如下的链接里找到。常用的邮件发送方式主要有TLS, SSL和default这几种。他们的主要差别在于TLS和SSL都是通过加密的方式进行数据通信,而default的则是没有加密的。所以默认的方式在大多数情况下都被禁用了。

TLS

    我们先看看一个TLS通信的简单示例,以gmail账户为例。假定我们有一个gmail的帐号,希望使用程序通过它发送邮件到一个指定的目的邮件地址。我们首先需要看一下gmail邮件服务器的相关设置信息:

配置项具体值
mail.smtp.authtrue
mail.smtp.starttls.enabletrue
mail.smtp.hostsmtp.gmail.com
mail.smtp.port587

    有了前面这些配置的信息,我们可以通过它们来和gmail邮件服务器通信。首先一个前面的这些内容将作为一个配置项传入给gmail smtp server。在我们的具体实现里可以将这部分写到一个配置文件里,然后读取出来,也可以手动的设置。

    手动设置的代码如下:

Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587");

    设置好这些属性之后下一步就是建立一个和邮件服务器连接的session了。采用这种方式需要提供用户名和密码信息。比如说我们已经有的gmail帐号为user@gmail.com, 密码为password。

那么建立session连接的代码如下:

   

Session session = Session.getInstance(props,
    new javax.mail.Authenticator() {
		protected PasswordAuthentication getPasswordAuthentication() {
			return new PasswordAuthentication(username, password);
		}
	  });

    设置好session之后的下一步就是设置我们需要发送的邮件内容等信息:

Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(username));
message.setRecipients(Message.RecipientType.TO,
    InternetAddress.parse("newuser@gmail.com"));
message.setSubject("Testing Subject");
message.setText("Dear user,"
    + "\n\n No spam to my email, please!");
 
Transport.send(message);

     我们设定收件人的邮件地址为newuser@gmail.com,邮件的主题为Testing Subject。真正实现发送邮件的这部分代码是Transport.send(),它将最后组装成的邮件字符串发送出去。

 

SSL

   SSL的发送方式其实和TLS大致相同,首先也是设置邮件发送的配置项,只是因为采用的协议和端口不一样,具体认证的方式也有差别。这里session的创建方式如下:

 

Session session = Session.getDefaultInstance(props,
    new javax.mail.Authenticator() {
	protected PasswordAuthentication getPasswordAuthentication() {
		return new PasswordAuthentication("abc@163.com","abc");
	}
});

    其他的代码基本上都是一样的,具体细节可以看附件里代码的详细实现。

    除了上述的两种方式,还有一种默认的邮件发送方式,因为它不是采用的通信加密,在一些本地局域网的测试环境里可能会用到。和前面的代码里主要的区别就在于它的创建session的方式很简单,一般不需要做任何身份验证,典型的代码实现如下:

Session session = Session.getDefaultInstance(props);

    这里的props就是环境的基本配置项,典型的如下:

mail.smtp.auth=false
mail.smtp.starttls.enable=false
mail.smtp.port=25
mail.smtp.host=localhost
username=
password=

 

环境安装和配置

    这里主要用到java邮件服务器james。其实我们可以使用的邮件服务器很多,比如postfix, sendmail。主要是james的安装配置比较简单。它的配置主要就以下几个步骤:

1. 安装jdk和jre

 

2. 安装james server并配置默认server名字等信息。

    安装james server比较简单,直接到官网下载整个的zip包到本地,然后解压就可以了。

    解压到本地之后,到本地目录的/james-2.3.2/apps/james/SAR-INF下面,打开config.xml文件。在这里配置邮箱的域名和服务器的名字。

<config>
   <James>
      <postmaster>support@abc.com</postmaster>

      <servernames autodetect="true" autodetectIP="true">

         <servername>abc.com</servername>
      </servernames>
   <James>
<config>

 

3. 配置环境变量JAVA_HOME

    将java安装环境的变量配置好,这个部分不同的系统和平台不一样,都可以参考网上的流程。

 

4. 启动James server

    在linux环境下启动james server的时候需要注意,因为考虑到发送邮件访问的权限。这里需要切换到具有管理员权限的帐号下然后再启动它们。

    启动的命令如下:./bin/run.sh

    启动后的界面如下图:

 

邮件内容组织

    我们从前面的代码内容里可以看到,javamail里发送的最后都是字符串。可是在我们实际发送的邮件里,可以包含有文件各种格式定义,甚至很多html的元素,这是怎么做到的呢?实际上这些是和做web应用的思想很类似。我们常用的web框架强调的是各种关注点分离,所以才有了MVC的结构思想。在邮件内容的输出里,我们也可以实现一种分离。我们将邮件需要发送的内容和内容组织的形式进行分离。这样,我们只需要在代码里将要显示的内容发送给模板,而在模板的组织里具体实现怎么来显示这些内容。

    同时,为了实现对我们定义的这种类型格式的支持,我们需要在发送的email message里设置一下:

message.setContent(content, "text/html")

我们常用的一个实现这种内容和组织形式的分离的工具就是velocity。我们可以在如下链接中下载它。

    我们实现模板解析的代码如下:

public String prepareMessage(MessagePayload payload, String templatePath) {
		if(payload == null || StringUtil.isNullOrEmpty(templatePath)) {
			throw new IllegalArgumentException("Invalid payload or template path.");
		}
		VelocityEngine engine = new VelocityEngine();
		engine.init();				
		VelocityContext context = new VelocityContext();
	    context.put("payload", payload);
	    Template t = engine.getTemplate(templatePath);
	    StringWriter writer = new StringWriter();
        t.merge( context, writer );
	    
		return writer.toString();
	}

     大家可以看到,在这部分代码里,无非就是将我们传入的MessagePayload对象揉合到模板中,并返回最终的字符串。那么这些我们传入的对象是怎么在模板里被处理的呢?我们来看看模板里的具体内容:

 

<html>
	<head>
		<title>Order Candy Service</title>
	</head>
	<body>
		<p>User $payload.getUserId() has successfully requested to order the stuff:
		#set($mpcInstance = $payload.getInstancePayload())
		#if(!$payload.isOrderForSelf())
		for user: $payload.getCustName()
		#end
		with the following information:<p> 
		Account Name: $payload.getAcctName() <br>
		Instance Name: $mpcInstance.getName() <br>
		#set($candyNumber = $mpcInstance.getCandies().size() / 10.0)
		Number of Candies: $candyNumber <br>
		<p>Best regards.<br>
		Candy Shop Team<br>
	</body>
</html>

   除了那些常用的html元素,我们看到了一些类似于常用编程语言的元素,比如#if, #set等。这些都是velocity里支持的模板语言。所以如果我们传入的是一个个的java对象,它也能够解析,就像我们使用普通的java对象一样。这样关于怎么判断和组织内容就通过这个模板语言解决了。如果使用过其他编程语言的web框架的,比如python之类的,对于这些东西应该就不会陌生了。

 

总结

    一个发送邮件的功能一般包含有配置邮件发送的协议,端口,邮件的发件人,收件人以及邮件内容等。如果我们希望能够很好的组织起来每个部分,需要针对每个不同的需求选择最合适的工具,这样对于长期的管理和维护来说也省了很多事。

 

参考材料

http://james.apache.org/server/

http://www.ibm.com/developerworks/library/j-james1/

http://velocity.apache.org/

用于Java邮件发送一个类方法 Java邮件发送类 这是第一部分第一个类:MailSenderInfo.java 1. package com.util.mail; 2. /** 3. * 发送邮件需要使用的基本信息 4. */ 5. import java.util.Properties; 6. public class MailSenderInfo { 7. // 发送邮件的服务器的IP和端口 8. private String mailServerHost; 9. private String mailServerPort = "25"; 10. // 邮件发送者的地址 11. private String fromAddress; 12. // 邮件接收者的地址 13. private String toAddress; 14. // 登陆邮件发送服务器的用户名和密码 15. private String userName; 16. private String password; 17. // 是否需要身份验证 18. private boolean validate = false; 19. // 邮件主题 20. private String subject; 21. // 邮件的文本内容 22. private String content; 23. // 邮件附件的文件名 24. private String[] attachFileNames; 25. /** 26. * 获得邮件会话属性 27. */ 28. public Properties getProperties(){ 29. Properties p = new Properties(); 30. p.put("mail.smtp.host", this.mailServerHost); 31. p.put("mail.smtp.port", this.mailServerPort); 32. p.put("mail.smtp.auth", validate ? "true" : "false"); 33. return p; 34. } 35. public String getMailServerHost() { 36. return mailServerHost; 37. } 38. public void setMailServerHost(String mailServerHost) { 39. this.mailServerHost = mailServerHost; 40. } 41. public String getMailServerPort() { 42. return mailServerPort; 43. } 44. public void setMailServerPort(String mailServerPort) { 45. this.mailServerPort = mailServerPort; 46. } 47. public boolean isValidate() { 48. return validate; 49. } 50. public void setValidate(boolean validate) { 51. this.validate = validate; 52. } 53. public String[] getAttachFileNames() { 54. return attachFileNames; 55. } 56. public void setAttachFileNames(String[] fileNames) { 57. this.attachFileNames = fileNames; 58. } 59. public String getFromAddress() { 60. return fromAddress; 61. } 62. public void setFromAddress(String fromAddress) { 63. this.fromAddress = fromAddress; 64. } 65. public String getPassword() { 66. return password; 67. } 68. public void setPassword(String password) { 69. this.password = password; 70. } 71. public String getToAddress() { 72. return toAddress; 73. } 74. public void setToAddress(String toAddress) { 75. this.toAddress = toAddress; 76. } 77. public String getUserName() { 78. return userName; 79. } 80. public void setUserName(String userName) { 81. this.userName = userName; 82. } 83. public String getSubject() { 84. return subject; 85. } 86. public void setSubject(String subject) { 87. this.subject = subject; 88. } 89. public String getContent() { 90. return content; 91. } 92. public void setContent(String textContent) { 93. this.content = textContent; 94. } 95. } 第二部分第二个类:SimpleMailSender.java Java代码 1. package com.util.mail; 2. 3. import java.util.Date; 4. import java.util.Properties; 5. import javax.mail.Address; 6. import javax.mail.BodyPart; 7. import javax.mail.Message; 8. import javax.mail.MessagingException; 9. import javax.mail.Multipart; 10. import javax.mail.Session; 11. import javax.mail.Transport; 12. import javax.mail.internet.InternetAddress; 13. import javax.mail.internet.MimeBodyPart; 14. import javax.mail.internet.MimeMessage; 15. import javax.mail.internet.MimeMultipart; 16. 17. /** 18. * 简单邮件(不带附件的邮件发送器 19. */ 20. public class SimpleMailSender { 21. /** 22. * 以文本格式发送邮件 23. * @param mailInfo 待发送邮件的信息 24. */ 25. public boolean sendTextMail(MailSenderInfo mailInfo) { 26. // 判断是否需要身份认证 27. MyAuthenticator authenticator = null; 28. Properties pro = mailInfo.getProperties(); 29. if (mailInfo.isValidate()) { 30. // 如果需要身份认证,则创建一个密码验证器 31. authenticator = new MyAuthenticator(mailInfo.getUserName(), mailInfo.getPassword()); 32. } 33. // 根据邮件会话属性和密码验证器构造一个发送邮件的session 34. Session sendMailSession = Session.getDefaultInstance(pro,authenticator); 35. try { 36. // 根据session创建一个邮件消息 37. Message mailMessage = new MimeMessage(sendMailSession); 38. // 创建邮件发送者地址 39. Address from = new InternetAddress(mailInfo.getFromAddress()); 40. // 设置邮件消息的发送者 41. mailMessage.setFrom(from); 42. // 创建邮件的接收者地址,并设置到邮件消息中 43. Address to = new InternetAddress(mailInfo.getToAddress()); 44. mailMessage.setRecipient(Message.RecipientType.TO,to); 45. // 设置邮件消息的主题 46. mailMessage.setSubject(mailInfo.getSubject()); 47. // 设置邮件消息发送的时间 48. mailMessage.setSentDate(new Date()); 49. // 设置邮件消息的主要内容 50. String mailContent = mailInfo.getContent(); 51. mailMessage.setText(mailContent); 52. // 发送邮件 53. Transport.send(mailMessage); 54. return true; 55. } catch (MessagingException ex) { 56. ex.printStackTrace(); 57. } 58. return false; 59. } 60. 61. /** 62. * 以HTML格式发送邮件 63. * @param mailInfo 待发送邮件信息 64. */ 65. public static boolean sendHtmlMail(MailSenderInfo mailInfo){ 66. // 判断是否需要身份认证 67. MyAuthenticator authenticator = null; 68. Properties pro = mailInfo.getProperties(); 69. //如果需要身份认证,则创建一个密码验证器 70. if (mailInfo.isValidate()) { 71. authenticator = new MyAuthenticator(mailInfo.getUserName(), mailInfo.getPassword()); 72. } 73. // 根据邮件会话属性和密码验证器构造一个发送邮件的session 74. Session sendMailSession = Session.getDefaultInstance(pro,authenticator); 75. try { 76. // 根据session创建一个邮件消息 77. Message mailMessage = new MimeMessage(sendMailSession); 78. // 创建邮件发送者地址 79. Address from = new InternetAddress(mailInfo.getFromAddress()); 80. // 设置邮件消息的发送者 81. mailMessage.setFrom(from); 82. // 创建邮件的接收者地址,并设置到邮件消息中 83. Address to = new InternetAddress(mailInfo.getToAddress()); 84. // Message.RecipientType.TO属性表示接收者的类型为TO 85. mailMessage.setRecipient(Message.RecipientType.TO,to); 86. // 设置邮件消息的主题 87. mailMessage.setSubject(mailInfo.getSubject()); 88. // 设置邮件消息发送的时间 89. mailMessage.setSentDate(new Date()); 90. // MiniMultipart类是一个容器类,包含MimeBodyPart类型的对象 91. Multipart mainPart = new MimeMultipart(); 92. // 创建一个包含HTML内容的MimeBodyPart 93. BodyPart html = new MimeBodyPart(); 94. // 设置HTML内容 95. html.setContent(mailInfo.getContent(), "text/html; charset=utf-8"); 96. mainPart.addBodyPart(html); 97. // 将MiniMultipart对象设置为邮件内容 98. mailMessage.setContent(mainPart); 99. // 发送邮件 100. Transport.send(mailMessage); 101. return true; 102. } catch (MessagingException ex) { 103. ex.printStackTrace(); 104. } 105. return false; 106. } 107. } 第三个类:MyAuthenticator.java Java代码 1. package com.util.mail; 2. 3. import javax.mail.*; 4. 5. public class MyAuthenticator extends Authenticator{ 6. String userName=null; 7. String password=null; 8. 9. public MyAuthenticator(){ 10. } 11. public MyAuthenticator(String username, String password) { 12. this.userName = username; 13. this.password = password; 14. } 15. protected PasswordAuthentication getPasswordAuthentication(){ 16. return new PasswordAuthentication(userName, password); 17. } 18. } 19. 下面给出使用上面三个类的代码: Java代码 1. public static void main(String[] args){ 2. //这个类主要是设置邮件 3. MailSenderInfo mailInfo = new MailSenderInfo(); 4. mailInfo.setMailServerHost("smtp.163.com"); 5. mailInfo.setMailServerPort("25"); 6. mailInfo.setValidate(true); 7. mailInfo.setUserName("han2000lei@163.com"); 8. mailInfo.setPassword("**********");//您的邮箱密码 9. mailInfo.setFromAddress("han2000lei@163.com"); 10. mailInfo.setToAddress("han2000lei@163.com"); 11. mailInfo.setSubject("设置邮箱标题"); 12. mailInfo.setContent("设置邮箱内容"); 13. //这个类主要来发送邮件 14. SimpleMailSender sms = new SimpleMailSender(); 15. sms.sendTextMail(mailInfo);//发送文体格式 16. sms.sendHtmlMail(mailInfo);//发送html格式 17. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值