下面是一个带有用户名验证的邮件发送:

 

import java.io.*;
import java.net.*;
public class MailSender
{
private String smtpServer = "smtp.163.com" ;
private int port = 25 ;

public static void main(String args[])
{
Message msg = new Message("123@163.com","456@qq.com","Testmail","Hi,This is a test mail from ***.");
new MailSender().sendMail(msg);
}

public void sendMail(Message msg)
{
Socket socket = null ;
try
{
socket = new Socket(smtpServer,port); //连接到服务器
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);

String username = "123"; //自己的用户名
String password = "111"; //自己的密码

username = new sun.misc.BASE64Encoder().encode(username.getBytes());   //在这两行编译器会产生错误,这里的解决办法稍后解释
password = new sun.misc.BASE64Encoder().encode(password.getBytes());

sendAndReceive(null,br,pw); //仅仅为了接收服务器响应数据
sendAndReceive("ehlo 163.com",br,pw);
sendAndReceive("AUTH LOGIN",br,pw);
sendAndReceive(username,br,pw);
sendAndReceive(password,br,pw);
sendAndReceive("mail from:<" + msg.from + ">",br,pw);
sendAndReceive("rcpt to:<" + msg.to +">",br,pw);
sendAndReceive("data",br,pw);
pw.println(msg.data);
System.out.println("Client>" + msg.data);
sendAndReceive(".",br,pw); //邮件发送完毕
sendAndReceive("quit",br,pw);
}catch(IOException e)
{
e.printStackTrace();
}finally
{
try
{
if(socket!=null)
socket.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}

/*发送一行字符串,并接收一行服务器响应*/
private void sendAndReceive(String str,BufferedReader br,PrintWriter pw)throws IOException
{
if(str != null)
{
System.out.println("client>" + str);
pw.print(str);
}
String response;
System.out.println("+1");                      //这里仅仅用于测试这个if有没有用到
if((response = br.readLine()) != null)
{
System.out.println("Server>" + response);
}
System.out.println("+1");                    //这里仅仅用于测试这个if有没有用到
}
private PrintWriter getWriter(Socket socket)throws IOException
{
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut,true);
}
private BufferedReader getReader(Socket socket)throws IOException
{
InputStream socketIn = socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}
}
class Message
{
String from ;
String to ;
String subject;
String content;
String data;
public Message(String from,String to,String subject,String content)
{
this.from=from;
this.to=to;
this.subject=subject;
this.content=content;
data="Subject:" + subject + "\r\n" + content;
}
}

 

到目前为止,由于中间那个BufferedReader的问题导致卡在了用户账号密码输入那一块,根据加进去的测试代码("System.out.println("+1");"),在向服务器发送了“ehlo 163.com”的信息后,BufferedReader的貌似遇到了什么不可预知的错误:

收到了“ehlo 163.com”之后,服务器会返回:

250-gz-t-163smtp2.163.com
250-mail
250-PIPELINING
250-8BITMIME
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN PLAIN
250 STARTTLS 38b4bb77-c40a-4374-b1e3-11a4049064b9

 

而BufferedReader在这里卡住了。这个问题解决了会在(二)中写出解决方法。

 

附:

username = new sun.misc.BASE64Encoder().encode(username.getBytes());
password = new sun.misc.BASE64Encoder().encode(password.getBytes());

这里会显示编译错误,解决办法如下:

像这样的异常信息,是eclipse设置问题,问题:
Access restriction: The type FileURLConnection is not accessible due to restriction on required library C:/Program Files/Java/jre6/lib/rt.jar

 

这个是eclipse设置问题,它默认把这些受访问限制的API设成了ERROR

解决方法:

只要把 Windows-Preferences-Java-Complicer-Errors/Warnings里面的Deprecated and restricted API中的Forbidden references(access rules)选为Warning就可以编译通过了。