Fix attachments and content-type problems #1276 [Jamis Buck] Fix to only...

Fix attachments and content-type problems #1276 [Jamis Buck] Fix to only perform the charset conversion if a 'from' and a 'to' charset are given (make no assumptions about what the charset was) #1276 [Jamis Buck]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1300 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 8983a097
*SVN*
* Fix to only perform the charset conversion if a 'from' and a 'to' charset are given (make no assumptions about what the charset was) #1276 [Jamis Buck]
* Fix attachments and content-type problems #1276 [Jamis Buck]
* Fixed the TMail#body method to look at the content-transfer-encoding header and unquote the body according to the rules it specifies #1265 [Jamis Buck]
* Added unquoting even if the iconv lib can't be loaded--in that case, only the charset conversion is skipped #1265 [Jamis Buck]
......
......@@ -14,18 +14,19 @@ def attachments
if multipart?
parts.collect { |part|
if part.header["content-type"].main_type != "text"
content = part.body.unpack("m")[0]
content = part.body if content.blank?
file_name = part.header["content-type"].params["name"]
content = part.body # unquoted automatically by TMail#body
file_name = part.header["content-type"].params["name"] ||
part.header["content-disposition"].params["filename"]
next if file_name.blank? || content.blank?
attachment = Attachment.new(content)
attachment.original_filename = file_name.strip.dup
attachment.original_filename = file_name.strip
attachment.content_type = part.content_type
attachment
end
}.compact
end
end
end
end
\ No newline at end of file
end
require 'base64'
module TMail
class Mail
def subject(to_charset = 'utf-8')
......@@ -29,9 +27,10 @@ def body(to_charset = 'utf-8', &block)
if multipart?
parts.collect { |part|
part.header["content-type"].main_type == "text" ?
header = part.header["content-type"]
header && header.main_type == "text" ?
part.unquoted_body(to_charset) :
attachment_presenter.call(part.header["content-type"].params["name"])
(header ? attachment_presenter.call(header.params["name"]) : "")
}.join
else
unquoted_body(to_charset)
......@@ -65,13 +64,14 @@ def unquote_quoted_printable_and_convert_to(text, to, from)
end
def unquote_base64_and_convert_to(text, to, from)
convert_to(Base64.decode64(text), to, from)
convert_to(Base64.decode(text).first, to, from)
end
begin
require 'iconv'
def convert_to(text, to, from)
text ? Iconv.iconv(to, from || "ISO-8859-1", text).first : ""
return text unless to && from
text ? Iconv.iconv(to, from, text).first : ""
end
rescue LoadError
# Not providing quoting support
......
From xxxxxxxxx.xxxxxxx@gmail.com Sun May 8 19:07:09 2005
Return-Path: <xxxxxxxxx.xxxxxxx@gmail.com>
X-Original-To: xxxxx@xxxxx.xxxxxxxxx.com
Delivered-To: xxxxx@xxxxx.xxxxxxxxx.com
Received: from localhost (localhost [127.0.0.1])
by xxxxx.xxxxxxxxx.com (Postfix) with ESMTP id 06C9DA98D
for <xxxxx@xxxxx.xxxxxxxxx.com>; Sun, 8 May 2005 19:09:13 +0000 (GMT)
Received: from xxxxx.xxxxxxxxx.com ([127.0.0.1])
by localhost (xxxxx.xxxxxxxxx.com [127.0.0.1]) (amavisd-new, port 10024)
with LMTP id 88783-08 for <xxxxx@xxxxx.xxxxxxxxx.com>;
Sun, 8 May 2005 19:09:12 +0000 (GMT)
Received: from xxxxxxx.xxxxxxxxx.com (xxxxxxx.xxxxxxxxx.com [69.36.39.150])
by xxxxx.xxxxxxxxx.com (Postfix) with ESMTP id 10D8BA960
for <xxxxx@xxxxxxxxx.org>; Sun, 8 May 2005 19:09:12 +0000 (GMT)
Received: from zproxy.gmail.com (zproxy.gmail.com [64.233.162.199])
by xxxxxxx.xxxxxxxxx.com (Postfix) with ESMTP id 9EBC4148EAB
for <xxxxx@xxxxxxxxx.com>; Sun, 8 May 2005 14:09:11 -0500 (CDT)
Received: by zproxy.gmail.com with SMTP id 13so1233405nzp
for <xxxxx@xxxxxxxxx.com>; Sun, 08 May 2005 12:09:11 -0700 (PDT)
DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;
s=beta; d=gmail.com;
h=received:message-id:date:from:reply-to:to:subject:in-reply-to:mime-version:content-type:references;
b=cid1mzGEFa3gtRa06oSrrEYfKca2CTKu9sLMkWxjbvCsWMtp9RGEILjUz0L5RySdH5iO661LyNUoHRFQIa57bylAbXM3g2DTEIIKmuASDG3x3rIQ4sHAKpNxP7Pul+mgTaOKBv+spcH7af++QEJ36gHFXD2O/kx9RePs3JNf/K8=
Received: by 10.36.10.16 with SMTP id 16mr1012493nzj;
Sun, 08 May 2005 12:09:11 -0700 (PDT)
Received: by 10.36.5.10 with HTTP; Sun, 8 May 2005 12:09:11 -0700 (PDT)
Message-ID: <e85734b90505081209eaaa17b@mail.gmail.com>
Date: Sun, 8 May 2005 14:09:11 -0500
From: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
Reply-To: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
To: xxxxx xxxx <xxxxx@xxxxxxxxx.com>
Subject: Fwd: Signed email causes file attachments
In-Reply-To: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
Mime-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_Part_5028_7368284.1115579351471"
References: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
------=_Part_5028_7368284.1115579351471
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
We should not include these files or vcards as attachments.
---------- Forwarded message ----------
From: xxxxx xxxxxx <xxxxxxxx@xxx.com>
Date: May 8, 2005 1:17 PM
Subject: Signed email causes file attachments
To: xxxxxxx@xxxxxxxxxx.com
Hi,
Just started to use my xxxxxxxx account (to set-up a GTD system,
natch) and noticed that when I send content via email the signature/
certificate from my email account gets added as a file (e.g.
"smime.p7s").
Obviously I can uncheck the signature option in the Mail compose
window but how often will I remember to do that?
Is there any way these kind of files could be ignored, e.g. via some
sort of exclusions list?
------=_Part_5028_7368284.1115579351471
Content-Type: application/pkcs7-signature; name=smime.p7s
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIGFDCCAs0w
ggI2oAMCAQICAw5c+TANBgkqhkiG9w0BAQQFADBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVt
YWlsIElzc3VpbmcgQ0EwHhcNMDUwMzI5MDkzOTEwWhcNMDYwMzI5MDkzOTEwWjBCMR8wHQYDVQQD
ExZUaGF3dGUgRnJlZW1haWwgTWVtYmVyMR8wHQYJKoZIhvcNAQkBFhBzbWhhdW5jaEBtYWMuY29t
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn90dPsYS3LjfMY211OSYrDQLzwNYPlAL
7+/0XA+kdy8/rRnyEHFGwhNCDmg0B6pxC7z3xxJD/8GfCd+IYUUNUQV5m9MkxfP9pTVXZVIYLaBw
o8xS3A0a1LXealcmlEbJibmKkEaoXci3MhryLgpaa+Kk/sH02SNatDO1vS28bPsibZpcc6deFrla
hSYnL+PW54mDTGHIcCN2fbx/Y6qspzqmtKaXrv75NBtuy9cB6KzU4j2xXbTkAwz3pRSghJJaAwdp
+yIivAD3vr0kJE3p+Ez34HMh33EXEpFoWcN+MCEQZD9WnmFViMrvfvMXLGVFQfAAcC060eGFSRJ1
ZQ9UVQIDAQABoy0wKzAbBgNVHREEFDASgRBzbWhhdW5jaEBtYWMuY29tMAwGA1UdEwEB/wQCMAAw
DQYJKoZIhvcNAQEEBQADgYEAQMrg1n2pXVWteP7BBj+Pk3UfYtbuHb42uHcLJjfjnRlH7AxnSwrd
L3HED205w3Cq8T7tzVxIjRRLO/ljq0GedSCFBky7eYo1PrXhztGHCTSBhsiWdiyLWxKlOxGAwJc/
lMMnwqLOdrQcoF/YgbjeaUFOQbUh94w9VDNpWZYCZwcwggM/MIICqKADAgECAgENMA0GCSqGSIb3
DQEBBQUAMIHRMQswCQYDVQQGEwJaQTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlD
YXBlIFRvd24xGjAYBgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0
aW9uIFNlcnZpY2VzIERpdmlzaW9uMSQwIgYDVQQDExtUaGF3dGUgUGVyc29uYWwgRnJlZW1haWwg
Q0ExKzApBgkqhkiG9w0BCQEWHHBlcnNvbmFsLWZyZWVtYWlsQHRoYXd0ZS5jb20wHhcNMDMwNzE3
MDAwMDAwWhcNMTMwNzE2MjM1OTU5WjBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENv
bnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVtYWlsIElz
c3VpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMSmPFVzVftOucqZWh5owHUEcJ3f
6f+jHuy9zfVb8hp2vX8MOmHyv1HOAdTlUAow1wJjWiyJFXCO3cnwK4Vaqj9xVsuvPAsH5/EfkTYk
KhPPK9Xzgnc9A74r/rsYPge/QIACZNenprufZdHFKlSFD0gEf6e20TxhBEAeZBlyYLf7AgMBAAGj
gZQwgZEwEgYDVR0TAQH/BAgwBgEB/wIBADBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLnRo
YXd0ZS5jb20vVGhhd3RlUGVyc29uYWxGcmVlbWFpbENBLmNybDALBgNVHQ8EBAMCAQYwKQYDVR0R
BCIwIKQeMBwxGjAYBgNVBAMTEVByaXZhdGVMYWJlbDItMTM4MA0GCSqGSIb3DQEBBQUAA4GBAEiM
0VCD6gsuzA2jZqxnD3+vrL7CF6FDlpSdf0whuPg2H6otnzYvwPQcUCCTcDz9reFhYsPZOhl+hLGZ
GwDFGguCdJ4lUJRix9sncVcljd2pnDmOjCBPZV+V2vf3h9bGCE6u9uo05RAaWzVNd+NWIXiC3CEZ
Nd4ksdMdRv9dX2VPMYIC5zCCAuMCAQEwaTBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3Rl
IENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVtYWls
IElzc3VpbmcgQ0ECAw5c+TAJBgUrDgMCGgUAoIIBUzAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcB
MBwGCSqGSIb3DQEJBTEPFw0wNTA1MDgxODE3NDZaMCMGCSqGSIb3DQEJBDEWBBQSkG9j6+hB0pKp
fV9tCi/iP59sNTB4BgkrBgEEAYI3EAQxazBpMGIxCzAJBgNVBAYTAlpBMSUwIwYDVQQKExxUaGF3
dGUgQ29uc3VsdGluZyAoUHR5KSBMdGQuMSwwKgYDVQQDEyNUaGF3dGUgUGVyc29uYWwgRnJlZW1h
aWwgSXNzdWluZyBDQQIDDlz5MHoGCyqGSIb3DQEJEAILMWugaTBiMQswCQYDVQQGEwJaQTElMCMG
A1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNv
bmFsIEZyZWVtYWlsIElzc3VpbmcgQ0ECAw5c+TANBgkqhkiG9w0BAQEFAASCAQAm1GeF7dWfMvrW
8yMPjkhE+R8D1DsiCoWSCp+5gAQm7lcK7V3KrZh5howfpI3TmCZUbbaMxOH+7aKRKpFemxoBY5Q8
rnCkbpg/++/+MI01T69hF/rgMmrGcrv2fIYy8EaARLG0xUVFSZHSP+NQSYz0TTmh4cAESHMzY3JA
nHOoUkuPyl8RXrimY1zn0lceMXlweZRouiPGuPNl1hQKw8P+GhOC5oLlM71UtStnrlk3P9gqX5v7
Tj7Hx057oVfY8FMevjxGwU3EK5TczHezHbWWgTyum9l2ZQbUQsDJxSniD3BM46C1VcbDLPaotAZ0
fTYLZizQfm5hcWEbfYVzkSzLAAAAAAAA
------=_Part_5028_7368284.1115579351471--
From xxxx@xxxx.com Tue May 10 11:28:07 2005
Return-Path: <xxxx@xxxx.com>
X-Original-To: xxxx@xxxx.com
Delivered-To: xxxx@xxxx.com
Received: from localhost (localhost [127.0.0.1])
by xxx.xxxxx.com (Postfix) with ESMTP id 50FD3A96F
for <xxxx@xxxx.com>; Tue, 10 May 2005 17:26:50 +0000 (GMT)
Received: from xxx.xxxxx.com ([127.0.0.1])
by localhost (xxx.xxxxx.com [127.0.0.1]) (amavisd-new, port 10024)
with LMTP id 70060-03 for <xxxx@xxxx.com>;
Tue, 10 May 2005 17:26:49 +0000 (GMT)
Received: from xxx.xxxxx.com (xxx.xxxxx.com [69.36.39.150])
by xxx.xxxxx.com (Postfix) with ESMTP id 8B957A94B
for <xxxx@xxxx.com>; Tue, 10 May 2005 17:26:48 +0000 (GMT)
Received: from xxx.xxxxx.com (xxx.xxxxx.com [64.233.184.203])
by xxx.xxxxx.com (Postfix) with ESMTP id 9972514824C
for <xxxx@xxxx.com>; Tue, 10 May 2005 12:26:40 -0500 (CDT)
Received: by xxx.xxxxx.com with SMTP id 68so1694448wri
for <xxxx@xxxx.com>; Tue, 10 May 2005 10:26:40 -0700 (PDT)
DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;
s=beta; d=xxxxx.com;
h=received:message-id:date:from:reply-to:to:subject:mime-version:content-type;
b=g8ZO5ttS6GPEMAz9WxrRk9+9IXBUfQIYsZLL6T88+ECbsXqGIgfGtzJJFn6o9CE3/HMrrIGkN5AisxVFTGXWxWci5YA/7PTVWwPOhJff5BRYQDVNgRKqMl/SMttNrrRElsGJjnD1UyQ/5kQmcBxq2PuZI5Zc47u6CILcuoBcM+A=
Received: by 10.54.96.19 with SMTP id t19mr621017wrb;
Tue, 10 May 2005 10:26:39 -0700 (PDT)
Received: by 10.54.110.5 with HTTP; Tue, 10 May 2005 10:26:39 -0700 (PDT)
Message-ID: <xxxx@xxxx.com>
Date: Tue, 10 May 2005 11:26:39 -0600
From: Test Tester <xxxx@xxxx.com>
Reply-To: Test Tester <xxxx@xxxx.com>
To: xxxx@xxxx.com, xxxx@xxxx.com
Subject: Another PDF
Mime-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_Part_2192_32400445.1115745999735"
X-Virus-Scanned: amavisd-new at textdrive.com
------=_Part_2192_32400445.1115745999735
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
Just attaching another PDF, here, to see what the message looks like,
and to see if I can figure out what is going wrong here.
------=_Part_2192_32400445.1115745999735
Content-Type: application/pdf; name="broken.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="broken.pdf"
JVBERi0xLjQNCiXk9tzfDQoxIDAgb2JqDQo8PCAvTGVuZ3RoIDIgMCBSDQogICAvRmlsdGVyIC9G
bGF0ZURlY29kZQ0KPj4NCnN0cmVhbQ0KeJy9Wt2KJbkNvm/od6jrhZxYln9hWEh2p+8HBvICySaE
ycLuTV4/1ifJ9qnq09NpSBimu76yLUuy/qzqcPz7+em3Ixx/CDc6CsXxs3b5+fvfjr/8cPz6/BRu
rbfAx/n3739/fuJylJ5u5fjX81OuDr4deK4Bz3z/aDP+8fz0yw8g0Ofq7ktr1Mn+u28rvhy/jVeD
QSa+9YNKHP/pxjvDNfVAx/m3MFz54FhvTbaseaxiDoN2LeMVMw+yA7RbHSCDzxZuaYB2E1Yay7QU
x89vz0+tyFDKMlAHK5yqLmnjF+c4RjEiQIUeKwblXMe+AsZjN1J5yGQL5DHpDHksurM81rF6PKab
gK6zAarIDzIiUY23rJsN9iorAE816aIu6lsgAdQFsuhhkHOUFgVjp2GjMqSewITXNQ27jrMeamkg
1rPI3iLWG2CIaSBB+V1245YVRICGbbpYKHc2USFDl6M09acQVQYhlwIrkBNLISvXhGlF1wi5FHCw
wxZkoGNJlVeJCEsqKA+3YAV5AMb6KkeaqEJQmFKKQU8T1pRi2ihE1Y4CDrqoYFFXYjJJOatsyzuI
8SIlykuxKTMibWK8H1PgEvqYgs4GmQSrEjJAalgGirIhik+p4ZQN9E3ETFPAHE1b8pp1l/0Rc1gl
fQs0ABWvyoZZzU8VnPXwVVcO9BEsyjEJaO6eBoZRyKGlrKoYoOygA8BGIzgwN3RQ15ouigG5idZQ
fx2U4Db2CqiLO0WHAZoylGiCAqhniNQjFjQPSkmjwfNTgQ6M1Ih+eWo36wFmjIxDJZiGUBiWsAyR
xX3EekGOizkGI96Ol9zVZTAivikURhRsHh2E3JhWMpSTZCnnonrLhMCodgrNcgo4uyJUJc6qnVss
nrGd1Ptr0YwisCOYyIbUwVjV4xBUNLbguSO2YHujonAMJkMdSI7bIw91Akq2AUlMUWGFTMAOamjU
OvZQCxIkY2pCpMFo/IwLdVLHs6nddwTRrgoVbvLU9eB0G4EMndV0TNoxHbt3JBWwK6hhv3iHfDtF
yokB302IpEBTnWICde4uYc/1khDbSIkQopO6lcqamGBu1OSE3N5IPSsZX00CkSHRiiyx6HQIShsS
HSVNswdVsaOUSAWq9aYhDtGDaoG5a3lBGkYt/lFlBFt1UqrYnzVtUpUQnLiZeouKgf1KhRBViRRk
ExepJCzTwEmFDalIRbLEGtw0gfpESOpIAF/NnpPzcVCG86s0g2DuSyd41uhNGbEgaSrWEXORErbw
------=_Part_2192_32400445.1115745999735--
Return-Path: <xxx@xxxx.xxx>
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id 6AAEE3B4D23 for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:23 -0500
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id j48HUC213279 for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:13 -0500
Received: from conversion-xxx.xxxx.xxx.net by xxx.xxxx.xxx id <0IG600901LQ64I@xxx.xxxx.xxx> for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:12 -0500
Received: from agw1 by xxx.xxxx.xxx with ESMTP id <0IG600JFYLYCAxxx@xxxx.xxx> for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:12 -0500
Date: Sun, 8 May 2005 12:30:08 -0500
From: xxx@xxxx.xxx
To: xxx@xxxx.xxx
Message-Id: <7864245.1115573412626.JavaMxxx@xxxx.xxx>
Subject: Filth
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary=mimepart_427e4cb4ca329_133ae40413c81ef
X-Mms-Priority: 1
X-Mms-Transaction-Id: 3198421808-0
X-Mms-Message-Type: 0
X-Mms-Sender-Visibility: 1
X-Mms-Read-Reply: 1
X-Original-To: xxx@xxxx.xxx
X-Mms-Message-Class: 0
X-Mms-Delivery-Report: 0
X-Mms-Mms-Version: 16
Delivered-To: xxx@xxxx.xxx
X-Nokia-Ag-Version: 2.0
This is a multi-part message in MIME format.
--mimepart_427e4cb4ca329_133ae40413c81ef
Content-Type: multipart/mixed; boundary=mimepart_427e4cb4cbd97_133ae40413c8217
--mimepart_427e4cb4cbd97_133ae40413c8217
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Content-Location: text.txt
Some text
--mimepart_427e4cb4cbd97_133ae40413c8217--
--mimepart_427e4cb4ca329_133ae40413c81ef
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
--
This Orange Multi Media Message was sent wirefree from an Orange
MMS phone. If you would like to reply, please text or phone the
sender directly by using the phone number listed in the sender's
address. To learn more about Orange's Multi Media Messaging
Service, find us on the Web at xxx.xxxx.xxx.uk/mms
--mimepart_427e4cb4ca329_133ae40413c81ef
--mimepart_427e4cb4ca329_133ae40413c81ef-
......@@ -373,5 +373,26 @@ def test_receive_decodes_base64_encoded_mail
assert_match(/Jamis/, TestMailer.received_body)
end
def test_receive_attachments
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email2")
mail = TMail::Mail.parse(fixture)
attachment = mail.attachments.last
assert_equal "smime.p7s", attachment.original_filename
assert_equal "application/pkcs7-signature", attachment.content_type
end
def test_decode_attachment_without_charset
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email3")
mail = TMail::Mail.parse(fixture)
attachment = mail.attachments.last
assert_equal 1026, attachment.read.length
end
def test_decode_message_without_content_type
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email4")
mail = TMail::Mail.parse(fixture)
assert_nothing_raised { mail.body }
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册