Merge lp:~openerp-dev/openobject-addons/trunk-fetchmail-inbox-tde into lp:openobject-addons
- trunk-fetchmail-inbox-tde
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~openerp-dev/openobject-addons/trunk-fetchmail-inbox-tde |
Merge into: | lp:openobject-addons |
Diff against target: |
899 lines (+264/-149) 23 files modified
email_template/email_template.py (+2/-4) fetchmail/fetchmail.py (+5/-5) mail/data/mail_demo.xml (+10/-6) mail/data/mail_group_data.xml (+3/-5) mail/mail_followers.py (+15/-12) mail/mail_message.py (+5/-2) mail/mail_thread.py (+79/-32) mail/res_partner.py (+18/-0) mail/security/ir.model.access.csv (+4/-3) mail/security/mail_security.xml (+9/-1) mail/static/src/css/mail.css (+4/-0) mail/static/src/js/mail.js (+1/-2) mail/tests/__init__.py (+1/-0) mail/tests/test_mail.py (+8/-40) mail/tests/test_mail_access_rights.py (+2/-2) mail/tests/test_mail_mockup.py (+54/-0) mail/wizard/mail_compose_message_view.xml (+5/-5) note/note.py (+1/-3) pad/pad.py (+1/-1) portal/mail_mail.py (+1/-1) portal/portal_demo.xml (+33/-20) portal/tests/test_portal.py (+2/-3) portal/wizard/portal_wizard.py (+1/-2) |
To merge this branch: | bzr merge lp:~openerp-dev/openobject-addons/trunk-fetchmail-inbox-tde |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenERP Core Team | Pending | ||
Review via email: mp+131936@code.launchpad.net |
This proposal has been superseded by a proposal from 2012-11-14.
Commit message
Mail: improve incoming/outgoing emails behavior
Main:
- updated overall code to match the new mail openerp tools
- message_route: after checking the headers to find if the incoming email is a reply in an existing discussion, it checks whether the email is a reply to a private discussion (without model, res_id), based on the message_id of the mail; it then relies on the aliases then fetchmail, as before
- incoming emails and quick posting through Chatter now calls message_
Misc:
- mail: improved set_message_read, fixed a bug with message_id
- fetchmail: fixed a bug in fetchmail module about non-existing variable
- portal: updated demo data
Description of the change
Preview Diff
1 | === modified file 'email_template/email_template.py' |
2 | --- email_template/email_template.py 2012-11-07 11:39:25 +0000 |
3 | +++ email_template/email_template.py 2012-11-14 09:23:22 +0000 |
4 | @@ -28,8 +28,6 @@ |
5 | from osv import fields |
6 | import tools |
7 | from tools.translate import _ |
8 | -from tools.html_sanitize import html_sanitize |
9 | -from tools import append_content_to_html |
10 | from urllib import quote as quote |
11 | _logger = logging.getLogger(__name__) |
12 | |
13 | @@ -293,10 +291,10 @@ |
14 | or False |
15 | if template.user_signature: |
16 | signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature |
17 | - values['body_html'] = append_content_to_html(values['body_html'], signature) |
18 | + values['body_html'] = tools.append_content_to_html(values['body_html'], signature) |
19 | |
20 | if values['body_html']: |
21 | - values['body'] = html_sanitize(values['body_html']) |
22 | + values['body'] = tools.html_sanitize(values['body_html']) |
23 | |
24 | values.update(mail_server_id=template.mail_server_id.id or False, |
25 | auto_delete=template.auto_delete, |
26 | |
27 | === modified file 'fetchmail/fetchmail.py' |
28 | --- fetchmail/fetchmail.py 2012-10-25 13:09:30 +0000 |
29 | +++ fetchmail/fetchmail.py 2012-11-14 09:23:22 +0000 |
30 | @@ -243,20 +243,20 @@ |
31 | |
32 | def create(self, cr, uid, values, context=None): |
33 | if context is None: |
34 | - context={} |
35 | + context = {} |
36 | fetchmail_server_id = context.get('fetchmail_server_id') |
37 | if fetchmail_server_id: |
38 | values['fetchmail_server_id'] = fetchmail_server_id |
39 | - res = super(mail_mail,self).create(cr, uid, values, context=context) |
40 | + res = super(mail_mail, self).create(cr, uid, values, context=context) |
41 | return res |
42 | |
43 | def write(self, cr, uid, ids, values, context=None): |
44 | if context is None: |
45 | - context={} |
46 | + context = {} |
47 | fetchmail_server_id = context.get('fetchmail_server_id') |
48 | if fetchmail_server_id: |
49 | - values['fetchmail_server_id'] = server_id |
50 | - res = super(mail_mail,self).write(cr, uid, ids, values, context=context) |
51 | + values['fetchmail_server_id'] = fetchmail_server_id |
52 | + res = super(mail_mail, self).write(cr, uid, ids, values, context=context) |
53 | return res |
54 | |
55 | |
56 | |
57 | === modified file 'mail/data/mail_demo.xml' |
58 | --- mail/data/mail_demo.xml 2012-11-12 15:27:53 +0000 |
59 | +++ mail/data/mail_demo.xml 2012-11-14 09:23:22 +0000 |
60 | @@ -11,44 +11,48 @@ |
61 | <record id="message_blogpost0" model="mail.message"> |
62 | <field name="model">mail.group</field> |
63 | <field name="res_id" ref="mail.group_all_employees"/> |
64 | - <field name="body">Your monthly meal vouchers arrived. You can get them at Christine's office. |
65 | -This month you also get 250 EUR of eco-vouchers if you have been in the company for more than a year.</field> |
66 | + <field name="body"><![CDATA[<p>Your monthly meal vouchers arrived. You can get them at Christine's office.</p>]]></field> |
67 | <field name="type">comment</field> |
68 | <field name="subtype_id" ref="mt_comment"/> |
69 | + <field name="author_id" ref="base.partner_root"/> |
70 | </record> |
71 | <record id="message_blogpost0_comment0" model="mail.message"> |
72 | <field name="model">mail.group</field> |
73 | <field name="res_id" ref="group_all_employees"/> |
74 | - <field name="body"><![CDATA[Great.]]></field> |
75 | + <field name="body"><![CDATA[<p>Oh, I had forgotten. This month you also get 250 EUR of eco-vouchers if you have been in the company for more than a year.</p>]]></field> |
76 | <field name="parent_id" ref="message_blogpost0"/> |
77 | <field name="type">comment</field> |
78 | <field name="subtype_id" ref="mt_comment"/> |
79 | + <field name="author_id" ref="base.partner_root"/> |
80 | </record> |
81 | <record id="message_blogpost0_comment1" model="mail.message"> |
82 | <field name="model">mail.group</field> |
83 | <field name="res_id" ref="group_all_employees"/> |
84 | - <field name="body">Thanks, but where is Christine's office, if I may ask? (I'm new here)</field> |
85 | + <field name="body"><![CDATA[<p>Thanks! Could you please remind me where is Christine's office, if I may ask? I'm new here!</p>]]></field> |
86 | <field name="parent_id" ref="message_blogpost0"/> |
87 | <field name="type">comment</field> |
88 | <field name="subtype_id" ref="mt_comment"/> |
89 | + <field name="author_id" ref="base.partner_demo"/> |
90 | </record> |
91 | <!-- This one is starred for having mailboxes with demo data --> |
92 | <record id="message_blogpost0_comment2" model="mail.message"> |
93 | <field name="model">mail.group</field> |
94 | <field name="res_id" ref="group_all_employees"/> |
95 | - <field name="body">Building B3, second floor on the right :-)</field> |
96 | + <field name="body"><![CDATA[<p>Building B3, second floor on the right :-).</p>]]></field> |
97 | <field name="parent_id" ref="message_blogpost0"/> |
98 | <field name="type">comment</field> |
99 | <field name="subtype_id" ref="mt_comment"/> |
100 | + <field name="author_id" ref="base.partner_root"/> |
101 | <field name="favorite_user_ids" eval="[(6, 0, [ref('base.user_root'), ref('base.user_demo')])]"/> |
102 | </record> |
103 | <record id="message_blogpost0_comment3" model="mail.message"> |
104 | <field name="model">mail.group</field> |
105 | <field name="res_id" ref="group_all_employees"/> |
106 | - <field name="body">Great news, I need to buy a new fridge, I think I can pay it with the eco-vouchers!</field> |
107 | + <field name="body"><![CDATA[<p>Many thanks. Actually that's good news, next year I'll have to buy a new fridge, I think I will pay it with the eco-vouchers!</p>]]></field> |
108 | <field name="parent_id" ref="message_blogpost0"/> |
109 | <field name="type">comment</field> |
110 | <field name="subtype_id" ref="mt_comment"/> |
111 | + <field name="author_id" ref="base.partner_demo"/> |
112 | </record> |
113 | |
114 | <!-- Demo user and admin conversation --> |
115 | |
116 | === modified file 'mail/data/mail_group_data.xml' |
117 | --- mail/data/mail_group_data.xml 2012-11-12 23:04:18 +0000 |
118 | +++ mail/data/mail_group_data.xml 2012-11-14 09:23:22 +0000 |
119 | @@ -18,11 +18,9 @@ |
120 | <field name="res_id" ref="mail.group_all_employees"/> |
121 | <field name="type">notification</field> |
122 | <field name="subject">Welcome to OpenERP!</field> |
123 | - <field name="body">Your homepage is a summary of messages you received and key information about documents you follow. |
124 | - |
125 | -The top menu bar contains all applications you installed. You can use this <i>Settings</i> menu to install more applications, activate others features or give access to new users. |
126 | - |
127 | -To setup your preferences (name, email signature, avatar), click on the top right corner.</field> |
128 | + <field name="body"><![CDATA[<p>Your homepage is a summary of messages you received and key information about documents you follow.<br /> |
129 | +The top menu bar contains all applications you installed. You can use this <i>Settings</i> menu to install more applications, activate others features or give access to new users.<br /> |
130 | +To setup your preferences (name, email signature, avatar), click on the top right corner.</p>]]></field> |
131 | </record> |
132 | </data> |
133 | </openerp> |
134 | |
135 | === modified file 'mail/mail_followers.py' |
136 | --- mail/mail_followers.py 2012-11-12 13:17:59 +0000 |
137 | +++ mail/mail_followers.py 2012-11-14 09:23:22 +0000 |
138 | @@ -84,11 +84,13 @@ |
139 | return False |
140 | |
141 | def set_message_read(self, cr, uid, msg_ids, read=None, context=None): |
142 | - """ Set a message and its child messages as (un)read for uid. |
143 | + """ Set messages as (un)read. Technically, the notifications related |
144 | + to uid are set to (un)read. If for some msg_ids there are missing |
145 | + notifications (i.e. due to load more or thread parent fetching), |
146 | + they are created. |
147 | |
148 | - :param bool read: read / unread |
149 | + :param bool read: (un)read notification |
150 | """ |
151 | - # TDE note: use child_of or front-end send correct values ? |
152 | user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0] |
153 | notif_ids = self.search(cr, uid, [ |
154 | ('partner_id', '=', user_pid), |
155 | @@ -100,10 +102,9 @@ |
156 | return self.write(cr, uid, notif_ids, {'read': read}, context=context) |
157 | |
158 | # some messages do not have notifications: find which one, create notification, update read status |
159 | - exist_notification = dict.fromkeys(msg_ids, False) |
160 | - for notification in self.browse(cr, uid, notif_ids, context=context): |
161 | - exist_notification[notification.message_id.id] = True |
162 | - for msg_id in exist_notification.keys(): |
163 | + notified_msg_ids = [notification.message_id.id for notification in self.browse(cr, uid, notif_ids, context=context)] |
164 | + to_create_msg_ids = list(set(msg_ids) - set(notified_msg_ids)) |
165 | + for msg_id in to_create_msg_ids: |
166 | self.create(cr, uid, {'partner_id': user_pid, 'read': read, 'message_id': msg_id}, context=context) |
167 | return self.write(cr, uid, notif_ids, {'read': read}, context=context) |
168 | |
169 | @@ -150,16 +151,18 @@ |
170 | |
171 | # add the context in the email |
172 | # TDE FIXME: commented, to be improved in a future branch |
173 | - # quote_context = self.pool.get('mail.message').message_quote_context(cr, uid, msg_id, context=context) |
174 | + quote_context = self.pool.get('mail.message').message_quote_context(cr, uid, msg_id, context=context) |
175 | |
176 | mail_mail = self.pool.get('mail.mail') |
177 | # add signature |
178 | body_html = msg.body |
179 | - # if quote_context: |
180 | - # body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False) |
181 | - signature = msg.author_id and msg.author_id.user_ids[0].signature or '' |
182 | + if quote_context: |
183 | + pass |
184 | + # print quote_context |
185 | + # body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False) |
186 | + signature = msg.author_id and msg.author_id.user_id and msg.author_id.user_ids[0].signature or '' |
187 | if signature: |
188 | - body_html = tools.append_content_to_html(body_html, signature) |
189 | + body_html = tools.append_content_to_html(body_html, tools.text2html(signature), plaintext=False) |
190 | |
191 | mail_values = { |
192 | 'mail_message_id': msg.id, |
193 | |
194 | === modified file 'mail/mail_message.py' |
195 | --- mail/mail_message.py 2012-11-12 14:04:08 +0000 |
196 | +++ mail/mail_message.py 2012-11-14 09:23:22 +0000 |
197 | @@ -25,6 +25,7 @@ |
198 | from email.header import decode_header |
199 | from openerp import SUPERUSER_ID |
200 | from openerp.osv import osv, orm, fields |
201 | +from openerp.tools import html_email_clean |
202 | from openerp.tools.translate import _ |
203 | |
204 | _logger = logging.getLogger(__name__) |
205 | @@ -280,7 +281,7 @@ |
206 | |
207 | return {'id': message.id, |
208 | 'type': message.type, |
209 | - 'body': message.body, |
210 | + 'body': html_email_clean(message.body), |
211 | 'model': message.model, |
212 | 'res_id': message.res_id, |
213 | 'record_name': message.record_name, |
214 | @@ -633,6 +634,8 @@ |
215 | def create(self, cr, uid, values, context=None): |
216 | if not values.get('message_id') and values.get('res_id') and values.get('model'): |
217 | values['message_id'] = tools.generate_tracking_message_id('%(res_id)s-%(model)s' % values) |
218 | + elif not values.get('message_id'): |
219 | + values['message_id'] = tools.generate_tracking_message_id('private') |
220 | newid = super(mail_message, self).create(cr, uid, values, context) |
221 | self._notify(cr, SUPERUSER_ID, newid, context=context) |
222 | return newid |
223 | @@ -763,7 +766,7 @@ |
224 | ], context=context) |
225 | fol_objs = fol_obj.read(cr, uid, fol_ids, ['partner_id'], context=context) |
226 | partners_to_notify |= set(fol['partner_id'][0] for fol in fol_objs) |
227 | - # when writing to a wall |
228 | + # remove me from notified partners, unless the message is written on my own wall |
229 | if message.get('author_id') and message.get('model') == "res.partner" and message.get('res_id') == message.get('author_id')[0]: |
230 | partners_to_notify |= set([message.get('author_id')[0]]) |
231 | elif message.get('author_id'): |
232 | |
233 | === modified file 'mail/mail_thread.py' |
234 | --- mail/mail_thread.py 2012-11-12 13:10:51 +0000 |
235 | +++ mail/mail_thread.py 2012-11-14 09:23:22 +0000 |
236 | @@ -319,10 +319,12 @@ |
237 | """ |
238 | assert isinstance(message, Message), 'message must be an email.message.Message at this point' |
239 | message_id = message.get('Message-Id') |
240 | + references = decode_header(message, 'References') |
241 | + in_reply_to = decode_header(message, 'In-Reply-To') |
242 | |
243 | # 1. Verify if this is a reply to an existing thread |
244 | - references = decode_header(message, 'References') or decode_header(message, 'In-Reply-To') |
245 | - ref_match = references and tools.reference_re.search(references) |
246 | + thread_references = references or in_reply_to |
247 | + ref_match = thread_references and tools.reference_re.search(thread_references) |
248 | if ref_match: |
249 | thread_id = int(ref_match.group(1)) |
250 | model = ref_match.group(2) or model |
251 | @@ -333,6 +335,14 @@ |
252 | message_id, model, thread_id, custom_values, uid) |
253 | return [(model, thread_id, custom_values, uid)] |
254 | |
255 | + # Verify this is a reply to a private message |
256 | + message_ids = self.pool.get('mail.message').search(cr, uid, [('message_id', '=', in_reply_to)], limit=1, context=context) |
257 | + if message_ids: |
258 | + message = self.pool.get('mail.message').browse(cr, uid, message_ids[0], context=context) |
259 | + _logger.debug('Routing mail with Message-Id %s: reply to a private message: %s, custom_values: %s, uid: %s', |
260 | + message_id, message.id, custom_values, uid) |
261 | + return [(False, 0, custom_values, uid)] |
262 | + |
263 | # 2. Look for a matching mail.alias entry |
264 | # Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values |
265 | # for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value. |
266 | @@ -376,14 +386,19 @@ |
267 | def message_process(self, cr, uid, model, message, custom_values=None, |
268 | save_original=False, strip_attachments=False, |
269 | thread_id=None, context=None): |
270 | - """Process an incoming RFC2822 email message, relying on |
271 | - ``mail.message.parse()`` for the parsing operation, |
272 | - and ``message_route()`` to figure out the target model. |
273 | + """ Process an incoming RFC2822 email message, relying on |
274 | + ``mail.message.parse()`` for the parsing operation, |
275 | + and ``message_route()`` to figure out the target model. |
276 | |
277 | - Once the target model is known, its ``message_new`` method |
278 | - is called with the new message (if the thread record did not exist) |
279 | + Once the target model is known, its ``message_new`` method |
280 | + is called with the new message (if the thread record did not exist) |
281 | or its ``message_update`` method (if it did). |
282 | |
283 | + There is a special case where the target model is False: a reply |
284 | + to a private message. In this case, we skip the message_new / |
285 | + message_update step, to just post a new message using mail_thread |
286 | + message_post. |
287 | + |
288 | :param string model: the fallback model to use if the message |
289 | does not match any of the currently configured mail aliases |
290 | (may be None if a matching alias is supposed to be present) |
291 | @@ -425,15 +440,18 @@ |
292 | for model, thread_id, custom_values, user_id in routes: |
293 | if self._name != model: |
294 | context.update({'thread_model': model}) |
295 | - model_pool = self.pool.get(model) |
296 | - assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \ |
297 | - "Undeliverable mail with Message-Id %s, model %s does not accept incoming emails" % \ |
298 | - (msg['message_id'], model) |
299 | - if thread_id and hasattr(model_pool, 'message_update'): |
300 | - model_pool.message_update(cr, user_id, [thread_id], msg, context=context) |
301 | + if model: |
302 | + model_pool = self.pool.get(model) |
303 | + assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \ |
304 | + "Undeliverable mail with Message-Id %s, model %s does not accept incoming emails" % \ |
305 | + (msg['message_id'], model) |
306 | + if thread_id and hasattr(model_pool, 'message_update'): |
307 | + model_pool.message_update(cr, user_id, [thread_id], msg, context=context) |
308 | + else: |
309 | + thread_id = model_pool.message_new(cr, user_id, msg, custom_values, context=context) |
310 | else: |
311 | - thread_id = model_pool.message_new(cr, user_id, msg, custom_values, context=context) |
312 | - model_pool.message_post(cr, uid, [thread_id], context=context, **msg) |
313 | + model_pool = self.pool.get('mail.thread') |
314 | + model_pool.message_post_user_api(cr, uid, [thread_id], context=context, content_subtype='html', **msg) |
315 | return thread_id |
316 | |
317 | def message_new(self, cr, uid, msg_dict, custom_values=None, context=None): |
318 | @@ -556,7 +574,6 @@ |
319 | """ |
320 | msg_dict = { |
321 | 'type': 'email', |
322 | - 'subtype': 'mail.mt_comment', |
323 | 'author_id': False, |
324 | } |
325 | if not isinstance(message, Message): |
326 | @@ -588,7 +605,7 @@ |
327 | else: |
328 | msg_dict['email_from'] = message.get('from') |
329 | partner_ids = self._message_find_partners(cr, uid, message, ['From', 'To', 'Cc'], context=context) |
330 | - msg_dict['partner_ids'] = partner_ids |
331 | + msg_dict['partner_ids'] = [(4, partner_id) for partner_id in partner_ids] |
332 | |
333 | if 'Date' in message: |
334 | date_hdr = decode(message.get('Date')) |
335 | @@ -629,7 +646,8 @@ |
336 | mail.message ID. Extra keyword arguments will be used as default |
337 | column values for the new mail.message record. |
338 | Auto link messages for same id and object |
339 | - :param int thread_id: thread ID to post into, or list with one ID |
340 | + :param int thread_id: thread ID to post into, or list with one ID; |
341 | + if False/0, mail.message model will also be set as False |
342 | :param str body: body of the message, usually raw HTML that will |
343 | be sanitized |
344 | :param str subject: optional subject |
345 | @@ -639,10 +657,13 @@ |
346 | ``(name,content)``, where content is NOT base64 encoded |
347 | :return: ID of newly created mail.message |
348 | """ |
349 | - context = context or {} |
350 | - attachments = attachments or [] |
351 | + if context is None: |
352 | + context = {} |
353 | + if attachments is None: |
354 | + attachments = {} |
355 | + |
356 | assert (not thread_id) or isinstance(thread_id, (int, long)) or \ |
357 | - (isinstance(thread_id, (list, tuple)) and len(thread_id) == 1), "Invalid thread_id" |
358 | + (isinstance(thread_id, (list, tuple)) and len(thread_id) == 1), "Invalid thread_id; should be 0, False, an ID or a list with one ID" |
359 | if isinstance(thread_id, (list, tuple)): |
360 | thread_id = thread_id and thread_id[0] |
361 | mail_message = self.pool.get('mail.message') |
362 | @@ -682,7 +703,6 @@ |
363 | # avoid loops when finding ancestors |
364 | processed_list = [] |
365 | if message_ids: |
366 | - _counter, _counter_max = 0, 200 |
367 | message = mail_message.browse(cr, SUPERUSER_ID, message_ids[0], context=context) |
368 | while (message.parent_id and message.parent_id.id not in processed_list): |
369 | processed_list.append(message.parent_id.id) |
370 | @@ -707,18 +727,45 @@ |
371 | |
372 | return mail_message.create(cr, uid, values, context=context) |
373 | |
374 | - def message_post_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False, attachment_ids=None, context=None): |
375 | - """ Wrapper on message_post, used only in Chatter (JS). The purpose is |
376 | - to handle attachments. |
377 | - # TDE FIXME: body is plaintext: convert it into html |
378 | + def message_post_user_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False, |
379 | + attachment_ids=None, context=None, content_subtype='plaintext', **kwargs): |
380 | + """ Wrapper on message_post, used for user input : |
381 | + - mail gateway |
382 | + - quick reply in Chatter (refer to mail.js), not |
383 | + the mail.compose.message wizard |
384 | + The purpose is to perform some pre- and post-processing: |
385 | + - if body is plaintext: convert it into html |
386 | + - if parent_id: handle reply to a previous message by adding the |
387 | + parent partners to the message |
388 | + - type and subtype: comment and mail.mt_comment by default |
389 | + - attachment_ids: supposed not attached to any document; attach them |
390 | + to the related document. Should only be set by Chatter. |
391 | """ |
392 | - new_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type='comment', |
393 | - subtype='mail.mt_comment', parent_id=parent_id, context=context) |
394 | - |
395 | - # HACK FIXME: Chatter: attachments linked to the document (not done JS-side), load the message |
396 | + ir_attachment = self.pool.get('ir.attachment') |
397 | + mail_message = self.pool.get('mail.message') |
398 | + |
399 | + # 1. Pre-processing: body, partner_ids, type and subtype |
400 | + if content_subtype == 'plaintext': |
401 | + body = tools.text2html(body) |
402 | + |
403 | + partner_ids = kwargs.pop('partner_ids', []) |
404 | + if parent_id: |
405 | + parent_message = self.pool.get('mail.message').browse(cr, uid, parent_id, context=context) |
406 | + partner_ids += [(4, partner.id) for partner in parent_message.partner_ids] |
407 | + # TDE FIXME HACK: mail.thread -> private message |
408 | + if self._name == 'mail.thread' and parent_message.author_id.id: |
409 | + partner_ids.append((4, parent_message.author_id.id)) |
410 | + |
411 | + message_type = kwargs.pop('type', 'comment') |
412 | + message_subtype = kwargs.pop('type', 'mail.mt_comment') |
413 | + |
414 | + # 2. Post message |
415 | + new_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type=message_type, |
416 | + subtype=message_subtype, parent_id=parent_id, context=context, partner_ids=partner_ids, **kwargs) |
417 | + |
418 | + # 3. Post-processing |
419 | + # HACK TDE FIXME: Chatter: attachments linked to the document (not done JS-side), load the message |
420 | if attachment_ids: |
421 | - ir_attachment = self.pool.get('ir.attachment') |
422 | - mail_message = self.pool.get('mail.message') |
423 | filtered_attachment_ids = ir_attachment.search(cr, SUPERUSER_ID, [ |
424 | ('res_model', '=', 'mail.compose.message'), |
425 | ('res_id', '=', 0), |
426 | |
427 | === modified file 'mail/res_partner.py' |
428 | --- mail/res_partner.py 2012-10-15 13:23:13 +0000 |
429 | +++ mail/res_partner.py 2012-11-14 09:23:22 +0000 |
430 | @@ -42,4 +42,22 @@ |
431 | 'notification_email_send': lambda *args: 'comment' |
432 | } |
433 | |
434 | + def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', |
435 | + subtype=None, parent_id=False, attachments=None, context=None, **kwargs): |
436 | + """ Override related to res.partner. In case of email message, set it as |
437 | + private: |
438 | + - add the target partner in the message partner_ids |
439 | + - set thread_id as None, because this will trigger the 'private' |
440 | + aspect of the message (model=False, res_id=False) |
441 | + """ |
442 | + if isinstance(thread_id, (list, tuple)): |
443 | + thread_id = thread_id[0] |
444 | + if type == 'email': |
445 | + partner_ids = kwargs.get('partner_ids', []) |
446 | + if thread_id not in partner_ids: |
447 | + partner_ids.append(thread_id) |
448 | + kwargs['partner_ids'] = partner_ids |
449 | + return super(res_partner_mail, self).message_post(cr, uid, False, body=body, subject=subject, |
450 | + type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, **kwargs) |
451 | + |
452 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
453 | |
454 | === modified file 'mail/security/ir.model.access.csv' |
455 | --- mail/security/ir.model.access.csv 2012-11-06 15:04:31 +0000 |
456 | +++ mail/security/ir.model.access.csv 2012-11-14 09:23:22 +0000 |
457 | @@ -7,12 +7,13 @@ |
458 | access_mail_followers_all,mail.followers.all,model_mail_followers,,1,0,0,0 |
459 | access_mail_followers_system,mail.followers.system,model_mail_followers,base.group_system,1,1,1,1 |
460 | access_mail_notification_all,mail.notification.all,model_mail_notification,,1,0,0,0 |
461 | -access_mail_notification_aystem,mail.notification.system,model_mail_notification,base.group_system,1,1,1,1 |
462 | +access_mail_notification_group_user,mail.notification.user,model_mail_notification,base.group_user,1,1,1,0 |
463 | +access_mail_notification_system,mail.notification.system,model_mail_notification,base.group_system,1,1,1,1 |
464 | access_mail_group_all,mail.group.all,model_mail_group,,1,0,0,0 |
465 | access_mail_group_user,mail.group.user,model_mail_group,base.group_user,1,1,1,1 |
466 | access_mail_alias_all,mail.alias.all,model_mail_alias,,1,0,0,0 |
467 | -access_mail_alias_user,mail.alias,model_mail_alias,base.group_user,1,1,1,0 |
468 | -access_mail_alias_system,mail.alias,model_mail_alias,base.group_system,1,1,1,1 |
469 | +access_mail_alias_user,mail.alias.user,model_mail_alias,base.group_user,1,1,1,0 |
470 | +access_mail_alias_system,mail.alias.system,model_mail_alias,base.group_system,1,1,1,1 |
471 | access_mail_message_subtype_all,mail.message.subtype.all,model_mail_message_subtype,,1,0,0,0 |
472 | access_mail_vote_all,mail.vote.all,model_mail_vote,,1,1,1,1 |
473 | access_mail_favorite_all,mail.favorite.all,model_mail_favorite,,1,1,1,1 |
474 | |
475 | === modified file 'mail/security/mail_security.xml' |
476 | --- mail/security/mail_security.xml 2012-10-19 09:59:19 +0000 |
477 | +++ mail/security/mail_security.xml 2012-11-14 09:23:22 +0000 |
478 | @@ -10,7 +10,7 @@ |
479 | <field name="domain_force">['|', '|', ('public', '=', 'public'), ('message_follower_ids', 'in', [user.partner_id.id]), '&', ('public','=','groups'), ('group_public_id','in', [g.id for g in user.groups_id])]</field> |
480 | </record> |
481 | |
482 | - <record id="mail_followers_read_own" model="ir.rule"> |
483 | + <record id="mail_followers_read_write_own" model="ir.rule"> |
484 | <field name="name">mail.followers: read and write its own entries</field> |
485 | <field name="model_id" ref="model_mail_followers"/> |
486 | <field name="domain_force">[('partner_id', '=', user.partner_id.id)]</field> |
487 | @@ -18,6 +18,14 @@ |
488 | <field name="perm_unlink" eval="False"/> |
489 | </record> |
490 | |
491 | + <record id="mail_notification_read_write_own" model="ir.rule"> |
492 | + <field name="name">mail.notification: read and write its own entries</field> |
493 | + <field name="model_id" ref="model_mail_notification"/> |
494 | + <field name="domain_force">[('partner_id', '=', user.partner_id.id)]</field> |
495 | + <field name="perm_create" eval="False"/> |
496 | + <field name="perm_unlink" eval="False"/> |
497 | + </record> |
498 | + |
499 | <!-- |
500 | This rule can not be uncommented, because we have a more wide method in mail.message. When we implement a many2one_variable field, we will be able to uncomment this. |
501 | <record id="mail_message_read_partner_or_author" model="ir.rule"> |
502 | |
503 | === modified file 'mail/static/src/css/mail.css' |
504 | --- mail/static/src/css/mail.css 2012-11-13 10:35:30 +0000 |
505 | +++ mail/static/src/css/mail.css 2012-11-14 09:23:22 +0000 |
506 | @@ -87,6 +87,10 @@ |
507 | margin-bottom: 0px; |
508 | margin-top: 2px; |
509 | } |
510 | +.openerp .oe_mail .oe_msg .oe_msg_content .oe_msg_body p{ |
511 | + margin-top: 2px; |
512 | + margin-bottom: 2px; |
513 | +} |
514 | |
515 | /* a) Indented Messages */ |
516 | |
517 | |
518 | === modified file 'mail/static/src/js/mail.js' |
519 | --- mail/static/src/js/mail.js 2012-11-13 14:57:22 +0000 |
520 | +++ mail/static/src/js/mail.js 2012-11-14 09:23:22 +0000 |
521 | @@ -590,7 +590,7 @@ |
522 | |
523 | if (body.match(/\S+/)) { |
524 | //session.web.blockUI(); |
525 | - this.parent_thread.ds_thread.call('message_post_api', [ |
526 | + this.parent_thread.ds_thread.call('message_post_user_api', [ |
527 | this.context.default_res_id, |
528 | mail.ChatterUtils.get_text2html(body), |
529 | false, |
530 | @@ -728,7 +728,6 @@ |
531 | |
532 | mail.ThreadMessage = mail.MessageCommon.extend({ |
533 | template: 'mail.thread.message', |
534 | - |
535 | |
536 | start: function () { |
537 | this._super.apply(this, arguments); |
538 | |
539 | === modified file 'mail/tests/__init__.py' |
540 | --- mail/tests/__init__.py 2012-09-14 11:58:15 +0000 |
541 | +++ mail/tests/__init__.py 2012-11-14 09:23:22 +0000 |
542 | @@ -18,6 +18,7 @@ |
543 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
544 | # |
545 | ############################################################################## |
546 | + |
547 | from . import test_mail, test_mail_access_rights |
548 | |
549 | checks = [ |
550 | |
551 | === modified file 'mail/tests/test_mail.py' |
552 | --- mail/tests/test_mail.py 2012-11-09 15:11:22 +0000 |
553 | +++ mail/tests/test_mail.py 2012-11-14 09:23:22 +0000 |
554 | @@ -21,8 +21,8 @@ |
555 | |
556 | import tools |
557 | |
558 | -from openerp.tests import common |
559 | -from openerp.tools.html_sanitize import html_sanitize |
560 | +from openerp.addons.mail.tests import test_mail_mockup |
561 | +from openerp.tools.mail import html_sanitize |
562 | |
563 | MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com> |
564 | To: {to} |
565 | @@ -84,43 +84,11 @@ |
566 | """ |
567 | |
568 | |
569 | -class TestMailMockups(common.TransactionCase): |
570 | - |
571 | - def _mock_smtp_gateway(self, *args, **kwargs): |
572 | - return True |
573 | - |
574 | - def _init_mock_build_email(self): |
575 | - self._build_email_args_list = [] |
576 | - self._build_email_kwargs_list = [] |
577 | - |
578 | - def _mock_build_email(self, *args, **kwargs): |
579 | - """ Mock build_email to be able to test its values. Store them into |
580 | - some internal variable for latter processing. """ |
581 | - self._build_email_args_list.append(args) |
582 | - self._build_email_kwargs_list.append(kwargs) |
583 | - return self._build_email(*args, **kwargs) |
584 | - |
585 | - def setUp(self): |
586 | - super(TestMailMockups, self).setUp() |
587 | - # Install mock SMTP gateway |
588 | - self._init_mock_build_email() |
589 | - self._build_email = self.registry('ir.mail_server').build_email |
590 | - self.registry('ir.mail_server').build_email = self._mock_build_email |
591 | - self._send_email = self.registry('ir.mail_server').send_email |
592 | - self.registry('ir.mail_server').send_email = self._mock_smtp_gateway |
593 | - |
594 | - def tearDown(self): |
595 | - # Remove mocks |
596 | - self.registry('ir.mail_server').build_email = self._build_email |
597 | - self.registry('ir.mail_server').send_email = self._send_email |
598 | - super(TestMailMockups, self).tearDown() |
599 | - |
600 | - |
601 | -class test_mail(TestMailMockups): |
602 | +class test_mail(test_mail_mockup.TestMailMockups): |
603 | |
604 | def _mock_send_get_mail_body(self, *args, **kwargs): |
605 | # def _send_get_mail_body(self, cr, uid, mail, partner=None, context=None) |
606 | - body = tools.append_content_to_html(args[2].body_html, kwargs.get('partner').name if kwargs.get('partner') else 'No specific partner') |
607 | + body = tools.append_content_to_html(args[2].body_html, kwargs.get('partner').name if kwargs.get('partner') else 'No specific partner', plaintext=False) |
608 | return body |
609 | |
610 | def setUp(self): |
611 | @@ -375,10 +343,10 @@ |
612 | _subject = 'Pigs' |
613 | _mail_subject = '%s posted on %s' % (user_admin.name, group_pigs.name) |
614 | _body1 = 'Pigs rules' |
615 | - _mail_body1 = 'Pigs rules\n<pre>Admin</pre>\n' |
616 | - _mail_bodyalt1 = 'Pigs rules\nAdmin' |
617 | + _mail_body1 = 'Pigs rules\n<div><p>Admin</p></div>\n' |
618 | + _mail_bodyalt1 = 'Pigs rules\nAdmin\n' |
619 | _body2 = '<html>Pigs rules</html>' |
620 | - _mail_body2 = html_sanitize('<html>Pigs rules\n<pre>Admin</pre>\n</html>') |
621 | + _mail_body2 = html_sanitize('<html>Pigs rules\n<div><p>Admin</p></div>\n</html>') |
622 | _mail_bodyalt2 = 'Pigs rules\nAdmin' |
623 | _attachments = [('First', 'My first attachment'), ('Second', 'My second attachment')] |
624 | |
625 | @@ -399,7 +367,7 @@ |
626 | # Test: sent_email: email send by server: correct subject, body, body_alternative |
627 | for sent_email in sent_emails: |
628 | self.assertEqual(sent_email['subject'], _subject, 'sent_email subject incorrect') |
629 | - self.assertEqual(sent_email['body'], _mail_body1 + '\n<pre>Bert Tartopoils</pre>\n', 'sent_email body incorrect') |
630 | + self.assertEqual(sent_email['body'], _mail_body1 + '\nBert Tartopoils\n', 'sent_email body incorrect') |
631 | # the html2plaintext uses etree or beautiful soup, so the result may be slighly different |
632 | # depending if you have installed beautiful soup. |
633 | self.assertIn(sent_email['body_alternative'], _mail_bodyalt1 + '\nBert Tartopoils\n', 'sent_email body_alternative is incorrect') |
634 | |
635 | === modified file 'mail/tests/test_mail_access_rights.py' |
636 | --- mail/tests/test_mail_access_rights.py 2012-10-25 11:30:48 +0000 |
637 | +++ mail/tests/test_mail_access_rights.py 2012-11-14 09:23:22 +0000 |
638 | @@ -19,11 +19,11 @@ |
639 | # |
640 | ############################################################################## |
641 | |
642 | -from openerp.addons.mail.tests import test_mail |
643 | +from openerp.addons.mail.tests import test_mail_mockup |
644 | from osv.orm import except_orm |
645 | |
646 | |
647 | -class test_mail_access_rights(test_mail.TestMailMockups): |
648 | +class test_mail_access_rights(test_mail_mockup.TestMailMockups): |
649 | |
650 | def setUp(self): |
651 | super(test_mail_access_rights, self).setUp() |
652 | |
653 | === added file 'mail/tests/test_mail_mockup.py' |
654 | --- mail/tests/test_mail_mockup.py 1970-01-01 00:00:00 +0000 |
655 | +++ mail/tests/test_mail_mockup.py 2012-11-14 09:23:22 +0000 |
656 | @@ -0,0 +1,54 @@ |
657 | +# -*- coding: utf-8 -*- |
658 | +############################################################################## |
659 | +# |
660 | +# OpenERP, Open Source Business Applications |
661 | +# Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com> |
662 | +# |
663 | +# This program is free software: you can redistribute it and/or modify |
664 | +# it under the terms of the GNU Affero General Public License as |
665 | +# published by the Free Software Foundation, either version 3 of the |
666 | +# License, or (at your option) any later version. |
667 | +# |
668 | +# This program is distributed in the hope that it will be useful, |
669 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
670 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
671 | +# GNU Affero General Public License for more details. |
672 | +# |
673 | +# You should have received a copy of the GNU Affero General Public License |
674 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
675 | +# |
676 | +############################################################################## |
677 | + |
678 | +from openerp.tests import common |
679 | + |
680 | + |
681 | +class TestMailMockups(common.TransactionCase): |
682 | + |
683 | + def _mock_smtp_gateway(self, *args, **kwargs): |
684 | + return True |
685 | + |
686 | + def _init_mock_build_email(self): |
687 | + self._build_email_args_list = [] |
688 | + self._build_email_kwargs_list = [] |
689 | + |
690 | + def _mock_build_email(self, *args, **kwargs): |
691 | + """ Mock build_email to be able to test its values. Store them into |
692 | + some internal variable for latter processing. """ |
693 | + self._build_email_args_list.append(args) |
694 | + self._build_email_kwargs_list.append(kwargs) |
695 | + return self._build_email(*args, **kwargs) |
696 | + |
697 | + def setUp(self): |
698 | + super(TestMailMockups, self).setUp() |
699 | + # Install mock SMTP gateway |
700 | + self._init_mock_build_email() |
701 | + self._build_email = self.registry('ir.mail_server').build_email |
702 | + self.registry('ir.mail_server').build_email = self._mock_build_email |
703 | + self._send_email = self.registry('ir.mail_server').send_email |
704 | + self.registry('ir.mail_server').send_email = self._mock_smtp_gateway |
705 | + |
706 | + def tearDown(self): |
707 | + # Remove mocks |
708 | + self.registry('ir.mail_server').build_email = self._build_email |
709 | + self.registry('ir.mail_server').send_email = self._send_email |
710 | + super(TestMailMockups, self).tearDown() |
711 | |
712 | === modified file 'mail/wizard/mail_compose_message_view.xml' |
713 | --- mail/wizard/mail_compose_message_view.xml 2012-11-13 08:41:53 +0000 |
714 | +++ mail/wizard/mail_compose_message_view.xml 2012-11-14 09:23:22 +0000 |
715 | @@ -8,11 +8,11 @@ |
716 | <form string="Compose Email" version="7.0"> |
717 | <group> |
718 | <!-- truly invisible fields for control and options --> |
719 | - <field name="composition_mode" invisible="1"/> |
720 | - <field name="model" invisible="1"/> |
721 | - <field name="res_id" invisible="1"/> |
722 | - <field name="parent_id" invisible="1"/> |
723 | - <field name="content_subtype" invisible="1"/> |
724 | + <field name="composition_mode" invisible="0"/> |
725 | + <field name="model" invisible="0"/> |
726 | + <field name="res_id" invisible="0"/> |
727 | + <field name="parent_id" invisible="0"/> |
728 | + <field name="content_subtype" invisible="0"/> |
729 | <!-- visible wizard --> |
730 | <label for="partner_ids" string="Recipients"/> |
731 | <div> |
732 | |
733 | === modified file 'note/note.py' |
734 | --- note/note.py 2012-11-02 13:17:59 +0000 |
735 | +++ note/note.py 2012-11-14 09:23:22 +0000 |
736 | @@ -20,9 +20,7 @@ |
737 | ############################################################################## |
738 | |
739 | from openerp.osv import osv, fields |
740 | -from tools.translate import _ |
741 | -import re |
742 | -from openerp.tools.misc import html2plaintext |
743 | +from openerp.tools import html2plaintext |
744 | |
745 | class note_stage(osv.osv): |
746 | """ Category of Note """ |
747 | |
748 | === modified file 'pad/pad.py' |
749 | --- pad/pad.py 2012-11-09 06:30:02 +0000 |
750 | +++ pad/pad.py 2012-11-14 09:23:22 +0000 |
751 | @@ -6,7 +6,7 @@ |
752 | import urllib2 |
753 | import logging |
754 | from tools.translate import _ |
755 | -from openerp.tools.misc import html2plaintext |
756 | +from openerp.tools import html2plaintext |
757 | from py_etherpad import EtherpadLiteClient |
758 | |
759 | _logger = logging.getLogger(__name__) |
760 | |
761 | === modified file 'portal/mail_mail.py' |
762 | --- portal/mail_mail.py 2012-10-01 09:14:41 +0000 |
763 | +++ portal/mail_mail.py 2012-11-14 09:23:22 +0000 |
764 | @@ -36,5 +36,5 @@ |
765 | if partner: |
766 | context = dict(context or {}, signup_valid=True) |
767 | partner = self.pool.get('res.partner').browse(cr, uid, partner.id, context) |
768 | - body = tools.append_content_to_html(body, "Log in our portal at: %s" % partner.signup_url) |
769 | + body = tools.append_content_to_html(body, ("<div><p>Log in our portal at: %s</p></div>" % partner.signup_url), plaintext=False) |
770 | return body |
771 | |
772 | === modified file 'portal/portal_demo.xml' |
773 | --- portal/portal_demo.xml 2012-09-20 14:57:53 +0000 |
774 | +++ portal/portal_demo.xml 2012-11-14 09:23:22 +0000 |
775 | @@ -1,22 +1,27 @@ |
776 | <?xml version="1.0"?> |
777 | <openerp> |
778 | - <data> |
779 | + <data noupdate="1"> |
780 | |
781 | - <!-- Create a portal member attached to a partner --> |
782 | - <record id="demo_user0" model="res.users"> |
783 | + <!-- Create a partner, that is also a portal user --> |
784 | + <record id="partner_demo_portal" model="res.partner"> |
785 | <field name="name">Demo Portal User</field> |
786 | + <field name="email">demo@portal.example.com</field> |
787 | + <field name="supplier" eval="False"/> |
788 | + <field name="customer" eval="True"/> |
789 | + </record> |
790 | + <record id="user_demo_portal" model="res.users"> |
791 | + <field name="partner_id" ref="partner_demo_portal"/> |
792 | <field name="login">portal</field> |
793 | <field name="password">portal</field> |
794 | + <field name="signature">-- |
795 | +Mr Demo Portal</field> |
796 | <!-- Avoid auto-including this user in any default group --> |
797 | <field name="groups_id" eval="[(5,)]"/> |
798 | - <field name="supplier" eval="False"/> |
799 | - <field name="customer" eval="True"/> |
800 | - <field name="email">demo@portal.wrong.address</field> |
801 | </record> |
802 | |
803 | <!-- Add the demo user to the portal (and therefore to the portal member group) --> |
804 | <record id="group_portal" model="res.groups"> |
805 | - <field name="users" eval="[(4,ref('demo_user0'))]"/> |
806 | + <field name="users" eval="[(4,ref('user_demo_portal'))]"/> |
807 | </record> |
808 | |
809 | <!-- Company news and comments --> |
810 | @@ -24,33 +29,41 @@ |
811 | <field name="subject">Our company's first blog-post !</field> |
812 | <field name="model">mail.group</field> |
813 | <field name="res_id" ref="company_news_feed"/> |
814 | - <field name="body"><![CDATA[Hello, and welcome to our company's portal ! |
815 | - |
816 | -Lorem ipsum <b>sit amet</b>, consectetur <em>adipiscing elit</em>. Pellentesque et quam sapien, in sagittis tellus. |
817 | -Praesent vel massa sed massa consequat egestas in tristique orci. Praesent iaculis libero et neque vehicula iaculis. Vivamus placerat tincidunt orci ac ornare. Proin ut dolor fringilla velit ultricies consequat. Maecenas sit amet ipsum non leo interdum imperdiet. Donec sapien mi. |
818 | - |
819 | -Fusce tempus elit volutpat mi auctor adipiscing. Nam congue luctus suscipit. Sed tellus libero, venenatis ut mollis ut, luctus quis dui. Sed rhoncus pulvinar orci in consectetur. |
820 | - |
821 | -Nulla turpis leo, rhoncus ut egestas sit amet, consectetur vitae urna. Mauris in dolor in sapien tempus vehicula.]]></field> |
822 | + <field name="body"><![CDATA[<p>Hello, and welcome to our company's portal !</p> |
823 | +<p>It is a great pleasure to announce you the creation of our portal by writing this first news! As you may have seen, a new discussion group is now present under your 'My groups' menu: <b>Company's News</b>. We will post news about the company and its employees in this discussion group. Moreover, we will be able to communicate with our partners that are given the opportunity to join us in our portal.</p> |
824 | +<p>A new era of communication has begun! <b>Feel free to post your feelings about our portal by replying on this message!</b></p>]]></field> |
825 | <field name="type">comment</field> |
826 | + <field name="subtype_id" ref="mail.mt_comment"/> |
827 | <field name="author_id" ref="base.partner_root"/> |
828 | </record> |
829 | |
830 | <record id="message_company_news0_comment0" model="mail.message"> |
831 | <field name="model">mail.group</field> |
832 | <field name="res_id" ref="company_news_feed"/> |
833 | - <field name="body"><![CDATA[Great first blogpost ! (first comment)]]></field> |
834 | - <field name="parent_id" ref="message_company_news0"/> |
835 | - <field name="type">comment</field> |
836 | + <field name="body"><![CDATA[<p>As your first portal member, I am very pleased to be able to be able to communicate directly with you. Be sure I'll read all news carefully!</p>]]></field> |
837 | + <field name="parent_id" ref="message_company_news0"/> |
838 | + <field name="type">comment</field> |
839 | + <field name="subtype_id" ref="mail.mt_comment"/> |
840 | + <field name="author_id" ref="partner_demo_portal"/> |
841 | + </record> |
842 | + |
843 | + <record id="message_company_news0_comment1" model="mail.message"> |
844 | + <field name="model">mail.group</field> |
845 | + <field name="res_id" ref="company_news_feed"/> |
846 | + <field name="body"><![CDATA[<p>That's good news! As said by <i>Demo Portal User</i> in the previous post, I'm looking forward to hearing from you!</p>]]></field> |
847 | + <field name="parent_id" ref="message_company_news0"/> |
848 | + <field name="type">comment</field> |
849 | + <field name="subtype_id" ref="mail.mt_comment"/> |
850 | <field name="author_id" ref="base.res_partner_1"/> |
851 | </record> |
852 | |
853 | - <record id="message_company_news0_comment1" model="mail.message"> |
854 | + <record id="message_company_news0_comment2" model="mail.message"> |
855 | <field name="model">mail.group</field> |
856 | <field name="res_id" ref="company_news_feed"/> |
857 | - <field name="body"><![CDATA[Thanks ! (second comment)]]></field> |
858 | + <field name="body"><![CDATA[<p>This feature is realy great! We will be able to communicate directly to our partners!</p>]]></field> |
859 | <field name="parent_id" ref="message_company_news0"/> |
860 | <field name="type">comment</field> |
861 | + <field name="subtype_id" ref="mail.mt_comment"/> |
862 | <field name="author_id" ref="base.partner_demo"/> |
863 | </record> |
864 | |
865 | |
866 | === modified file 'portal/tests/test_portal.py' |
867 | --- portal/tests/test_portal.py 2012-10-09 15:54:56 +0000 |
868 | +++ portal/tests/test_portal.py 2012-11-14 09:23:22 +0000 |
869 | @@ -19,12 +19,11 @@ |
870 | # |
871 | ############################################################################## |
872 | |
873 | -from openerp.addons.mail.tests import test_mail |
874 | -from openerp.tools import append_content_to_html |
875 | +from openerp.addons.mail.tests import test_mail_mockup |
876 | from osv.orm import except_orm |
877 | |
878 | |
879 | -class test_portal(test_mail.TestMailMockups): |
880 | +class test_portal(test_mail_mockup.TestMailMockups): |
881 | |
882 | def setUp(self): |
883 | super(test_portal, self).setUp() |
884 | |
885 | === modified file 'portal/wizard/portal_wizard.py' |
886 | --- portal/wizard/portal_wizard.py 2012-10-25 13:09:30 +0000 |
887 | +++ portal/wizard/portal_wizard.py 2012-11-14 09:23:22 +0000 |
888 | @@ -24,10 +24,9 @@ |
889 | |
890 | from osv import osv, fields |
891 | from tools.translate import _ |
892 | -from tools.misc import email_re |
893 | +from tools import email_re |
894 | from openerp import SUPERUSER_ID |
895 | |
896 | -from base.res.res_partner import _lang_get |
897 | _logger = logging.getLogger(__name__) |
898 | |
899 | # welcome email sent to portal users |