annotate rhodecode/lib/rcmail/response.py @ 2031:82a88013a3fd

merge 1.3 into stable
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 26 Feb 2012 17:25:09 +0200
parents b3a3890b7160
children d95ef6587bca
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
1905
fbddaf2f9728 mail response garden
Marcin Kuzminski <marcin@python-works.com>
parents: 1869
diff changeset
44 ADDRESS_HEADERS_WHITELIST = ['From', 'To', 'Delivered-To', 'Cc']
1717
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
1905
fbddaf2f9728 mail response garden
Marcin Kuzminski <marcin@python-works.com>
parents: 1869
diff changeset
48
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
49 def normalize_header(header):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
50 return string.capwords(header.lower(), '-')
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
51
1905
fbddaf2f9728 mail response garden
Marcin Kuzminski <marcin@python-works.com>
parents: 1869
diff changeset
52
1818
cf51bbfb120e auto white-space removal
Marcin Kuzminski <marcin@python-works.com>
parents: 1717
diff changeset
53 class EncodingError(Exception):
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
54 """Thrown when there is an encoding error."""
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
55 pass
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
56
1905
fbddaf2f9728 mail response garden
Marcin Kuzminski <marcin@python-works.com>
parents: 1869
diff changeset
57
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
58 class MailBase(object):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
59 """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
60 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
61 class, but it's more raw.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
62 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
63 def __init__(self, items=()):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
64 self.headers = dict(items)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
65 self.parts = []
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
66 self.body = None
1818
cf51bbfb120e auto white-space removal
Marcin Kuzminski <marcin@python-works.com>
parents: 1717
diff changeset
67 self.content_encoding = {'Content-Type': (None, {}),
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
68 'Content-Disposition': (None, {}),
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
69 'Content-Transfer-Encoding': (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 __getitem__(self, key):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
72 return self.headers.get(normalize_header(key), None)
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 __len__(self):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
75 return len(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 __iter__(self):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
78 return iter(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 __contains__(self, key):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
81 return normalize_header(key) in self.headers
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 __setitem__(self, key, value):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
84 self.headers[normalize_header(key)] = value
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 __delitem__(self, key):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
87 del self.headers[normalize_header(key)]
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 __nonzero__(self):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
90 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
91
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
92 def keys(self):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
93 """Returns the sorted keys."""
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
94 return sorted(self.headers.keys())
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
95
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
96 def attach_file(self, filename, data, ctype, disposition):
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 A file attachment is a raw attachment with a disposition that
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
99 indicates the file name.
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 assert filename, "You can't attach a file without a filename."
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
102 ctype = ctype.lower()
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
103
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
104 part = MailBase()
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
105 part.body = data
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
106 part.content_encoding['Content-Type'] = (ctype, {'name': filename})
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
107 part.content_encoding['Content-Disposition'] = (disposition,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
108 {'filename': filename})
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
109 self.parts.append(part)
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 def attach_text(self, data, ctype):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
112 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
113 This attaches a simpler text encoded part, which doesn't have a
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
114 filename.
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 ctype = ctype.lower()
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
117
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
118 part = MailBase()
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
119 part.body = data
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
120 part.content_encoding['Content-Type'] = (ctype, {})
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
121 self.parts.append(part)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
122
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
123 def walk(self):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
124 for p in self.parts:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
125 yield p
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
126 for x in p.walk():
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
127 yield x
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
128
1905
fbddaf2f9728 mail response garden
Marcin Kuzminski <marcin@python-works.com>
parents: 1869
diff changeset
129
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
130 class MailResponse(object):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
131 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
132 You are given MailResponse objects from the lamson.view methods, and
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
133 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
134 same basic functionality as MailRequest, but it is designed to be written
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
135 to, rather than read from (although you can do both).
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 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
138 as __init__ parameters, or by setting those attributes.
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 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
141 use the dict notation to change them: msg['From'] = 'joe@test.com'.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
142
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
143 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
144 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
145 send it out when it's ready.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
146 """
1869
682057a38cd3 white space cleanup
Marcin Kuzminski <marcin@python-works.com>
parents: 1846
diff changeset
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>
parents: 1818
diff changeset
148 separator="; "):
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
149 self.Body = Body
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
150 self.Html = Html
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
151 self.base = MailBase([('To', To), ('From', From), ('Subject', Subject)])
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
152 self.multipart = self.Body and self.Html
7ff304d3028f Notification fixes
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>
parents: 1818
diff changeset
154 self.separator = separator
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
155
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
156 def __contains__(self, key):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
157 return self.base.__contains__(key)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
158
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
159 def __getitem__(self, key):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
160 return self.base.__getitem__(key)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
161
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
162 def __setitem__(self, key, val):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
163 return self.base.__setitem__(key, val)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
164
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
165 def __delitem__(self, name):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
166 del self.base[name]
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
167
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
168 def attach(self, filename=None, content_type=None, data=None,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
169 disposition=None):
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
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
172 Simplifies attaching files from disk or data as files. To attach
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
173 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
174 give the data/content_type/filename/disposition combination.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
175
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
176 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
177 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
178 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
179 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
180 use.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
181 """
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 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
184 "attach.")
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
185 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
186 "data given.")
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 self.multipart = True
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
189
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
190 if filename and not content_type:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
191 content_type, encoding = mimetypes.guess_type(filename)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
192
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
193 assert content_type, ("No content type given, and couldn't guess "
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
194 "from the filename: %r" % filename)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
195
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
196 self.attachments.append({'filename': filename,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
197 'content_type': content_type,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
198 'data': data,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
199 'disposition': disposition,})
1908
b3a3890b7160 code garden
Marcin Kuzminski <marcin@python-works.com>
parents: 1905
diff changeset
200
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
201 def attach_part(self, part):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
202 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
203 Attaches a raw MailBase part from a MailRequest (or anywhere)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
204 so that you can copy it over.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
205 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
206 self.multipart = True
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 self.attachments.append({'filename': None,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
209 'content_type': None,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
210 'data': None,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
211 'disposition': None,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
212 'part': part,
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
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
215 def attach_all_parts(self, mail_request):
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 Used for copying the attachment parts of a mail.MailRequest
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
218 object for mailing lists that need to maintain attachments.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
219 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
220 for part in mail_request.all_parts():
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
221 self.attach_part(part)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
222
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
223 self.base.content_encoding = mail_request.base.content_encoding.copy()
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
224
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
225 def clear(self):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
226 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
227 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
228 headers for a series of different messages with different attachments.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
229 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
230 del self.attachments[:]
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
231 del self.base.parts[:]
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
232 self.multipart = False
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 def update(self, message):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
235 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
236 Used to easily set a bunch of heading from another dict
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
237 like object.
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 for k in message.keys():
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
240 self.base[k] = message[k]
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
241
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
242 def __str__(self):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
243 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
244 Converts to a string.
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 return self.to_message().as_string()
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
247
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
248 def _encode_attachment(self, filename=None, content_type=None, data=None,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
249 disposition=None, part=None):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
250 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
251 Used internally to take the attachments mentioned in self.attachments
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
252 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
253 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
254 if part:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
255 self.base.parts.append(part)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
256 elif filename:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
257 if not data:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
258 data = open(filename).read()
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 self.base.attach_file(filename, data, content_type,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
261 disposition or 'attachment')
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
262 else:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
263 self.base.attach_text(data, content_type)
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 ctype = self.base.content_encoding['Content-Type'][0]
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 if ctype and not ctype.startswith('multipart'):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
268 self.base.content_encoding['Content-Type'] = ('multipart/mixed', {})
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
269
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
270 def to_message(self):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
271 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
272 Figures out all the required steps to finally craft the
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
273 message you need and return it. The resulting message
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
274 is also available as a self.base attribute.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
275
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
276 What is returned is a Python email API message you can
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
277 use with those APIs. The self.base attribute is the raw
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
278 lamson.encoding.MailBase.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
279 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
280 del self.base.parts[:]
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.Body and self.Html:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
283 self.multipart = True
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
284 self.base.content_encoding['Content-Type'] = (
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
285 'multipart/alternative', {})
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.multipart:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
288 self.base.body = None
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
289 if self.Body:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
290 self.base.attach_text(self.Body, 'text/plain')
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
291
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
292 if self.Html:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
293 self.base.attach_text(self.Html, 'text/html')
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
294
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
295 for args in self.attachments:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
296 self._encode_attachment(**args)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
297
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
298 elif self.Body:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
299 self.base.body = self.Body
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
300 self.base.content_encoding['Content-Type'] = ('text/plain', {})
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
301
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
302 elif self.Html:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
303 self.base.body = self.Html
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
304 self.base.content_encoding['Content-Type'] = ('text/html', {})
7ff304d3028f Notification fixes
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>
parents: 1818
diff changeset
306 return to_message(self.base, separator=self.separator)
1717
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 def all_parts(self):
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 Returns all the encoded parts. Only useful for debugging
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
311 or inspecting after calling to_message().
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 return self.base.parts
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
314
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
315 def keys(self):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
316 return self.base.keys()
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
317
1905
fbddaf2f9728 mail response garden
Marcin Kuzminski <marcin@python-works.com>
parents: 1869
diff changeset
318
1846
349a0ca30a75 Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
parents: 1818
diff changeset
319 def to_message(mail, separator="; "):
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
320 """
1818
cf51bbfb120e auto white-space removal
Marcin Kuzminski <marcin@python-works.com>
parents: 1717
diff changeset
321 Given a MailBase message, this will construct a MIMEPart
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
322 that is canonicalized for use with the Python email API.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
323 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
324 ctype, params = mail.content_encoding['Content-Type']
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
325
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
326 if not ctype:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
327 if mail.parts:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
328 ctype = 'multipart/mixed'
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
329 else:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
330 ctype = 'text/plain'
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
331 else:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
332 if mail.parts:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
333 assert ctype.startswith(("multipart", "message")), \
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
334 "Content type should be multipart or message, not %r" % ctype
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
335
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
336 # adjust the content type according to what it should be now
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
337 mail.content_encoding['Content-Type'] = (ctype, params)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
338
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
339 try:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
340 out = MIMEPart(ctype, **params)
1905
fbddaf2f9728 mail response garden
Marcin Kuzminski <marcin@python-works.com>
parents: 1869
diff changeset
341 except TypeError, exc: # pragma: no cover
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
342 raise EncodingError("Content-Type malformed, not allowed: %r; "
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
343 "%r (Python ERROR: %s" %
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
344 (ctype, params, exc.message))
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
345
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
346 for k in mail.keys():
7ff304d3028f Notification fixes
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>
parents: 1818
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>
parents: 1818
diff changeset
349 mail[k],
349a0ca30a75 Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
parents: 1818
diff changeset
350 not_email=False,
349a0ca30a75 Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
parents: 1818
diff changeset
351 separator=separator
349a0ca30a75 Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
parents: 1818
diff changeset
352 )
1717
7ff304d3028f Notification fixes
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>
parents: 1818
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>
parents: 1818
diff changeset
355 mail[k],
349a0ca30a75 Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
parents: 1818
diff changeset
356 not_email=True
349a0ca30a75 Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
parents: 1818
diff changeset
357 )
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
358
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
359 out.extract_payload(mail)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
360
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
361 # go through the children
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
362 for part in mail.parts:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
363 out.attach(to_message(part))
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
364
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
365 return out
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
366
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
367 class MIMEPart(MIMEBase):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
368 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
369 A reimplementation of nearly everything in email.mime to be more useful
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
370 for actually attaching things. Rather than one class for every type of
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
371 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
372 encode what you ask it.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
373 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
374 def __init__(self, type, **params):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
375 self.maintype, self.subtype = type.split('/')
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
376 MIMEBase.__init__(self, self.maintype, self.subtype, **params)
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 add_text(self, content):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
379 # this is text, so encode it in canonical form
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
380 try:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
381 encoded = content.encode('ascii')
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
382 charset = 'ascii'
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
383 except UnicodeError:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
384 encoded = content.encode('utf-8')
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
385 charset = 'utf-8'
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 self.set_payload(encoded, charset=charset)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
388
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
389 def extract_payload(self, mail):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
390 if mail.body == None: return # only None, '' is still ok
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
391
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
392 ctype, ctype_params = mail.content_encoding['Content-Type']
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
393 cdisp, cdisp_params = mail.content_encoding['Content-Disposition']
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
394
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
395 assert ctype, ("Extract payload requires that mail.content_encoding "
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
396 "have a valid Content-Type.")
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
397
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
398 if ctype.startswith("text/"):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
399 self.add_text(mail.body)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
400 else:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
401 if cdisp:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
402 # replicate the content-disposition settings
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
403 self.add_header('Content-Disposition', cdisp, **cdisp_params)
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 self.set_payload(mail.body)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
406 encoders.encode_base64(self)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
407
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
408 def __repr__(self):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
409 return "<MIMEPart '%s/%s': %r, %r, multipart=%r>" % (
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
410 self.subtype,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
411 self.maintype,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
412 self['Content-Type'],
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
413 self['Content-Disposition'],
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
414 self.is_multipart())
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
1846
349a0ca30a75 Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
parents: 1818
diff changeset
417 def header_to_mime_encoding(value, not_email=False, separator=", "):
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
418 if not value: return ""
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
419
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
420 encoder = Charset(DEFAULT_ENCODING)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
421 if type(value) == list:
1846
349a0ca30a75 Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
parents: 1818
diff changeset
422 return separator.join(properly_encode_header(
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
423 v, encoder, not_email) for v in value)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
424 else:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
425 return properly_encode_header(value, encoder, not_email)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
426
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
427 def properly_encode_header(value, encoder, not_email):
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 The only thing special (weird) about this function is that it tries
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
430 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
431 it. Since random headers could have an email address, and email addresses
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
432 have weird special formatting rules, we have to check for it.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
433
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
434 Normally this works fine, but in Librelist, we need to "obfuscate" email
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
435 addresses by changing the '@' to '-AT-'. This is where
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
436 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
437 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
438 check different, then change this.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
439 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
440 try:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
441 return value.encode("ascii")
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
442 except UnicodeEncodeError:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
443 if not_email is False and VALUE_IS_EMAIL_ADDRESS(value):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
444 # 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
445 name, address = parseaddr(value)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
446 return '"%s" <%s>' % (
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
447 encoder.header_encode(name.encode("utf-8")), address)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
448
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
449 return encoder.header_encode(value.encode("utf-8"))