SMTP
簡單郵件傳輸協(xié)議(Simple Mail Transfer Protocol,SMTP)由 RFC 821 定義。它定義了發(fā)送電子郵件的機制。在 JavaMail API 環(huán)境中,您基于 JavaMail 的程序?qū)⒑湍墓净蛞蛱鼐W(wǎng)服務(wù)供應(yīng)商的(Internet Service Provider's,ISP's)SMTP 服務(wù)器通信。SMTP 服務(wù)器會中轉(zhuǎn)消息給接收方 SMTP 服務(wù)器以便最終讓用戶經(jīng)由 POP 或 IMAP 獲得。這不是要求 SMTP 服務(wù)器成為開放的中繼,盡管 SMTP 服務(wù)器支持身份驗證,不過還是得確保它的配置正確。像配置服務(wù)器來中繼消息或添加刪除郵件賬號這類任務(wù)的實現(xiàn),JavaMail API 中并不支持。
POP |
POP 代表郵局協(xié)議(Post Office Protocol)。目前用的是版本 3,也稱 POP3,RFC 1939 定義了這個協(xié)議。POP 是一種機制,因特網(wǎng)上大多數(shù)人用它得到郵件。它規(guī)定每個用戶一個郵箱的支持。這就是它所能做的,而這也造成了許多混淆。使用 POP 時,用戶熟悉的許多性能并不是由 POP 協(xié)議支持的,如查看有幾封新郵件消息這一性能。這些性能內(nèi)建于如 Eudora 或 Microsoft Outlook 之類的程序中,它們能記住一些事,諸如最近一次收到的郵件,還能計算出有多少是新的。所以當(dāng)使用 JavaMail API 時,如果您想要這類信息,您就必須自己算。
IMAP
IMAP 是更高級的用于接收消息的協(xié)議。在 RFC 2060 中被定義,IMAP 代表因特網(wǎng)消息訪問協(xié)議(Internet Message Access Protocol),目前用的是版本 4,也稱 IMAP4。在用到 IMAP 時,郵件服務(wù)器必需支持這個協(xié)議。不能僅僅把使用 POP 的程序用于 IMAP,并指望它支持 IMAP 所有性能。假設(shè)郵件服務(wù)器支持 IMAP,基于 JavaMail 的程序可以利用這種情況 — 用戶在服務(wù)器上有多個文件夾(folder),并且這些文件夾可以被多個用戶共享。
因為有這一更高級的性能,您也許會認(rèn)為所有用戶都會使用 IMAP。事實并不是這樣。要求服務(wù)器接收新消息,在用戶請求時發(fā)送到用戶手中,還要在每個用戶的多個文件夾中維護(hù)消息。這樣雖然能將消息集中備份,但隨著用戶長期的郵件夾越來越大,到磁盤空間耗盡時,每個用戶都會受到損失。使用 POP,就能卸載郵件服務(wù)器上保存的消息了。
MIME |
MIME 代表多用途因特網(wǎng)郵件擴(kuò)展標(biāo)準(zhǔn)(Multipurpose Internet Mail Extensions)。它不是郵件傳輸協(xié)議。但對傳輸內(nèi)容的消息、附件及其它的內(nèi)容定義了格式。這里有很多不同的有效文檔:RFC 822、RFC 2045、RFC 2046 和 RFC 2047。作為一個 JavaMail API 的用戶,您通常不必對這些格式操心。無論如何,一定存在這些格式而且程序會用到它。
NNTP 及其它 |
因為 JavaMail API 將供應(yīng)商和所有其它的東西分開了,您就能輕松添加額外的協(xié)議支持。Sun 保留了一張第三方供應(yīng)商列表,他們利用了 Sun 不提供超出(out-of-the-box)支持范圍的協(xié)議。您會找到 NNTP(網(wǎng)絡(luò)新聞傳輸協(xié)議)[新聞組]、S/MIME(安全多用途因特網(wǎng)郵件擴(kuò)展)及其它支持。
SMTP提供了一種郵件傳輸?shù)臋C制,當(dāng)收件方和發(fā)件方都在一個網(wǎng)絡(luò)上時,可以把郵件直傳給對方;當(dāng)雙方不在同一個網(wǎng)絡(luò)上時,需要通過一個或幾個中間服務(wù)器轉(zhuǎn)發(fā)。SMTP首先由發(fā)件方提出申請,要求與接收方SMTP建立雙向的通信渠道,收件方可以是最終收件人也可以是中間轉(zhuǎn)發(fā)的服務(wù)器。收件方服務(wù)器確認(rèn)可以建立連接后,雙發(fā)就可以開始通信。下面是SMTP的模型示意圖。
![]() |
發(fā)件方SMTP向收件方發(fā)處MAIL命令,告知發(fā)件方的身份;如果收件方接受,就會回答OK。發(fā)件方再發(fā)出RCPT命令,告知收件人的身份,收件方SMTP確認(rèn)是否接收或轉(zhuǎn)發(fā),如果同意就回答OK;接下來就可以進(jìn)行數(shù)據(jù)傳輸了。通信過程中,發(fā)件方SMTP與收件方SMTP 采用對話式的交互方式,發(fā)件方提出要求,收件方進(jìn)行確認(rèn),確認(rèn)后才進(jìn)行下一步的動作。整個過程由發(fā)件方控制,有時需要確認(rèn)幾回才可以。
![]() |
為了保證回復(fù)命令的有效,SMTP要求發(fā)件方必須提供接收方的服務(wù)器及郵箱。郵件的命令和答復(fù)有嚴(yán)格的語法定義,并且回復(fù)具有相應(yīng)的數(shù)字代碼。所有的命令由ASCII碼組成。命令代碼是大小寫無關(guān)的,如MAIL和 mail ﹑mAIL是等效的。
2. SMTP的基本命令
SMTP定義了14個命令,它們是:
HELO
MAIL FROM:
RCPT TO:
DATA
RSET
SEND FROM:
SOML FROM:
SAML FROM:
VRFY
EXPN
HELP [ ]
NOOP
QUIT
TURN
其中使得SMTP工作的基本的命令有7個,分別為:HELO﹑MAIL﹑RCPT﹑DATA﹑REST﹑NOOP和QUIT.下面分別介紹如下。
HELO--發(fā)件方問候收件方,后面是發(fā)件人的服務(wù)器地址或標(biāo)識。收件方回答OK時標(biāo)識自己的身份。問候和確認(rèn)過程表明兩臺機器可以進(jìn)行通信,同時狀態(tài)參量被復(fù)位,緩沖區(qū)被清空。
MAIL--這個命令用來開始傳送郵件,它的后面跟隨發(fā)件方郵件地址(返回郵件地址)。它也用來當(dāng)郵件無法送達(dá)時,發(fā)送失敗通知。為保證郵件的成功發(fā)送,發(fā)件方的地址應(yīng)是被對方或中間轉(zhuǎn)發(fā)方同意接受的。這個命令會清空有關(guān)的緩沖區(qū),為新的郵件做準(zhǔn)備。
RCPT --這個命令告訴收件方收件人的郵箱。當(dāng)有多個收件人時,需要多次使用該命令,每次只能指明一個人。如果接收方服務(wù)器不同意轉(zhuǎn)發(fā)這個地址的郵件,它必須報550錯誤代碼通知發(fā)件方。如果服務(wù)器同意轉(zhuǎn)發(fā),它要更改郵件發(fā)送路徑,把最開始的目的地(該服務(wù)器)換成下一個服務(wù)器。
DATA--收件方把該命令之后的數(shù)據(jù)作為發(fā)送的數(shù)據(jù)。數(shù)據(jù)被加入數(shù)據(jù)緩沖區(qū)中,以單獨一行是"."的行結(jié)束數(shù)據(jù)。結(jié)束行對于接收方同時意味立即開始緩沖區(qū)內(nèi)的數(shù)據(jù)傳送,傳送結(jié)束后清空緩沖區(qū)。如果傳送接受,接收方回復(fù)OK。
REST--這個命令用來通知收件方復(fù)位,所有已存入緩沖區(qū)的收件人數(shù)據(jù),發(fā)件人數(shù)據(jù)和待傳送的數(shù)據(jù)都必須清除,接收放必須回答OK.
NOOP--這個命令不影響任何參數(shù),只是要求接收放回答OK, 不會影響緩沖區(qū)的數(shù)據(jù)。
QUIT--SMTP要求接收放必須回答OK,然后中斷傳輸;在收到這個命令并回答OK前,收件方不得中斷連接,即使傳輸出現(xiàn)錯誤。發(fā)件方在發(fā)出這個命令并收到OK答復(fù)前,也不得中斷連接。
下面是SMTP答復(fù)中用到的代碼和含義:
500 Syntax error, command unrecognized
[This may include errors such as command line too long]
501 Syntax error in parameters or arguments
502 Command not implemented
503 Bad sequence of commands
504 Command parameter not implemented
211 System status, or system help reply
214 Help message
[Information on how to use the receiver or the meaning of a
particular non-standard command; this reply is useful only to the human user]
220 Service ready
221 Service closing transmission channel
421 Service not available, closing transmission channel
[This may be a reply to any command if the service knows it must shut down]
250 Requested mail action okay, completed
251 User not local; will forward to
450 Requested mail action not taken: mailbox unavailable
[E.g., mailbox busy]
550 Requested action not taken: mailbox unavailable
[E.g., mailbox not found, no access]
451 Requested action aborted: error in processing
551 User not local; please try
452 Requested action not taken: insufficient system storage
552 Requested mail action aborted: exceeded storage allocation
553 Requested action not taken: mailbox name not allowed
[E.g., mailbox syntax incorrect]
354 Start mail input; end with .
554 Transaction failed
最后,讓我們看一個RFC821中給出的例子。這封信是Smith在主機Alpha.ARPA 發(fā)給主機Beta.ARPA上的
Jones,Green和 Brown.并且假定兩臺主機在同一個網(wǎng)絡(luò)上。
S: MAIL FROM:
R: 250 OK
S: RCPT TO:
R: 250 OK
S: RCPT TO:
R: 550 No such user here
S: RCPT TO:
R: 250 OK
S: DATA
R: 354 Start mail input; end with .
S: Blah blah blah...
S: ...etc. etc. etc.
S: .
R: 250 OK
郵件最后被對方接受。
◆ 電子郵件的工作原理
電子郵件與普通郵件有類似的地方,發(fā)信者注明收件人的姓名與地址(即郵件地址),發(fā)送方服務(wù)器把郵件傳到收件方服務(wù)器,收件方服務(wù)器再把郵件發(fā)到收件人的郵箱中。如下圖所示:
![]() |
更進(jìn)一步的解釋涉及到以下幾個概念:
MUA -- Mail User Agent, 郵件用戶代理,幫助用戶讀寫郵件;
MTA -- Mail Transport Agent, 郵件傳輸代理,負(fù)責(zé)把郵件由一個服務(wù)器傳到另一個服務(wù)
器或郵件投遞代理;
MDA -- Mail Delivery Agent, 郵件投遞代理,把郵件放到用戶的郵箱里。
整個郵件傳輸過程如下:
目前使用的SMTP 協(xié)議是存儲轉(zhuǎn)發(fā)協(xié)議,意味著它允許郵件通過一系列的服務(wù)器發(fā)送到最終目的地。服務(wù)器在一個隊列中存儲到達(dá)的郵件,等待發(fā)送到下一個目的地。下一個目的地可以是本地用戶,或者是另一個郵件服務(wù)器,如下圖所示。
![]() |
如果下游的服務(wù)器暫時不可用,MTA 就暫時在隊列中保存信件,并在以后嘗試發(fā)送。
◆ 電子郵件的信頭結(jié)構(gòu)及分析
1 .郵件的結(jié)構(gòu)
在最高層,郵件的結(jié)構(gòu)是非常簡單的,用戶從終端機上看到的郵件格式一般為:
1. From: user1@domain1.com
2. To: user2@domain2.com
3. Subject: Explaination of mail format
4. Date: Thu, 1 Apr 1999. 10:00:00 GMT
5. Hi, Jack
7. This mail is to explain you the mail format
8. - - - -
9. Thanks
10. Bob
其中, 1~~4 行稱作信件信頭(message header) 6~~10行描述信件要表達(dá)的內(nèi)容,稱為信體 (message body)。第5行是空行,根據(jù)RFC822的要求,信頭和信體之間必須加入一空行。[i]信頭通常包含字段From, To, Subject 和Date,有的郵件還包含cc,bcc等字段。
2. 郵件的信頭
事實上,郵件在傳輸過程中,服務(wù)器要把它打包成一個數(shù)據(jù)對象,包括上面的信件和一個信封。郵件的投遞是依靠信封上的地址或信封信頭(envelop address 或envelop header),而不是上面講的信件上的地址。
從表面上看,一封郵件是從發(fā)件人的機器直接傳送到收件人的機器,但通常這并不正確,一封郵件發(fā)送和接受過程至少要經(jīng)過四臺計算機。參考下圖所示。用戶通常在自己的電腦前編寫閱讀郵件,我們把它叫做客戶端 (client 1~~4 )。大部分組織里,都是用一臺專門的機器處理郵件,稱作郵件服務(wù)器 (SMTP1, SMTP2). 如果用戶是從家里撥號上網(wǎng),那末郵件服務(wù)器是ISP 提供的。
![]() |
當(dāng)某個用戶在自己的電腦 Client1 前編寫完一個郵件,然后把它發(fā)送到他的ISP 的郵件服務(wù)器SMTP1。此時她的機器已經(jīng)完成了所有的工作,但郵件服務(wù)器SMTP1還必須想法把郵件發(fā)送到目的地。SMTP1 通過閱讀信頭或信封上的地址,找到收件認(rèn)得郵件服務(wù)器SMTP2, 然后與該服務(wù)器建立連接,把郵件發(fā)到收件人的服務(wù)器上,等待收件人來取閱。
下面我們將通過一個例子說明整個郵件傳送過程及郵件的信頭變化。假設(shè)發(fā)件人的名字叫 Sender, email地址是 sender@domain1.com使用的電腦名字叫 client1, IP 地址是 [111.11.1.1] (假設(shè)的地址)。 收件人的名字叫 receipt, email 地址是 receipt@domain2.com, 使用的電腦的名字叫 client2,IP 地址是 [222.22.2.2] (假設(shè)的地址)。當(dāng)郵件編輯完傳送給其郵件服務(wù)器mail.domain1.com 時,郵件的信頭格式為:
From: sender@domain1.com
To: receipt@domain2.com
Date: Tue, Mar 18 1998 15:36:24 GMT
X-mailer:Sendmail 8.9.0
Subject: Greetings
當(dāng)郵件服務(wù)器 mail.domain1.com 把郵件傳到接收方的服務(wù)器 mail.domain2.com 時,接受方服務(wù)器會在信頭上記錄下有關(guān)的計算機信息,郵件的信頭變成:
Received: from client1.domain1.com (client1.domain1.com [111.11.1.1]) by mail.domain1.com (8.8.5) id 004A21; Tue, Mar 18 1998 15:3 7:24 GMT
From: sender@domain1.com
To: receipt@domain2.com
Date: Tue, Mar 18 1998 15:36:24 GMT
Message-Id:
X-mailer:Sendmail 8.9.0
Subject: Greetings
當(dāng)收件人服務(wù)器mail.domain2.com 把郵件接收并存初下來,等待收件人來閱讀時,郵件的信頭將會再加入一條記錄:
Received: from mail.domain1.com (mail.domain1.com [111.11.1.0] ) by mail.domain2.com (8.8.5/8.7.2) with ESMTP id LAA20869; Tue, Mar 18 1998 15:39:44 GMT
Received: from client1.domain1.com (client1.domain1.com [111.11.1.1]) by mail.domain1.com (8.8.5) id 004A21; Tue, Mar 18 1998 15:37:24 GMT
From: sender@domain1.com
To: receipt@domain2.com
Date: Tue, Mar 18 1998 15:36:24 GMT
Message-Id:
X-mailer:Sendmail 8.9.0
Subject: Greetings
上面整個記錄就將是收件人看到的完整的郵件信頭。讓我們逐行看一下信頭中各行的含義:
Received: from mail.domain1.com (mail.domain1.com [111.11.1.0] ) by mail.domain2.com (8.8.5/8.7.2) with ESMTP id LAA20869; Tue, Mar 18 1998 15:39:44 GMT
這封信是從一臺自稱為 mail.domain1.com 的機器上接收的;這臺機器的IP 地址是[111.11.1.0],真實名字就是標(biāo)稱名字 mail.domain1.com; 接收方的機器名稱是 mail.domain2.com, 運行的郵件服務(wù)器是 Sendmail, 版本(8.8.5/8.7.2) 。接收方機器給郵件的編號是ESMTP id LAA20869, 接收到的時間是 Tue, Mar 18 1998 15:39:44 GMT。
Received: from client1.domain1.com (client1.domain1.com [111.11.1.1]) by mail.domain1.com (8.8.5) id 004A21; Tue, Mar 18 1998 15:37:24 GMT
這條記錄表明信件是由機器client1.domain1.com ( IP 地址是 [111.11.1.1]) 在Tue, Mar 18 1998 15:37:24 GMT交給mail.domain1.com,并賦給編號id 004A21。
From,TO ,Date和Subject 都易于理解,分別指明發(fā)件人,收件人,信件編輯日期及信件主題。
Message-Id:
這是由發(fā)件方郵件服務(wù)器賦給這封郵件的編號。與其它編號不同,這個編號自始至終跟隨郵件。
------------------------------------
方法一:沒有使用JavaMail API,而是根據(jù)SMTP協(xié)議的要求直接處理協(xié)議的細(xì)節(jié)發(fā)送郵件。
MailMessage.java
----------------------------------------
//這個類其實就是一個基本的JavaBean,用于完成一些基本信息的設(shè)置,也可以不要這個東西,直接在程序中寫明就可以,不過這樣條理較清楚一些,而且修改也方便一些.

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283


2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74
