1
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
|
SignedMessage extends email.Message.Message in order to provide easy
access to signed content and the signature of messages.
You can create it from a string using signed_message_from_string. It
basically the same as using email.message_from_string and passing
SignedMessage as the _class parameter, but it also ensures that all
the attributes are correctly set.
>>> from lp.services.mail.interfaces import ISignedMessage
>>> from lp.services.mail.signedmessage import signed_message_from_string
>>> from lp.services.webapp.testing import verifyObject
>>> msg = signed_message_from_string('To: someone\n\nHello.')
>>> verifyObject(ISignedMessage, msg)
True
>>> msg['To']
'someone'
>>> msg.parsed_string
'To: someone\n\nHello.'
We have some test messages that can be easily accessed by
read_test_message. Let's start with a simple message, where the
signature is inline with the signed content:
>>> from lp.services.mail.tests.helpers import read_test_message
>>> msg = read_test_message('signed_inline.txt')
You can access the headers of the message:
>>> print msg['From']
Sample Person <test@canonical.com>
The raw text that was signed is available as msg.signedContent:
>>> print msg.signedContent
Some signed content.
<BLANKLINE>
With multiple paragraphs.
And to make it easier to work with, it's available as an email.Message
object as well:
>>> signed_msg = msg.signedMessage
>>> print signed_msg.get_payload()
Some signed content.
<BLANKLINE>
With multiple paragraphs.
Finally the signature can be accessed via msg.signature:
>>> print msg.signature
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)
<BLANKLINE>
iD8DBQFCXaoOuiuTid/SBUMRAoRkAJoCuy/kSVPCN1kBTqMG+cgsbhhFbwCfeSjH
/Uc8UVJBiA94yh4G50qgD8o=
=lNZi
-----END PGP SIGNATURE-----
If some lines in the signed content begin with a '-', that means that
they have been dash escaped by the client. The dash escaping is done
after the content has been signed, so the signed content should be
unescaped.
>>> msg = read_test_message('signed_dash_escaped.txt')
>>> print msg.get_payload()
-----BEGIN PGP SIGNED MESSAGE-----
...
- --
Sample Person
...
>>> print msg.signedContent
Some signed content.
<BLANKLINE>
--
Sample Person
It also works when the signature is detached, that is the message
contains of two MIME parts, the signed text, and the signature:
>>> msg = read_test_message('signed_detached.txt')
The signed content includes the MIME headers as well:
>>> print msg.signedContent
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
<BLANKLINE>
Some signed content.
In signedMessage you can access the headers and the content
separately:
>>> print msg.signedMessage['Content-Type']
text/plain; charset=us-ascii
>>> print msg.signedMessage.get_payload()
Some signed content.
And of course the signature is accessible as well:
>>> print msg.signature
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)
<BLANKLINE>
iD8DBQFCXah8uiuTid/SBUMRAotfAJwOYuLfnW0mV3EA67gXhuhnE/Ur7wCfRVMZ
xIlThcNdAY9Wkd289kB5W8I=
=fQDd
-----END PGP SIGNATURE-----
If the message is unsigned, all attributes will be None:
>>> msg = read_test_message('unsigned_multipart.txt')
>>> msg.signedContent is None
True
>>> msg.signedMessage is None
True
>>> msg.signature is None
True
It handles signed multipart messages as well:
>>> msg = read_test_message('signed_multipart.txt')
>>> content, attachment = msg.signedMessage.get_payload()
>>> print content.get_payload()
Some signed content.
<BLANKLINE>
>>> print attachment.get_payload()
A signed attachment.
<BLANKLINE>
>>> print msg.signature
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)
<BLANKLINE>
iD8DBQFCXajSjn63CGxkqMURAtNPAJ4myfPemSBEMR3e4TGvg9LgqiBOJwCdHjRu
cdC/h/xgiwwrHaUFTk/guuY=
=fBjf
-----END PGP SIGNATURE-----
>>> msg = read_test_message('signed_folded_header.txt')
>>> print msg.signedContent #doctest: -NORMALIZE_WHITESPACE
Content-Type: multipart/mixed;
boundary="--------------------EuxKj2iCbKjpUGkD"
...
|