利用socket编程,Java基于pop3实现收邮件的功能

6 篇文章 0 订阅
4 篇文章 0 订阅

java实现POP3邮件客户端

java实现POP3邮件客户端

第一步:利用socket编程,在客户端与服务器端之间建立TCP连接,POP3默认端口号为110;

第二步:通过pop3定义的各种命令,用户可以操作自己的邮箱。

注:

POP3协议中有三种状态,认正状态,处理状态,和更新状态。 命令的执行可以改变协议的状态,而对于具体的某命令,它只能在具体的某状态下使用,这些请参看表1和RFC193。

客户机与服务器刚与服务器建立连接时,它的状态为认证状态;一旦客户机提供了自己身份并被成功地确认,即由认可状态转入处理状态; 在完成相应的操作后客户机发出QUIT命令(具体说明见后续内容),则进入更新状态,更新之后又重返认可状态;当然在认可状态下执行QUIT命令,可释放连接。状态间的转移如图 1所示。

---建立连接---|认可|--认证成功--|处理|--执行QUIT--|更新|        

            |_______ -QUIT结束_________________|

 

 

常用命令:

命令

参数

使用在何种状态中

描述

USER

Username

认证

此命令与下面的pass命令若成功,将导致状态转换

PASS

Password

认证

此命令若成功,状态转化为更新

APOP

Name,Digest

认证

Digest是MD5消息摘要

STAT

None

处理

请求服务器发回关于邮箱的统计资料,如邮件总数和总字节数

UIDL

[Msg#](邮件号,下同)

处理

返回邮件的唯一标识符,POP3会话的每个标识符都将是唯一的

LIST

[Msg#]

处理

返回邮件的唯一标识符,POP3会话的每个标识符都将是唯一的

RETR

[Msg#]

处理

返回由参数标识的邮件的全部文本

DELE

[Msg#]

处理

服务器将由参数标识的邮件标记为删除,由QUIT命令执行

TOP

[Msg#]

处理

服务器将返回由参数标识的邮件的邮件头+前n行内容,n必须是正整数

NOOP

None

处理

服务器返回一个肯定的响应,用于测试连接是否成功

QUIT

None

处理、认证

1)        如果服务器处于“处理”状态,么将进入“更新”状态以删除任何标记为删除的邮件,并重返“认证”状态。

2)        如果服务器处于“认证”状态,则结束会话,退出连接

 

/**
 * @author hewenwu
 * 这个程序实现了基于POP3协议的邮件接收功能
 * */
package mail;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.StringTokenizer;

public class POP3Client {

    private Socket socket = null;
 
    private boolean debug=true;
 
    public static void main(String[] args) throws UnknownHostException, IOException {
  
        String server="pop3.163.com";//POP3服务器地址
  
        String user="**********";//用户名,填写自己的邮箱用户名
  
        String password="*********";//密码,填写自己的密码
 
        POP3Client pop3Client=new POP3Client(server,110);
 
    pop3Client.recieveMail(user,password);
 }
 
    /*构造函数*/
    public POP3Client(String server,int port) throws UnknownHostException, IOException{
        try{
   
            socket=new Socket(server,port);//在新建socket的时候就已经与服务器建立了连接

        }catch(Exception e){
   
            e.printStackTrace();
 
        }finally{
 
            System.out.println("建立连接!");
        }
    }
 
    
    //接收邮件程序
    public boolean recieveMail(String user,String password){
            
        try {
                BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
       
                BufferedWriter out=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
      
                user(user,in,out);//输入用户名
       
                System.out.println("user 命令执行完毕!");
                
                pass(password,in,out);//输入密码
      
                System.out.println("pass 命令执行完毕!");
      
                stat(in,out);
      
                System.out.println("stat 命令执行完毕!");
                
                list(in,out);
                  
                System.out.println("list 命令执行完毕!");
                
                retr(2,in,out);
                
                System.out.println("retr 命令执行完毕!");
      
                quit(in,out);
                
                System.out.println("quit 命令执行完毕!");
     
            }catch(Exception e){
      
                e.printStackTrace();
      
                return false;
            }
            return true;
        }
    
    //得到服务器返回的一行命令
    public String getReturn(BufferedReader in){
    
        String line="";
  
        try{
            line=in.readLine();
   
            if(debug){
   
                System.out.println("服务器返回状态:"+line);
            }
        }catch(Exception e){
 
            e.printStackTrace();
        }
        return line;
    }
 
    //从返回的命令中得到第一个字段,也就是服务器的返回状态码(+OK或者-ERR)
    public String getResult(String line){

        StringTokenizer st=new StringTokenizer(line," ");

        return st.nextToken();
    }
 
    //发送命令
    private String sendServer(String str,BufferedReader in,BufferedWriter out) throws IOException{
        
        out.write(str);//发送命令
 
        out.newLine();//发送空行
 
        out.flush();//清空缓冲区
  
        if(debug){
  
            System.out.println("已发送命令:"+str);
         }
         return getReturn(in);
     }
 
    //user命令
    
    public void user(String user,BufferedReader in,BufferedWriter out) throws IOException{

        String result = null;
 
        result=getResult(getReturn(in));//先检测连接服务器是否已经成功
 
        if(!"+OK".equals(result)){
   
            throw new IOException("连接服务器失败!");
        }
 
        result=getResult(sendServer("user "+user,in,out));//发送user命令

        if(!"+OK".equals(result)){
  
            throw new IOException("用户名错误!");
        }
    }
 
    //pass命令
    public void pass(String password,BufferedReader in,BufferedWriter out) throws IOException{
 
        String result = null;
 
        result = getResult(sendServer("pass "+password,in,out)); 
 
        if(!"+OK".equals(result)){

            throw new IOException("密码错误!");
        }
    }

    
    //stat命令

    public int stat(BufferedReader in,BufferedWriter out) throws IOException{
 
        String result = null;
 
        String line = null;
  
        int mailNum = 0;
 
        line=sendServer("stat",in,out); 
 
        StringTokenizer st=new StringTokenizer(line," ");
  
        result=st.nextToken();
  
        if(st.hasMoreTokens())
 
            mailNum=Integer.parseInt(st.nextToken());
 
        else{
            
            mailNum=0;
            
        }
        
        if(!"+OK".equals(result)){
 
            throw new IOException("查看邮箱状态出错!");
        }
 
        System.out.println("共有邮件"+mailNum+"封");
        return mailNum;
 }
    
        //无参数list命令
        public void list(BufferedReader in,BufferedWriter out) throws IOException{
     
            String message = "";
     
            String line = null;
     
            line=sendServer("list",in,out); 
     
            while(!".".equalsIgnoreCase(line)){
       
                message=message+line+"\n";    
            
                line=in.readLine().toString();
                }
            
                System.out.println(message);
     }
        
          //带参数list命令
                public void list_one(int mailNumber ,BufferedReader in,BufferedWriter out) throws IOException{

                    String result = null;
                     
                    result = getResult(sendServer("list "+mailNumber,in,out)); 
             
                    if(!"+OK".equals(result)){

                        throw new IOException("list错误!");
                    }
             }
 
 //得到邮件详细信息
 
    public String getMessagedetail(BufferedReader in) throws UnsupportedEncodingException{
 
        String message = "";
  
        String line = null;
 
        try{
            line=in.readLine().toString();
  
            while(!".".equalsIgnoreCase(line)){
   
                message=message+line+"\n";
   
                line=in.readLine().toString();
            }
        }catch(Exception e){
  
            e.printStackTrace();
        }
    
            return message;
    }
 
 //retr命令
    public void retr(int mailNum,BufferedReader in,BufferedWriter out) throws IOException, InterruptedException{
  
            String result = null;
   
            result=getResult(sendServer("retr "+mailNum,in,out));
  
            if(!"+OK".equals(result)){
  
                throw new IOException("接收邮件出错!");
            }
            
            System.out.println("第"+mailNum+"封");
            System.out.println(getMessagedetail(in));
            Thread.sleep(3000);
    }
 
    //退出
    public void quit(BufferedReader in,BufferedWriter out) throws IOException{
 
        String result;
 
        result=getResult(sendServer("QUIT",in,out));
 
        if(!"+OK".equals(result)){
  
            throw new IOException("未能正确退出");
        }
    }
 
}

 

总结:

    这个项目其实非常简单,关键要理解两个方面,一是怎么利用socket编程连接到服务器,二是POP3协议命令的格式和返回值的格式。理解了这两个方面,就好做了。首先建立连接,然后通过socket对象获取输入输出流对象,在输入输出流对象上发送命令和接受返回值,接收到返回值之后自己本地处理这些返回值就行啦。

说到输入输出流,java的输入输出流真的比较多,有点不好记,但是每个输出流的原理是一样,而且有封装的特性。接下来一定要狠狠的把它搞懂了!

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值