James+Javamail构建邮件服务(五)

8 Javamail的高级应用
8.1 用Javamail实现对邮件的查找
  在邮件的高级应用中,当遇到某个帐户中的邮件数非常多的时候,而用户往往只需要对其中的某几封邮件进行处理。倘若要把所有的邮件都取出来,再进行对应信息的判断提取,这无疑将大大加重邮件服务器的负担。为了改善这种状况,Javamail内部提供了一个专门用于邮件查找的包:javax.mail.search。这个包将通过对SearchTerm对象进行设置,而后提交给服务器,服务器端有相应的过滤器,根据SearchTerm对象的设置将邮件过滤的结果传回给客户端。以提高工作效率,减轻服务器端负担。下面就让我们一起来做一个例子说明一下我们应该如何使用search这个包吧。
8.1.1 业务描述
  编写一个类,实现对helloworld@localhost邮件中邮件的条件搜索功能。在本例中实现对主题中包含“测试”,发件人是chenfengcn@localhost,的邮件的搜索。
8.1.2 编码实现

Java代码
  1. package com.newland.javamail.sample1;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.Properties;   
  5. import javax.mail.Folder;   
  6. import javax.mail.Message;   
  7. import javax.mail.MessagingException;   
  8. import javax.mail.NoSuchProviderException;   
  9. import javax.mail.Session;   
  10. import javax.mail.Store;   
  11. import javax.mail.internet.InternetAddress;   
  12. import javax.mail.search.AndTerm;   
  13. import javax.mail.search.FromTerm;   
  14. import javax.mail.search.SearchTerm;   
  15. import javax.mail.search.SubjectTerm;   
  16.   
  17. /**  
  18.  * 使用Javamail的Search包实现对邮件的搜索功能  
  19.  * @author Chen.Feng(Kevin)<br>  
  20.  *         mail:chenfengcn@yeah.net<br>  
  21.  *         qq:67758633  
  22.  *  
  23.  */  
  24. public class SearchMail {   
  25.     private static ArrayList<SearchTerm> list=new ArrayList();   
  26.     public static void main(String[] args) {   
  27.         //用户信息   
  28.         String user = "helloworld";   
  29.         String password = "881213";   
  30.         // 配置服务器属性   
  31.         Properties props = new Properties();   
  32.         props.put("mail.smtp.host""localhost"); // smtp服务器   
  33.         props.put("mail.smtp.auth""true"); // 是否smtp认证   
  34.         props.put("mail.smtp.port""25"); // 设置smtp端口   
  35.         props.put("mail.transport.protocol""smtp"); // 发邮件协议   
  36.         props.put("mail.store.protocol""pop3"); // 收邮件协议   
  37.         //创建会话   
  38.         Session session = Session.getInstance(props, null);   
  39.         Store store=null;   
  40.         try {   
  41.             //连接Store   
  42.             store = session.getStore("pop3");   
  43.             store.connect("localhost", user, password);   
  44.             //打开Folder   
  45.             Folder folder = store.getFolder("inbox");   
  46.             folder.open(Folder.READ_ONLY);   
  47.             //构造搜索规则   
  48.             SearchTerm subterm = new SubjectTerm("测试");   
  49.             SearchTerm fterm = new FromTerm(new InternetAddress("chenfengcn@localhost"));   
  50.             SearchTerm st=new AndTerm(subterm,fterm);   
  51.             Message[] message=folder.search(st);   
  52.             //输出搜索到的邮件的主题   
  53.             for (int i = 0; i < message.length; i++) {   
  54.                 System.out.println(message[i].getSubject());   
  55.             }   
  56.         } catch (NoSuchProviderException e) {   
  57.             // TODO Auto-generated catch block   
  58.             e.printStackTrace();   
  59.         } catch (MessagingException e) {   
  60.             // TODO Auto-generated catch block   
  61.             e.printStackTrace();   
  62.         }   
  63.     }   
  64. }  


  本例只展示如何使用Javamail的Search包实现对邮件的搜索功能,在实际应用中,Search包中还存在许多功能相当完备的API,若对这部分内容有兴趣可自行参考Javamail API。
  API明细:/javamail-1.4.1/docs/javadocs/javax/mail/search/package-frame.html


9 James邮件服务器的高级应用与配置
9.1 配置邮箱域名
  配置config.xml文件,文件位于/apps/james/SAR-INF目录下。在配置文件中找到:

Xml代码
  1. <postmaster>Postmaster@localhost</postmaster>  
  2. <servernames autodetect="true" autodetectIP="true">  
  3. <!-- CONFIRM? -->  
  4.          <servername>localhost</servername>  
  5. </servernames>  


  这两项内容,把其中的localhost改成你所要配置的域名即可。
9.2 将用户信息配置为数据库存储方式
  James服务器提供了相当完善的配置方案,可选择将用户信息保存在文件、数据库或其他介质中。在默认的情况下,服务器将用户信息以加密形式保存于/james-2.3.1/apps/james
  /var/users目录下的文件中。我们可以通过改变其配置信息从而改变用户信息的保存方式。在此仅以MYSQL数据库的配置方式为例说明。
第一步:
  将相应数据库的JDBC驱动包复制到lib目录下
即我们需要把mysql-connector-java-3.1.13-bin.jar的MYSQL数据库驱动包复制到/james-2.3.1/lib目录下
第二步:
  新建数据库,建立一个用于存放James用户信息的数据库(表不用建,由James自动创建),在这里,我们假设新建的数据库为mail
第三步:
  配置config.xml文件,文件位于/apps/james/SAR-INF目录下。打开config.xml,找到以下内容:

Xml代码
  1. <repository name="LocalUsers" class="org.apache.james.userrepository.UsersFileRepository">  
  2. <destination URL="file://var/users/"/>  
  3. </repository>  


  把这部分内容修改为:

Xml代码
  1. <repository name="LocalUsers" class="org.apache.james.userrepository.JamesUsersJdbcRepository" destinationURL="db://maildb/users">  
  2.     <sqlFile>file://conf/sqlResources.xml</sqlFile>  
  3. </repository>  


第四步:
  找到MySQL配置位置

     

Xml代码
  1. <!-- Example, connecting to a MySQL database called "mail" on localhost-->  
  2.       <!-- -->  
  3.       <!-- The max value is the maximum number of concurrent connections James will -->  
  4.       <!-- open to this database-->  
  5.       <!-- If you see "SQLException: Giving up... no connections available." in your -->  
  6.       <!-- log files or bounced mail you should increase this value -->  
  7.       <!--   
  8.       <data-source name="maildb" class="org.apache.james.util.dbcp.JdbcDataSource">  
  9.          <driver>com.mysql.jdbc.Driver</driver>  
  10.          <dburl>jdbc:mysql://127.0.0.1/mail?autoReconnect=true</dburl>  
  11.          <user>username</user>  
  12.          <password>password</password>  
  13.          <max>20</max>  
  14.       </data-source>  
  15.       -->  

  首先,去掉data-source标签前后的注释标识(”<!-- -->”),然后按照你的实际情况配置好相应的数据库信息(包括URL、用户名、密码、最大连接数)。然后保存,重新启动James。James会在数据库中自动创建users表用于存放邮箱的用户信息。这样配置以后,我们除了可以通过telnet操作用户信息外,同样可以通过此users表来操作用户信息。
  值得注意的是,James的用户密码使用的是SHA单向加密算法,若需添加用户或对用户密码进行修改,则会遇到SHA的加密问题。我们应该如何来解决这个问题呢?查看James的源码中org.apache.james.userrepository包中的DefaultUser.java文件,我们可以发现,James中提供verifyPassword()和setPassword()两个方法,verifyPassword()是用来做密码认证的,而setPassword()则是用来实现密码转换的,即将明文密码转换成密文。通过仔细研究这两个方法,可以很容易地实现将自己的密码进行SHA加密了。
9.3 通过操作数据库实现用户信息操作
  在上一节我们讨论了可以将James的用户信息配置到数据库中使用,但会存在SHA加密的问题,在这一节里,我们将讨论如何来解决这个问题,从而真正实现通过操作数据库来操作James服务器的用户信息。
9.3.1 业务描述
  本例是基于上一节“将用户信息配置为数据库存储方式”后,通过操作数据库,即:对数据库的信息进行增、删、查、改等操作。本例只实现用户信息的添加,关键在于使用James源码包中提供的SHA加密算法实现用户密码的加密,其余功能跟一般数据库操作无异,故不赘述。
9.3.2 编码实现

用户添加类:AddUserByDB.java

Java代码
  1. package com.newland.james.user.sample1;   
  2.   
  3. import java.security.NoSuchAlgorithmException;   
  4. import java.sql.Connection;   
  5. import java.sql.DriverManager;   
  6. import java.sql.SQLException;   
  7. import org.apache.james.security.DigestUtil;   
  8.   
  9. /**  
  10.  * 通过操作数据库来添加James用户  
  11.  *   
  12.  * @author Chen.Feng(Kevin)<br>  
  13.  *         mail:chenfengcn@yeah.net<br>  
  14.  *         qq:67758633  
  15.  */  
  16. public class AddUserByDB {   
  17.     public static void main(String[] args) {   
  18.         // 连接数据库   
  19.         String driverName = "com.mysql.jdbc.Driver";   
  20.         String dbURL = "jdbc:mysql://localhost/mail?autoReconnect=true";   
  21.         String userName = "root";   
  22.         String userPwd = "881213";   
  23.         Connection conn = null;   
  24.         try {   
  25.             Class.forName(driverName);   
  26.             conn = DriverManager.getConnection(dbURL, userName, userPwd);   
  27.         } catch (ClassNotFoundException e) {   
  28.             e.printStackTrace();   
  29.         } catch (SQLException e) {   
  30.             e.printStackTrace();   
  31.         }   
  32.         // 构造并执行SQL语句,关键在于DigestUtil.digestString("881213", "SHA"),实现对密码的SHA加密   
  33.         // 注:用户信息的后四个属性需要使用('SHA',0,NULL,0,null)此四个默认值,若用错,则新建用户可能不能使用   
  34.         String sql = "";   
  35.         try {   
  36.             sql = "insert into users values('hello','"  
  37.                     + DigestUtil.digestString("881213""SHA")   
  38.                     + "','SHA',0,NULL,0,null)";   
  39.             conn.createStatement().executeUpdate(sql);   
  40.             conn.close();   
  41. System.out.println("用户添加成功");   
  42.         } catch (NoSuchAlgorithmException e) {   
  43.             // TODO Auto-generated catch block   
  44.             e.printStackTrace();   
  45.         } catch (SQLException e) {   
  46.             // TODO Auto-generated catch block   
  47.             e.printStackTrace();   
  48.         }   
  49.     }   
  50. }  


  上述程序成功运行后,系统将在数据库添加一条hello用户的记录,那么我们应该如何测试此用户是否真正创建成功并可使用呢?方法有很多,可以使用前面所述的,通过Telnet命令中的listusers来查看,当然,同样也可以使用Foxmail将此用户添加进去,帐户能正常接收到Foxmail发送的邮件即表明此用户可正常使用了。
  在此例子编写的过程中要注意以下两点:1、用户信息的后四个属性需要使用('SHA',0,NULL,0,null)此四个默认值,若用错,则新建用户可能不能使用;2、在程序运行过程中,需要使用到james-2.3.1.jar包和相应的数据库驱动包,在程序运行前请确保这些包已添加到相关的位置。
9.4 通过Java调用Telnet实现用户信息操作(未完成)
  通过前面的介绍,我们可以很方便地通过Telnet或数据库方式来对James的用户信息进行操作,Telnet是相对外部的较慢的方式,如果我们要实现批量添加或批量修改用户信息,使用外部的Telnet来操作就很难实现了。好在Apache组织提供了在Java里调用Telnet的方法(即:commons-net-1.4.1.jar包),在此,我们主要展示如何使用Apache的net包实现添加一个James服务器用户,当然,你同样可以使用此技术进行查询James里的用户、修改用户信息等James的Telnet命令提供的所有功能。
9.4.1 业务描述
  本例将展示如何在Java里调用Telnet命令实现James邮件用户的添加。当然,你同样可以使用此技术执行其他可以使用Telnet进行的操作。
9.4.2 编码实现

AddUserByTelnet.java

Java代码
  1. package com.newland.james.user.sample1;   
  2.   
  3. import java.io.BufferedReader;   
  4. import java.io.IOException;   
  5. import java.io.InputStreamReader;   
  6. import java.io.OutputStreamWriter;   
  7. import java.net.SocketException;   
  8. import org.apache.commons.net.telnet.TelnetClient;   
  9. /**  
  10.  * 通过Java调用Telnet命令添加James用户  
  11.  *   
  12.  * @author Chen.Feng(Kevin)<br>  
  13.  *         mail:chenfengcn@yeah.net<br>  
  14.  *         qq:67758633  
  15.  *   
  16.  */  
  17. public class AddUserByTelnet {   
  18.     //设置回车换行   
  19.     public static final String LINE_SEPARATOR = System.getProperties()   
  20.             .getProperty("line.separator");   
  21.     public static void main(String[] args) {   
  22.         BufferedReader m_reader;   
  23.         OutputStreamWriter m_writer;   
  24.         TelnetClient m_telnetClient = new TelnetClient();   
  25.         try {   
  26.             //设置Telnet超时   
  27.             m_telnetClient.setDefaultTimeout(1000);   
  28.             //设置Telnet服务器地址及端口   
  29.             m_telnetClient.connect("localhost"4555);   
  30.             //创建读取缓冲对象   
  31.             m_reader = new BufferedReader(new InputStreamReader(m_telnetClient   
  32.                     .getInputStream()));   
  33.             //创建用于发送Telnet命令对象   
  34.             m_writer = new OutputStreamWriter(m_telnetClient.getOutputStream());   
  35.             //不断接收登陆成功的信号,超时抛出异常,则跳至一下条代码执行   
  36.             try {   
  37.                 for (;;) {   
  38.                     System.out.println(m_reader.readLine());   
  39.                 }   
  40.             } catch (Exception e) {   
  41.             }   
  42.             //输入James服务器用户名,此为管理员用户名,而非普通用户,默认为root   
  43.             m_writer.write("root" + LINE_SEPARATOR);   
  44.             m_writer.flush();   
  45.             System.out.println(m_reader.readLine());   
  46.             //输入root用户密码   
  47.             m_writer.write("root" + LINE_SEPARATOR);   
  48.             m_writer.flush();   
  49.             System.out.println(m_reader.readLine());   
  50.             //输入Telnet命令添加用户   
  51.             m_writer.write("adduser helloman 881213" + LINE_SEPARATOR);   
  52.             m_writer.flush();   
  53.             System.out.println(m_reader.readLine());   
  54.             //输出用户列表   
  55.             m_writer.write("listusers" + LINE_SEPARATOR);   
  56.             m_writer.flush();   
  57.             //显示用户列表   
  58.             try {   
  59.                 for (;;) {   
  60.                     System.out.println(m_reader.readLine());   
  61.                 }   
  62.             } catch (Exception e) {   
  63.             }   
  64.         } catch (SocketException e) {   
  65.             // TODO Auto-generated catch block   
  66.             e.printStackTrace();   
  67.         } catch (IOException e) {   
  68.             // TODO Auto-generated catch block   
  69.             e.printStackTrace();   
  70.         }   
  71.     }   
  72. }  


10 常见问题与解决
10.1 Javamail常见问题
1、接收或发送邮件时,提示如下报错:
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream
at javax.mail.Session.loadProvidersFromStream(Session.java:928)
at javax.mail.Session.access$000(Session.java:174)
at javax.mail.Session$1.load(Session.java:870)
at javax.mail.Session.loadResource(Session.java:1084)
at javax.mail.Session.loadProviders(Session.java:889)
at javax.mail.Session.<init>(Session.java:210)
at javax.mail.Session.getInstance(Session.java:232)
at com.newland.javamail.sample1.ReceiveMail.main(ReceiveMail.java:41)
  此问题与J2EE的版本有关,将J2EE的版本换成1.4即解决问题。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值