Thư điện tử, hay email (từ chữ electronic mail), đôi khi được dịch không chính xác là điện thư, là một hệ thống chuyển nhận thư từ qua các mạng máy tính.
Email là một phương tiện thông tin rất nhanh. Một mẫu thông tin (thư từ) có thể được gửi đi ở dạng mã hoá hay dạng thông thường và được chuyển qua các mạng máy tính đặc biệt là mạng Internet. Nó có thể chuyển mẫu thông tin từ một máy nguồn tới một hay rất nhiều máy nhận trong cùng lúc.
Ngày nay, email chẳng những có thể truyền gửi được chữ, nó còn có thể truyền được các dạng thông tin khác như hình ảnh, âm thanh, phim, và đặc biệt các phần mềm thư điện tử kiểu mới còn có thể hiển thị các email dạng sống động tương thích với kiểu tệpHTML.
71 trang |
Chia sẻ: tlsuongmuoi | Lượt xem: 1986 | Lượt tải: 1
Bạn đang xem trước 20 trang tài liệu Thư điện tử, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
ng truyeàn phaûi bò ñöùt) vaø bò treo
ñöôøng truyeàn khi cuoäc goïi ñaõ hoaøn thaønh.
Pppd daemon baét ñaàu xaùc laäp caùc thoâng soá keát noái vôùi heä thoáng töø xa
baèng caùch chuyeån ñoåi ñòa chæ IP, vaø xaùc laäp caùc giaù trò keát noái döïa treân thoâng
tin truyeàn. Khi ñaõ hoaøn taát, pppd seõ xaùc laäp lôùp network cho Linux kernel cuûa
chuùng ta duøng PPP link baèng caùch thieát laäp giao tieáp thaønh “/dev/pppd0” (neáu
ñaây laø PPP link ñaàu tieân active treân maùy).
Neáu chuùng ta muoán chuyeån ñoåi caùc thieát laäp maëc nhieân cuûa pppd
daemon, chuùng ta coù theå thöïc hieän ñieàu naøy thoâng qua caùc option töø doøng leänh
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 32
hoaëc file ñieàu khieån. Söû duïng caùc file thì toát hôn neáu chuùng ta muoán chuyeån ñoåi
thoâng soá cho moãi laàn thöïc hieän keát noái duøng PPP.
Tröôùc khi thöïc hieän doøng leänh, pppd seõ xem xeùt taát caû caùc file option coù
theå coù. File “/etc/ppp/options” thöôøng duøng ñeå chöùa caùc giaù trò maëc nhieân. Ví
duï:
# /etc/ppp/options: globabl definitions
domain merlin.com
auth # force authentication
usehostname # use local hostname for authentication
lock # use file locking UUCP-style
domain ñöôïc thieát laäp vôùi töø khoùa domain theo sau vôùi teân domain ñaày
ñuû. Hai doøng keá tieáp (auth vaø usehostname) duøng vôùi quaù trình authentication
cuûa PPP, traùnh vieäc söû duïng vaø truy xuaát khoâng mong muoán. Chuùng ta seõ xem
xeùt quaù trình authentication trong phaàn sau. Töø khoùa lock noùi pppd khoùa file
theo kieåu UUCP ñeå traùnh söï xung ñoät giöõa caùc thieát bò. Locking neân duøng vôùi
taát caû caùc heä thoáng PPP ñeå traùnh loãi xaûy ra.
4. KIEÅÅM TRA LOÃÃI
Pppd daemon seõ phaûn hoài taát caû caùc warning vaø error tôùi syslog moät
caùch uyeån chuyeån. Neáu chuùng ta coù vaán ñeà gì trong keát noái PPP, chuùng ta coù theå
kieåm tra syslog ñeå tìm loãi.
Syslog seõ chöùa taát caû caùc warning vaø error, tröø khi muïc nhaäp trong
“/etc/syslog.conf” ñöôïc taùi ñònh höôùng laïi ñeå chuyeån sang file khaùc. Ñeå löu
nhöõng message töø pppd vaø chat, theâm doøng sau vaøo file “/etc/syslog.conf”:
daemon.* /tmp/ppp-log
Muïc naøy noùi syslog löu taát caû caùc message töø daemon tôùi file
“/tmp/ppp-log”.
5. PPP AUTHENTICATION
Giao thöùc PPP raát phuø cho vieäc giao tieáp thoâng qua moñem, nhöng coù
moät vaán ñeà chuû yeáu laø: coù nhöõng loã hoång raát lôùn veà tính an toaøn. Neáu caáu hình
khoâng chính xaùc duø laø raát nhoû thì baát kyø ai cuõng coù theå vaøo trong heä thoáng thoâng
qua ñöôøng line ppp, hoaëc söû duïng line ppp ñeå ñi ra heä thoáng khaùc. Ñeå traùnh tình
traïng naøy, cô cheá authentiction ñaõ ñöôïc söû duïng.
PPP söû duïng hai cô cheá authentiction laø :Password Authentication
Protocol (PAP) vaø Challenge Handshake Authentication Protocol (CHAP).
PAP gioáng nhö moät thuû tuïc ñeà login. Khi moät maùy naøo ñoù göûi ñi thoâng tin login
vaø password tôùi maùy khaùc, beân maùy nhaän seõ kieåm tra thoâng tin baèng cô sôû döõ
lieäu maø noù coù, vôùi tính ñôn giaûn cuûa noù neân noù coù moät vaán ñeà ñoù caàn chuù yù laø
baát kyø ai cuõng coù theå maéc reõ nhaùnh vaøo ñöôøng daây ñieän thoaïi cuûa mình ñeå laáy
thoâng tin password truyeàn treân ñöôøng daây.
Ñeå giaûi quyeát vaán ñeà naøy chuùng ta duøng cô cheá CHAP vaø ñaây laø daïng
ñöôïc duøng nhieàu trong kieåu noái PPP. CHAP cho pheùp moät maùy (maùy A) göûi moät
chuoãi baát kyø tôùi moät maùy khaùc cuøng vôùi teân hostname cuûa noù. Beân nhaän (maùy
B) söû duïng hostname naøy ñeå tìm ra reply ñuùng, toå hôïp chuùng vôùi chuoãi kyù töï
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 33
ban ñaàu, maõ hoùa chuùng roài göûi laïi cho maùy A cuøng vôùi teân hostname cuûa noù.
Maùy A seõ th75c hieän cuõng caùc thao taùc nhö maùy B ñoái vôùi chuoãi kyù töï noù ñaõ göûi
ñi luùc ñaàu, neáu hai reply gioáng nhau vieäc authentication chaám döùt. CHAP
khoâng thöïc hieän vieäc Authentication vaøo luùc khôûi ñoäng, maø vaøo baát kyø luùc naøo
trong suaát quaù trình keát noái.
Khi hai maùy keát noái vôùi nhau, chuùng seõ khoâng thöïc hieän vieäc
authentication neáu khoâng coù chæ ñònh. Neáu cô cheá authentication ñöôïc active,
ñaàu tieân,moät maùy seõ söû duïng CHAP, neáu maùy kia khoâng hoã trôï CHAP, thì noù seõ
söû duïng PAP. Neáu caû hai cô cheá ñeàu khoâng ñöôïc hoã trôï, vieäc keát noái seõ bò ñoùng
laïi.
Taát caû nhöõng thoâng tin caàn thieát cho PAP vaø CHAP ñöôïc ñaët trong hai
file: /etc/ppp/cap-serects vaø /etc/ppp/ppp-serects. Khi authentication ñöôïc
active, maùy A seõ kieåm tra maùy B thoâng qua caùc file naøy vaø söû dung CHAP
tröôùc. Neáu chuùng ta söû duïng authentication cho moïi cuoäc keát noái, thí chuùng ta
taïo ra caùc file chap-serects vaø pap-serects. Neáu chuùng ta ñaët caáu hình cho caû
chap-serects vaø pap-serecs vaø xaùc ñònh option trong /etc/ppp/option thì khoâng
maùy naøo maø khoâng coù authentication coù theå connect vaøo maùy mình.
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 34
PHAÀÀN III
HIEÄÄN THÖÏÏC CHÖÔNG TRÌNH
SHAREMAIL
DDDD
CHÖÔNG I : CHÖÔNG TRÌNH POP3 CLIENT
CHÖÔNG II : CHÖÔNG TRÌNH DELIVER
CHÖÔNG III : CHÖÔNG TRÌNH SMTP CLIENT
CHÖÔNG IV : CHÖÔNG TRÌNH SMTP SERVER.
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 35
CHÖÔNG I:
CHÖÔNG TRÌNH POP3 CLIENT.
Pop3Client thöïc hieän keát noái vôùi Pop3Server töø xa söû duïng giao thöùc
POP3 (Post Office Protocol version 3) cho pheùp user coù theå laáy thö cuûa mình
naèm treân hoäp thö cuûa moät maùy server töø xa.
Nhieäm vuï cuûa Pop3Client laø laáy Mail naèm trong Mailbox cuûa Server
Mail veà hoäp mail: “/var/spool/sharedmail/inbox” trong heä thoáng. Do giao thöùc
POP3 ñoøi hoûi phaûi coù username vaø password trong quaù trình Authorization ñeå
login neân chuùng ta caàn phaûi coù username vaø password duøng ñeå login vaøo hoäp
Mail cuûa chuùng ta naèm treân maùy Server. Username vaø password ñöôïc cung caáp
bôûi nhaø cung caáp dòch vuï. Sau khi login vaøo Server Mail, chöông trình seõ laáy
taát caû caùc Mail coù trong Mailbox cuûa Server ñem veà Inbox trong heä thoáng (ôû
ñaây khoâng thöïc hieän quaù trình loïc mail).
Chöông trình Pop3 Client coù theå thöïc hieän laïi keát noái trong tröôøng hôïp
keát noái bò ngaét giöõa chöøng, noù seõ laáy böùc thö ñang laáy maø bò ngaét giöõa chöøng vaø
caùc böùc thö keå töø ñoù trôû ñi, khoâng phaûi laáy laïi töø ñaàu khi keát noái ñöôïc thieát laäp
trôû laïi. Ñieàu naøy raát laø coù ích vì khi keát noái laïi, neáu chuùng ta cöù laáy laïi töø ñaàu
caùc böùc mail trong Mailbox cuûa Server thì raát toán thôøi gian vaø noù thaät söï khoâng
caàn thieát vì ñaõ nhaän ñöôïc roài.
I. GIÔÙÙI THIEÄÄU CAÁÁU TRUÙÙC POP3_SERVER:
struct POP3_SERVER {
char host[POP3_HOST_L];
/*teân hay IP address cuûa maùy Server*/
char logid[POP3_LOGID_L];
/*username duøng ñeå login vaøo heä thoáng*/
char logpass[POP3_LOGPASS_L];
/*password cuûa username*/
char mailbox[POP3_MAILBOX_L];
/*nôi duøng ñeå löu giöõ mail laáu töø server veà*/
}
II. HOAÏÏT ÑOÄÄNG CUÛÛA CHÖÔNG TRÌNH
POP3CLIENT:
Chöông trình Pop3Client ñöôïc thöïc thi ñaàu tieân khi coù keát noái vôùi
Server Mail cuûa nhaø cung caáp dòch vuï. Khi ñöôïc thöïc thi, ñaàu tieân, noù seõ goïi
haøm read_cf(), laø haøm ñöôïc söû duïng ñeå laáy caùc thoâng tin nhö: teân maùy hoaëc ñòa
chæ IP Server Mail cuûa nhaø cung caáp dòch vuï, ñaây chính laø Server gôûi Mail,
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 36
username vaø password duøng ñeå login vaøo Mailbox treân maùy Server nhaän Mail,
hoäp thö Inbox treân maùy cuïc boä duøng ñeå löu giöõ caùc thö ñöôïc nhaän veà, soá laàn keát
noái laïi neáu chöông trình ñang nhaän maø bò ngaét giöõa chöøng, vaø thôøi gian timeout
trong tröôøng hôïp Server khoâng traû lôøi.
Keá tieáp, chöông trình seõ khôûi taïo caùc signal duøng ñeå xöû lyù caùc bieán coá coù
theå xaûy ra trong quaù trình nhaän Mail, ví duï: ñöôøng truyeàn bò ngaét, timeout,….
Neáu caùc bieán coá naøy xaûy ra thì quaù trình seõ goïi caùc haøm caøi ñaët saún ñi keøm vôùi
bieán coá ñeå xöû lyù.
Tieáp theo, chöông trình seõ thöïc hieän vieäc kieåm tra laïi xem username vaø
password duøng ñeå login vaøo Mailbox cuûa Server Mail ñaõ coù trong caáu truùc
POP3_SERVER chöa, neáu ñaõ coù thì chöông trình seõ duøng username vaø
password naøy ñeå thöïc hieän quaù trình login vaøo Mailbox cuûa Server, neáu chöa
coù thì seõ hieån thò yeâu caàu nhaäp vaøo username vaø password ñeå thöïc hieän quaù
trình login.
Sau ñoù, Pop3Client seõ môû moät socket ñeå thöïc hieän moät keát noái tôùi
Server nhaän Mail, maø teân hoaëc ñòa chæ IP cuûa computer maø chöông trình
Pop3Server ñang chaïy ñöôïc löu giöõ trong tröôøng host cuûa caáu truùc
POP3_SERVER. Neáu laø teân, chöông trình seõ thöïc hieän vieäc chuyeån ñoåi sang
ñòa chæ IP ñeå thöïc hieän keát noái.
Neáu keát noái thöïc hieän thaønh coâng, Pop3 Client seõ nhaän ñöôïc moät lôøi
chaøo ñöôïc gôûi tôùi bôûi Pop3 Server vaø session seõ böôùc vaøo quaù trình
AUTHORIZATION. Luùc naøy, Pop3Client seõ gôûi username vaø password tôùi cho
Pop3Server kieåm tra.
Neáu quaù trình AUTHORIZATION thöïc hieän thaønh coâng, session seõ
böôùc vaøo quaù trình TRANSACTION, neáu khoâng thaønh coâng, Pop3Server seõ gôûi
thoâng baùo loãi laïi cho Pop3Client. Luùc naøy, Pop3Client coù theå thöïc hieän vieäc
ñaêng nhaäp laïi vôùi username vaø password khaùc hoaëc coù theå gôûi leänh “QUIT” ñeå
thoaùt.
Döôùi ñaây laø ñoaïn code thöïc hieän quaù trình login, haøm AskAnswer coù
nhieäm vuï gôûi noäi dung cuûa boä ñeäm buf qua socket tôùi Server vaø nhaän keát quaû
traû veà töø Server.
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 37
/*gôûi leänh USER username tôùi Server*/
sprintf(buf, "USER %s", host->logid);
if (AskAnswer(sfp, qsocket, buf, SVRBUFSIZ) != OK)
return LOOKERRNO;
if (buf[0] != '+') return LOGIN_FAIL;
/* gôûi leänh PASS password tôùi Server */
sprintf(buf, "PASS %s", host->logpass);
if (AskAnswer(sfp, qsocket, buf, SVRBUFSIZ) != OK)
return LOOKERRNO;
if (buf[0] != '+') return LOGIN_FAIL;
Böôùc vaøo quaù trình TRANSATION, ñaàu tieân Pop3 Client seõ gôûi leänh
“STAT” tôùi server ñeå kieåm tra xem coù mail trong mailbox hay khoâng. Neáu coù,
server seõ traû veà toång soá thö hieän coù trong mailbox vaø kích thöôùc cuûa mailbox.
Tieáp ñoù, Pop3Client seõ gôûi leänh “LIST” ñeå laáy kích thöôùc cuûa töøng message.
Sau khi coù ñöôïc toång soá message coù trong mailbox, Pop3 Client seõ böôùc
vaøo voøng laëp duøng ñeå nhaän mail, vôùi moãi böôùc cuûa voøng laëp seõ thöïc hieän moät
leänh “RETR” vôùi soá thöù töï töông öùng vôùi chæ soá cuûa voøng laëp duøng ñeå nhaän
message töông öùng.
for ( i = 1; i <= num; i++)
{
sprintf(buf, “RETR %d”, i);
if (AskAnswer(sfp, socket, buf, SVRBUFSIZ) != OK)
return MISSOCKET;
if (*buf != ‘+’) break;
while ((cur = readline(sfp, buf, SVRBUFSIZ)) > 0)
{
if (!strcmp(buf, ".\n")) break;
if (*buf == '.') fputs(buf+1, mboxfp);
else fputs(buf, mboxfp);
}
fputs("\n", mboxfp);
fflush(mboxfp);
/*sau khi nhaän xong message, gôûi leänh DELE i, vôùi i laø chæ soá
cuûa message ñeå baùo cho Server bieát böùc Mail naøy ñaõ ñöôïc nhaän roài,
caàn phaûi xoùa boû noù.*/
sprintf(buf, "DELE %d", i);
if (AskAnswer(sfp, qsocket, buf, SVRBUFSIZ) != OK)
return MISSOCKET;
return OK;
}
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 38
Sau khi nhaän xong message, Pop3Client seõ gôûi leänh “DELE i” tôùi
server ñeå xoùa message naøy.
Sau khi laáy heát caùc message coù trong mailbox cuûa server, Pop3Client seõ
gôûi leänh “QUIT” tôùi server ñeå yeâu caàu server chuyeån Pop session sang traïng
thaùi Update vaø thoaùt.
Ñoái vôùi Server, khi böôùc vaøo traïng thaùi UPDATE, noù seõ xoùa thaät söï caùc
message ñaõ ñöôïc ñaùnh daáu xoùa trong Mailbox vaøo ñoùng keát noái. Neáu moät keát
noái ñaõ ñoùng laïi maø Server khoâng böôùc vaøo traïng thaùi UPDATE thì caùc message
ñöôïc ñaùnh daáu xoùa seõ khoâng ñöôïc xoùa trong Mailbox maø noù seõ trôû laïi traïng thaùi
ban ñaàu.
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 39
Yes
Yes
Yes
Taïo socket
Connect server
taïi port 110
Gôûi leänh
USER username \r\n
Response = +OK
Gôûi leänh
PASS password \r\n
Response = +OK
Gôûi leänh
STAT \r\n
Response = +OK
1
Baùo loãi
Ñoùng Socket
No
No
No
No
LÖU ÑOÀ CHO GETMAIL
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 40
LÖU ÑOÀ CHO GETMAIL (Continue)
No
1
Xöû lyù haøng nhaän ñöôïc laáy
toång soá sessage
Gaùn i=1
Gôûi leänh
RETR i
Ñoïc töøng vaøo töøng doøng töø
socket vaø ghi File cho ñeán
khi keát thuùc böùc mail.
incr i
i <= soá msg
Gôûi leänh QUIT
Ñoùng Socket
Yes
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 41
CHÖÔNG II:
CHÖÔNG TRÌNH DELIVER
Chöông trình Deliver thöïc hieän vieäc phaân phoái Mail tôùi ñuùng caùc ngöôøi
nhaän ôû trong heä thoáng cuïc boä cuûa chuùng ta. Chöông trình seõ döïa vaøo phaàn
fullname ñeå tìm ra ngöôøi nhaän thöïc söï cuûa böùc Mail vaø gôûi böùc Mail vaøo
Mailbox cuûa ngöôøi nhaän.
I. CAÙÙC CAÁÁU TRUÙÙC DUØØNG ÑEÅÅ LÖU GIÖÕÕ ÑÒA CHÆ
NGÖÔØØI NHAÄÄN VAØØ THOÂÂNG TIN CUÛÛA BÖÙÙC MAIL:
struct DLVTO
{
char *host;
/*address cuûa ngöôøi nhaän*/
struct DLVTO *next;
};
Caáu truùc DLVTO duøng ñeå löu giöõ caùc ñòa chæ ngöôøi nhaän trong moät böùc
mail. Tröôøng host coù theå chöùa phaàn ñòa chæ naèm trong caùc tröôøng “To:”, hoaëc
“Cc:” cuûa böùc mail.
struct SENDTO
{
int id;
/*soá thöù töï cuûa böùc mail*/
char *from;
/*ñòa chæ cuûa ngöôøi gôûi böùc mail*/
struct DLVTO *to;
/*danh saùch ñòa chæ ngöôøi nhaän*/
long mleng;
/*kích thöôùc cuûa böùc mail*/
long msgseek;
/*khoaûng caùch cuûa böùc mail so vôùi ñaàu mail box*/
char *havemail;
/*kieåm tra xem mail ñaõ ñöôïc nhaän hay chöa*/
struct SENDTO *next;
};
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 42
Caáu truùc SENDTO duøng ñeå löu giöõ caùc thoâng tin cuûa böùc mail caàn phaûi
coù trong quaù trình phaân tích ñeå tìm ra ngöôøi nhaän thöïc söï trong heä thoáng cuûa
chuùng ta.
II. HOAÏÏT ÑOÄÄNG CUÛÛA CHÖÔNG TRÌNH DELIVER:
Chöông trình Deliver seõ ñöôïc thöïc thi sau khi quaù trình gôûi caùc böùc
Mail trong hoäp Mail: “/var/spool/sharedmail/outbox” keát thuùc, töùc laø sau khi
chöông trình Smtp Client thöïc hieän xong. Khi thöïc thi, vieäc ñaàu tieân laø noù seõ
goïi haøm read_cf() ñeå laáy caùc thoâng tin caàn thieát töø file caáu hình
“Deliver.conf”. Caùc thoâng tin naøy bao goàm: thoâng tin veà hoäp thö chöùa caùc mail
caàn phaân phoái, nôi löu tröõ thö cuûa caùc user, user admin.
Tieáp ñeán, Deliver seõ goïi haøm OpenFolder() ñeå laáy toång soá mail coù trong
hoäp thö caàn phaân phoái. Neáu khoâng coù mail caàn phaân phoái hoaëc coù loãi trong quaù
trình môû hoäp thö thì seõ thoaùt khoûi chöông trình.
Sau ñoù, Deliver seõ goïi haøm Delivery(int mails) ñeå phaân phoái caùc mail
naøy tôùi töøng user trong heä thoáng. Trong quaù trình phaân phoái, neáu khoâng tìm ra
ngöôøi nhaän cuûa moät böùc mail hoaëc böùc mail bò gôûi sai ñòa chæ thì caùc böùc mail
naøy seõ ñöôïc gôûi tôùi user admin. Neáu xaûy ra loãi trong quaù trình phaân phoái thì
Deliver seõ goïi haøm goïi haøm CloserFolder() ñeå giaûi phoùng caùc taøi nguyeân caáp
phaùt tröôùc ñoù vaø thoaùt.
Cuoái cuøng, sau khi phaân phoái caùc mail tôùi töøng ngöôøi nhaän thaønh coâng,
Deliver seõ goïi haøm CloserFolder() ñeå giaûi phoùng caùc taøi nguyeân caáp phaùt tröôùc
ñoù vaø thoaùt.
1. HAØØM OPENFOLDER():
Haøm OpenFolder() thöïc hieän moät loaït caùc taùc vuï, ñoù laø taïo ra moät file
taïm duøng ñeå chöùa caùc mail ñöôïc ñoïc töø hoäp thö ñeå duøng cho quaù trình Deliver.
Ñoàng thôøi taïo ra danh saùch ngöôøi nhaän *p cuûa böùc mail naøy. Trong ñoù, ñòa chæ
ngöôøi nhaän ñöôïc xöû lyù sao cho coá gaéng ñöa ñöôïc veà daïng môû roäng cuûa mình.
Khi ñöôïc goïi thöïc thi, ñaàu tieân, haøm OpenFolder() seõ taïo ra moät file
taïm duøng ñeå chöùa caùc böùc Mail ñoïc ñöôïc töø outbox.
Keá tieáp, noù seõ ñoïc laàn löôït caùc böùc mail trong hoäp thö caàn phaân phoái,
moãi laàn ñoïc vaøo moät haøng cuûa böùc mail, vaø xöû lyù.
· Neáu haøng ñoïc vaøo thuoäc phaàn header, noù seõ kieåm tra xem:
+ Neáu haøng baét ñaàu baèng “From: …” thì thoâng tin theo sau seõ ñöôïc löu
vaøo p->from.
+ Neáu haøng baét ñaàu baèng “To:…” hoaëc baèng “Cc:…”, ñaây laø caùc haøng
chöùa thoâng tin ñòa chæ cuûa ngöôøi nhaän. Caùc ngöôøi nhaän seõ ñöôïc taùch ra vaø löu
vaøo p->to.
+ Ñoàng thôøi vôùi vieäc xöû lyù naøy laø ghi laïi caùc thoâng tin naøy vaøo file taïm.
p = stInsert((struct SENDTO**) &send);
if (p == NULL) goto tmperr;
p->id = ++mails; /*soá thöù töï cuûa böùc Mail*/
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 43
fputs(buf, fld);
p->msgseek = ftell(fld);
p->havemail = (char *)malloc(2*SVRBUFSIZ*sizeof(char));
strcpy(p->havemail,"");
while (fgets(buf, SVRBUFSIZ, fp) != NULL)
{
if (!isheader(buf)) break;
else if (ismailfrom(buf)) hf = S_FROM;
else if (ismailto(buf) || ismailcc(buf)) hf = S_TO;
else if (ismailbcc(buf)) hf = S_BCC;
else if (*buf > ' ') hf = S_COMMON;
switch (hf)
{
/*save sender addr, write to top header: from*/
case S_FROM:
if (p->from == NULL)
{
p->from = (char*) malloc(strlen(buf));
if (p->from == NULL) goto tmperr;
strcpy(p->from, &buf[5]);
chop(p->from);
}
break;
case S_TO:
case S_BCC:
{
strcpy(addr_add, buf);
make_addr(addr_add, mailbox);
while (i = pos("\"", addr_add))
addr_add = delete(addr_add, i, 1);
if (AddToAddr(p, addr_add)) goto tmperr;
break;
}
}
fflush(fld);
· Neáu khoâng phaûi laø phaàn header thì ñaây chính laø phaàn data cuûa böùc
mail, thöïc hieän ghi luoân leân file taïm.
do
{
if (ismailstart(buf)) break;
fputs(buf, fld);
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 44
} while (fgets(buf, SVRBUFSIZ, fp) != NULL);
fputs("\n", fld);
Neáu khoâng coù loãi xaûy ra thì haøm seõ traû laïi toång soá böùc mail coù trong hoäp
thö caàn phaân phaùt, coøn ngöôïc laïi seõ traû veà maõ loãi.
2. HAØØM DELIVERY():
Nhieäm vuï chính cuûa haøm Delivery() laø phaân phoái caùc message tôùi töøng
mailbox cuûa caùc user trong heä thoáng döïa vaøo phaàn ñòa chæ môû roäng cuûa mail.
Khi baét ñaàu thöïc thi, noù seõ böôùc ngay vaøo voøng laëp for vôùi p = send chæ
tôùi phaàn thoâng tin löu giöõ trong caáu truùc SENDTO cuûa böùc mail ñaàu tieân.
for (p = send; p != NULL; p = p->next)
{
/*Thaân voøng for*/
}
Delivery() seõ thöïc hieän kieåm tra xem coù ñòa chæ cuûa ngöôøi nhaän trong
tröôøng “to” cuûa caáu truùc SENDTO, vaø trong tröôøng “to” naøy coù ngöôøi naøo hay
khoâng, neáu khoâng coù, noù seõ thoâng baùo loãi vaø seõ chuyeån sang message keá tieáp.
for (p = send; p != NULL; p = p->next)
{
if ((p->to == NULL) || (p->to->host == NULL))
{
printf("no destinative address. abort mail %d#\n", p->id);
continue;
}
/*caùc phaàn xöû lyù keá tieáp*/
}
Sau khi kieåm tra ñaõ coù phaàn ñòa chæ cuûa ngöôøi nhaän, Delivery() seõ böôùc
vaøo voøng for thöù hai loàng trong voøng for ñaàu vôùi r = p->to chæ tôùi ñòa chæ cuûa
ngöôøi ñaàu tieân trong danh saùch ñòa chæ ñöôïc löu giöõ trong caáu truùc DLVTO.
for (r = p->to; r != NULL; r = r->next)
{
/*thaân voøng for*/
}
Tieáp theo, Delivery() seõ kieåm tra xem phaàn ñòa chæ thöïc söï cuûa böùc mail
(phaân bieät vôùi ñòa chæ môû roäng) coù ñuùng laø ñòa chæ email internet cuûa mình
khoâng. Neáu khoâng ñuùng thì böùc mail nay ñaõ ñöôïc gôûi sai ñòa chæ vaø noù seõ ñöôïc
chuyeån cho admin.
Neáu böùc mail naøy ñaõ gôûi ñuùng ñòa chæ cuûa chuùng ta, nhöng noù khoâng coù
phaàn ñòa chæ môû roäng, ñaây laø moät böùc mail khoâng hôïp leä, vaø chuùng ta cuõng seõ
chuyeån noù tôùi cho admin.
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 45
Neáu coù phaàn môû roäng, chuùng ta seõ laáy phaàn môû roäng naøy vaø thöïc hieän
vieäc tìm kieám trong file “/etc/passwd” ñeå laáy ra user öùng vôùi teân môû roäng naøy,
neáu tìm trong file “/etc/passwd” khoâng coù, chuùng ta seõ tìm tieáp trong file
“/etc/mapping”, laø moät file aùnh xaï töø teân môû roäng thaønh teân cuûa user trong heä
thoáng, maø ñöôïc thöïc hieän bôûi ngöôøi quaûn trò. Neáu khoâng tìm thaáy user trong file
naøy, coù nghóa laø user naøy khoâng coù trong heä thoáng. Do ñoù, ñòa chæ cuûa böùc mail
naøy cuõng khoâng hôïp leä, vaø böùc mail naøy seõ ñöôïc chuyeån cho admin ñeå xöû lyù.
Neáu tìm thaáy user trong heä thoáng thì böùc mail naøy seõ ñöôïc chuyeån tôùi mailbox
cuûa user naøy.
for (r = p->to; r != NULL; r = r->next)
{
tmp = emailaddr(r->host);
/* kieåm tra domain cuûa böùc mail */
if (strcmp(tmp, mailbox/*MYDOMAIN*/)) tmp = admin;
/* kieåm tra phaàn ñòa chæ môû roäng */
else if ((tmp = extendaddr(r->host)) == NULL) tmp = admin;
/* kieåm tra coù user trong heä thoáng khoâng */
else if ((tmp = scanpasswd(tmp)) == NULL) tmp = admin;
/* kieåm tra xem user ñaõ nhaän böùc mail naøy chöa */
if (strstr(p->havemail, tmp)) continue;
/* ñaùnh daáu laø user ñaõ nhaän böùc mail naøy roài */
strcat(p->havemail, tmp);
strcpy(pathname, inbox);
strcat(pathname, tmp);
/* lock file laïi, sau ñoù môùi ghi leân file */
dest_fi=open(pathname, O_CREAT | O_APPEND | O_RDWR);
if (!(dest_fi > 0)) return 0;
lock_file = flock(dest_fi, LOCK_EX);
if (lock_file < 0)
{
close(dest_fi);
return;
}
f = fdopen(dest_fi, "a+t");
if (f == NULL)
{
close(dest_fi);
return;
}
/* taïo laïi phaàn header bò maát */
fprintf(f,"%s %s %s\n","From",emailaddr(p->from), timenow());
fseek(fld, p->msgseek, SEEK_SET);
while (fgets(tmp1, SVRBUFSIZ - 1, fld) != NULL)
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 46
{
if (ismailstart(tmp1)) break;
fputs(tmp1, f);
}
flock(dest_fi, LOCK_UN);
fclose(f);
close(dest_fi);
}
Quaù trình naøy seõ ñöôïc laëp laïi cho ñeán khi khoâng coøn ngöôøi nhaän trong
caáu truùc DLVTO, töùc laø r == NULL. Vaø luùc naøy, noù seõ chuyeån sang böùc mail keá
tieáp ñeå xöû lyù.
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 47
No
Yes
No
No
Yes
No
Yes
No
Yes
Yes
Yes
No
No
Môû Inbox ?
Ñoïc töøng doøng moät böùc Mail töø
Inbox leân.
Taïo ra file taïm ?
Tröôøng “From”
Tröôøng “To”
Tröôøng “Cc”
Thoâng baùo loãi
töông öùng vaø thoaùt
Ghi vaøo tröôøng From cuûa
caáu truùc SENTO vaø ghi
vaøo file taïm
Ghi vaøo file taïm.
Xöû lyù roài ghi vaøo danh saùch ngöôøi
nhaän cuûa caáu truùc SENTO
Data cuûa böùc Mail Yes Ghi vaøo file taïm.
Coøn Mail trong
Mailbox ?
Ñoùng outbox vaø thoaùt.
Löu ñoà ñoïc Mail
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 48
No
No
No
No
Yes
Yes
Yes
Yes
Ñoïc danh saùch ngöôøi nhaän vaø
laáy ra ngöôøi ñaàu tieân
Xöû lyù phaàn ñòa chæ môû roäng
Coù ñòa chæ môû roäng ?
Laø user trong heä thoáng ?
Chuyeån thö tôùi ngöôøi nhaän
töông öùng
Môû hoäp mail
cuûa user vaø
lock laïi
Heát ngöôøi nhaän?
Thoaùt khoûi chöông trình
Chuyeån thö tôùi admin
Löu ñoà phaân phoái Mail
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 49
CHÖÔNG III:
CHÖÔNG TRÌNH SMTPCLIENT
I. CAÙÙC CAÁÁU TRUÙÙC DÖÕÕ LIEÄÄU DUØØNG TRONG
MODULE SMTP CLIENT:
struct DLVTO
{
char *host;
struct DLVTO *next;
};
struct SENTO
{
int id ;
/*chæ soá id cuûa thö*/
char *from ;
/*mail from*/
struct DLVTO *to ;
/*send to*/
long mleng ;
/*chieàu daøi cuûa noäi dung thö*/
long msgseek;
/*vò trí cuûa thö coù chæ soá laø id trong file*/
};
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 50
II. SÔ ÑOÀÀ KHOÁÁI:
1. SÔ ÑOÀÀ TOÅÅNG QUAÙÙT:
Yes
Deliver mail vaø taïo back up
neáu coù yeâu caàu
Ñoùng keát noái
Môû vaø ñoïc file outbox
Coù thö caàn gôûi?
Taïo socket keát noái tôùi server
Thoaùt vaø baùo loãi töông
öùng
No
END
BEGIN
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 51
2. SÔ ÑOÀÀ KHOÁÁI CHO KHOÁÁI MÔÛÛ VAØØ ÑOÏÏC FILE:
Yes
Môû file outbox ñeå ñoïc
vaø xoùa.
Taïo ra danh saùch ngöôøi
nhaän ñoái vôùi mail naøy.
Coù tröôøng Bcc?
End of file?
Thoaùt vaø ñoùng file
Yes
No
No
Taïo danh saùch send, ñoïc töø outbox
va ghi vaøo file taïm
BEGIN
END
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 52
3. SÔ ÑOÀÀ KHOÁÁI CHO KHOÁÁI DELIVER:
Yes
Baùo Loãi vaø gôûi QUIT
Yes
No
P = send ;
P != NULL?
Gôûi leänh HELO
Reply == 250?
Gôûi MAIL FROM:
Reply == 250?
No
Yes
No
2
BEGIN
Baùo Loãi vaø Thoaùt
R = p -> to ;
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 53
No
Yes
R != NULL?
Gôûi RCPT TO:<ñòa chæ töøng
ngöôøi nhaän>
Reply == 250?
Gôûi DATA vaø mail data
Reply ==354?
Gôûi QUIT, thoâng baùo thaønh coâng
2
Yes
No
Th
oa
ùt v
aø
ba
ùo
lo
ãi
Th
oa
ùt v
aø
ba
ùo
lo
ãi
END
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 54
III. HOAÏÏT ÑOÄÄNG CUÛÛA MODULE SMTP CLIENT:
Khi chöông trình ñöôïc kích hoaït, haøm OpenFolder() ñöôïc goïi ñaåu tieân.
Haøm naøy coù nhieäm vuï môû file outbox – file chöùa caùc thö caàn göûi ra ngoaøi – ñeå
kieåm tra xem coù thö caàn göûi khoâng? Neáu coù noù seõ laøm caùc coâng vieäc sau:
- Tìm ra vò trí ñaàu tieân cuûa mail trong file outbox ñeå laáy ra phaàn
thoâng tin header cuûa mail, sau ñoù taïo ra danh saùch send maø moãi
phaàn töû coù kieåu caáu truùc döõ lieäu laø SENDTO.
- Kieåm tra xem trong thö coù tröôøng BCC khoâng? Neáu coù thì taïo ra
danh saùch nhöõng ngöôøi nhaän seõ nhaän cuøng moät noäi dung mail naøy
maø moãi phaàn töû cuûa danh saùch coù kieåu döõ lieäu laø DLVTO.
- Neáu trong file sntpclient.conf coù chöùa phaàn header caàn cheøn vaøo thì
cheøn vaøo file ñeå gôûi ñi.
Sau khi haøm OpenFolder thöïc hieän song, chuùng ta coù ñöôïc moät danh
saùch caùc laù thö caàn göûi ñoàng thôøi öùng vôùi moãi laù thö neáu coù tröôøng BCC thì
chuùng ta laïi coù theâm moät danh saùch ngöôøi nhaän ñoái vôùi thö töông öùng naøy.
Tieáp theo phaûi taïo ra caàu noái TCP tôùi server ñeå trao ñoåi thoâng tin. Khi
taïo caàu noái thaønh coâng, haøm dilevery ñöôïc goïi. Haøm delivery hoaït ñoäng nhö
sau:
- Ñaàu tieân göûi ñi leänh HELO, neáu nhaän ñöôïc traû lôøi 250 thì chöông
trình böôùc vaøo voøng for ñeå duyeät danh saùch caùc thö caàn göûi.
for (p=send,p!=NULL,p=p->next) {
göûi leänh MAIL FROM;
/* duyeät danh saùch ngöôøi nhaän ñoái vôùi laù thö naøy*/
for ( r=p->to;p!=NULL;r=r->next) {
göûi caùc leänh RCPT TO;
}
göûi leänh DATA vaø noäi dung thöïc söï cuûa mail, keát
thuùc baèng daáu chaám “.”.
}
- Göûi leänh QUIT keát thuùc trao ñoåi.
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 55
CHÖÔNG IV:
CHÖÔNG TRÌNH SMTPD
I. GIÔÙÙI THIEÄÄU:
Chöông trình SMTPD laø moät chöông trình mail server. Noù hieän thöïc
giao thöùc SMTP (Simple Mail Transfer Protocol) ñöôïc moâ taû trong RFC 821. ÔÛ
ñaây, chuùng em chæ hieän thöïc moät phaàn cuûa giao thöùc naøy ñeå thöïc hieän yeâu caàu
cuûa ñeà taøi.
SMTPD seõ chaïy treân maùy tính ñöôïc chæ ñònh laøm server cuûa heä thoáng.
Ñaây cuõng chính laø maùy keát noái tröïc tieáp vôùi Internet. Khi thöïc thi, noù seõ laéng
nghe treân TCP port 25, nhaän caùc böùc mail töø caùc maùy client vaø gôûi tôùi caùc ñòa
chæ ñaõ ñöôïc chæ ñònh trong böùc mail naøy. ÔÛ ñaây, chöông trình seõ phaân bieät:
- Neáu böùc mail naøy ñöôc gôûi cho caùc user ôû trong heä thoáng, töùc laø ñòa chæ
ngöôøi nhaän cuûa böùc mail naøy laø ñòa chæ cuïc boä, thì böùc mail naøy seõ ñöôïc
chuyeån tröïc tieáp tôùi mailbox cuûa ngöôøi nhaän.
- Neáu böùc mail naøy ñöôïc gôûi cho caùc user ôû beân ngoaøi heä thoáng, töùc laø ñòa
chæ ngöôøi nhaän cuûa böùc mail khoâng phaûi laø ñòa chæ cuïc boä cuûa heä thoáng,
thì böùc mail naøy seõ ñöôïc chuyeån ñeán hoäp thö outbox
“/var/spool/sharedmail/outbox”. Ñaây laø hoäp thö duøng ñeå chöùa caùc böùc
mail gôûi ra beân ngoaøi cuûa heä thoáng. Do heä thoáng cuûa chuùng ta khoâng keát
noái vôùi Internet lieân tuïc neân khi coù yeâu caàu keát noái thì seõ coù moät chöông
trình SMTP-Client thöïc hieän nhieäm vuï keát noái vôùi Server Mail cuûa nhaø
dòch vuï cung caáp dòch vuï mail vaø nhôø chöông trình Server naøy gôûi caùc
böùc mail naøy tôùi caùc ñòa chæ cuûa ngöôøi nhaän.
Nhö vaäy, chöông trình SMTPD ôû ñaây phaûi phaân bieät ñöôïc ñòa chæ ngöôøi
nhaän laø cuïc boä vaø ñòa chæ ngöôøi nhaän beân ngoaøi. Ñieàu naøy coù phaàn quan troïng
trong böùc moät böùc mail, tröôøng “Return-path” löu giöõ ñòa chæ ngöôøi gôûi, ñòa chæ
löu giöõ trong tröôøng naøy seõ ñöôïc söû duïng trong tröôøng hôïp ngöôøi nhaän ñöôïc
mail muoán hoài ñaùp laïi vôùi ngöôøi gôûi hoaëc böùc mail khoâng theå ñeán ñöôïc ngöôøi
nhaän do sai ñòa chæ hoaëc do moät lyù do naøo ñoù thì caùc chöông trình mail server
seõ döïa vaøo ñòa chæ naøy ñeå gôûi traû laïi böùc mail cho ngöôøi gôûi. Do ñoù, neáu laø
ngöôøi nhaän cuïc boä thì vieäc gôûi ñôn giaûn chæ laø ñöa böùc mail vaøo mailbox cuûa
ngöôøi nhaän vaø tröôøng “Return-path” ñôn giaûn chæ chöùa ñòa chæ cuûa ngöôøi gôûi
trong cuïc boä.
Trong tröôøng hôïp böùc mail ñöôïc gôûi ra beân ngoaøi, töùc laø ngöôøi nhaän
khoâng naèm trong heä thoáng. Luùc naøy, do heä thoáng mail cuûa chuùng ta laø duøng
chung moät account Internet mail, neân beân ngoaøi chæ bieát ñöôïc chuùng ta döïa treân
ñòa chæ mail naøy, ñieàu naøy coù nghóa laø coù theå beân trong heä thoáng cuûa chuùng ta
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 56
coù nhieàu users, account mail cuïc boä cuûa cac users naøy coù theå khaùc nhau. Nhöng
khi caùc users naøy gôûi mail ra beân ngoaøi thì beân ngoaøi chæ nhìn thaáy ñöôïc hoï
döôùi moät ñòa chæ duy nhaát, ñoù laø ñòa chæ mail ñaõ ñöôïc ñaêng kyù vôùi nhaø dòch vuï.
Do ñoù, ñeå phaân bieät ñöôïc ai laø ngöôøi gôûi böùc mail ñeå ñöa vaøo tröôøng “Return-
path”, chuùng ta ñaõ giaûi quyeát baèng caùch ñöa theâm vaøo tröôùc ñòa chæ mail ñaõ
ñaêng kyù vôùi nhaø dòch vuï moät phaàn ñòa chæ môû roäng, ñoù chính laø phaàn teân ñaày ñuû
cuûa user trong heä thoáng cuûa chuùng ta. Do ñoù, phaàn ñòa chæ mail trong tröôøng
“Return-path” khi gôûi ra ngoaøi seõ coù daïng: fullname_of_user .
Ñeå coù theå laøm ñöôïc ñieàu naøy, chöông trình SMTPD ñaõ thöïc hieän chuyeån
ñoåi töø: username laø teân login cuûa user trong heä thoáng cuûa chuùng ta thaønh
fullname cuûa user naøy. Quaù trình chuyeån ñoåi naøy döïa treân file: “/etc/passwd”,
ñaây laø file chöùa caùc thoâng tin veà user cuûa heä thoáng. Trong file “/etc/passwd”,
thoâng tin cuûa moãi user ñöôïc löu giöõ treân moät haøng, bao goàm nhieàu tröôøng, moãi
tröôøng caùch nhau baèng daáu “:”. Daïng format cuûa moät haøng trong file
“/etc/passwd” laø: login-name:encrypted-password:user-ID:group-
ID:miscellany:login-directory:shell.
Sau khi chuyeån ñoåi xong, phaàn môû roäng cuûa user seõ ñöôïc keát hôïp vôùi ñòa
chæ mail ñöôïc caáp bôûi nhaø cung caáp dòch vuï ñeå ñöa vaøo tröôøng “Return-path”.
II. CAÙÙC CAÁÁU TRUÙÙC CUÛÛA SMTPD:
1. CAÁÁU TRUÙÙC LÖU GIÖÕÕ TRAÏÏNG THAÙÙI:
typedef fd_set smtp_state_set;
typedef fd_set *smtp_state;
Hai caáu truùc naøy duøng ñeå löu giöõ traïng thaùi cuûa SMTPD trong quaù trình
nhaän caùc yeâu caàu töø client. Caùc traïng thaùi seõ ñöôïc thieát laäp khi nhaän ñöôïc leänh:
“HELO” hoaëc “EHLO”, “MAIL FROM:”, “RCPT TO:”, “DATA” töø client,
theo thöù töï. Trong tröôøng hôïp caùc leänh nhaän ñöôïc khoâng naèm trong caùc leänh
treân thì chöông trình seõ thöïc hieän caùc leänh naøy vaø traïng thaùi seõ khoâng ñöôïc thieát
laäp. Neáu caùc leänh nhaän ñöôïc laø caùc leänh treân, nhöng khoâng theo ñuùng thöù töï thì
moät thoâng baùo loãi seõ ñöôïc traû laïi cho client.
2. CAÁÁU TRUÙÙC LÖU GIÖÕÕ THOÂÂNG TIN:
typedef struct smtp_info
{
FILE *ifile;
/*input socket*/
int ofile;
/*output socket*/
char myhostname[MAXHOSTNAMELEN + 1];
/*computer run this program*/
char myaddr[15];
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 57
/*address of this computer*/
char clientname[MAXHOSTNAMELEN + 1];
/*name of client*/
char clientaddr[15];
/*address of this client*/
unsigned short port;
char sender[256];
/*user send this mail*/
char receiver[MAX_USER][256];
/*list of local reciever*/
int num_recv;
/*number of local receiver*/
char userfar[MAX_USER][256];
/*list of non_local receiver*/
int num_userfar;
/*number of non_local receiver*/
}smtp_info;
3. CAÙÙCH HOAÏÏT ÑOÄÄNG CUÛÛA CHÖÔNG TRÌNH SMTPD:
Khi chöông trình SMTPD thöïc thi, ñaàu tieân, noù seõ khôûi taïo moät khoái
smtp_info baèng caùch goïi haøm:
smtp = (smtp_info *)malloc(sizeof (smtp_info));
Sau khi khôûi taïo khoái smtp_info xong, tieáp ñeán, noù löu laïi teân maùy vaø
ñòa chæ IP maø chöông trình SMTPD ñang chaïy vaøo trong bieán smtp-
>myhostname vaø smtp->myaddr. Sau khi hoaøn thaønh xong taùc vuï naøy, SMTPD
seõ khôûi taïo socket vaø chôø yeâu caàu keát noái töø maùy client. Neáu coù yeâu caàu keát noái
töø client, noù seõ löu laïi ñòa chæ IP cuûa maùy client trong smtp->clientaddr vaø thöïc
hieän vieäc tìm kieám teân maùy client baèng gethostbyaddr(), neáu coù, seõ löu laïi teân
maùy trong smtp->clientname. Sau ñoù, SMTPD seõ taïo ra hai stream duøng cho
vieäc trao ñoåi döõ lieäu vôùi moät ñaàu vaøo ñöôïc löu giöõ bôûi smtp->ifile (vôùi FILE
*smtp->ifile) vaø ñaàu ra ñöôïc löu giöõ bôûi smtp->ofile (vôùi int smtp->ofile), keát
hôïp vôùi socket ôû treân.
Sau khi keát noái thaønh coâng, SMTPD seõ gôûi laïi cho client thoâng baùo:
220 smtp->myhostname Simple Mail Transfer Service Ready.
Sau ñoù, noù seõ baét ñaàu vaøo voøng laëp chôø nhaän caùc yeâu caàu töø client gôûi
ñeán vaø thöïc hieän noù.
while (1)
{
readlh(smtp->ifile, inbuf, SIZBUF);
memcpy(last_state, current_state, sizeof(smtp_state_set));
chop(inbuf);
smtp_parse_cmd(inbuf, current_state);
...
}
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 58
Khi coù yeâu caàu töø phía client gôûi qua, SMTPD seõ löu giöõ noù vaøo bieán
inbuf, sau ñoù noù seõ goïi haøm smtp_parse_cmd(inbuf, current_state) ñeå phaân tích
yeâu caàu naøy vaø xöû lyù noù.
Nhö chuùng ta bieát, caùc leänh cuûa giao thöùc SMTP (Simple Mail Transfer
Protocol) thöôøng coù ñoä daøi laø 4 kyù töï. Do ñoù, khi ñöôïc goïi leân thöïc thi, haøm
smtp_parse_cmd() seõ laáy 4 kyù töï ñaàu tieân cuûa inbuf ñeå kieåm tra xem ñoù laø leänh
gì ñeå thöïc hieän theo yeâu caàu cuûa client. Trong tröôøng hôïp leänh bò sai hoaëc
SMTPD khoâng hoå trôï leänh naøy thì noù seõ thoâng baùo laïi cho client bieát ñeå xöû lyù.
Khi client gôûi leänh “helo” SMTPD seõ traû veà cho client chuoåi:
“250 smtp->myhostname Hello smtp->clientname [ smtp->clientaddr ],
please to meet you.”
Ñeå baùo cho client bieát phieân thöïc hieän vöøa roài laø thaønh coâng, yeâu caàu
client gôûi leänh tieáp theo theo trình töï cuûa nghi thöùc.
Phaàn code moâ taû quaù trình thöïc hieän nhieäm vuï naøy:
if ((strcasecmp(verb, "HELO") == 0) || (cmd_ok(EHLO, state) &&
(strcasecmp(verb, "EHLO") == 0)))
{
/*kieåm tra xem leänh “helo” ñaõ ñöôïc gôûi hay chöa */
if (!cmd_ok(HELO, state))
{
sprintf(outbuf, "503 Duplicate HELO/EHLO\n");
writeline(smtp->ofile, outbuf);
state_change(state, HELO, FAILURE);
return;
}
SPANBLANK(buf);
/*kieåm tra xem coù phaàn döõ lieäu ñi theo sau leänh helo hay khoâng*/
if (*buf == '\0')
{
sprintf(outbuf, "501 %s requires domain address\n",verb);
writeline(smtp->ofile, outbuf);
state_change(state, HELO, FAILURE);
return;
}
sendinghost = strdup(buf);
if (sendinghost == NULL) exit(-1);
if (!strcasecmp(verb, "HELO"))
{
sprintf(outbuf, "250 %s Hello %s [%s], pleased to meet you\n",
smtp->myhostname, smtp->clientname, smtp->clientaddr);
writeline(smtp->ofile, outbuf);
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 59
}
else
{
sprintf(outbuf, "250-%s Hello %s [%s], pleased to meet you\n",
smtp->myhostname, smtp->clientname, smtp->clientaddr);
writeline(smtp->ofile, outbuf);
}
state_change(state, HELO, SUCCESS);
}
Khi client gôûi tieáp leänh “mail from: sender@domain “, thoâng soá
sender@domain seõ ñöôïc duøng laøm “Return-path” cuûa böùc mail trong tröôøng
hôïp ngöôøi nhaän thuoäc heä thoáng cuûa chuùng ta. Neáu ngöôøi nhaän khoâng thuoäc heä
thoáng (böùc mail gôûi ra beân ngoaøi thì chöông trình seõ thöïc hieän vieäc aùnh xaï töø
sender@domain thaønh fullname_of_sender ñeå laøm “Return-
path” cho böùc mail, vôùi fullname_of_sender laø teân ñaày ñuû cuûa user trong heä
thoáng cuûa chuùng ta, vaø mail_address laø ñòa chæ mail do nhaø cung caáp dòch vuï
mail caáp cho chuùng ta.
Neáu thöïc hieän leänh naøy thaønh coâng, SMTPD seõ gôûi laïi cho client thoâng
baùo: “250 sender@domain ... Sender Ok”. Trong tröôøng hôïp ngöôïc laïi, SMTPD
seõ gôûi thoâng baùo loãi laïi cho client ñeå client xöû lyù.
Phaàn code moâ taû quaù trình thöïc hieän nhieäm vuï naøy:
if (strcasecmp(verb, "MAIL") == 0)
{
char *name;
if (!cmd_ok(MAIL, state))
{
/*kieåm tra xem ñaõ coù leänh “helo” chöa ?*/
if (cmd_ok(HELO, state))
{
sprintf(outbuf, "503 Need HELO before MAIL\n");
writeline(smtp->ofile, outbuf);
state_change(state, MAIL, FAILURE);
}
/*kieåm tra xem client ñaõ gôûi leänh “mail” chöa ?*/
else
{
sprintf(outbuf, "503 Sender already specified\n");
writeline(smtp->ofile, outbuf);
state_change(state, MAIL, ERROR);
}
return;
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 60
}
/*kieåm tra xem sau chuoåi “mail” coù phaûi laø chuoåi “from” khoâng ?*/
SPANBLANK(buf);
if (strncasecmp(buf, "FROM:", 5) != 0)
{
sprintf(outbuf, "501 Syntax error in parameters or arguments\n");
writeline(smtp->ofile, outbuf);
state_change(state, MAIL, ERROR);
return;
}
buf += 5;
SPANBLANK(buf);
/*xöû lyù phaàn ñòa chæ nhaän ñöôïc*/
return_path = del_bracket(buf);
if (strstr(return_path, smtp->myhostname) || strstr(return_path,
"localhost"))
{
name = username(return_path);
strcpy(smtp->sender, name);
free(name);
}
else
strcpy(smtp->sender, return_path);
sprintf(outbuf, "250 %s... Sender ok\n", buf);
writeline(smtp->ofile, outbuf);
state_change(state, MAIL, SUCCESS);
}
Keá tieáp, client seõ gôûi leänh “rcpt to: receiver@domain” . Vì moät laù thö
coù theå ñöôïc gôûi cho nhieàu ngöôøi neân phaàn ñòa chæ ngöôøi nhaän seõ ñöôïc kieåm tra
vaø löu giöõ laïi. Neáu ngöôøi nhaän ôû trong cuøng heä thoáng thì phaàn ñòa chæ naøy ñöôïc
löu giöõ laïi ôû trong daõy smtp->receiver (ñoái vôùi ngöôøi nhaän cuïc boä, ta coù theå chæ
gôûi teân user thoâi, khoâng caàn theâm daáu “@” vaø teân domain cuûa noù). Vaø neáu
ngöôøi nhaän khoâng ôû trong heä thoáng, töùc laø gôûi ra beân ngoaøi thì ñòa chæ ngöôøi
nhaän seõ ñöôïc löu giöõ trong daõy smtp->userfar.
Trong quùa trình kieåm tra ngöôøi nhaän, neáu coù loãi xaûy ra, thoâng baùo loãi seõ
ñöôïc gôûi cho client. Trong tröôøng hôïp ngöôïc laïi, chuoåi “250 receiver@domain
... Receiver Ok” seõ ñöôïc gôûi laïi cho client.
Phaàn code moâ taû quaù trình thöïc hieän nhieäm vuï naøy:
if (strcasecmp(verb, "RCPT") == 0)
{
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 61
char *victim, *name;
struct passwd *pwd;
int i, yes_user;
/*kieåm tra xem client ñaõ gôûi leänh “mail” chöa*/
if (!cmd_ok(RCPT, state))
{
sprintf(outbuf, "503 Need MAIL before RCPT\n");
writeline(smtp->ofile, outbuf);
state_change(state, RCPT, ERROR);
return;
}
/*kieåm tra xem ñi sau chuoåi “rcpt” coù phaûi laø chuoåi “to:” hay khoâng ?*/
SPANBLANK(buf);
if ((strlen(buf) < 3) || strncasecmp(buf, "TO:", 3) != 0)
{
sprintf(outbuf, "501 Syntax error in parameters or arguments\n");
writeline(smtp->ofile, outbuf);
state_change(state, RCPT, ERROR);
return;
}
buf += 3;
SPANBLANK(buf);
/*tröôøng hôïp khoâng coù daáu “@”, ñaây laø ngöôøi nhaän cuïc boä, löu giöõ laïi
vaøo daõy smtp->receiver*/
victim = del_bracket(buf);
if (!strchr(victim, '@'))
{
if (smtp->num_recv < MAX_USER)
{
i = 0;
yes_user = 0;
while (i num_recv)
{
if (!strcmp(pwd->pw_name, smtp->receiver[i]))
{
yes_user = 1;
break;
}
else i++;
}
if (!yes_user)
{
strcpy(smtp->receiver[smtp->num_recv], victim);
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 62
smtp->num_recv++;
}
}
}
else
{
name = username(victim);
/*tröôøng hôïp coù daáu “@”, kieåm tra xem user coù naèm trong heä
thoáng hay khoâng ?*/
if ((pwd = getpwnam(name)) && ((strstr(victim, smtp->
myhostname)) || (strstr(victim, "localhost"))))
{
if (smtp->num_recv < MAX_USER)
{
i = 0;
yes_user = 0;
while (i num_recv)
{
if (!strcmp(pwd->pw_name, smtp->receiver[i]))
{
yes_user = 1;
break;
}
else i++;
}
if (!yes_user)
{
strcpy(smtp->receiver[smtp->num_recv], pwd->
pw_name);
smtp->num_recv++;
}
}
}
else /*goi cho user o ben ngoai he thong*/
{
if (smtp->num_userfar < MAX_USER)
{
i = 0;
yes_user = 0;
while (i num_userfar)
{
if (!strcmp(pwd->pw_name, smtp->userfar[i]))
{
yes_user = 1;
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 63
break;
}
else i++;
}
if (!yes_user)
{
strcpy(smtp->userfar[smtp->num_userfar], pwd->
pw_name);
smtp->num_userfar++;
}
}
}
}
sprintf(outbuf, "250 %s... Ricipient ok\n", victim);
writeline(smtp->ofile, outbuf);
state_change(state, RCPT, SUCCESS);
}
Tieáp ñeán, client seõ gôûi leänh “data” vaø sau ñoù, noù seõ tuaàn töï gôûi noäi dung
cuûa böùc mail. Phaàn döõ lieäu naøy seõ khoâng qua xöû lyù cuûa haøm smtp_parse_cmd(),
bôûi vì ñaây laø phaàn noäi dung cuûa böùc mail, khoâng phaûi laø leänh. SMTPD nhaän
phaàn döõ lieäu naøy vaø löu giöõ vaøo trong moät file taïm. Döõ lieäu ñöôïc keát thuùc baèng
chuoãi “.\r\n”.
Phaàn code moâ taû quaù trình thöïc hieän nhieäm vuï naøy:
if ((!test_state(SNARF_DATA, last_state)) &&
(test_state(SNARF_DATA, current_state)))
{
tempfile = (char *)malloc(80*sizeof(char));
strcpy(tempfile, TMPFILE);
if ((f_tmp = fdopen(mkstemp(tempfile), "w+t")) == NULL)
{
/*tröôøng hôïp môû file khoâng thaønh coâng*/
clear_state(SNARF_DATA, current_state);
clear_state(OK_RCPT, current_state);
clear_state(OK_MAIL, current_state);
}
else
{
readlh(smtp->ifile, inbuf, SIZBUF);
while (inbuf[0] != '.')
{
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 64
fixcrlf(inbuf, 0);
fputs(inbuf, f_tmp);
readlh(smtp->ifile, inbuf, SIZBUF);
}
fclose(f_tmp);
}
}
Ñoái vôùi ngöôøi nhaän cuïc boä thì thö seõ ñöôïc chuyeån ngay ñeán mailbox cuûa
ngöôøi nhaän ngay sau khi client gôûi leänh “data” vaø döõ lieäu qua. Coøn ñoái vôùi caùc
ngöôøi nhaän khoâng cuïc boä thì thö seõ ñöôïc chuyeån ñeán hoäp thö outbox
“/var/spool/sharedmail/outbox” ñeå gôûi ra ngoaøi.
Khi client gôûi leänh “quit”, SMTPD seõ gôûi laïi cho client chuoåi:
“221 smtp->hostname Service closing transmission channel”
vaø keát noái seõ ñöôïc ñoùng laïi.
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 65
CAÙC LÖU ÑOÀ
no
yes
Löu laïi domain cuûa sender
return(message(250, ...))
( Sender send “MAIL FROM:” )
Client ñaõ gôûi
leänh “helo” chöa
?
return(message(503, ...))
Löu ñoà leänh HELO
return(message(221, ...))
Löu ñoà leänh QUIT
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 66
Löu ñoà leänh MAIL FROM
yes
no
yes
no Ñaõ coù leänh HELO
chöa ?
Ñaõ coù leänh MAIL
chöa ?
Löu laïi phaàn ñòa chæ ngöôøi gôûi.
Return(message(250,...)).
Return(message(503,...)).
no
yes
Ngöôøi nhaän coù ôû
trong heä thoáng ?
yes
no
yes
no Ñaõ coù leänh
MAIL chöa ?
Ñaõ coù leänh
DATA chöa ?
Löu laïi phaàn ñòa chæ ngöôøi trong
danh saùch smtp->receiver.
Return(message(250,...)).
Return(message(503,...)).
Löu laïi phaàn ñòa chæ ngöôøi trong
danh saùch smtp->userfar.
Return(message(250,...)).
Löu ñoà leänh RCPT TO
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 67
Löu ñoà leänh DATA vôùi ngöôøi nhaän cuïc boä
yes
no Ñaõ coù leänh RCPT
chöa ?
Return(message(503,...)). Return(message(354,...)).
(end with .)
Môõ file taïm ñeå chöùa message töø
client gôûi qua.
yes
no
no
yes
Coù bao nhieâu ngöôøi nhaän.
Môõ hoäp thö cuûa
töøng ngöôøi nhaän
vaø lock laïi
Chuyeån thö tôùi ngöôøi nhaän töông öùng
Heát ngöôøi nhaän
chöa ?
Return(quit()). Return(message(250,...)). Chuyeån thö thaønh coâng.
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 68
Löu ñoà leänh DATA vôùi ngöôøi nhaän beân ngoaøi
yes
no Ñaõ coù leänh RCPT
chöa ?
Return(message(503,...)). Return(message(354,...)).
(end with .)
Môõ file taïm ñeå chöùa message töø
client gôûi qua.
yes
no
no
yes
Coù bao nhieâu ngöôøi nhaän.
Môû outbox vaø
lock laïi
Chuyeån thö cuûa ngöôøi nhaän töø xa tôùi outbox.
Heát ngöôøi nhaän
chöa ?
Return(quit()). Return(message(250,...)). Chuyeån thö thaønh coâng.
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 69
yes
no
no
no
yes
yes
Khôûi taïo khoái smtp_info
Laáy teân Host
cuûa maùy Server
Laáy ñòa chæ IP
cuûa maùy Client
Taïo hai Stream
cho Input,
Return (+OK) Return (-1)
Khôûi taïo caùc thoâng tin caàn thieát
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 70
no
no
yes
yes
yes
no
Khôûi taïo caùc thoâng tin caàn thieát
Return (message(250, +0K))
Laáy message töø
Input
Return (message(550, -ERR)).
Ñoùng keát noái vaø thoaùt.
Phaân tích döõ lieäu nhaän ñöôïc ñeå
laáy leänh caàn thöïc hieän
Leänh nhaän ra
ñöôïc bôûi Smtpd
Thöïc hieän leänh töông öùng
Thöïc hieän leänh
thaønh coâng
Return(message(250, +OK)). Return(message( , -
ERR))
Quaù trình thöïc hieän leänh
LUAÄN VAÊN TOÁT NGHIEÄP GVHD : NGUYEÃN CAO ÑAÏT
SVTH : Traàn Ngoïc Sôn & Hoaøng Ñöùc Quang Trang 71
PHAÀÀN IV:
NHAÄÄN XEÙÙT VAØØ HÖÔÙÙNG PHAÙÙT
TRIEÅÅN
1. MOÄÄT SOÁÁ KHAÛÛ NAÊÊNG CUÛÛA CHÖÔNG TRÌNH:
- Chöông trình ñaõ thöïc hieän ñöôïc taùc vuï cho pheùp nhieàu ngöôøi cuøng gôûi vaø
nhaän Mail maø chæ söû duïng moät Account Mail ñöôïc caáp bôûi nhaø cung caáp
dòch vuï.
- Mail cuûa caùc user cuïc boä gôûi cho nhau seõ ñöôïc gôûi tröïc tieáp tôùi mailbox cuûa
moãi ngöôøi.
- Mail cuûa caùc user gôûi ra ngoaøi heä thoáng seõ ñöôïc löu giöõ laïi trong mailbox
rieâng. Keát noái vôùi nhaø cung caáp dòch vuï thoâng qua modem vaøo nhöõng thôøi
ñieåm ñònh tröôùc. Khi coù keát noái thì caùc mail naøy seõ ñöôïc gôûi ñi.
- Cho pheùp Administrator coù theå caáu hình ñoái vôùi heä thoáng töø xa thoâng qua
Webmin.
2. HÖÔÙÙNG PHAÙÙT TRIEÅÅN CUÛÛA CHÖÔNG TRÌNH:
Tuy chöông trình ñaõ giaûi quyeát ñöôïc moät soá vaán ñeà ñaõ ñaët ra, nhöng
chöông trình vaãn coøn nhieàu vaán ñeà coù theå phaùt trieån leân ñöôïc nhö:
- Xöû lyù theâm caùc daïng ñòa chæ ñeå cho pheùp ngöôøi söû duïng ñöôïc uyeån chuyeån
hôn trong vieäc gôûi vaø nhaän Mail.
- Neân thöïc hieän taùc vuï loïc Mail khi nhaän Mail töø Server veà ñeå phoøng choáng
Spam.
- Cho pheùp coù theå laøm vieäc treân moät soá chuaån Mail khaùc.
Trang chuû | Muïc luïc
Các file đính kèm theo tài liệu này:
- Thư điện tử.pdf