使用JavaMail收发Internet邮件

JavaMail是JavaEE中的一个组件,用来开发邮件客户端程序(MUA)。JavaMail API本身是与具体的消息协议无关的,可以在运行程序之前设置实现具体协议的providers,例如在Sun的mail.jar中提供了一个缺省的文件javamail.default.providers,里面提供了三个协议(imap, smtp和pop3)的实现,其中smtp的provider类是com.sun.mail.smtp.SMTPTransport。如果用户需要开发NNTP协议的客户端程序,可以考虑其他的provider,例如GNU JavaMail。

JavaMail需要JavaSE中的 JavaBeans Activation Framework(JAF)才能运行,JAF位于package: javax.activation.*。这是因为接口Part/MimePart(实现类包括 Message,MimeMessage,BodyPart和MimeBodyPart)需要javax.activation.DataHandler来处理邮件的内容。


********Message的结构********

javax.mail.Message类是一个抽象类,针对Internet邮件,JavaMail中提供了一个具体类javax.mail.internet.MimeMessage。

一条邮件消息Message包含header和content两部分。

header包含Part接口中定义的通用头属性和实现类(比如Message,MimeMessage)中定义的头属性。例如MimeMessage的setHeader("X-Mailer","ljsspace")设置Internet邮件的X-Mailer头,MimeBodyPart的setHeader("Content-ID","a5c8x3f7i98")设置一个BodyPart的Content-ID,以便在其他Part的content中通过cid:a5c8x3f7i98引用该部分内容。

content可以是文本(包含text/plain或text/html),DataHandler或者Multipart/MimeMultipart。例如Part接口的setText(String)用来设置text/plain内容,setContent(String,"text/html")用来设置text/html内容,setContent(Multipart)用来设置Multipart内容,setDataHandler(DataHandler)设置DataHandler内容。另外,为了获取Message的内容,使用getDataHandler和getContent是具有同等效果。

上面提到的Multipart/MimeMultipart类是一个容器,它可以包含多个BodyPart/MimeBodyPart作为该容器中的组成部分,例如一封Internet邮件包含一个text/plain正文和一个附件,正文是一个MimeBodyPart,附件也是一个MimeBodyPart,合起来就是一个MimeMultipart,然后该MimeMultipart作为邮件MimeMessage的content。BodyPart也是Part接口的实现,即也是包含header和content两部分,显然BodyPart的content也可以是一个Multipart,甚至更多级的层次结构。


********接收和发送邮件********

接收邮件在JavaMail中使用的术语的是store,对应的Internet邮件协议有pop3和imap等(遵照JavaMail的习惯,协议名称一律用小写),每一个store中可以能有多有folders(一般情况下pop3中只支持INBOX这一个folder)。发送邮件在JavaMail中使用的术语是transport,对应的Internet邮件协议有smtp等。

在收发邮件之前需要建立一个Session对象,它是一个Factory类,可以生成收发邮件的Store和Transport对象。在smtp协议中,大部分MTA需要用邮件发送人地址的帐号通过认证才允许发邮件,以防open relay产生垃圾邮件,因此需要设置mail.smtp.auth为true,并在构建Session对象时指定一个Authenticator(也可以在transport.connect()时指定认证帐号)。

发送邮件可以用transport.send()或Transport.send(),后者是一个静态方法。如果使用静态方法,JavaMail会根据接收人的邮件地址构造transport对象来发送邮件,这是在后台自动完成的。另外Transport.send有两个重载方法,Transport.send(MimeMessage)根据message中的接收人列表发送邮件,Transport(MimeMessage,InternetAddress[])忽略message中的接收人列表,而直接按第二个参数的地址列表发送邮件,利用这个特点可以给邮件组(mailing list)发送邮件,参考以下代码实现。

接收邮件在JavaMail中使用一个lightweight的类MimeMessage,例如在调用inbox.getMessages()之后,并不是立即将有所有的邮件头和内容全部从store中读取过来,只有在需要的时候才读取。为此,JavaMail还提供了一个FetchProfile类,可以从store中获取所有邮件的部分头信息,而不必读取邮件内容。


********总结********

JavaMail是一个独立于具体协议的邮件或消息框架,除了上面介绍的核心内容之外,JavaMail还支持类似于Swing/AWT中的事件响应机制,而且还有一个专门的package(javax.mail.search)用来根据过滤条件从folder中检索邮件。使用JavaMail可以较轻松地构建一个跨平台的Internet邮件客户端程序,或者在企业环境下开发出邮件或消息子系统。

参考:JavaMail 1.4: http://www.oracle.com/technetwork/java/javamail/index.html

代码:

 

import java.io.File;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.FetchProfile;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

/**
*
* JavaMail examples: send and fetch mail messages
*  
* Copyright (c) 2011 ljs (http://blog.csdn.net/ljsspace/)
* Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php)
*
* @author ljs
* 2011-10-10
*
*/
public class JavaMail {
	/**
	 * send a message to a mailing list (e.g. java-list@ljsspace.org). The actual receivers (e.g. toAddr)
	 * are specified at the last moment when transport.send is called.
	 */
	public void sendMail(String host, final String user,
			final String password,
			String fromAddr,String toAddr,String subject,
			String msgText,File attachment,String filename) {
//		Transport transport = null;
		try {
			Properties props = System.getProperties(); //use system properties
			props.put("mail.debug", "true"); //or: session.setDebug(true)
			props.put("mail.transport.protocol", "smtp"); 			
			props.put("mail.smtp.host", host);
			props.put("mail.smtp.user", user);	
			
			//if SMTP authentication is required, we must set this property
			props.put("mail.smtp.auth", "true");  


			Authenticator auth = new Authenticator() {
				public PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication(user, password);
				}
			};
			Session session = Session.getInstance(props, auth);//use authentication
			// session = Session.getDefaultInstance(props, null);
			
			MimeMessage msg = new MimeMessage(session); 
			
			msg.setFrom(new InternetAddress(fromAddr));
			//InternetAddress[] toAddress = {new InternetAddress(toAddr)};
			//msg.setRecipients(Message.RecipientType.TO, toAddress);
			String mailingListAddr = "java-list@ljsspace.org";
			msg.addRecipient(Message.RecipientType.TO, new InternetAddress(mailingListAddr,"Java List"));
			msg.setSubject(subject);
			
		
		    msg.setHeader("X-Mailer", "ljsspace-javamail");
		    msg.setSentDate(new Date());
		    
		    //create a multipart as the content
		    MimeMultipart multipart = new MimeMultipart();
		    
	    	MimeBodyPart mbp1 = new MimeBodyPart();
	    	mbp1.setText(msgText); 
	    	multipart.addBodyPart(mbp1);
		      
	    	//attachment
	    	DataSource fileDS = new FileDataSource(attachment);
			DataHandler fileDH = new DataHandler(fileDS);
			MimeBodyPart file_attachment = new MimeBodyPart();
			file_attachment.setDataHandler(fileDH);   
			file_attachment.setFileName(filename);				
			multipart.addBodyPart(file_attachment);
			
			//set content for the message; the content is a multipart object
			msg.setContent(multipart);
			//msg.saveChanges(); //unnecessary: Transport.send will call saveChanges
			
			//transport = session.getTransport(); 
			//transport.connect();
			//transport.send(msg);
			
			InternetAddress[] toAddress = {new InternetAddress(toAddr)};
			//Transport.send(msg); //only send to message's getRecipients()
			Transport.send(msg,toAddress); //ignore message's getRecipients()
		} catch (Exception e) {
			e.printStackTrace();
		} 
//		finally{	
//			try {
//				transport.close();
//			} catch (Exception ex) {
//				ex.printStackTrace();
//			}
//		}
	}

	/**
	 * Fetch messages from the INBOX store
	 * @param preview If true, display all messages' profiles; otherwise, display the contents of the first two new messages 
	 */
	public void fetchMail(boolean preview,String host, final String user,
			final String password) {
		Store store = null;
		Folder inbox = null;
		try {
			Properties props = System.getProperties();			
			props.put("mail.debug", "true");
			props.put("mail.store.protocol", "pop3"); //or store like imap
			props.put("mail.pop3.user", user); //no password!
			props.put("mail.pop3.host", host); 
			
			Authenticator auth = new Authenticator() {
				public PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication(user, password);
				}
			};
			Session session = Session.getDefaultInstance(props, auth);
			
			// Get hold of a POP3 message store using session (a factory object)
			store = session.getStore();  //the same as session.getStore("pop3"). Since we've set mail.store.protocol property, we just call session.getStore().
			// store.connect(host, user, password); //use authenticator instead
			store.connect(); //connect using session's authenticator

			// inbox = store.getDefaultFolder(); //the root folder in the default namespace
			inbox = store.getFolder("INBOX"); //the only folder in POP3
			inbox.open(inbox.READ_WRITE);

			// Get the messages (a light-weight operation)
			Message[] msgs = inbox.getMessages();

			if(preview){
				FetchProfile fp = new FetchProfile();
				fp.add(FetchProfile.Item.ENVELOPE); //fetch subject, from, etc.
				fp.add("X-mailer"); //fetch x-mailer
				inbox.fetch(msgs, fp);	
				
				for (int i = 0; i < inbox.getMessageCount(); i++) {
					displayMessageProfile(msgs[i]);
				}
			}else{
				//read the first 2 messages only (from the newest to the oldest)
				for (int i = inbox.getMessageCount()-1; i>=0 && i > inbox.getMessageCount() - 3; i--) {
					processMessage(msgs[i]);
					//msgs[i].setFlag(Flags.Flag.DELETED, true);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (inbox != null)
					inbox.close(true); //expunge the deleted message
				if (store != null)
					store.close();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	// display a light-weight message's profile
	private void displayMessageProfile(Message message) {
		try {
			System.out.println(message.getFrom()[0] + "\t" + message.getSubject());
		} catch (MessagingException e) {			
			e.printStackTrace();
		}		
	}
	private void processMessage(Message message) {
		try {
			System.out.println("*******" + message.getSubject() + "*******");
			readPart(message);
		} catch (MessagingException e) {			
			e.printStackTrace();
		}	
	}
	
	private void readPart(Part p) {
		try {
			Object content = p.getContent();
			if(content instanceof String){
				System.out.println(content);
			}else if (content instanceof Multipart) {
				Multipart mp = (Multipart) content;
				int count = mp.getCount();
				for (int i = 0; i < count; i++) {
					Part bodyPart = mp.getBodyPart(i); //or check: boyPart.getDisposition()
					readPart(bodyPart); //recursion
				}
			}else if (content instanceof InputStream) {
				System.out.println("****found inputstream as a part's content****");
			}else{
				System.out.println("****unknown type****");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {		
		//test store: pop3
		String pop3host="pop.126.com";
		String pop3user="abc"; //test account
		String pop3pass="******";
		JavaMail mailer = new JavaMail();
		mailer.fetchMail(true,pop3host, pop3user, pop3pass);
		
		
		//test transport: smtp
		String smtphost="smtp.126.com";
		String smtpuser="abc"; //test account
		String smtppass="******";
		String fromAddr="abc@126.com";
		String toAddr="someone@somewhere.com";		
		String subject="A Test Message sent via JavaMail";
		String msgText = "Please see the attachment for details.";
		File attachment = new File("/tmp/test.pdf");
		String filename = "test.pdf";
		mailer.sendMail(smtphost, smtpuser,smtppass,
				fromAddr,toAddr,subject,
				msgText,attachment,filename);
	}

}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
收发邮件需要使用JavaMail API,以下是在Linux下利用JavaMail收发邮件的步骤: 1.下载JavaMail API,这里建议使用最新的JavaMail 1.6.2版本,下载地址为:https://javaee.github.io/javamail/,下载后解压到任意目录。 2.在Linux系统上安装SMTP和POP3服务,这里以Postfix和Dovecot为例,安装命令为: ``` sudo apt-get install postfix dovecot-core dovecot-imapd dovecot-pop3d ``` 3.配置Postfix和Dovecot,具体配置步骤可以参考相关文档。 4.编写Java程序,实现邮件收发功能,以下是一个简单的JavaMail收发邮件示例代码: ``` import java.util.*; import javax.mail.*; import javax.mail.internet.*; public class MailClient { public static void main(String[] args) throws Exception { String host = "localhost"; String user = "your_username"; String password = "your_password"; // 创建Properties对象,设置邮件服务器的相关信息 Properties props = new Properties(); props.setProperty("mail.smtp.host", host); props.setProperty("mail.smtp.auth", "true"); props.setProperty("mail.smtp.port", "587"); props.setProperty("mail.smtp.starttls.enable", "true"); // 创建Session对象,用于和邮件服务器交互 Session session = Session.getInstance(props, new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(user, password); } }); // 创建MimeMessage对象,设置邮件的相关信息 MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress("[email protected]")); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("[email protected]")); message.setSubject("Test Email"); message.setText("Hello World!"); // 发送邮件 Transport.send(message); // 接收邮件 Store store = session.getStore("pop3"); store.connect(host, user, password); Folder inbox = store.getFolder("INBOX"); inbox.open(Folder.READ_ONLY); Message[] messages = inbox.getMessages(); for (Message msg : messages) { System.out.println("Subject: " + msg.getSubject()); System.out.println("From: " + msg.getFrom()[0]); System.out.println("Content: " + msg.getContent().toString()); } inbox.close(false); store.close(); } } ``` 在上述代码中,需要把`host`、`user`和`password`替换成实际的邮件服务器、用户名和密码。 5.编译并运行程序,如果一切正常,就可以在控制台上看到发送的邮件接收到的邮件的相关信息了。 注意:在Linux系统中,如果要使用SSL加密连接邮件服务器,需要在Java程序中添加相关的配置信息。具体配置方法可以参考JavaMail API的文档和示例代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值