annotate rhodecode/lib/rcmail/response.py @ 3625:260a7a01b054 beta

follow Python conventions for boolean values True and False might be singletons and the "default" values for "boolean" expressions, but "all" values in Python has a boolean value and should be evaluated as such. Checking with 'is True' and 'is False' is thus confusing, error prone and unnessarily complex. If we anywhere rely and nullable boolean fields from the database layer and don't want the null value to be treated as False then we should check explicitly for null with 'is None'.
author Mads Kiilerich <madski@unity3d.com>
date Thu, 28 Mar 2013 01:10:45 +0100
parents d95ef6587bca
children b84c83b651de
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
2452
d95ef6587bca fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
parents: 1908
diff changeset
367
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
368 class MIMEPart(MIMEBase):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
369 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
370 A reimplementation of nearly everything in email.mime to be more useful
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
371 for actually attaching things. Rather than one class for every type of
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
372 thing you'd encode, there's just this one, and it figures out how to
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
373 encode what you ask it.
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 def __init__(self, type, **params):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
376 self.maintype, self.subtype = type.split('/')
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
377 MIMEBase.__init__(self, self.maintype, self.subtype, **params)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
378
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
379 def add_text(self, content):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
380 # this is text, so encode it in canonical form
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
381 try:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
382 encoded = content.encode('ascii')
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
383 charset = 'ascii'
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
384 except UnicodeError:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
385 encoded = content.encode('utf-8')
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
386 charset = 'utf-8'
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
387
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
388 self.set_payload(encoded, charset=charset)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
389
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
390 def extract_payload(self, mail):
2452
d95ef6587bca fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
parents: 1908
diff changeset
391 if mail.body == None:
d95ef6587bca fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
parents: 1908
diff changeset
392 return # only None, '' is still ok
1717
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 ctype, ctype_params = mail.content_encoding['Content-Type']
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
395 cdisp, cdisp_params = mail.content_encoding['Content-Disposition']
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 assert ctype, ("Extract payload requires that mail.content_encoding "
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
398 "have a valid Content-Type.")
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
399
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
400 if ctype.startswith("text/"):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
401 self.add_text(mail.body)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
402 else:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
403 if cdisp:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
404 # replicate the content-disposition settings
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
405 self.add_header('Content-Disposition', cdisp, **cdisp_params)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
406
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
407 self.set_payload(mail.body)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
408 encoders.encode_base64(self)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
409
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
410 def __repr__(self):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
411 return "<MIMEPart '%s/%s': %r, %r, multipart=%r>" % (
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
412 self.subtype,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
413 self.maintype,
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
414 self['Content-Type'],
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
415 self['Content-Disposition'],
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
416 self.is_multipart())
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
1846
349a0ca30a75 Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
parents: 1818
diff changeset
419 def header_to_mime_encoding(value, not_email=False, separator=", "):
2452
d95ef6587bca fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
parents: 1908
diff changeset
420 if not value:
d95ef6587bca fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
parents: 1908
diff changeset
421 return ""
1717
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 encoder = Charset(DEFAULT_ENCODING)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
424 if type(value) == list:
1846
349a0ca30a75 Changed default recipients separator for mails to ', '
Marcin Kuzminski <marcin@python-works.com>
parents: 1818
diff changeset
425 return separator.join(properly_encode_header(
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
426 v, encoder, not_email) for v in value)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
427 else:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
428 return properly_encode_header(value, encoder, not_email)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
429
2452
d95ef6587bca fixes #481 rhodecode emails are sent without Date header
Marcin Kuzminski <marcin@python-works.com>
parents: 1908
diff changeset
430
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
431 def properly_encode_header(value, encoder, not_email):
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
432 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
433 The only thing special (weird) about this function is that it tries
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
434 to do a fast check to see if the header value has an email address in
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
435 it. Since random headers could have an email address, and email addresses
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
436 have weird special formatting rules, we have to check for it.
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 Normally this works fine, but in Librelist, we need to "obfuscate" email
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
439 addresses by changing the '@' to '-AT-'. This is where
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
440 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
441 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
442 check different, then change this.
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
443 """
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
444 try:
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
445 return value.encode("ascii")
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
446 except UnicodeEncodeError:
3625
260a7a01b054 follow Python conventions for boolean values
Mads Kiilerich <madski@unity3d.com>
parents: 2452
diff changeset
447 if not not_email and VALUE_IS_EMAIL_ADDRESS(value):
1717
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
448 # 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
449 name, address = parseaddr(value)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
450 return '"%s" <%s>' % (
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
451 encoder.header_encode(name.encode("utf-8")), address)
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
452
7ff304d3028f Notification fixes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
453 return encoder.header_encode(value.encode("utf-8"))