现贴出主要类,主要流程都在这个类中:
package com.blankenhorn.net.mail;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Date;
import java.util.StringTokenizer;
/**
* Provides a simple way to send emails to an SMTP server.
*
* @author Kai Blankenhorn <<a href="mailto:pub01@bitfolge.de">pub01@bitfolge.de</a>>
*/
public class EasySMTPConnection {
private String server = null;
private BufferedReader in = null;
private BufferedWriter out = null;
private Socket socket = null;
/**
* Usage example.
*/
public static void main(String[] args) {
try {
EasySMTPConnection smtp = new EasySMTPConnection("127.0.0.1");
Message msg = new Message();
msg.setTo("");
String[] source = {
"From: Test User <test.user@foo.bar>",
"To: Kai Blankenhorn <pub01@bitfolge.de>,
Somebody <somebodysaddress@somebodysserver.com>",
"Subject: EasySMTPConnection Test",
"Date: insertdate",
"Content-Type: text/plain; charset=iso-8859-1",
// you may set the message ID, but you don't have to
// "Message-ID:
"+EasySMTPConnection.createMessageID("yourserver.com"),
"",
"first line,",
"second line",
"as you can see, no need for newlines (\\n)",
""
};
msg = new Message(source);
smtp.sendMessage(msg);
} catch(MailProtocolException e) {
e.printStackTrace();
}
catch(InstantiationException e) {
e.printStackTrace();
}
}
/**
* Creates a unique message ID for an email message.
*
* @param hostName the internet name of the computer the mail is being sent from
*/
public static String createMessageID(String hostName) {
String msgID = new Date().getTime() + ".";
msgID += Thread.currentThread().hashCode();
msgID += hostName;
msgID = "<"+msgID+">";
return msgID;
}
/**
* Establishes a connection to the specified SMTP server.
*
* @param server the SMTP server to connect to
*/
public EasySMTPConnection(String server) throws InstantiationException {
this.server = server;
try {
this.open();
} catch(SocketTimeoutException e) {
throw new InstantiationException("Timeout: " + e.getMessage());
}
catch(IOException e) {
throw new InstantiationException("IO error: " + e.getMessage());
}
}
/**
* Opens the connection to the server stored in <code>server</code>.
*/
protected void open() throws SocketTimeoutException, IOException {
socket = new Socket(server, 25);
socket.setSoTimeout(5000);
socket.setKeepAlive(true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String response = read();
if(!response.startsWith("220")) {
throw new IOException(response);
}
writeln("HELO " + InetAddress.getByName(InetAddress.getLocalHost().getHostAddress())
.getHostName());
response = read();
if(!response.startsWith("2")) {
throw new IOException(response);
}
}
/**
* Close the connection.
*/
public void close() {
try {
writeln("QUIT");
socket.close();
} catch(SocketTimeoutException e) {
}
catch(IOException e) {
}
}
private String read() throws SocketTimeoutException, IOException {
String line = in.readLine();
return line;
}
private void writeln(String line) throws SocketTimeoutException, IOException {
out.write(line);
out.newLine();
out.flush();
}
/**
* Reads the server's response and checks the response code.
*
* @throws MailProtocolException if the code from the server is an error code (4xx or 5xx)
* @throws SocketTimeoutException if there was a timeout while reading from the server
* @throws IOException if there was some sort of network error
*/
protected void checkResponse() throws MailProtocolException, SocketTimeoutException, IOException {
String response = read();
if(response.startsWith("4") || response.startsWith("5")) {
throw new MailProtocolException(response);
}
}
/**
* Sends an array of Strings to the server. This method just constructs a new Message object
* based on <code>msgSource</code> and then calls {@link #sendMessage(Message)}
*
* @param msgSource An array of Strings, each element containing one line of the message source.
*
Note that
there has to be an empty line to seperate header and body of the
message.
*
You don't have
to (and you're not able to) end your message with a "." line, though.
*/
public void send(String[] msgSource) throws MailProtocolException {
Message msg = new Message(msgSource);
this.sendMessage(msg);
}
/**
* Sends a Message through the server corresponding to this instance of EasySMTPConnection.
*
* @param msg the Message to send
* @throws MailProtocolException if the server replied an error to one of the commands
*/
public void sendMessage(Message msg) throws MailProtocolException {
if (msg.getMessageID()==null || msg.getMessageID().equals("")) {
msg.setMessageID(EasySMTPConnection.createMessageID("yourserver.com"));
}
try {
socket.setSoTimeout(10000);
writeln("MAIL FROM:" + extractEmail(msg.getFrom()));
checkResponse();
StringTokenizer t = new StringTokenizer(msg.getTo(), ";,");
while(t.hasMoreTokens()) {
writeln("RCPT TO:" + extractEmail(t.nextToken()));
checkResponse();
}
t = new StringTokenizer(msg.getCC(), ";,");
while(t.hasMoreTokens()) {
writeln("RCPT TO:" + extractEmail(t.nextToken()));
checkResponse();
}
t = new StringTokenizer(msg.getBCC(), ";,");
while(t.hasMoreTokens()) {
writeln("RCPT TO:" + extractEmail(t.nextToken()));
checkResponse();
}
writeln("DATA");
checkResponse();
for(int i = 0; i < msg.getHeader().length; i++) {
writeln(encodeDot(msg.getHeader()[i]));
}
writeln("X-Sent-Through: EasySMTPConnection Java class
(http://www.bitfolge.de/en)");
writeln("");
for(int i = 0; i < msg.getBody().length; i++) {
writeln(encodeDot(msg.getBody()[i]));
}
writeln(".");
checkResponse();
} catch(IOException io) {
throw new MailProtocolException(io);
}
}
protected String extractEmail(String nameAndEmail) {
String result = nameAndEmail;
if(nameAndEmail.indexOf('<') > -1) {
result =
nameAndEmail.substring(nameAndEmail.indexOf('<') + 1,
nameAndEmail.indexOf('>'));
}
return result;
}
protected String encodeDot(String line) {
String result = line;
if(line.startsWith(".")) {
result = "." + result;
}
return result;
}
/**
* Closes the connection to the server upon finalization.
*/
public void finalize() {
this.close();
}
}