本文根据Ian F. Darwin的《Java Cookbook》整理而成,原书用整章的文字介绍如何发邮件,可能头绪会比较乱,本文则将其浓缩成一篇文章,力求使完全不懂JavaMail的人,都可以根据文中指示稍作修改,拿来就可以用。如果对其中原理还有不清楚,你可以参考原书。
一、首先要用到三个java文件:
1.MailConstants.java,properties文件的助记符:
///////////////////////////////////////////////////////////////////////
package untitled2;
/** Simply a list of names for the Mail System to use.
* If you "implement" this interface, you don't have to prefix
* all the names with MailProps in your code.
*/
public interface MailConstants {
public static final String PROPS_FILE_NAME = "MailClient.properties";
public static final String SEND_PROTO = "Mail.send.protocol";
public static final String SEND_USER = "Mail.send.user";
public static final String SEND_PASS = "Mail.send.password";
public static final String SEND_ROOT = "Mail.send.root";
public static final String SEND_HOST = "Mail.send.host";
public static final String SEND_DEBUG = "Mail.send.debug";
public static final String RECV_PROTO = "Mail.receive.protocol";
public static final String RECV_PORT = "Mail.receive.port";
public static final String RECV_USER = "Mail.receive.user";
public static final String RECV_PASS = "Mail.receive.password";
public static final String RECV_ROOT = "Mail.receive.root";
public static final String RECV_HOST = "Mail.receive.host";
public static final String RECV_DEBUG = "Mail.receive.debug";
}
///////////////////////////////////////////////////////////////////////
2.FileProperties.java,从文件中读取properties:
///////////////////////////////////////////////////////////////////////
package untitled2;
import java.io.*;
import java.util.*;
/**
* The <CODE>FileProperties</CODE> class extends <CODE>Properties</CODE>,
* "a persistent set of properties [that] can be saved to a stream
* or loaded from a stream". This subclass attends to all the mundane
* details of opening the Stream(s) for actually saving and loading
* the Properties.
*
* <P>This subclass preserves the useful feature that
* a property list can contain another property list as its
* "defaults"; this second property list is searched if
* the property key is not found in the original property list.
*
* @author Ian F. Darwin, ian@darwinsys.com
* @version $Id: FileProperties.java,v 1.5 2001/04/28 13:22:37 ian Exp $
*/
public class FileProperties
extends Properties {
protected String fileName = null;
/**
* Construct a FileProperties given a fileName.
* @param loadsaveFileName the progerties file name
* @throws IOException
*/
public FileProperties(String loadsaveFileName) throws IOException {
super();
fileName = loadsaveFileName;
load();
}
/** Construct a FileProperties given a fileName and
* a list of default properties.
* @param loadsaveFileName the properties file name
* @param defProp the default properties
* @throws IOException
*/
public FileProperties(String loadsaveFileName, Properties defProp) throws
IOException {
super(defProp);
fileName = loadsaveFileName;
load();
}
/** The InputStream for loading */
protected InputStream inStr = null;
/** The OutputStream for loading */
protected OutputStream outStr = null;
/** Load the properties from the saved filename.
* If that fails, try again, tacking on the .properties extension
* @throws IOException
*/
public void load() throws IOException {
try {
if (inStr == null) {
inStr = new FileInputStream(fileName);
}
}
catch (FileNotFoundException fnf) {
if (!fileName.endsWith(".properties")) {
inStr = new FileInputStream(fileName + ".properties");
// If we succeeded, remember it:
fileName += ".properties";
}
else {
// It did end with .properties and failed, re-throw exception.
throw fnf;
}
}
// now message the superclass code to load the file.
load(inStr);
}
/** Save the properties for later loading. *
* @throws IOException
*/
public void save() throws IOException {
if (outStr == null) {
outStr = new FileOutputStream(fileName);
}
// Get the superclass to do most of the work for us.
store(outStr, "# Written by FileProperties.save() at " + new Date());
}
public void close() {
try {
if (inStr != null) {
inStr.close();
}
if (outStr != null) {
outStr.close();
}
}
catch (IOException e) {
// don't care
}
}
}
///////////////////////////////////////////////////////////////////////
3.Mailer.java,将javamail发邮件的部分进行封装:
///////////////////////////////////////////////////////////////////////
package untitled2;
import java.util.*;
import java.io.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;
public class Mailer {
/** The javamail session object. */
protected Session session;
/** The sender's email address */
protected String from;
/** The subject of the message. */
protected String subject;
/** The recipient ("To:"), as Strings. */
protected ArrayList toList = new ArrayList();
/** The CC list, as Strings. */
protected ArrayList ccList = new ArrayList();
/** The BCC list, as Strings. */
protected ArrayList bccList = new ArrayList();
/** The text of the message. */
protected String body;
/** The SMTP relay host */
protected String mailHost;
/** The accessories list, as Strings.*/
protected ArrayList accessories = new ArrayList();
/** The verbosity setting */
protected boolean verbose;
/** Get from
* @return where the mail from
*/
public String getFrom() {
return from;
}
/** Set from
* @param fm where the mail from
*/
public void setFrom(String fm) {
from = fm;
}
/** Get subject
* @return the mail subject
*/
public String getSubject() {
return subject;
}
/** Set subject
* @param subj the mail subject
*/
public void setSubject(String subj) {
subject = subj;
}
// SETTERS/GETTERS FOR TO: LIST
/** Get tolist, as an array of Strings
* @return the list of toAddress
*/
public ArrayList getToList() {
return toList;
}
/** Set to list to an ArrayList of Strings
* @param to the list of toAddress
*/
public void setToList(ArrayList to) {
toList = to;
}
/** Set to as a string like "tom, mary, robin@host". Loses any
* previously-set values.
* @param s the list of toAddress*/
public void setToList(String s) {
toList = tokenize(s);
}
/** Add one "to" recipient
* @param to the toAddress
*/
public void addTo(String to) {
toList.add(to);
}
// SETTERS/GETTERS FOR CC: LIST
/** Get cclist, as an array of Strings
* @return the list of ccAddress
*/
public ArrayList getCcList() {
return ccList;
}
/** Set cc list to an ArrayList of Strings
* @param cc the list of ccAddress
*/
public void setCcList(ArrayList cc) {
ccList = cc;
}
/** Set cc as a string like "tom, mary, robin@host". Loses any
* previously-set values.
* @param s the list of ccAddress
*/
public void setCcList(String s) {
ccList = tokenize(s);
}
/** Add one "cc" recipient
* @param cc the address of cc
*/
public void addCc(String cc) {
ccList.add(cc);
}
// SETTERS/GETTERS FOR BCC: LIST
/** Get bcclist, as an array of Strings
* @return the list of bcc
*/
public ArrayList getBccList() {
return bccList;
}
/** Set bcc list to an ArrayList of Strings
* @param bcc the address of bcc
*/
public void setBccList(ArrayList bcc) {
bccList = bcc;
}
/** Set bcc as a string like "tom, mary, robin@host". Loses any
* previously-set values.
* @param s the address of bcc
*/
public void setBccList(String s) {
bccList = tokenize(s);
}
/** Add one "bcc" recipient
* @param bcc the address of bcc
*/
public void addBcc(String bcc) {
bccList.add(bcc);
}
// SETTER/GETTER FOR MESSAGE BODY
/** Get message
* @return the mail body
*/
public String getBody() {
return body;
}
/** Set message
* @param text the mail body
*/
public void setBody(String text) {
body = text;
}
// SETTER/GETTER FOR ACCESSORIES
/** Get accessories
* @return the arrayList of the accessories
*/
public ArrayList getAccessories() {
return accessories;
}
/** Set accessories
* @param accessories the arrayList of the accessories
*/
public void setAccessories(ArrayList accessories) {
this.accessories = accessories;
}
// SETTER/GETTER FOR VERBOSITY
/** Get verbose
* @return verbose
*/
public boolean isVerbose() {
return verbose;
}
/** Set verbose
* @param v the verbose
*/
public void setVerbose(boolean v) {
verbose = v;
}
/** Check if all required fields have been set before sending.
* Normally called e.g., by a JSP before calling doSend.
* Is also called by doSend for verification.
* @return if complete return true else return false
*/
public boolean isComplete() {
if (from == null || from.length() == 0) {
System.err.println("doSend: no FROM");
return false;
}
if (subject == null || subject.length() == 0) {
System.err.println("doSend: no SUBJECT");
return false;
}
if (toList.size() == 0) {
System.err.println("doSend: no recipients");
return false;
}
if (body == null || body.length() == 0) {
System.err.println("doSend: no body");
return false;
}
if (mailHost == null || mailHost.length() == 0) {
System.err.println("doSend: no server host");
return false;
}
return true;
}
public void setServer(String s) {
mailHost = s;
}
/** Send the message.
* @throws MessagingException
*/
public synchronized void doSend() throws MessagingException {
if (!isComplete()) {
throw new IllegalArgumentException(
"doSend called before message was complete");
}
/** Properties object used to pass props into the MAIL API */
Properties props = new Properties();
props.put("mail.smtp.host", mailHost);
// Create the Session object
if (session == null) {
session = Session.getDefaultInstance(props, null);
if (verbose) {
session.setDebug(true); // Verbose!
}
}
// create a message
final Message mesg = new MimeMessage(session);
InternetAddress[] addresses;
// TO Address list
addresses = new InternetAddress[toList.size()];
for (int i = 0; i < addresses.length; i++) {
addresses[i] = new InternetAddress( (String) toList.get(i));
}
mesg.setRecipients(Message.RecipientType.TO, addresses);
// From Address
mesg.setFrom(new InternetAddress(from));
// CC Address list
addresses = new InternetAddress[ccList.size()];
for (int i = 0; i < addresses.length; i++) {
addresses[i] = new InternetAddress( (String) ccList.get(i));
}
mesg.setRecipients(Message.RecipientType.CC, addresses);
// BCC Address list
addresses = new InternetAddress[bccList.size()];
for (int i = 0; i < addresses.length; i++) {
addresses[i] = new InternetAddress( (String) bccList.get(i));
}
mesg.setRecipients(Message.RecipientType.BCC, addresses);
// The Subject
mesg.setSubject(subject);
// Now the message body.
Multipart mp = new MimeMultipart();
MimeBodyPart mbp = null;
mbp = new MimeBodyPart();
mbp.setText(body);
mp.addBodyPart(mbp);
// Now the accessories.
int accessoriesCount = accessories.size();
File f;
DataSource ds;
String uf;
int j;
for (int i = 0; i < accessoriesCount; i++) {
mbp = new MimeBodyPart();
f = new File( (String) accessories.get(i));
ds = new FileDataSource(f);
mbp.setDataHandler(new DataHandler(ds));
j = f.getName().lastIndexOf(File.separator);
uf = f.getName().substring(j + 1);
mbp.setFileName(uf);
mp.addBodyPart(mbp);
}
mesg.setContent(mp);
// Finally, send the message! (use static Transport method)
// Do this in a Thread as it sometimes is too slow for JServ
// new Thread() {
// public void run() {
// try {
Transport.send(mesg);
// } catch (MessagingException e) {
// throw new IllegalArgumentException(
// "Transport.send() threw: " + e.toString());
// }
// }
// }.start();
}
/** Convenience method that does it all with one call.
* @param mailhost - SMTP server host
* @param recipient - domain address of email (user@host.domain)
* @param sender - your email address
* @param subject - the subject line
* @param message - the entire message body as a String with embedded \n's
* @param accessories - the accessories list
* @throws MessagingException
*/
public static void send(String mailhost,
String recipient, String sender, String subject,
String message, ArrayList accessories) throws
MessagingException {
Mailer m = new Mailer();
m.setServer(mailhost);
m.addTo(recipient);
m.setFrom(sender);
m.setSubject(subject);
m.setBody(message);
m.setAccessories(accessories);
m.doSend();
}
/** Convert a list of addresses to an ArrayList. This will work
* for simple names like "tom, mary@foo.com, .com]123.45@c$.com"
* but will fail on certain complex (but RFC-valid) names like
* "(Darwin, Ian) <ian@darwinsys.com>".
* Or even "Ian Darwin <ian@darwinsys.com>".
* @param s the string of some list
* @return the list after split
*/
protected ArrayList tokenize(String s) {
ArrayList al = new ArrayList();
StringTokenizer tf = new StringTokenizer(s, ",");
// For each word found in the line
while (tf.hasMoreTokens()) {
// trim blanks, and add to list.
al.add(tf.nextToken().trim());
}
return al;
}
}
///////////////////////////////////////////////////////////////////////
二、创建一个properties文件:
MailClient.properties:
///////////////////////////////////////////////////////////////////////
# This file contains my default Mail properties.
#
# Values for sending
Mail.send.proto=smtp
Mail.send.host=student.zsu.edu.cn
Mail.send.debug=true
#
# Values for receiving
Mail.receive.host=student.zsu.edu.cn
Mail.receive.protocol=pop3
Mail.receive.user=xx
Mail.receive.pass=ASK
Mail.receive.root=d:\test
///////////////////////////////////////////////////////////////////////
三、创建主程序,生成Mailer.java里面的Mailer类的对象,设置参数,发出邮件。
首先import:
///////////////////////////////////////////////////////////////////////
import java.io.*;
import java.util.*;
import javax.mail.internet.*;
import javax.mail.*;
import javax.activation.*;
///////////////////////////////////////////////////////////////////////
然后用下面的代码完成发送:
///////////////////////////////////////////////////////////////////////
try {
Mailer m = new Mailer();
FileProperties props =
new FileProperties(MailConstants.PROPS_FILE_NAME);
String serverHost = props.getProperty(MailConstants.SEND_HOST);
if (serverHost == null) {
System.out.println("\"" + MailConstants.SEND_HOST +
"\" must be set in properties");
System.exit(0);
}
m.setServer(serverHost);
String tmp = props.getProperty(MailConstants.SEND_DEBUG);
m.setVerbose(tmp != null && tmp.equals("true"));
String myAddress = props.getProperty("Mail.address");
if (myAddress == null) {
System.out.println("\"Mail.address\" must be set in properties");
System.exit(0);
}
m.setFrom(myAddress);
//以下根据具体情况设置:===============================================
m.setToList("xx@zsu.edu.cn");//收件人
m.setCcList("xx@163.com,yy@163.com");//抄送,每个地址用逗号隔开;或者用一个ArrayList的对象作为参数
// m.setBccList(bccTF.getText());
m.setSubject("demo");//主题
// Now copy the text from the Compose TextArea.
m.setBody("this is a demo");//正文
// XXX I18N: use setBody(msgText.getText(), charset)
ArrayList v=new ArrayList();
v.add("d:\\test.htm");
m.setAccessories(v);//附件
//以上根据具体情况设置=================================================
// Finally, send the sucker!
m.doSend();
}
catch (MessagingException me) {
me.printStackTrace();
while ( (me = (MessagingException) me.getNextException()) != null) {
me.printStackTrace();
}
System.out.println("Mail Sending Error:\n" + me.toString());
}
catch (Exception ex) {
System.out.println("Mail Sending Error:\n" + ex.toString());
}
///////////////////////////////////////////////////////////////////////