传统的,当我们接收邮件的时候,邮件客户端软件会连接到支持Post Office Protocol, Version 3 (POP3) or Internet Message Access Protocol, Version 4 (IMAP4) 协议的邮件服务器.
由于通常一个MIDLet是通过HTTP协议来和服务器进行数据交换,因此通常就需要一个Servlet来作为邮件接收适配器来实现接收邮件的功能。
接收邮件的代码由Servlet完成,MIDlet仅仅和Servlet进行交互并显示结果
下边的代码说明了如何在移动设备上实现一个简单的邮件客户端来接收邮件
/*运行在移动设备上的MIDlet*/
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.io.*;
import java.io.InputStream;
import java.io.PrintStream;
public class CheckMail extends MIDlet implements CommandListener {
private String MAIL_SERVER_URL =
"http://localhost:8080/examples/servlet/CheckMailServlet?";
private int MSG_LIST_SIZE = 5;
Display display = null;
List menu = null;
List dmenu = null;
TextBox input = null;
String[] msgs = new String[MSG_LIST_SIZE];
String user = null;
int status = 0;
Command backCommand = new Command("Back", Command.BACK, 0);
Command submitCommand = new Command("Submit", Command.OK, 2);
Command exitCommand = new Command("Exit", Command.STOP, 3);
public CheckMail() { }
public void startApp() throws MIDletStateChangeException {
display = Display.getDisplay(this);
displayMenu();
}
public void pauseApp() { }
public void destroyApp(boolean unconditional) {
notifyDestroyed();
}
public void commandAction(Command c, Displayable d) {
if(c == exitCommand ) {
destroyApp(true);
} else if (c == backCommand) {
handleBack();
} else if (c == submitCommand) {
user = input.getString();
retreiveMail(0, null);
} else if (d == dmenu) {
handleMainMenu();
} else if (d == menu) {
handleMsgMenu();
} else
loginUser();
}
/* 显示主屏幕 */
private void displayMenu() {
dmenu = new List("Check Email", Choice.IMPLICIT);
if (user == null)
dmenu.append("Login", null);
else
dmenu.append("Logout", null);
dmenu.append("Check Mail", null);
dmenu.addCommand(exitCommand);
dmenu.setCommandListener(this);
display.setCurrent(dmenu);
status = 0;
}
/* 采集邮件地址和密码*/
private void loginUser() {
input = new TextBox(
"Enter Login Name/Password (Seperate by /) :", "", 25,
TextField.ANY);
input.addCommand(submitCommand);
input.addCommand(backCommand);
input.setCommandListener(this);
display.setCurrent(input);
}
/* 此方法取回邮件号码为msgNum的邮件,如果没有指定msgNum则显示所有邮件的列表*/
private void retreiveMail(int s, String msgNum) {
String popURL = MAIL_SERVER_URL + "u=" + user;
if (s == 0)
popURL = popURL // 登录
if (s == 1)
// 列出邮件
popURL = popURL + "&s=" + msgNum + "&a=l";
else if (s == 2)
// 取回邮件 i=msgNum
popURL = popURL + "&i=" + msgNum + "&a=r";
StreamConnection c = null;
InputStream is=null;
StringBuffer sb = null;
String err = null;
try {
c = (StreamConnection)Connector.open(popURL,
Connector.READ_WRITE);
is = c.openInputStream();
int ch;
sb = new StringBuffer();
while ((ch = is.read()) != -1) {
sb.append((char)ch);
}
} catch(Exception ex){ err = ex.getMessage(); } finally {
try {
if(is!= null) {is.close(); }
if(c != null) {c.close(); }
} catch(Exception exp) { err = exp.getMessage(); }
}
if (err == null) {
if (s == 0) {
user = sb.toString();
if (user.indexOf("INVALIDUSR") >= 0) {
user = null;
showAlert("不正确的用户名和口令");
} else {
input = null;
dmenu = null;
displayMenu();
}
} else if (s == 1) // 取回列表
showMList(sb.toString());
else // s ==2, 显示邮件
showMsg(sb.toString());
} else
showAlert(err); // 显示错误页
}
/* 显示被选择的邮件*/
private void showMsg(String msg) {
StringBuffer buffer = new StringBuffer(200);
int delim = '?';
int j = msg.indexOf(delim);
int i =0;
// 获取 FROM
buffer.append(msg.substring(0,j ));
for (int k=0;k<4;k++) {
i = j+1;
j = msg.indexOf(delim, i);
// 获取 TO, CC, Subject, Date
buffer.append(msg.substring(i,j ));
}
// 邮件内容
buffer.append("/n" + msg.substring(j+1 ));
showAlert(buffer.toString());
}
/* 显示错误信息*/
private void showAlert(String err) {
Alert a = new Alert("");
a.setString(err);
a.setTimeout(Alert.FOREVER);
display.setCurrent(a);
}
/* 显示邮件列表*/
private void showMList(String msgStr) {
for (int i=0;i<MAX_LIST_SIZE;i++) {
msgs[i] = "";
}
menu = new List("Messages", Choice.IMPLICIT);
int delim = '?';
String sub = null;
int i =0;
int k = 0;
int l =0;
int j =msgStr.indexOf(delim);
while( j >= 0) {
sub = msgStr.substring(i,j);
if ((k % 2) == 0) {
msgs[l] = sub; // 第一项是邮件编号
l++;
} else
menu.append(sub, null);
k++;
i = j + 1;
j = msgStr.indexOf(delim, i);
}
sub = msgStr.substring(i);
menu.append(sub, null);
menu.addCommand(backCommand);
menu.addCommand(exitCommand);
menu.setCommandListener(this);
status = 1;
display.setCurrent(menu);
}
private void handleBack() {
if (status == 1) {
dmenu = null;
displayMenu();
} else
display.setCurrent(menu);
}
private void handleMainMenu() {
int index = dmenu.getSelectedIndex();
switch(index) {
case 0 :
if (user != null) {
retreiveMail(1, "0");
break;
}
case 1 :
status = 1;
loginUser();
break;
case 2 :
break;
}
}
private void handleMsgMenu() {
int index = menu.getSelectedIndex();
if (!msgs[index].equals("")) {
retreiveMail(2, msgs[index]); // 获取邮件
}
}
}
/*和邮件服务器通讯的Servlet*/
import java.io.*;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.mail.*;
import javax.mail.internet.MimeMessage;
import javax.servlet.*;
import javax.servlet.http.*;
public class CheckMailServlet extends HttpServlet {
private static String MSG_NOMAIL = "NOMAIL";
private static String MSG_INVALID_USER = "INVALIDUSR";
private static String MSG_CRITCAL_ERR = "UNEXPECTEDERROR";
public CheckMailServlet() {
String hostname = "yourserver.com"
//获取系统属性
Properties props = System.getProperties();
props.put("mail.pop3.host", "hostname");
Session session = Session.getDefaultInstance(props, null);
Store store = session.getStore("pop3");
}
/*获取请求参数 */
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException {
try {
String action = request.getParameter("a");
if(action == null)
doLogin(request, response);
else if(action.equals("r")) //获取
doRetrieve(request, response);
else if(action.equals("l")) //列表
doList(request, response);
} catch(Exception e) {
PrintWriter writer = response.getWriter();
writer.println(MSG_CRITCAL_ERR);
writer.flush();
}
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException {
doGet(request, response);
}
/* 执行登录操作*/
private void doLogin(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException, MessagingException {
String uid = request.getParameter("u");
String pwd, tmpUID ;
String responeStr = null;
if ((uid == null) || (uid.equals("")) ) {
responeStr = MSG_INVALID_USER;
} else {
int j =uid.indexOf('/');
if (j > 0) {
tmpUID = uid.substring(0,j);
pwd = uid.substring(j+1);
if(login(tmpUID,pwd)) {
responeStr = tmpUID;
flag = true;
} else
responeStr = MSG_INVALID_USER;
} else
responeStr = MSG_INVALID_USER;
}
PrintWriter writer = response.getWriter();
writer.print(responeStr);
writer.flush();
}
public boolean login(String uid, String pwd) // 登录
{
store.connect(hostname,uid,pwd);
if (store.isConnected()) {
return true;
} else
return false;
}
/* 列出收件箱中所有的邮件*/
private void doList(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException, MessagingException {
String uid = request.getParameter("u");
String responeStr = "";
MailLister lister = null;
StringBuffer buffer = new StringBuffer(200);
try {
lister = getMailLister(uid);
} catch(Exception exp) {
throw new ServletException(exp.getMessage());
}
if ( (lister != null) && (lister.size() > 0)) {
Vector vect = lister.keys();
int listSize = vect.size();
int endingNum = (listSize > 8) ? (listSize - 8) : 0;
for (int j = listSize-1; j>=endingNum; j--) {
String curKey = (String)vect.elementAt(j);
String msgString = (String)lister.get(curKey);
if (j != endingNum)
buffer.append( curKey + "?" + msgString + "?");
else
buffer.append(curKey + "?" + msgString);
}
responeStr = buffer.toString();
} else
responeStr = MSG_NOMAIL;
PrintWriter writer = response.getWriter();
writer.print(responeStr);
writer.flush();
}
/* 将所有的邮件存在Hashtable里 */
private MailLister getMailLister(String uid) throws Exception {
MailLister lister = null;
int j =uid.indexOf('/');
String ud;
String pwd;
if (j > 0) {
ud = uid.substring(0,j);
pwd = uid.substring(j+1);
if(login(ud,pwd)) {
// 打开文件夹
Folder folder = store.getDefaultFolder();
if (folder == null) {
System.out.println("No default folder");
return null;
}
folder = folder.getFolder("INBOX");
if (folder == null) {
System.out.println("Invalid folder");
return null;
}
folder.open(Folder.READ_ONLY);
// 获得目录
Message message[] = folder.getMessages();
lister = new MailLister()
for (int i=0, n=message.length; i<n; i++) {
Message m = folder.getMessage(i);
lister.put(m,i);
}
} else
return lister;
} else
return lister;
return lister;
}
/* 从收件箱中获取邮件编号为msgID的邮件*/
private void doRetrieve(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException, MessagingException {
String msgId = request.getParameter("i");
String uid = request.getParameter("u");
try {
Message msg = getMessageFromStore(msgId, uid);
if (msg == null)
throw new ServletException(
"Could not Load the Message File");
writeMessage(msg, request, response, uid, msgId);
} catch(Exception exp) {
throw new ServletException(exp.getMessage());
}
}
private String getMsgHeading(Message msg) throws Exception {
StringBuffer buffer = new StringBuffer(300);
buffer.append("From:");
getAddressesList(msg.getFrom(), buffer);
buffer.append(" To:");
getAddressesList(
msg.getRecipients(javax.mail.Message.RecipientType.TO),
buffer);
buffer.append(" Subject:");
buffer.append(msg.getSubject());
buffer.append(" Date:");
buffer.append(msg.getSentDate());
return buffer.toString();
}
private void getAddressesList(Address addresses[], StringBuffer buffer)
throws Exception {
String uName;
String uEmail;
if(addresses != null) {
for(int i = 0; i < addresses.length; i++) {
buffer.append(addresses[i] + ";");
}
}
}
/* 根据MIME类型编写邮件然后发送给移动设备*/
protected void writeMessage(Message msg, HttpServletRequest request,
HttpServletResponse response, String uid, String msgId)
throws Exception {
if(msg.isMimeType("multipart/*")) {
Multipart multipart = (Multipart)msg.getContent();
int msgPartCount = multipart.getCount();
StringBuffer buffer = new StringBuffer(200);
for(int i = 0; i < msgPartCount; i++) {
Part p = multipart.getBodyPart(i);
if (i == 0) {
buffer.append(getMsgHeading(msg));
}
if(p.isMimeType("text/plain")) {
String content = (String)p.getContent();
buffer.append(content.trim());
} else {
String filename = p.getFileName();
buffer.append(" --- Has attachement " + filename);
}
if (i == (msgPartCount-1)) {
response.setContentType("text/plain");
PrintWriter writer = null;
writer = response.getWriter();
writer.print(removeExtraChar(buffer.toString(), '/n'));
writer.flush();
}
}
} else if(msg.isMimeType("text/plain")) {
printAscii(response, (String)msg.getContent() , msg);
} else // HTML或者其他类型的内容
{
writePart(msg, -1, response);
}
}
private void printAscii(HttpServletResponse response,
String currentText, Message msg ) throws Exception {
PrintWriter writer = response.getWriter();
if (currentText.length() > 1500)
currentText = currentText.substring(0,1500);
writer.print(getMsgHeading(msg) + currentText);
writer.flush();
}
private Message getMessageFromStore(String msgUID, String uid)
throws Exception {
MailLister lister = getMailLister(uid)
if(lister != null) {
return lister.get(msgUID);
} else
return null;
}
private void writePart(Message msg, int partnr,
HttpServletResponse response) throws Exception {
Part p = msg;
String responseStr ;
if (p.isMimeType("text/html")) {
String str = (String)p.getContent();
if (str.length() > 1500)
str = str.substring(0,1500);
responseStr = removeHTMLFormatting(str);
responseStr = removeExtraChar(responseStr, '/n');
} else
responseStr = "移动设备不支持此MIME类型的邮件";
response.setContentType("text/plain");
PrintWriter writer = response.getWriter();
writer.print(getMsgHeading(msg) + responseStr);
writer.flush();
}
private String removeHTMLFormatting(String str) {
boolean insideTag = false;
String token;
StringBuffer buffer = new StringBuffer(200);
StringTokenizer st = new StringTokenizer( str , "<>", true);
while( st.hasMoreTokens() ) {
token = st.nextToken();
if ( token.equals( "<" ) )
insideTag = true;
else if ( token.equals( ">" ) )
insideTag = false;
else if ( insideTag == false )
buffer.append( token );
}
return buffer.toString();
}
private String removeExtraChar(String str, int delim) {
StringBuffer buffer = new StringBuffer(200);
// 第一个子串
int j =str.indexOf(delim);
int i = 0;
while( j >= 0) {
// Add some extra space
buffer.append(" " + str.substring(i,j));
i = j + 1;
j = str.indexOf(delim, i); // 剩下的子串
}
buffer.append(str.substring(i)); // 最后一个子穿
return buffer.toString();
}
/* 这个MailLister类存储所有的邮件到一个Hashtable中并且可以根据指定的key取回这些邮件*/
public class MailLister implements java.io.Serializable {
private Hashtable hash;
private Vector vect;
public MailLister() {
vect = new Vector();
hash = new Hashtable(vect.capacity());
}
public Object get(Object obj) {
return hash.get(obj);
}
public void put(Object key, Object val) {
if(!vect.contains(key))
vect.insertElementAt(key, vect.size());
hash.put(key, val);
}
}
}