annotate rhodecode/lib/rcmail/response.py @ 1818:cf51bbfb120e beta

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