James+Javamail構建郵箱服務(一)

1 電子郵件是如何工作的? ??

原則上,電子郵件很簡單.使用郵件用戶代理(MUA)。MUA有多種形式,包括基于文本的、基于Web的和GUI應用程序;MicrosoftOutlook和Netscape Messenger屬于最后一類。每個電子郵件客戶端被配置為將郵件發送到郵件傳送代理(MTA),并可用于輪詢MTA以獲取發送到用戶地址的電子郵件。為此,您需要郵件服務器上的電子郵件帳戶(技術上是MTA),并且可以使用標準的Internet協議,或者脫機處理電子郵件(使用POP 3),或者將電子郵件保留在服務器上(使用IMAP)。用于從客戶端向MTA發送郵件以及在MTA之間發送郵件的協議是SMTP(簡單郵件傳輸協議)。

MTA之間真正發生的事情只是稍微有趣一些。電子郵件服務器嚴重依賴dns和特定于電子郵件的記錄。郵件傳送(或MX)記錄。MX記錄與用于解析URL的DNS記錄略有不同,后者包含一些用于更有效地路由郵件的附加優先級信息。我不會在這里深入研究這些細節,但重要的是要理解DNS是成功和高效地路由電子郵件的關鍵。James是一個MTA,而JavaMailAPI為MUA提供了一個框架。在本文中,我們將使用JavaMail為我們的James安裝設置一個測試。在本系列文章中,我們將使用JamesMailetAPI來展示如何開發您自己的James應用程序。

2 Javamail快速入門?

  進行Javamail開發需要用到兩個包:mail.jar和activation.jar,在開始Javamail編程之前,請自己將這兩個包添加到IDE的Build path中或將這兩個包的路徑配置到環境變量中。?

2.1使用Javamail向James的郵箱帳戶發送郵件?

2.1.1業務描述?

????本例將使用Javamail實現郵件的發送功能。發送郵件需要配置郵件服務器屬性信息,配置郵件接收地址,使用SMTP認證獲得會話(Session),構建郵件體(MimeMessage),發送郵件。具體編碼如下:?

2.1.2編碼實現?

  發送郵件需要兩個類:一個是SMTP用戶身份認證類(James在默認情況下,是需要SMTP身份認證的);另一個就是我們的郵件發送類,為簡單起見,我們直接將郵件的相關信息,如:標題、內容、發送者、接收者等信息直接寫在類中,運行main()函數即發送。當然,你同樣可以為自己的郵件發送系統構造一個郵件發送介面,通過Servlet將相關參數傳遞至后臺進行處理與發送。其主要代碼也就是此main()函數中的內容,故不贅述。請各位按需修改,demo代碼是截圖,不便之處請諒解,可以到我的git獲取代碼。

記得提供get、set方法

?SendMail.java發送郵件代碼:

值得一提的是,本程序已經實現了帶附件郵件的發送功能,如果要發送帶附件的郵件,則只需要將附件的路徑傳到fileAttachment變量中就可以了。郵件發送成功后,程序將在后臺打印出“發送成功”,這樣我們就完成了郵件發送功能。那么,我們應該如何檢驗服務器是否確實收到我們發送的測試郵件呢?Javamail可以發送郵件,當然也能接收郵件啦,下面讓我們一起使用Javamail編寫郵件接收功能來檢驗吧。?

2.2使用Javamail接收郵件?

2.2.1業務描述?

  在上一節,我們已經向James的accidentaly用戶發送了一封測試郵件,我們應該如何使用Javamail來收取這封郵件呢??

  為讀取郵件,必須首先設置服務器屬性(Properties),獲取一個會話(Session),然后獲取并連接郵箱所在的存儲器(Store對象),打開該用戶的郵箱(Folder),獲取所希望閱讀的消息,最后關閉目錄和連接。?

  下面的程序實現了接收accidentaly@dascomyun郵箱中所有郵件,并將發送人和主題打印出來

程序運行成功后,將會把accidentaly用戶的郵件從James服務器中取出,并將此郵箱中所有郵件的發件人、主題打印在后臺。若要打印該郵件的內容等信息,則只要將message[i]對象中的郵件內容等信息讀取出來就可以了。?

  注:鑒于郵件的存儲結構(將在第五章介紹),讀取郵件附件是一個比較復雜的過程,因為郵件的文本內容和附件信息都是保存在BodyPart對象中的,BodyPart用于標識類型的標記不明確,造成對附件的判斷較為復雜。對于附件的操作本人將在今后的改進版本中加以介紹。

3 Mailet快速入門?

  Mailet API是一個用來創建郵件處理程序的簡單的API,它被配置在郵件服務器端執行,分匹配器Matcher和Mailet的接口兩種,匹配器根據特定的條件匹配郵件消息,并觸發相應的Mailet.?

  Mailet這個詞是跟Servlet相似,功能也相似,他們的共同之處都是在服務器端觸發并執行,只是Servlet的Matcher通常是url的pattern,跟Servlet的接口一樣,Mailet也有init()方法,service()方法和destroy()方法.即他們都有類似的生命周期. Mailet的簡單可編程接口可以用來做一些郵件處理,比如反垃圾郵件,檢查郵件病毒以及郵件博客等等,利用移動設備可發送email的功能,可以做到手機通過mail發送信息到郵件服務器交給Mailet處理,形成移動博客的模型.?

  Mailet的運行需要mailet-2.3.jar和mailet-api-2.3.jar兩個包的支持,James本身就有這兩個包,可不作修改,但在開發的時候還是需要開發者自己將這兩個包導入到工程的Build path中或配置到系統環境變量中。?

3.1 用Mailet做一個Hello的例子?

3.1.1 業務描述?

  我們要實現當外部發送給James服務器中名字含accidentaly的郵箱時,服務器在這封郵件的主題前加入“Hello”,并在服務器后臺輸出“Received a piece of Email”。如前所述,Mailet包括匹配器Matcher和Mailet兩種接口,現在就讓我們用Mailet API實現這兩個接口吧。?

匹配器BizMatcher.java?

?BizMaillet.java?

?3.1.3 配置部署?

  Mailet跟Servlet一樣,是服務器端程序,是不能直接在客戶端運行的,必須要部署到服務器端方可生效。部署具體步驟如下:?

1、 將我們編寫的Matcher和Mailet打包成jar文件;?

2、 在\james-2.3.1\apps\james\SAR-INF目錄下新建一個lib文件夾;?

3、 將打包好的jar文件復制到剛剛新建的lib文件夾下;?

4、 打開config.xml配置文件,找到以下這段代碼:?

XML代碼:

?前半部分是用于配置Mailet包所在位置,后半部分是用于配置Matcher包所在位置,我們把我們剛編寫的Mailet和Matcher所在位置配置進去就可以了。配置后的結果如下:?

Xml代碼?

這樣就完成了包的配置。我們都知道,Mailet的工作過程是:首先由Matcher來匹配所接收到的郵件,然后提交給相應的Mailet處理,但是哪個匹配器對應哪個Mailet呢?我們還需要配置Mailet的對應關系。同樣在config.xml中找到下面的代碼,并在這段代碼下面加入我們自己的Mailet:

Xml代碼 ?

? ? <mailet ?match="All" class="PostmasterAlias"?/>

Xml代碼 ?

<mailet??match="BizMatcher" class="BizMaillet"?/>

?這樣就完成了我們自定義的Mailet的配置部署工作了。重啟James服務器,則此Mailet即可生效。?

3.1.4 測試Mailet?

  前面我們已經完成了Mailet的編碼和部署工作,現在就讓我們來測試一下我們的Mailet是否生效吧。首先,需要在James服務器上新建一個名稱含accidentaly的用戶。前面已介紹過新建用戶的方法了,在此就不重復敘述了。?

  使用adduser accidentaly?881213命令新建一個accidentaly用戶。?

  使用上面所談及的“使用Javamail向James的郵箱帳戶發送郵件”來向accidentaly@dascomyun發送一封郵件(當然,你同樣可以使用Foxmail或Outlook向此地址發送郵件),郵件發送成功后,James服務器后臺將輸出“Receive a piece of email”。運行效果如下圖所示:?

4 常用Javamail API簡介?

  核心JavaMail API可以分為兩部分,一部分由七個類組成:Session、Message、Address、Authenticator、Transport、Store及Folder,它們都來自Javamail API頂級包(但開發者需要使用的具體子類可能在javax.mail.internet包內)。可以用這些類完成大量常見的電子郵件任務,包括發送消息、檢索消息、刪除消息、認證、回復消息、轉發消息、管理附件、處理基于HTML文件格式的消息以及搜索或過濾郵件列表,這類任務主要屬于MTA范疇。下圖描繪了Javamail郵件收發過程。?

下面給出這七個核心類的簡單介紹,以使讀者能對Javamail框架有一個大體了解:?

4.1 javax.mail.Session?

  Session類定義了一個基本郵件會話,它是Javamail API最高層入口類,所有其它類都必須經由Session對象才得以生效。Session對象管理配置選項和用于與郵件系統交互的用戶認證信息,它使用java.util.Properties對象獲取信息,如郵件服務器、用戶名、密碼及整個應用程序中共享的其它信息。?

  Session類的構造器是私有的,它不能被繼承,也不能使用new語句來創建實例,但它提供了兩個表態方法getInstance和getDefaultInstance來獲取Session實例,前者創建一個獨立的會話,否則獲取缺省的共享會話。?

  API明細:/javamail-1.4.1/docs/javadocs/javax/mail/Session.html?

4.2 javax.mail.Message?

  獲得Session對象后,可以開始繼續創建要發送的郵件消息,這由Message類來完成,Message實現了Part接口,它表示一個郵件消息,包含一系列屬性(attribute)和一個消息內容(content)。消息屬性標識了消息地址信息,定義了消息內容的結構(包括內容類型);消息內容使用DataHandler對象包裝實際數據。當郵件消息位于目錄(folder)中時,系統還使用一個標志位集合來描述它的狀態。?

  Message是抽象類,實際使用時必需用一個子類代替以表示具體的郵件格式。比如說,Javamail API提供了MimeMessage(位于javax.mail.internet.MimeMessage包)類,該類擴展自Message,實現了RFC822和MIME標準。Message的子類通常通過字節流構建其實例,相應的,它們也可以生成字節流來傳輸自身。?

  API明細:/javamail-1.4.1/docs/javadocs/javax/mail/Message.html?

4.3 javax.mail.Address?

  Address類表示電子郵件地址,它是一個抽象類。其子類(最經常使用的子類是javax.mail.internet.InternetAddress)提供具體實現,且通常可串行化。?

在創建了Session和Message,并設置了消息內容后,可以用Address確定郵件消息的發送者和接收者地址。?

  API明細:/javamail-1.4.1/docs/javadocs/javax/mail/Address.html?

4.4 javax.mail.Authenticator?

  Authenticator代表一個可以為網絡連接獲取認證信息的對象,它通常通過提示用戶輸入用戶名和密碼來收集認證信息,使連接可以訪問受保護的資源。對于Javamail API來說,這些資源就是郵件服務器。Javamail Authenticator在javax.mail包中,它和java.net中同名的類Authenticator不同。?

  要使用Authenticator,必須先創建一個它的子類實例,并且在會話對象創建時為會話注冊該Authenticator對象。在需要認證的時候,就會通知Authenticator。程序可以彈出窗口,也可以從配置文件中(雖然沒有加密是不安全的)讀取用戶名和密碼,并使用它們作為構造函數參數創建一個PasswordAuthentication對象返回給調用程序。?

  API明細:/javamail-1.4.1/docs/javadocs/javax/mail/Authenticator.html?

4.5 javax.mail.Transport?

  消息發送的最后步驟是使用Transport類。該類使用指定協議發送消息(通常是SMTP)。Transport是抽象類,它的工作方式與Session有些類似,可以通過靜態方法或實例方法發送消息。Transport繼承自Service類,而后者提供了很多通用方法,如命名傳輸、連接服務器、監聽傳輸事件等等。?

  API明細:/javamail-1.4.1/docs/javadocs/javax/mail/Transport.html?

4.6 javax.mail.Store?

  Store是一個抽象類,它模擬了消息存儲器及其內部目錄(Folder)訪問協議,以存儲和讀取消息,其子類提供具體實現。?

  Store定義的存儲器包括一個分層的目錄體系,消息存儲在目錄內,。客戶程序可以通過獲取一個實現了數據庫訪問協議的Store對象來訪問消息存儲器,絕大多數存儲器要求用戶在訪問前提供認證信息,connect方法執行了該認證過程。?

  Store store = session.getStore("pop3");//指定協議?

  store.connect(host,usename,password);//?

  API明細:/javamail-1.4.1/docs/javadocs/javax/mail/Store.html?

4.7 javax.mail.Folder?

  Folder是一個抽象類,用于分級組織郵件,其子類提供針對具體協議的實現。Folder代表的目錄可以容納消息或子目錄,存儲在目錄內的消息被順序計數(從1開始到消息總數),該順序被稱為“郵箱順序”,通常基于郵件消息到達目錄的順序。郵件順序的變動將改變消息的序列號,這種情況僅發生在客戶程序調用Expunge方法擦除目錄內設置了Flags.Flag.DELETED標志位的消息時。執行擦除操作后,目錄內消息將重新編號。?

  客戶程序可以通過消息序列號或直接通過相應的Message對象應用目錄中的消息,由于消息序列號在會話中很可能改變,因此應盡可能保存Message對象而非序列號來反復引用對象。?

  連接到Store之后,接下來可以獲取一個文件夾(Folder)。該文件夾必須先使用open()方法打開,然后才能讀取里面的消息:?

Folder folder = store.getDefaultFolder();?

//或 : Folder folder = store.getFolder("inbox");?

folder.open(Folder.READ_WRITE);?

Message message[] = folder.getMessage();?

  open()方法指定了要打開的文件夾及打開方式(如Folder.READ_WRITE)。 inbox是POP3唯一可以使用的文件夾。如果使用IMAP,還可以用其它的文件夾。獲得Message之后,就可以用getContent()獲得其內容,或者用writeTo()將內容寫入輸出流。getContent()方法之能得到消息內容,而writeTo()的輸出卻包含消息頭.讀完郵件之后要關閉與Folder和Store的連接:?

folder.close(aBoolean);?

store.close();?

  API明細:/javamail-1.4.1/docs/javadocs/javax/mail/Folder.html?


5 常用Mailet API簡介?

Mailet主要包含兩個包:org.apache.mailet和org.apache.mailet.dates?

5.1 org.apache.mailet?

  此包主要用于匹配器和Mailet的編寫。自定義的Mailet類需要繼承org.apache.mailet.GenericMailet,自定義的Matcher類需要繼承org.apache.mailet.GenericMatcher或org.apache.mailet.GenericRecipientMatcher。例子詳見第四章Mailet快速入門。?

  API明細:/MailetSDK/javadocs/org/apache/mailet/package-summary.html?

5.2 org.apache.mailet.dates?

  此包主要用于郵件中的日期格式的轉換。?

  API明細:/MailetSDK/javadocs/org/apache/mailet/dates/package-summary.html?

碼云:https://gitee.com/AccidentalyAcross/projects

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容

  • 概述 郵件相關的標準 廠商所提供的 JavaMail 服務程序可以有選擇地實現某些郵件協議,常見的郵件協議包括: ...
    靜默虛空閱讀 2,165評論 -1 4
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,776評論 18 139
  • Java Mail 簡介 常見的郵件協議包括:SMTP(Simple Mail Transfer Protocol...
    Josaber閱讀 3,289評論 1 9
  • 一、簡述發送和收取郵件的協議 SMTP 簡單郵件傳輸協議(Simple Mail Transfer Protoco...
    淚催伊人心閱讀 1,178評論 5 4
  • 本文包括:1、名詞解釋2、郵件收發過程3、JavaMail 知識概要4、發送一封符合 MIME 協議的 JavaM...
    廖少少閱讀 4,054評論 2 13