返回列表 发帖

[Zend权威认证试题讲解]第八章 - 处理电子邮件

没有了E-Mail,这世界会变成什么样?网络交流把人们拉得更近,让公司能够更有效的开展业务,不幸的是,也带来了垃圾信息。& s0 ]7 o6 H  h* [1 R+ ?: ]% ]
还好,你不需要成为一个反垃圾邮件专家就能使用PHP处理电子邮件的功能。事实上,不管你是在运营一家在线商店,还是在编写一套论坛程序,你都会发现发送邮件是你工作中很重要的一部分——与用户保持联系这点非常重要。
6 E6 E: O% K. [/ Z' w用PHP编写邮件管理脚本很简单,但也不失挑战性。如果你只是想发送一封文本邮件,mail函数对你来说就够了。而如果你需要处理更复杂的电子信息——例如HTML邮件和附件时,那么你就需要深入学习一下E-Mail的工作原理了。6 N( `$ g+ o/ T% E! H1 ]$ x7 ^0 D
+ J1 U1 Y& K8 q8 e- Q( u8 u

; Q  g+ B- W+ Z! a问题
. A# K  m2 x, j) [8 [2 B) I
7 Z* F1 K0 a7 j% J4 n1.以下哪个不是合法的电子邮件地址?
& s$ @, I5 C- i! A) v4 t6 o
. H, `8 m- ]3 P6 v$ F; BA.john@89w.org1 _: N" {: h- W6 o' Y8 b; i3 e+ ?
B."John Coggeshall" <someone@89w.org>, |2 v+ S, h( G3 y/ h
C.joe @ 89w.org
: w# T5 j, a$ P4 V, QD.jean-cóggeshall@89w.org; o9 R) m/ J) C- }+ ~
E.john: y) v0 ?# A3 d; C0 _7 K' f
( s3 f1 `# h# W6 ^8 c8 `: A" v

* l$ `( u6 `1 I, C6 }( l2.在PHP中,使用sendmail程序从Windows或Novell系统中发送邮件的方式,与从类UNIX系统中发送的方式不同。以下哪些选项说明了这个不同?(双选)
0 |0 c# X3 t- l" V* |* ]) Q  q+ c2 D& p% s
A.Windows/Novell不需要第三方软件的支持就能实现该功能+ ^" y; w* D( h9 c$ p
B.UNIX中,sendmail_from的配置来决定了邮件头中的From:信息。# g, x, N! G  V+ b; ~
C.在Windows/Novell中,你无法发送有多个收件人的电子邮件,每个收件人都必须单独发送
& d3 o4 F( G5 }" H: Q1 |. f- nD.有可能完全相同,这取决于sendmail_path的配置
/ j& R2 d2 x6 U& H! }E.不同与Windows/Novell,在UNIX中,你必须用SMTP和smtp_port配置好MTA主机和端口
$ Q5 i7 f! B- P, E6 I; D, {) _2 @0 O/ b1 C
4 @3 m9 t  u1 U% B
3.通过PHP发送有多个收件人或者MIME兼容的邮件,需要遵循什么步骤?
6 l0 b+ s$ C/ i1 P6 J* M
# H3 S: J+ S, k+ n/ f# NA.将必要的头信息(header)通过$message参数(第三个参数)传递给mail函数9 d' h5 t' G7 N' t
B.用PHP代码,通过SMTP直接与MTA连接。2 O; R2 a0 l6 e, z: E; B3 _4 x  Q
C.将附加的头信息传递给mail函数的$additional_headers参数(第四个参数),每个header一行。) X% e$ S. B/ {& G' M
D.向多个收件人发送E-Mail是允许的。PHP不支持发送MIME E-Mail。
0 W% h' v% L/ R9 L* Q% k2 W$ VE.向mail函数传递$additional_headers参数,每个header一行,行以\r\n结尾
' k+ Q2 G5 v. I6 @+ Z6 ?, Z% M+ f) f# m7 D, v5 V, s, {  w+ |  w

: c2 {- N3 O# c% {8 M6 g4.使用MIME发送有附件的邮件时,邮件正文和附件必须靠一个特殊的分隔符分开。MIME E-Mail的头信息里如何定义这个分隔符?4 s0 C' K7 S4 v1 a" p) M
# s. w  S- J/ }/ s8 B) Q% h+ m( {/ Z
答案:____________
: ]2 U$ d) p% q1 q
9 d2 p# Y- J& Q* A' L7 A" N! V+ Z- k1 H. {" A0 B9 v: z
5.使用MIME发送HTML邮件时,经常会用到一些经典的HTML标签,比如用<img>嵌入图片。以下那些方法能做到这点?(双选)
/ l( {: g2 L/ T" X1 [/ C
) I1 Y. q# E4 `& cA.直接用<img>标签把图片文件嵌入邮件内容中,邮件客户端能自动显示
6 s3 Y2 D; p% B1 A7 ^0 TB.通过给<img>标签添加一个URL的src属性来调用外部服务器上的图片' z; p% k) W! N% M3 `: y% z
C.把图片作为MIME内容直接嵌入邮件中,再把<img>标签的src属性指定为内容ID
/ l- e- c; y! r% H) cD.把图片作为附件,再把<img>标签的src属性指定为图片的文件名. C+ a: C1 K$ Q9 [
E.只有一个答案正确: M; G9 X& a" G: E
+ E" [! x; _: ]7 z
5 J5 Q) z$ n; q: S, ]
6.以下那种情况会用到mail函数的第五个(最后一个)参数$additional_parameters?
) m" o( P7 d7 W6 T4 ]  _, X- p1 X5 O4 x- y# C; E( J% o
A.从UNIX或Windows/Novell发送邮件时都会用到
8 j' `  x+ ~% Y! [7 b% {: kB.只有在Windows/Novell平台上用SMTP命令向MTA发送邮件时
+ L  _% s9 Q: ^- k" ^C.只有在和sendmail或一个指定了sendmail_path的打包程序协作发送时7 {0 g0 l( v8 ~- [. D
D.PHP里用不到这个参数
+ w; q$ j! O8 F9 J3 K$ N
& p( Q) d. R8 l- u, R+ A. H5 G) g" _+ U
7.以下那种情况需要在头信息中添加邮件内容编码(Content-Transfer-Encoding)?+ Q0 F  p- B  R( I1 c
; e2 x: `  W7 V4 \
A.只有在发送非普通文本(ASCII)数据时$ @1 {$ f6 R6 o
B.需要指出E-Mail的格式时,例如HTML,普通文本(plain text),富文本(rich text)- R) G4 K5 c1 J3 b
C.任何时候都可以用它来指出MIME的编码类型
5 s  B+ ]7 \) Q: S, o0 N; `& `, L0 PD.只能用来指定特殊的编码格式(例如base64)
2 ~! N5 G1 w2 a3 C, uE.以上都不对" o4 A" Y8 s9 m
* C$ g0 |# i: f* [  L0 Q( w' w/ T9 p
8.以下关于在头信息Content-Type中定义的MIME分隔符的描述,哪些正确?(三选)7 ^+ }, B. Y# N" _- q# \5 J( c

( i3 v% Y1 A( N8 w) o3 g$ m$ fA.分隔符至少要8个字符0 b8 @$ b) m: e, ^
B.分隔符必须以两个连字号作为前缀(例如:--abcdefghi)和后缀来表示起止(例如:--abcdefghi--)
: s8 c( ^4 }3 S+ h% B# }' DC.分隔符在MIME邮件中必须是独一无二的
. O2 J. S$ w4 X6 n. X. dD.分隔符不能嵌套的其他分隔符中
. _" Y0 _0 v  R8 ~0 c9 H9 A1 bE.用什么做分隔符都无所谓
+ @0 ?" D- c+ n. j) N
6 n" N: I8 q& V: }: E+ Z. r: G) c7 r& B! H
9.考虑如下E-Mail:
; J0 O- _3 _9 a( O8 X4 L, ^/ ^, y. Q
From: John Coggeshall <john@php.net>
* W! k& M9 L. L7 V: n  A. N5 }$ {7 W1 ^To: Joe User <joe@example.comt>  J4 P+ c/ k* G/ W$ J
Subject: Hello from John!
% M0 G/ U$ o# C5 RDate: Wed, 20 Dec 2004 20:18:47 -04001 Y) Q. n6 z6 w( \
Message-ID: <1234@local.machine.example>
/ t! u+ g& j+ Q& sHello, How are you?
6 G- [! W2 B/ F( E  v3 S* a" H$ x/ ~7 w/ q7 r( G2 N- z6 [
在头信息里添加什么才能让它成为一份MIME邮件?(不定项选择)$ G* _' T2 C6 q6 t3 Y$ t

" _! j$ K( \9 x4 |A.MIME-Version
4 o! t1 `' ?% MB.Content-Disposition& M0 }" M. H6 I0 T# L3 W
C.Content-Type
, k- \9 b1 _+ cD.Content-Transfer-Encoding( B' B! C7 O2 h/ O# L% B
E.Content-ID' X9 P1 U0 x% ?, |

! }/ C: q- q8 g
3 [. n& L5 s* Z; h- \& F10.发送一封包含HTML、富文本和普通文本三个版本的邮件,要想客户端能选择一个合适的版本打开,MIME的content-type应该是什么?
0 N) a8 u1 \# |) [/ f6 y2 B* U+ [0 \9 O& R; w( L
A.multipart/mixed
& M2 {# ^2 K& g/ VB.multipart/alternative
* q/ F9 [8 H* Z. V2 MC.multipart/default9 i) v7 N; t6 _7 t" I7 W
D.multipart/related9 A# Y0 @/ C) D: ^. @' V+ i
E.不可能用content-type实现8 ~, |% h: U+ d

) F% }+ y& W& ^: s7 f1 z
6 c. P( p  y' \! N7 h5 x11.假设你的机器上没有安装sendmail,要想mail函数能在Windows下使用,需要做什么?
( t' a: W0 C8 S+ Z3 b5 `, K, @/ q
A.安装sendmail服务器6 U+ H" T9 _' U% c# `$ \5 q
B.安装Microsoft Exchange# S0 K$ N4 U# W0 R7 g, G+ @
C.在你的电脑上安装任何一种邮件服务器3 V" J, s% W1 @* U6 ]( f  \
D.改变php.ini的设置
- [' T/ p8 Y9 M3 j4 `6 ?E.写一个连接公共电子邮件服务器的脚本
7 q% a1 b2 _1 r, F# g. R; d) ]! o

1 d+ R9 O$ W7 d$ o' M12.有一个向用户提交的地址发送指定内容的文本邮件的表单,以下哪种方法有助于防止通过该表单进行跨站攻击?(双选)
6 t; c: y: ]2 {. |9 P- C& R, `2 G+ @# @$ K) z1 E! W9 D
A.使用GET方式传值
  `& u- D6 W: Z3 RB.用htmlentities()处理电子邮件地址
' {4 x; g4 `+ Y% c3 R" UC.使用POST方式传值
$ H, O! T# r9 m4 @& |! SD.用htmlentities()处理邮件正文
7 H8 O/ {- u, O% zE.确保填写邮件地址的文本域不能有换行符  B. g+ s" s! g2 t

' ]/ G7 Y' w* F
+ v. F7 g( A3 {- P! Q13.如何将一个数组作为附件发送,并要能在接收后重新组合?
" U# f, }8 d* {6 r! j+ c) v" Z0 K& y! g
A.用serialize()把它转换成字符串,再用htmlentities()处理一下+ F. F/ Z! Y/ @) Q
B.把它存在文件中,并用base64_encode()进行编码
' y1 i) r7 x6 w5 ^8 J" ZC.用serialize()把它转换成数组- ?* x- N0 Y2 |5 o
D.用serialize()把它转换成数组,再用base64_encode()进行编码
5 W. D% t' P2 {; A6 aE.把它存在文件中,再用convert_uuencode()进行编码" p/ W  d" i, o( m1 n
7 e# S% e: M* c% _$ `/ O

* {' j5 h+ K% t( `! s' N14.要确定需要嵌入在MIME/multipart 邮件中的文件该使用什么MIME类型,以下那种方法最好?; d& e  Y/ m$ D9 K( @4 x5 }

: ^1 L# f" I- R$ p/ @1 tA.堆一个检测脚本出来
- O- v" F" L4 r% ]7 o, v. \B.创建一个MIME类型和文件后缀名的列表,根据后缀名选定需要的MIME类型4 [: C8 M3 [$ V: ~% m
C.写一个识别文件MIME类型与内容是否相符的函数
+ z- M3 |) K* S/ a+ [  [D.使用mime_content_type函数' |$ Z8 S3 ^- e) y
E.把文件上传到外部服务器上& O/ O4 |/ \, B. f% B

3 p- q* i1 a! N8 a  v1 f( z- p+ x1 g" k8 A
15.在UNIX环境下使用本地安装的sendmail,如何才能随意设置邮件的发件人名字与发件人地址?(三选)
! D2 b5 `1 A. M# x( h% @! ~" {- c. q, `
A.添加一个From头信息
$ l, i4 k, ], H. h; jB.使用-f参数
* g) @3 N, d; g' _' G# p) zC.添加一个Reply-to的头信息
5 M$ z- M2 q& N6 j5 cD.确保运行Apache的用户有修改sendmail设置的权利
# O' Z- f  f8 z& Z3 D' S* ^E.确保Apache在root用户下运行: Z4 E- F0 d; A8 X
答案速查1 m5 x5 v" N5 R& M8 Y6 ]5 P* `  z
1:D
: T4 f! |; F' z6 h& `2:AD& w8 y& o* P2 H$ C: `, `! U
3:E0 Q; ]. |/ S* Q+ ]- V$ c8 m1 u
4:Content-Type:MIME
, A4 p& R% U$ ^5:BC( }2 ^5 C' x1 r  K
6:A
/ j4 R+ N' [. e7 v3 w7:C, Z& |+ B( N0 U$ |
8:BCE* o: f$ P3 i0 ?9 _
9:ACD
1 @, N* |$ |% U1 L10:B, E- _/ `) k- w" f, q
11:D
, f% B8 k" w' T) n0 a12:CE% e9 p; Y/ G1 K; |+ ^1 H& _
13:D/ ^) f9 t6 m' E% Q9 }6 t
14:D
7 O- Q5 E/ X$ b; u, S, Y/ A% I; i8 ?15:ABD5 n- `& q/ |3 W% f1 o/ b( s; \+ E
- N: a- u' s7 j
% o! b% T; i! P+ H
, ~/ Q  n5 w4 v) p8 _( @4 a( X
答案详解
9 q: r  v4 C, d7 M( F! x2 I7 E
; ^- h3 g1 w- ^! N6 r1.列出的E-Mail地址中只有D不合法。A和B都是最经典、常用的电子邮件地址。C看起来不合法,但邮件传输代理(MTA)会自动过滤多余的空格。E可以在本地发送时使用。那么就只剩下D了,它里面有一个非法字符。1 K3 B* [6 r9 f  {: Q1 D

/ o* b: n- q: u! n. q2.正确答案是A和D。UNIX版本的PHP需要用sendmail程序(或者功能等同的替代品)通过MTA发送邮件,Windows/Novell版本的则通过SMTP直接用MTA发送。然而,如果允许的话,Windows/Novell上的PHP也可以进行配置,来通过“sendmail封装器”模拟sendmail发信。也就是说PHP在这三个版本上能够以相同的方式实现此功能。注意,在Windows/Novell上使用mail()时,需要配置sendmail_from。而UNIX则把这件事交给sendmail程序自己来处理。2 t- d* D: x. r; K; w. ~. f1 p/ E+ b
+ G! N8 Z5 K% f" W: J" c6 y
3.PHP可以用mail函数发送任何格式合法的电子邮件,于是编写用SMTP发信的PHP脚本成为了下策。要在E-Mail中添加额外的头信息,则必须向函数传递$additional_headers参数,每个头信息以一个回车符和一个换行符结尾(\r\n)。发送复杂的邮件,比如带附件的或者HTML格式的邮件,则不仅需要添加额外的头信息,还要添加MIME类型。所以答案是E。. p0 q) O+ j$ }. z; Q( J$ x4 C+ Q
8 q9 x6 m8 I7 J. N% ?8 b. {, |
4.发送由多个部分组成的MIME邮件时,你必须指定一个分隔符(任何US-ASCII字符串),它必须不同于邮件主题中任何一个部分。分隔符必须与MIME信息中嵌入的任何一部分都不同。分隔符在Content-Type: MIME中定义。5 U% x: o& e1 o% N
9 c+ ~8 m# W, v2 U% a! z+ G
5.有两个选项指出了在HTML邮件中包含图片等资源的正确方法。最快的方法就是直接引用一张远程图片。然而,图片以及其他资源能够以MIME内容块的形式嵌入MIME邮件自身。这些内容块会被赋予ID,可以通过把src属性设置为cid:资源标识加内容ID的方式来调用。因此答案B和C正确。
4 h( l$ o5 S6 ^+ g- s3 j0 o+ R9 f& w
6.mail函数的最后一个参数用来向sendmail程序传递参数,不过这只能在安装了sendmail的UNIX系统上进行。如果Windows/Novell系统上配置了sendmail_path,那么这个参数同样也是可用的。
) J# a2 F7 i$ ?  m$ A1 D. X* Z. j' U  G% Z
7.答案是C。MIME头信息里的内容编码(Content-Transfer-Encoding)用来指出MIME邮件中各个片段的编码。头信息中包含一组指出了编码算法的二进制数据。默认情况下,7bit,quoted-printable,base64,8bit和binary是可用的编码类型。不过任何人也可以通过使用x-<unique name for encoding>来声明自己的编码格式。
% n1 V# B7 r# ]5 Q" W9 v3 L8 Z- w) x+ n( r) O
8.正确答案是B,C和E。分隔符是MIME邮件中至关重要的一部分。虽然分隔符的长度没有官方限制,但由于分隔符由文本字符构成,因此它绝对不能出现在邮件主体中,否则就会造成混乱。考虑一种灾难性的情况:假设我们用John做分隔符,那么邮件中提到的人名John就会分隔邮件,导致邮件内容的混乱。8 G3 P) f8 o& u6 @
( s3 q8 i, H1 l6 R
9.要从给定的文本信息中创建一份合法的MIME邮件,正确的答案是A,C和D。MIME邮件在开头处必须有MIME-Version头信息,而邮件的每个片段(包括“root”片段)都必须有Content-Type和content-transfer-encoding这两个部分。答案中提到的另外两个头信息是可选的:Content-Disposition用来指出片段要如何显示(比如显示为附件),Content-ID是片段中的各个内容的唯一识别符。" w3 g3 w9 M5 r% u8 ^6 v) Y) y: T

7 t" @+ H4 U" F! r7 s* N10.正确答案是B。这种特殊的MIME类型用来定义一个含多个内容相同的子版本片段的母片段。比如说,一个multipart/alternative片段包含一个text/plain和一个text/html版本的片段。然后由电子邮件客户端选择一个最合适的版本来显示给用户。通常情况下,最好放入一个文本格式的版本,这样不支持MIME的邮件客户端也能正常读取。0 I( d7 L6 L( F( k2 t2 _' F
( t( G, s: i; L& K) y
11.在类UNIX系统中,PHP依靠sendmail程序来处理邮件。而在Windows中,除非已有sendmail包装器,否则将使用服务器的SMTP配置来进行。答案是D。
1 q$ w( ^9 z/ z% s' }( C
# |! N5 k$ L5 `4 t0 a* Q8 v# d. t12.在普通文本邮件中使用htmlentities()不能防止跨站攻击,反而可能会让邮件内容变得不可读。强制使用POST传递变量只能让攻击变的困难,但并非绝对安全。确保E-Mail文本域(将变成To:的部分)中没有换行符,能够防止恶意用户把自己的邮件地址添加进收件人地址中。因此答案是C和E。
9 q8 I% U/ j5 l3 O+ `# D; J7 x7 s- H9 z( T& h& S/ ^- a! X1 T- a
13.把数组序列化成一个字符串是传输这个数组的正确方式——第一步先让数组变得可以通过E-Mail网络传输。接下来你需要对它进行编码,以使得它能够安全传输。在PHP4中,最简单的方法是用base64_encode把它编码成每字符7bit的形式。答案是D。9 L( K, M0 L* O8 @, I4 P: l

7 A2 l1 }2 ^, X# J  Q9 y% M5 k6 R14.要判断一个文件的MIME类型,最简单的方法是使用mime_content_type函数。答案是D。注意,虽然别的扩展库里有能更好的解决这个问题的函数(译者注:比如PECL的FileInfo),但在这里使用mime_content_type仍然是可以的。
8 N! n8 L- [6 q" N4 J9 f* \5 `
15.在头信息中添加From不能完全保证sendmail不会在邮件中重写你的发件人地址。事实上,你需要通过发送器向sendmail传递-f参数。除此之外,你还必须确保运行Apache的用户有修改头信息中的From内容的权限。因此答案是A,B和D。

返回列表
【捌玖网络】已经运行: