Java郵件服務學習之三:郵箱服務客戶端-Java Mail

 

1、java mail的兩個JAR包html

一、mail.jar:不在JDK中,核心功能依賴JDK4及以上,該jar包已經加入到java EE5;java

下載地址:http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-eeplat-419426.html服務器

 

二、activation.jar:JavaMail依賴JAF(JavaBeans Activation Framework),JAF在Java6以後已經合併到JDK中,而JDK5以前須要另外下載JAF的類庫。session

最好單獨下載加入到工程中。oracle

下載地址:http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html測試

 

2、經常使用API介紹this

  1. javax.mail.Session:會話類,如服務器的主機名、端口號、協議名稱等  主要用來建立郵件對象、實現郵件對象中數據的封裝並可指定郵件服務器認證的客戶端屬性。它表示程序與某一個郵件服務器即將創建通訊,在創建的過程能夠進行口令認證。
  2. javax.mail.Message:郵件模型,發送郵件和接收郵件的媒介,封裝了郵件的信息,如發件人、收件人、郵件標題、郵件內容等  
  3. javax.mail.Transport:郵件發送類 鏈接郵件SMTP服務器,發送郵件  
  4. javax.mail.Store:郵件接收類 鏈接郵件POP三、IMAP服務器,收取郵件, 郵件服務器中的存儲庫,裏面放着全部的郵件文件夾
  5. javax.mail.internet.InternetAddress 主要是表示郵件發送人和郵件接收人的地址
  6. javax.mail.Folder  該文件夾就是消息的具體所在文件夾,默認的郵件均在INBOX文件中

3、使用java mail 發送郵件編碼

基本步驟:spa

1 利用Properties來設置Session,通常主要設置兩個mail.smtp.host和mail.smtp.auth,第一個主要是設置郵件服務器名,第二個是設置口令true或者false.net

2 利用Session.getInstance(Properties)啓動一個與郵件服務器的會話

3 根據獲取的Session來傳建一個消息Message

4 定義消息的發信人地址InternetAddress和消息的收信人地址。

5 設置消息發送的主題和內容

6 利用Message.saveChanges()來存儲填寫的郵件信息

7 根據Session.getTransport("smtp")獲取郵件發送類

8 利用發送人的用戶名和密碼鏈接到指定的郵件服務器

9 將該消息發送

10 關閉鏈接

eg:

(1)發送一個純文本郵件

package mail;

import java.util.Date;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

/**
 * 郵件發送服務
 */
public class SendMailService
{

    /**
     * 發送純文本郵件
     * @param smtpHost 郵件服務器
     * @param to 收件人(能夠是多個,使用逗號分隔)
     * @param cc 抄送人(能夠是多個,使用逗號分隔)
     * @param bcc密送人(能夠是多個,使用逗號分隔)
     * @param sender發件人
     * @param title郵件標題
     * @param content郵件內容
     * @param username郵箱用戶名(通常是去掉@以前的那一部分)
     * @param password(郵箱密碼)
     * @throws MessagingException
     */
    public static void sendPlainTextEmail(String smtpHost,
            String to,
            String cc,
            String bcc,
            String sender,
            String title,
            String content,
            String username,
            String password
            ) throws MessagingException
    {
        //第一步 利用Properties來設置Session,通常主要設置兩個mail.smtp.host和mail.smtp.auth,第一個主要是設置郵件服務器名,第二個是設置口令true或者false
        Properties props = new Properties();
        props.put("mail.host", smtpHost);
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true");
        
        //第二步 利用Session.getInstance(Properties)啓動一個與郵件服務器的會話
        Session session = Session.getInstance(props);
        session.setDebug(true);
        
        //第三步 根據獲取的Session來傳建一個消息Message
        MimeMessage message = new MimeMessage(session);
        
        //第四步 定義消息的發信人地址InternetAddress和消息的收信人地址。
        //發件人
        InternetAddress sendaddr = new InternetAddress(sender);
        message.setFrom(sendaddr);
        //收件人
        InternetAddress[] toaddrs = InternetAddress.parse(to);
        message.setRecipients(Message.RecipientType.TO, toaddrs);
        //抄送人
        InternetAddress[] ccaddrs = InternetAddress.parse(cc);
        message.setRecipients(Message.RecipientType.CC, ccaddrs);
        //密送人
        InternetAddress[] bccaddrs = InternetAddress.parse(bcc);
        message.setRecipients(Message.RecipientType.BCC, bccaddrs);
        //第五步 設置消息發送的主題、內容、時間
        message.setSubject(title);
        message.setText(content);
        message.setSentDate(new Date());
        //第六步 利用Message.saveChanges()來存儲填寫的郵件信息
        message.saveChanges();
        //第七步 根據Session.getTransport("smtp")獲取郵件發送類
        Transport ts = session.getTransport("smtp");
        //第八步 利用發送人的用戶名和密碼鏈接到指定的郵件服務器
        ts.connect(smtpHost, username, password);  
        //第九步將該消息發送
        ts.sendMessage(message, message.getAllRecipients());
        //第十步 關閉鏈接
        ts.close();
    }
    
}

(2)先建立已經過身份驗證的會話鏈接 再發送郵件

package mail;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;

/**
 * 用戶身份認證
 * @author Administrator
 *
 */
public class SmtpAuth extends Authenticator 
{

    private String username;
    private String password;
    
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    
    public void setUserinfo(String username,String password)
    {
        this.username = username;
        this.password = password;
    }

    protected PasswordAuthentication getPasswordAuthentication()
    {
        return new PasswordAuthentication(username,password);
    }
    
    
}
package mail;

import java.util.Date;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

/**
 * 郵件發送服務
 */
public class SendMailService
{

    /**
     * 發送純文本郵件
     * @param smtpHost 郵件服務器
     * @param to 收件人(能夠是多個,使用逗號分隔)
     * @param cc 抄送人(能夠是多個,使用逗號分隔)
     * @param bcc密送人(能夠是多個,使用逗號分隔)
     * @param sender發件人
     * @param title郵件標題
     * @param content郵件內容
     * @param username郵箱用戶名(通常是去掉@以前的那一部分)
     * @param password(郵箱密碼)
     * @throws MessagingException
     */
    
    public static void sendPlainTextEmailByAuth(String smtpHost,
            String to,
            String cc,
            String bcc,
            String sender,
            String title,
            String content,
            String username,
            String password
            ) throws MessagingException
    {
        //第一步 利用Properties來設置Session,通常主要設置兩個mail.smtp.host和mail.smtp.auth,第一個主要是設置郵件服務器名,第二個是設置口令true或者false
                Properties props = new Properties();
                props.put("mail.host", smtpHost);
                props.put("mail.transport.protocol", "smtp");
                props.put("mail.smtp.auth", "true");
                
                //第二步 利用Session.getInstance(Properties)啓動一個與郵件服務器的會話
                SmtpAuth sa = new SmtpAuth();
                sa.setUserinfo(username, password);
                //Session session = Session.getInstance(props, sa);
                Session session = Session.getDefaultInstance(props, sa);
                session.setPasswordAuthentication(new URLName(smtpHost), sa.getPasswordAuthentication());
                session.setDebug(true);
                
                //第三步 根據獲取的Session來傳建一個消息Message
                MimeMessage message = new MimeMessage(session);
                
                //第四步 定義消息的發信人地址InternetAddress和消息的收信人地址。
                //發件人
                InternetAddress sendaddr = new InternetAddress(sender);
                message.setFrom(sendaddr);
                //收件人
                InternetAddress[] toaddrs = InternetAddress.parse(to);
                message.setRecipients(Message.RecipientType.TO, toaddrs);
                //抄送人
                InternetAddress[] ccaddrs = InternetAddress.parse(cc);
                message.setRecipients(Message.RecipientType.CC, ccaddrs);
                //密送人
                InternetAddress[] bccaddrs = InternetAddress.parse(bcc);
                message.setRecipients(Message.RecipientType.BCC, bccaddrs);
                //第五步 設置消息發送的主題、內容、時間
                message.setSubject(title);
                message.setText(content);
                message.setSentDate(new Date());
                //第六步 利用Message.saveChanges()來存儲填寫的郵件信息
                message.saveChanges();
                //第七步將該消息發送
                Transport.send(message);
    }
    
    
    public static void main(String[] args) 
    {
        try 
        {
            sendPlainTextEmailByAuth("smtp.163.com", "cac2020@163.com", "ssssss@qq.com", "", "cac2020@163.com", "測試一個純文本郵件", "ssssss", "cac2020", "ffafasdfsdfsaf");
        } 
        catch (MessagingException e) 
        {
            e.printStackTrace();
        }
        
    }

}

(3)發送一封含圖片的郵件

package mail;

import java.util.Date;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

/**
 * 郵件發送服務
 */
public class SendMailService
{

    
    /**
     * 發送內嵌圖片郵件
     * @param smtpHost 郵件服務器
     * @param to 收件人(能夠是多個,使用逗號分隔)
     * @param cc 抄送人(能夠是多個,使用逗號分隔)
     * @param bcc密送人(能夠是多個,使用逗號分隔)
     * @param sender發件人
     * @param title郵件標題
     * @param username郵箱用戶名(通常是去掉@以前的那一部分)
     * @param password(郵箱密碼)
     * @throws MessagingException
     */
    public static void sendImageEmail(String smtpHost,
            String to,
            String cc,
            String bcc,
            String sender,
            String title,
            String username,
            String password) throws MessagingException
    {
        Properties props = new Properties();
        props.put("mail.host", smtpHost);
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true");
        
        Session session = Session.getDefaultInstance(props);
        session.setDebug(true);
        Transport ts = session.getTransport();
        ts.connect(smtpHost, username, password);
        
        //建立含圖片郵件
        MimeMessage msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress(sender));
        msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
        msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc));
        msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(bcc));
        msg.setSubject(title);
        msg.setSentDate(new Date());
        
        //郵件正文文本
        MimeBodyPart text = new MimeBodyPart();
        text.setContent("這是一封郵件正文帶圖片<img src='cid:576f707a5ba85.JPG'>的郵件", "text/html;charset=UTF-8");
        
        //郵件正文中的圖片
        MimeBodyPart image = new MimeBodyPart();
        image.setContentID("576f707a5ba85.JPG");
        DataHandler dh = new DataHandler(new FileDataSource("src\\576f707a5ba85.JPG"));
        image.setDataHandler(dh);
        
        MimeMultipart mmp = new MimeMultipart();
        mmp.addBodyPart(text);
        mmp.addBodyPart(image);
        mmp.setSubType("related");
        
        msg.setContent(mmp);
        msg.saveChanges();

ts.sendMessage(msg, msg.getAllRecipients()); ts.close(); } }

(4)發送包含附件的圖片

package mail;

import java.util.Date;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

/**
 * 郵件發送服務
 */
public class SendMailService
{

    /**
     * 發送含附件郵件
     * @param smtpHost 郵件服務器
     * @param to 收件人(能夠是多個,使用逗號分隔)
     * @param cc 抄送人(能夠是多個,使用逗號分隔)
     * @param bcc密送人(能夠是多個,使用逗號分隔)
     * @param sender發件人
     * @param title郵件標題
     * @param username郵箱用戶名(通常是去掉@以前的那一部分)
     * @param password(郵箱密碼)
     * @throws MessagingException
     */
    public static void sendAttachEmail(String smtpHost,
            String to,
            String cc,
            String bcc,
            String sender,
            String title,
            String username,
            String password) throws MessagingException
    {
        Properties props = new Properties();
        props.put("mail.host", smtpHost);
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true");
        
        Session session = Session.getDefaultInstance(props);
        session.setDebug(true);
        Transport ts = session.getTransport();
        ts.connect(smtpHost, username, password);
        
        //建立含圖片郵件
        MimeMessage msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress(sender));
        msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
        msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc));
        msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(bcc));
        msg.setSubject(title);
        msg.setSentDate(new Date());
        
        //郵件正文文本
        MimeBodyPart text = new MimeBodyPart();
        text.setContent("使用JavaMail建立的帶附件的郵件", "text/html;charset=UTF-8");
        
        //郵件附件
        MimeBodyPart attach = new MimeBodyPart();
        DataHandler dh = new DataHandler(new FileDataSource("src\\576f707a5ba85.JPG"));
        attach.setDataHandler(dh);
        attach.setFileName(dh.getName());
        
        //建立個區塊之間關係
        MimeMultipart mmp = new MimeMultipart();
        mmp.addBodyPart(text);
        mmp.addBodyPart(attach);
        mmp.setSubType("mixed");
        
        msg.setContent(mmp);
        msg.saveChanges();
        
        ts.sendMessage(msg, msg.getAllRecipients());
        ts.close();
    }
    

}

(5)發送包含內嵌圖片和附件的複雜郵件

package mail;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

/**
 * 郵件發送服務
 */
public class SendMailService
{

    
    /**
     * 發送含附件郵件
     * @param smtpHost 郵件服務器
     * @param to 收件人(能夠是多個,使用逗號分隔)
     * @param cc 抄送人(能夠是多個,使用逗號分隔)
     * @param bcc密送人(能夠是多個,使用逗號分隔)
     * @param sender發件人
     * @param title郵件標題
     * @param username郵箱用戶名(通常是去掉@以前的那一部分)
     * @param password(郵箱密碼)
     * @throws MessagingException
     * @throws IOException 
     * @throws FileNotFoundException 
     */
    public static void sendComplexEmail(String smtpHost,
            String to,
            String cc,
            String bcc,
            String sender,
            String title,
            String username,
            String password) throws MessagingException, FileNotFoundException, IOException
    {
        Properties props = new Properties();
        props.put("mail.host", smtpHost);
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true");
        
        Session session = Session.getDefaultInstance(props);
        session.setDebug(true);
        Transport ts = session.getTransport();
        ts.connect(smtpHost, username, password);
        
        //建立含圖片郵件
        MimeMessage msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress(sender));
        msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
        msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc));
        msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(bcc));
        msg.setSubject(title);
        msg.setSentDate(new Date());
        
        //郵件正文文本
        MimeBodyPart text = new MimeBodyPart();
        text.setContent("測試<br/><img src='cid:1.PNG'>","text/html;charset=UTF-8");
        
        //圖片
        MimeBodyPart image = new MimeBodyPart();
        image.setContentID("1.PNG");
        image.setDataHandler(new DataHandler(new FileDataSource("src\\1.PNG")));
        
        //附件1
        MimeBodyPart attach1 = new MimeBodyPart();
        DataHandler dh = new DataHandler(new FileDataSource("src\\1.rar"));
        attach1.setDataHandler(dh);
        attach1.setFileName(dh.getName());
        
        //附件2  注意附件名是中文名
        MimeBodyPart attach2 = new MimeBodyPart();
        DataHandler dh2 = new DataHandler(new FileDataSource("src\\測試中文附件名.rar"));
        attach2.setDataHandler(dh2);
        attach2.setFileName(MimeUtility.encodeText(dh2.getName()));
        
        //描述關係:正文和圖片
        MimeMultipart mp1 = new MimeMultipart();
        mp1.addBodyPart(text);
        mp1.addBodyPart(image);
        mp1.setSubType("related");
        //將正文和圖片組合做爲一個總體 的正文內容
        MimeBodyPart content = new MimeBodyPart();
        content.setContent(mp1);
        
        //描述關係:正文和附件
        MimeMultipart mp2 = new MimeMultipart();
        mp2.addBodyPart(attach1);
        mp2.addBodyPart(attach2);
        mp2.addBodyPart(content);
        mp2.setSubType("mixed");
        
        //message設置郵件內容
        msg.setContent(mp2);
        msg.saveChanges();
        msg.writeTo(new FileOutputStream("E:\\MixedMail.eml"));
        
        ts.sendMessage(msg, msg.getAllRecipients());
        ts.close();
    }

}

 

 

 

 

4、使用java mail 接收郵件

基本步驟:

1 利用Properties建立一個屬性,不須要設置任何屬性,之間傳遞Session使用

2 Session.getDefaultInstance()獲取一個郵件會話

3 使用該會話向某種提供者請求一個存儲庫,ss.getStore("pop3");獲取一個Store

4 存儲庫向指定的郵件服務器創建鏈接

5 經過getFolder("INBOX"),獲取該存儲庫中INBOX文件夾

6 打開INBOX文件夾

7 消息處理

8 關閉文件夾

9 關閉存儲庫

 

package mail;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Header;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeUtility;

public class ReceiveMailService 
{

    public static void receiveMail(String popHost,    String username,String password) throws MessagingException, IOException
    {
        
        //1 利用Properties建立一個屬性,不須要設置任何屬性,之間傳遞Session使用
        Properties props = new Properties();
        //props.put("mail.host", smtpHost);
        //props.put("mail.smtp.auth", "true");
        //props.put("mail.transport.protocol", "smtp");
        //props.put("mail.transport.port", "25");
        props.put("mail.store.port", "pop3");
        
        //2 Session.getDefaultInstance()獲取一個郵件會話
        Session session = Session.getDefaultInstance(props);
        //3 使用該會話向某種提供者請求一個存儲庫,ss.getStore("pop3"); 也能夠是IMAP 獲取一個Store
        Store store = session.getStore("pop3");
        //4 存儲庫向指定的郵件服務器創建鏈接
        store.connect(popHost, username, password);
        //5 經過getFolder("INBOX"),獲取該存儲庫中INBOX文件夾
        Folder folder = store.getFolder("INBOX");
        //6 打開INBOX文件夾
        folder.open(Folder.READ_ONLY);
        //7 消息處理
        Message[] messages = folder.getMessages();
        for (int i = 0; i < messages.length; i++) 
        {
            System.out.println("------------Message--" + (i + 1) + "------------");
            // 解析地址爲字符串 發件人
            String from = InternetAddress.toString(messages[i].getFrom());
            if (from != null) 
            {
                String cin = getChineseFrom(from);
                System.out.println("From:" + cin);
            }
            //回覆給發件人
            String replyTo = InternetAddress.toString(messages[i].getReplyTo());
            if (replyTo != null)
            {
                String rest = getChineseFrom(replyTo);
                System.out.println("Reply To:" + rest);
               }
            //
            String to = InternetAddress.toString(messages[i].getRecipients(Message.RecipientType.TO));
            if (to != null)
            {
                String tos = getChineseFrom(to);
                System.out.println("To:" + tos);
            }
            //郵件主題
            String subject = messages[i].getSubject();
            if (subject != null)
            {
                System.out.println("Subject:" + subject);
            }
            //發送日期 
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date sent = messages[i].getSentDate();
            if (sent != null)
            {
                System.out.println("Sent Date:" + sdf.format(sent));
            }
            //接收日期
            Date ress = messages[i].getReceivedDate();
            if (ress != null)
            {
                System.out.println("Receive Date:" + sdf.format(ress));
            }
               
            // 顯示消息的全部首部信息
            Enumeration<Header> headers = messages[i].getAllHeaders();
            while(headers.hasMoreElements())
            {
                Header h=(Header)headers.nextElement();
                String res=h.getName();
                String val=h.getValue();
                System.out.println(res+":"+val);
            }
             System.out.println();
             //讀取消息主題部分
             Object content = messages[i].getContent();
             System.out.println(content);
             //根據指定的編碼格式讀出內容
             Reader read = new InputStreamReader(messages[i].getInputStream());
             int a=0;
             while((a=read.read())!=-1)
             {
                 System.out.print((char)a);
             }
             //獲取該消息的類型
             String type=messages[i].getContentType();
             String sender=InternetAddress.toString(messages[i].getFrom());
             System.out.println("Sender:"+sender);
             System.out.println("Content-type:"+type);
        }
        //8 關閉文件夾但不刪除服務器上的消息 false表明不是刪除
        folder.close(false);//當爲true時會刪掉已經標記爲刪除的郵件
        //9 關閉存儲庫
        store.close();
    }
    
    // 解決中文亂碼問題
    public static String getChineseFrom(String res)
    {
        String from = res;
        try 
        {
            if (from.startsWith("=?GB") || from.startsWith("=?gb") || from.startsWith("=?UTF")) 
            {
                from = MimeUtility.decodeText(from);
            } 
            else 
            {
                from = new String(from.getBytes("ISO8859_1"), "GBK");
            }
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }
        
        return from;
    }
    
    public static void main(String[] args)
    {
        try 
        {
            receiveMail("pop3.163.com", "cac2020", "fadgfjkssdfkasjg");
        } 
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

}

 

 

 

參考:

http://blog.csdn.net/ghsau/article/details/17839983

http://www.cnblogs.com/xdp-gacl/p/4216311.html

http://computerdragon.blog.51cto.com/6235984/1197390

http://blog.sina.com.cn/s/blog_67196ddc0101fdrn.html

相關文章
相關標籤/搜索