1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
1 # The code in this module is entirely lifted from the Lamson project
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
2 # (http://lamsonproject.org/). Its copyright is:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
3
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
4 # Copyright (c) 2008, Zed A. Shaw
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
5 # All rights reserved.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
6
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
7 # It is provided under this license:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
8
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
9 # Redistribution and use in source and binary forms, with or without
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
10 # modification, are permitted provided that the following conditions are met:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
11
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
12 # * Redistributions of source code must retain the above copyright notice, this
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
13 # list of conditions and the following disclaimer.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
14
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
15 # * Redistributions in binary form must reproduce the above copyright notice,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
16 # this list of conditions and the following disclaimer in the documentation
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
17 # and/or other materials provided with the distribution.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
18
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
19 # * Neither the name of the Zed A. Shaw nor the names of its contributors may
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
20 # be used to endorse or promote products derived from this software without
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
21 # specific prior written permission.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
22
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
23 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
24 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
25 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
26 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
27 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
28 # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
29 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
30 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
31 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
32 # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
33 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
34 # POSSIBILITY OF SUCH DAMAGE.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
35
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
36 import os
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
37 import mimetypes
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
38 import string
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
39 from email import encoders
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
40 from email.charset import Charset
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
41 from email.utils import parseaddr
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
42 from email.mime.base import MIMEBase
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
43
|
1905
|
44 ADDRESS_HEADERS_WHITELIST = ['From', 'To', 'Delivered-To', 'Cc']
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
45 DEFAULT_ENCODING = "utf-8"
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
46 VALUE_IS_EMAIL_ADDRESS = lambda v: '@' in v
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
47
|
1905
|
48
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
49 def normalize_header(header):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
50 return string.capwords(header.lower(), '-')
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
51
|
1905
|
52
|
1818
|
53 class EncodingError(Exception):
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
54 """Thrown when there is an encoding error."""
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
55 pass
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
56
|
1905
|
57
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
58 class MailBase(object):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
59 """MailBase is used as the basis of lamson.mail and contains the basics of
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
60 encoding an email. You actually can do all your email processing with this
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
61 class, but it's more raw.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
62 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
63 def __init__(self, items=()):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
64 self.headers = dict(items)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
65 self.parts = []
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
66 self.body = None
|
1818
|
67 self.content_encoding = {'Content-Type': (None, {}),
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
68 'Content-Disposition': (None, {}),
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
69 'Content-Transfer-Encoding': (None, {})}
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
70
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
71 def __getitem__(self, key):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
72 return self.headers.get(normalize_header(key), None)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
73
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
74 def __len__(self):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
75 return len(self.headers)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
76
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
77 def __iter__(self):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
78 return iter(self.headers)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
79
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
80 def __contains__(self, key):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
81 return normalize_header(key) in self.headers
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
82
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
83 def __setitem__(self, key, value):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
84 self.headers[normalize_header(key)] = value
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
85
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
86 def __delitem__(self, key):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
87 del self.headers[normalize_header(key)]
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
88
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
89 def __nonzero__(self):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
90 return self.body != None or len(self.headers) > 0 or len(self.parts) > 0
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
91
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
92 def keys(self):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
93 """Returns the sorted keys."""
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
94 return sorted(self.headers.keys())
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
95
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
96 def attach_file(self, filename, data, ctype, disposition):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
97 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
98 A file attachment is a raw attachment with a disposition that
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
99 indicates the file name.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
100 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
101 assert filename, "You can't attach a file without a filename."
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
102 ctype = ctype.lower()
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
103
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
104 part = MailBase()
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
105 part.body = data
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
106 part.content_encoding['Content-Type'] = (ctype, {'name': filename})
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
107 part.content_encoding['Content-Disposition'] = (disposition,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
108 {'filename': filename})
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
109 self.parts.append(part)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
110
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
111 def attach_text(self, data, ctype):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
112 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
113 This attaches a simpler text encoded part, which doesn't have a
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
114 filename.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
115 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
116 ctype = ctype.lower()
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
117
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
118 part = MailBase()
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
119 part.body = data
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
120 part.content_encoding['Content-Type'] = (ctype, {})
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
121 self.parts.append(part)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
122
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
123 def walk(self):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
124 for p in self.parts:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
125 yield p
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
126 for x in p.walk():
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
127 yield x
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
128
|
1905
|
129
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
130 class MailResponse(object):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
131 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
132 You are given MailResponse objects from the lamson.view methods, and
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
133 whenever you want to generate an email to send to someone. It has the
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
134 same basic functionality as MailRequest, but it is designed to be written
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
135 to, rather than read from (although you can do both).
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
136
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
137 You can easily set a Body or Html during creation or after by passing it
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
138 as __init__ parameters, or by setting those attributes.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
139
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
140 You can initially set the From, To, and Subject, but they are headers so
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
141 use the dict notation to change them: msg['From'] = 'joe@test.com'.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
142
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
143 The message is not fully crafted until right when you convert it with
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
144 MailResponse.to_message. This lets you change it and work with it, then
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
145 send it out when it's ready.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
146 """
|
1869
|
147 def __init__(self, To=None, From=None, Subject=None, Body=None, Html=None,
|
1846
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
148 separator="; "):
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
149 self.Body = Body
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
150 self.Html = Html
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
151 self.base = MailBase([('To', To), ('From', From), ('Subject', Subject)])
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
152 self.multipart = self.Body and self.Html
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
153 self.attachments = []
|
1846
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
154 self.separator = separator
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
155
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
156 def __contains__(self, key):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
157 return self.base.__contains__(key)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
158
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
159 def __getitem__(self, key):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
160 return self.base.__getitem__(key)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
161
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
162 def __setitem__(self, key, val):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
163 return self.base.__setitem__(key, val)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
164
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
165 def __delitem__(self, name):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
166 del self.base[name]
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
167
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
168 def attach(self, filename=None, content_type=None, data=None,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
169 disposition=None):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
170 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
171
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
172 Simplifies attaching files from disk or data as files. To attach
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
173 simple text simple give data and a content_type. To attach a file,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
174 give the data/content_type/filename/disposition combination.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
175
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
176 For convenience, if you don't give data and only a filename, then it
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
177 will read that file's contents when you call to_message() later. If
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
178 you give data and filename then it will assume you've filled data
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
179 with what the file's contents are and filename is just the name to
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
180 use.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
181 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
182
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
183 assert filename or data, ("You must give a filename or some data to "
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
184 "attach.")
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
185 assert data or os.path.exists(filename), ("File doesn't exist, and no "
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
186 "data given.")
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
187
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
188 self.multipart = True
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
189
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
190 if filename and not content_type:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
191 content_type, encoding = mimetypes.guess_type(filename)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
192
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
193 assert content_type, ("No content type given, and couldn't guess "
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
194 "from the filename: %r" % filename)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
195
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
196 self.attachments.append({'filename': filename,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
197 'content_type': content_type,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
198 'data': data,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
199 'disposition': disposition,})
|
1908
|
200
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
201 def attach_part(self, part):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
202 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
203 Attaches a raw MailBase part from a MailRequest (or anywhere)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
204 so that you can copy it over.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
205 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
206 self.multipart = True
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
207
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
208 self.attachments.append({'filename': None,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
209 'content_type': None,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
210 'data': None,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
211 'disposition': None,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
212 'part': part,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
213 })
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
214
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
215 def attach_all_parts(self, mail_request):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
216 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
217 Used for copying the attachment parts of a mail.MailRequest
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
218 object for mailing lists that need to maintain attachments.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
219 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
220 for part in mail_request.all_parts():
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
221 self.attach_part(part)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
222
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
223 self.base.content_encoding = mail_request.base.content_encoding.copy()
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
224
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
225 def clear(self):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
226 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
227 Clears out the attachments so you can redo them. Use this to keep the
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
228 headers for a series of different messages with different attachments.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
229 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
230 del self.attachments[:]
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
231 del self.base.parts[:]
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
232 self.multipart = False
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
233
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
234 def update(self, message):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
235 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
236 Used to easily set a bunch of heading from another dict
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
237 like object.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
238 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
239 for k in message.keys():
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
240 self.base[k] = message[k]
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
241
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
242 def __str__(self):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
243 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
244 Converts to a string.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
245 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
246 return self.to_message().as_string()
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
247
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
248 def _encode_attachment(self, filename=None, content_type=None, data=None,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
249 disposition=None, part=None):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
250 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
251 Used internally to take the attachments mentioned in self.attachments
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
252 and do the actual encoding in a lazy way when you call to_message.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
253 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
254 if part:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
255 self.base.parts.append(part)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
256 elif filename:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
257 if not data:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
258 data = open(filename).read()
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
259
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
260 self.base.attach_file(filename, data, content_type,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
261 disposition or 'attachment')
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
262 else:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
263 self.base.attach_text(data, content_type)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
264
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
265 ctype = self.base.content_encoding['Content-Type'][0]
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
266
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
267 if ctype and not ctype.startswith('multipart'):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
268 self.base.content_encoding['Content-Type'] = ('multipart/mixed', {})
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
269
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
270 def to_message(self):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
271 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
272 Figures out all the required steps to finally craft the
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
273 message you need and return it. The resulting message
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
274 is also available as a self.base attribute.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
275
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
276 What is returned is a Python email API message you can
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
277 use with those APIs. The self.base attribute is the raw
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
278 lamson.encoding.MailBase.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
279 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
280 del self.base.parts[:]
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
281
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
282 if self.Body and self.Html:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
283 self.multipart = True
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
284 self.base.content_encoding['Content-Type'] = (
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
285 'multipart/alternative', {})
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
286
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
287 if self.multipart:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
288 self.base.body = None
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
289 if self.Body:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
290 self.base.attach_text(self.Body, 'text/plain')
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
291
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
292 if self.Html:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
293 self.base.attach_text(self.Html, 'text/html')
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
294
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
295 for args in self.attachments:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
296 self._encode_attachment(**args)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
297
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
298 elif self.Body:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
299 self.base.body = self.Body
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
300 self.base.content_encoding['Content-Type'] = ('text/plain', {})
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
301
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
302 elif self.Html:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
303 self.base.body = self.Html
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
304 self.base.content_encoding['Content-Type'] = ('text/html', {})
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
305
|
1846
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
306 return to_message(self.base, separator=self.separator)
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
307
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
308 def all_parts(self):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
309 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
310 Returns all the encoded parts. Only useful for debugging
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
311 or inspecting after calling to_message().
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
312 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
313 return self.base.parts
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
314
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
315 def keys(self):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
316 return self.base.keys()
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
317
|
1905
|
318
|
1846
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
319 def to_message(mail, separator="; "):
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
320 """
|
1818
|
321 Given a MailBase message, this will construct a MIMEPart
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
322 that is canonicalized for use with the Python email API.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
323 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
324 ctype, params = mail.content_encoding['Content-Type']
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
325
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
326 if not ctype:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
327 if mail.parts:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
328 ctype = 'multipart/mixed'
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
329 else:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
330 ctype = 'text/plain'
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
331 else:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
332 if mail.parts:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
333 assert ctype.startswith(("multipart", "message")), \
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
334 "Content type should be multipart or message, not %r" % ctype
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
335
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
336 # adjust the content type according to what it should be now
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
337 mail.content_encoding['Content-Type'] = (ctype, params)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
338
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
339 try:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
340 out = MIMEPart(ctype, **params)
|
1905
|
341 except TypeError, exc: # pragma: no cover
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
342 raise EncodingError("Content-Type malformed, not allowed: %r; "
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
343 "%r (Python ERROR: %s" %
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
344 (ctype, params, exc.message))
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
345
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
346 for k in mail.keys():
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
347 if k in ADDRESS_HEADERS_WHITELIST:
|
1846
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
348 out[k.encode('ascii')] = header_to_mime_encoding(
|
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
349 mail[k],
|
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
350 not_email=False,
|
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
351 separator=separator
|
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
352 )
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
353 else:
|
1846
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
354 out[k.encode('ascii')] = header_to_mime_encoding(
|
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
355 mail[k],
|
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
356 not_email=True
|
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
357 )
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
358
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
359 out.extract_payload(mail)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
360
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
361 # go through the children
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
362 for part in mail.parts:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
363 out.attach(to_message(part))
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
364
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
365 return out
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
366
|
2452
d95ef6587bca
fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
367
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
368 class MIMEPart(MIMEBase):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
369 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
370 A reimplementation of nearly everything in email.mime to be more useful
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
371 for actually attaching things. Rather than one class for every type of
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
372 thing you'd encode, there's just this one, and it figures out how to
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
373 encode what you ask it.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
374 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
375 def __init__(self, type, **params):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
376 self.maintype, self.subtype = type.split('/')
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
377 MIMEBase.__init__(self, self.maintype, self.subtype, **params)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
378
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
379 def add_text(self, content):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
380 # this is text, so encode it in canonical form
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
381 try:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
382 encoded = content.encode('ascii')
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
383 charset = 'ascii'
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
384 except UnicodeError:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
385 encoded = content.encode('utf-8')
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
386 charset = 'utf-8'
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
387
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
388 self.set_payload(encoded, charset=charset)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
389
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
390 def extract_payload(self, mail):
|
2452
d95ef6587bca
fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
391 if mail.body == None:
|
d95ef6587bca
fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
392 return # only None, '' is still ok
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
393
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
394 ctype, ctype_params = mail.content_encoding['Content-Type']
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
395 cdisp, cdisp_params = mail.content_encoding['Content-Disposition']
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
396
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
397 assert ctype, ("Extract payload requires that mail.content_encoding "
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
398 "have a valid Content-Type.")
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
399
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
400 if ctype.startswith("text/"):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
401 self.add_text(mail.body)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
402 else:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
403 if cdisp:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
404 # replicate the content-disposition settings
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
405 self.add_header('Content-Disposition', cdisp, **cdisp_params)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
406
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
407 self.set_payload(mail.body)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
408 encoders.encode_base64(self)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
409
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
410 def __repr__(self):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
411 return "<MIMEPart '%s/%s': %r, %r, multipart=%r>" % (
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
412 self.subtype,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
413 self.maintype,
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
414 self['Content-Type'],
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
415 self['Content-Disposition'],
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
416 self.is_multipart())
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
417
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
418
|
1846
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
419 def header_to_mime_encoding(value, not_email=False, separator=", "):
|
2452
d95ef6587bca
fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
420 if not value:
|
d95ef6587bca
fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
421 return ""
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
422
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
423 encoder = Charset(DEFAULT_ENCODING)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
424 if type(value) == list:
|
1846
349a0ca30a75
Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
425 return separator.join(properly_encode_header(
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
426 v, encoder, not_email) for v in value)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
427 else:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
428 return properly_encode_header(value, encoder, not_email)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
429
|
2452
d95ef6587bca
fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
diff
changeset
|
430
|
1717
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
431 def properly_encode_header(value, encoder, not_email):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
432 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
433 The only thing special (weird) about this function is that it tries
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
434 to do a fast check to see if the header value has an email address in
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
435 it. Since random headers could have an email address, and email addresses
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
436 have weird special formatting rules, we have to check for it.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
437
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
438 Normally this works fine, but in Librelist, we need to "obfuscate" email
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
439 addresses by changing the '@' to '-AT-'. This is where
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
440 VALUE_IS_EMAIL_ADDRESS exists. It's a simple lambda returning True/False
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
441 to check if a header value has an email address. If you need to make this
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
442 check different, then change this.
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
443 """
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
444 try:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
445 return value.encode("ascii")
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
446 except UnicodeEncodeError:
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
447 if not_email is False and VALUE_IS_EMAIL_ADDRESS(value):
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
448 # this could have an email address, make sure we don't screw it up
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
449 name, address = parseaddr(value)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
450 return '"%s" <%s>' % (
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
451 encoder.header_encode(name.encode("utf-8")), address)
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
452
|
Marcin Kuzminski <marcin@python-works.com>
parents:
diff
changeset
|
453 return encoder.header_encode(value.encode("utf-8"))
|