[REF] mail_mail: body_html is back, holding the body of emails to send.

Body of send emails is mail_mail.body_html, not body anymore.
Signature adding is back to mail_followers.notify().
Subject adding is still done just before sending.
Updated mail_mail view. mail.compose.message: body_text inside <pre>. 
[TESTS] mail: added tests for message_post, updated tests for mail.message.compose to test the composer only.

bzr revid: tde@openerp.com-20120830085116-o5h13yqodt0vof0k
This commit is contained in:
Thibault Delavallée 2012-08-30 10:51:16 +02:00
parent d8c65aa88e
commit bec83eef6f
5 changed files with 199 additions and 68 deletions

View File

@ -21,6 +21,7 @@
from osv import osv
from osv import fields
import tools
class mail_followers(osv.Model):
""" mail_followers holds the data related to the follow mechanism inside
@ -82,24 +83,39 @@ class mail_notification(osv.Model):
msg_obj = self.pool.get('mail.message')
msg = msg_obj.browse(cr, uid, msg_id, context=context)
# add signature
body_html = msg.body
signature = msg.author_id and msg.author_id.user_ids[0].signature or ''
insertion_point = body_html.find('</html>')
if insertion_point > -1:
insertion_point = body_html.find('</html>')
body_html = body_html[:insertion_point] + '<div>%s</div>' % tools.ustr(signature) + body_html[insertion_point:]
else:
body_html = body_html + '<div>%s</div>' % tools.ustr(signature)
towrite = {
'mail_message_id': msg.id,
'email_to': [],
'user_signature': True,
'auto_delete': True,
'auto_delete': False,
'body_html': body_html,
}
for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context):
# Do not send an email to the writer
if partner.user_id.id == uid:
if partner.user_ids and partner.user_ids[0].id == uid:
continue
# Do not send to partners without email address defined
if not partner.email:
continue
# Partner does not want to receive any emails
if partner.notification_email_send=='none' or not partner.email:
if partner.notification_email_send == 'none':
continue
# Partner want to receive only emails and comments
if partner.notification_email_send=='comment' and msg.type not in ('email','comment'):
# Partner wants to receive only emails and comments
if partner.notification_email_send == 'comment' and msg.type not in ('email', 'comment'):
continue
# Partner wants to receive only emails
if partner.notification_email_send == 'email' and msg.type != 'email':
continue
if partner.email not in towrite['email_to']:
towrite['email_to'].append(partner.email)
towrite['email_to'] = ', '.join(towrite['email_to'])

View File

@ -39,6 +39,8 @@ class mail_mail(osv.Model):
_name = 'mail.mail'
_description = 'Outgoing Mails'
_inherits = {'mail.message': 'mail_message_id'}
_order = 'id desc'
_columns = {
'mail_message_id': fields.many2one('mail.message', 'Message', required=True, ondelete='cascade'),
'mail_server_id': fields.many2one('ir.mail_server', 'Outgoing mail server', readonly=1),
@ -51,13 +53,12 @@ class mail_mail(osv.Model):
], 'Status', readonly=True),
'auto_delete': fields.boolean('Auto Delete',
help="Permanently delete this email after sending it, to save space"),
'user_signature': fields.boolean('Add Signature',
help="If checked, the user's signature will be appended to the text version of the message"),
'references': fields.text('References', help='Message references, such as identifiers of previous messages', readonly=1),
'email_from': fields.char('From', size=128, help='Message sender, taken from user preferences.'),
'email_to': fields.text('To', help='Message recipients'),
'email_cc': fields.char('Cc', size=256, help='Carbon copy message recipients'),
'reply_to':fields.char('Reply-To', size=256, help='Preferred response address for the message'),
'body_html': fields.text('Rich-text Contents', help="Rich-text/HTML message"),
}
def _get_default_from(self, cr, uid, context=None):
@ -71,7 +72,6 @@ class mail_mail(osv.Model):
_defaults = {
'state': 'outgoing',
'email_from': lambda self, cr, uid, ctx=None: self._get_default_from(cr, uid, ctx),
'user_signature': False,
}
def mark_outgoing(self, cr, uid, ids, context=None):
@ -145,19 +145,13 @@ class mail_mail(osv.Model):
ir_mail_server = self.pool.get('ir.mail_server')
for message in self.browse(cr, uid, ids, context=context):
try:
body = message.body
body = message.body_html
# handle attachments
attachments = []
for attach in message.attachment_ids:
attachments.append((attach.datas_fname, base64.b64decode(attach.datas)))
# add signature if flag set
if message.user_signature:
signature = message.author_id and message.author_id.user_ids[0].signature or ''
insertion_point = body.find('</html>')
body = body[:insertion_point] + signature + body[:insertion_point]
# no subject, res_id, model: '<Author> posted on <Resource>'
if not message.subject and message.model and message.res_id:
subject = '%s posted on %s' % (message.author_id.name, message.record_name)
@ -171,11 +165,11 @@ class mail_mail(osv.Model):
# build an RFC2822 email.message.Message object and send it
# without queuing
msg = ir_mail_server.build_email(
email_from = message.email_from,
email_to = tools.email_split(message.email_to),
subject = subject,
body = body,
body_alternative = body_alternative,
email_from = message.email_from,
email_to = tools.email_split(message.email_to),
email_cc = tools.email_split(message.email_cc),
reply_to = message.reply_to,
attachments = attachments,

View File

@ -29,7 +29,7 @@
</group>
<notebook>
<page string="Body">
<field name="body"/>
<field name="body_html"/>
</page>
</notebook>
</page>

View File

@ -63,9 +63,16 @@ Content-Transfer-Encoding: quoted-printable
------=_Part_4200734_24778174.1344608186754--
"""
class test_mail(common.TransactionCase):
def _mock_smtp_gateway(self, *args, **kwargs):
return True
def _mock_build_email(self, *args, **kwargs):
self._build_email_args = args
self._build_email_kwargs = kwargs
return self.build_email_real(*args, **kwargs)
def setUp(self):
super(test_mail, self).setUp()
self.ir_model = self.registry('ir.model')
@ -80,7 +87,9 @@ class test_mail(common.TransactionCase):
self.res_partner = self.registry('res.partner')
# Install mock SMTP gateway
self.registry('ir.mail_server').send_email = lambda *a,**kwargs: True
self.build_email_real = self.registry('ir.mail_server').build_email
self.registry('ir.mail_server').build_email = self._mock_build_email
self.registry('ir.mail_server').send_email = self._mock_smtp_gateway
# groups@.. will cause the creation of new mail groups
self.mail_group_model_id = self.ir_model.search(self.cr, self.uid, [('model','=', 'mail.group')])[0]
@ -234,77 +243,191 @@ class test_mail(common.TransactionCase):
self.assertTrue(all(id in follower_ids for id in [user_admin.partner_id.id]),
'Admin the only Pigs group followers')
def test_20_message_post_and_compose(self):
""" Tests designed for message_post and the mail.compose.message wizard. """
def test_20_message_post(self):
""" Tests designed for message_post. """
cr, uid = self.cr, self.uid
self.res_users.write(cr, uid, [uid], {'signature': 'Admin', 'email': 'a@a'})
user_admin = self.res_users.browse(cr, uid, uid)
group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id)
# 0 - Admin
p_a_id = user_admin.partner_id.id
# 1 - Bert Tartopoils, with email, should receive emails for comments and emails
p_b_id = self.res_partner.create(cr, uid, {'name': 'Bert Tartopoils', 'email': 'b@b'})
# 2 - Carine Poilvache, with email, should never receive emails
p_c_id = self.res_partner.create(cr, uid, {'name': 'Carine Poilvache', 'email': 'c@c', 'notification_email_send': 'email'})
# 3 - Dédé Grosbedon, without email, to test email verification; should receive emails for every message
p_d_id = self.res_partner.create(cr, uid, {'name': 'Dédé Grosbedon', 'notification_email_send': 'all'})
# Subscribe #1, #2
group_pigs.message_subscribe([p_b_id, p_c_id])
# Mail data
_subject = 'Pigs'
_mail_subject = '%s posted on %s' % (user_admin.name, group_pigs.name)
_body1 = 'Pigs rules'
_mail_body1 = 'Pigs rules<div>Admin</div>'
_mail_bodyalt1 = 'Pigs rules\nAdmin'
_body2 = '<html>Pigs rules</html>'
_mail_body2 = '<html>Pigs rules<div>Admin</div></html>'
_mail_bodyalt2 = 'Pigs rules\nAdmin'
# Post comment with body and subject, comment preference
msg_id = self.mail_group.message_post(cr, uid, self.group_pigs_id, body=_body1, subject=_subject, msg_type='comment')
# Fetch: created mail_message, mail_mail, send_email
message = self.mail_message.browse(cr, uid, msg_id)
mail_ids = self.mail_mail.search(cr, uid, [], limit=1)
mail = self.mail_mail.browse(cr, uid, mail_ids[0])
send_email = self._build_email_kwargs
# Test: mail_message: subject is _subject, body is _body1 (no formatting done)
self.assertEqual(message.subject, _subject,
'mail.message subject is %s; should be %s' % (message.subject, _subject))
self.assertEqual(message.body, _body1,
'mail.message body is %s; should be %s' % (message.body, _body1))
# Test: mail_mail: subject is _subject, body_html is _mail_body1 (signature appended)
self.assertEqual(mail.subject, _subject,
'mail.mail subject is %s; should be %s' % (mail.subject, _subject))
self.assertEqual(mail.body_html, _mail_body1,
'mail.mail body_html is %s; should be %s' % (mail.body_html, _mail_body1))
self.assertTrue(mail.mail_message_id and mail.mail_message_id.id == msg_id,
'mail_mail.mail_message_id is not the id of its related mail_message; got %s, should be %s' % (mail.mail_message_id.id, msg_id))
# Test: send_email: email send by server: correct subject and body
self.assertEqual(send_email['subject'], _subject,
'send_email subject is %s; should be %s' % (send_email['subject'], _subject))
self.assertEqual(send_email['body'], _mail_body1,
'send_email body is %s; should be %s' % (send_email['body'], _mail_body1))
self.assertEqual(send_email['body_alternative'], _mail_bodyalt1,
'send_email body_alternative is %s; should be %s' % (send_email['body_alternative'], _mail_bodyalt1))
# Test: mail_message: partner_ids = group followers
message_pids = [partner.id for partner in message.partner_ids]
test_pids = [p_a_id, p_b_id, p_c_id]
self.assertTrue(all(pid in message_pids for pid in test_pids) and len(message_pids) == len(test_pids),
'mail.message partners are %s; should be %s' % (message_pids, test_pids))
# Test: notification linked to this message = group followers = partner_ids
notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', message.id)])
notif_pids = [notif.partner_id.id for notif in self.mail_notification.browse(cr, uid, notif_ids)]
self.assertTrue(all(pid in notif_pids for pid in test_pids) and len(notif_pids) == len(test_pids),
'mail.message notification partners are %s; should be %s' % (notif_pids, test_pids))
# Test: send_email: email_to should contain b@b, not c@c (pref email), not a@a (writer)
test_emails = ['b@b']
self.assertTrue(all(email in send_email['email_to'] for email in test_emails) and len(send_email['email_to']) == len(test_emails),
'send_email email_to is %s; should be %s' % (send_email['email_to'], test_emails))
# New post: test automatic subject, signature in html, add a partner, email preference, parent_id previous message
msg_id2 = self.mail_group.message_post(cr, uid, self.group_pigs_id, body=_body2, msg_type='email', partner_ids=[(6, 0, [p_d_id])], parent_id=msg_id)
# Fetch: created mail_message, mail_mail, send_email
message = self.mail_message.browse(cr, uid, msg_id2)
mail_ids = self.mail_mail.search(cr, uid, [], limit=1)
mail = self.mail_mail.browse(cr, uid, mail_ids[0])
send_email = self._build_email_kwargs
# Test: mail_message: subject is False, body is _body1 (no formatting done), parent_id is msg_id
self.assertEqual(message.subject, False,
'mail.message subject is %s; should be %s' % (message.subject, False))
self.assertEqual(message.body, _body2,
'mail.message body is %s; should be %s' % (message.body, _body2))
self.assertEqual(message.parent_id.id, msg_id,
'mail.message parent_id is %s; should be %s' % (message.parent_id.id, msg_id))
# Test: mail_mail: subject is False, body_html is _mail_body1 (signature appended)
self.assertEqual(mail.subject, False,
'mail.mail subject is %s; should be %s' % (mail.subject, False))
self.assertEqual(mail.body_html, _mail_body2,
'mail.mail body_html is %s; should be %s' % (mail.body_html, _mail_body2))
self.assertTrue(mail.mail_message_id and mail.mail_message_id.id == msg_id2,
'mail_mail.mail_message_id is not the id of its related mail_message; got %s, should be %s' % (mail.mail_message_id.id, msg_id2))
# Test: send_email: email send by server: correct subject and body
self.assertEqual(send_email['subject'], _mail_subject,
'send_email subject is %s; should be %s' % (send_email['subject'], _mail_subject))
self.assertEqual(send_email['body'], _mail_body2,
'send_email body is %s; should be %s' % (send_email['body'], _mail_body2))
self.assertEqual(send_email['body_alternative'], _mail_bodyalt2,
'send_email body_alternative is %s; should be %s' % (send_email['body_alternative'], _mail_bodyalt2))
# Test: mail_message: partner_ids = group followers
message_pids = [partner.id for partner in message.partner_ids]
test_pids = [p_a_id, p_b_id, p_c_id, p_d_id]
self.assertTrue(all(pid in message_pids for pid in test_pids) and len(message_pids) == len(test_pids),
'mail.message partners are %s; should be %s' % (message_pids, test_pids))
# Test: notification linked to this message = group followers = partner_ids
notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', message.id)])
notif_pids = [notif.partner_id.id for notif in self.mail_notification.browse(cr, uid, notif_ids)]
self.assertTrue(all(pid in notif_pids for pid in test_pids) and len(notif_pids) == len(test_pids),
'mail.message notification partners are %s; should be %s' % (notif_pids, test_pids))
# Test: send_email: email_to should contain b@b, c@c, not a@a (writer)
test_emails = ['b@b', 'c@c']
self.assertTrue(all(email in send_email['email_to'] for email in test_emails) and len(send_email['email_to']) == len(test_emails),
'send_email email_to is %s; should be %s' % (send_email['email_to'], test_emails))
def test_21_message_post_attachments(self):
""" Tests designed for attachments. """
def test_22_message_compose_wizard(self):
""" Tests designed for the mail.compose.message wizard. """
cr, uid = self.cr, self.uid
mail_compose = self.registry('mail.compose.message')
self.res_users.write(cr, uid, [uid], {'signature': 'Admin', 'email': 'a@a'})
user_admin = self.res_users.browse(cr, uid, uid)
self.res_users.write(cr, uid, [uid], {'signature': 'Admin'})
user_admin.refresh()
group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id)
# Mail data
_subject = 'Pigs'
_mail_subject = '%s posted a comment on %s' % (user_admin.name, group_pigs.name)
_mail_subject = '%s posted on %s' % (user_admin.name, group_pigs.name)
_body_text = 'Pigs rules'
_body_html = '<b>Pigs</b> rules'
_msg_body1 = '<pre>Pigs rules</pre>'
_body_html = '<html>Pigs rules</html>'
_msg_body2 = '<html>Pigs rules</html>'
# Create partners
# 0 - Create an email address for Admin, to check email sending
self.res_users.write(cr, uid, [uid], {'email': 'a@a'})
# 0 - Admin
p_a_id = user_admin.partner_id.id
# 1 - Bert Tartopoils, with email, should receive emails for comments and emails
partner_bert_id = self.res_partner.create(cr, uid, {'name': 'Bert Tartopoils', 'email': 'b@b'})
# 2 - Raoul Grosbedon, without email, to test email verification; should receive emails for every message
partner_raoul_id = self.res_partner.create(cr, uid, {'name': 'Raoul Grosbedon', 'notification_email_send': 'all'})
# 3 - Roger Poilvache, with email, should never receive emails
partner_roger_id = self.res_partner.create(cr, uid, {'name': 'Roger Poilvache', 'email': 'r@r', 'notification_email_send': 'none'})
p_b_id = self.res_partner.create(cr, uid, {'name': 'Bert Tartopoils', 'email': 'b@b'})
# 2 - Carine Poilvache, with email, should never receive emails
p_c_id = self.res_partner.create(cr, uid, {'name': 'Carine Poilvache', 'email': 'c@c', 'notification_email_send': 'email'})
# 3 - Dédé Grosbedon, without email, to test email verification; should receive emails for every message
p_d_id = self.res_partner.create(cr, uid, {'name': 'Dédé Grosbedon', 'notification_email_send': 'all'})
# Create a new comment on group_pigs
# Subscribe #1
group_pigs.message_subscribe([p_b_id])
# Comment group_pigs: body_text
compose_id = mail_compose.create(cr, uid,
{'subject': _subject, 'body_text': _body_text, 'partner_ids': [(4, partner_bert_id), (4, partner_raoul_id), (4, partner_roger_id)]},
{'mail.compose.message': 'comment', 'default_model': 'mail.group', 'default_res_id': self.group_pigs_id})
{'subject': _subject, 'body_text': _body_text, 'partner_ids': [(4, p_c_id), (4, p_d_id)]},
{'mail.compose.message.mode': 'comment', 'default_model': 'mail.group', 'default_res_id': self.group_pigs_id})
compose = mail_compose.browse(cr, uid, compose_id)
# Test: model, res_id
self.assertTrue(compose.model == 'mail.group' and compose.res_id == self.group_pigs_id,
'Wizard message has model %s and res_id %s; should be mail.group and %s' % (compose.model, compose.res_id, self.group_pigs_id))
'mail.compose.message has model %s and res_id %s; should be mail.group and %s' % (compose.model, compose.res_id, self.group_pigs_id))
# Post the comment, get created message
mail_compose.send_mail(cr, uid, [compose_id])
group_pigs.refresh()
first_com = group_pigs.message_ids[0]
msg = group_pigs.message_ids[0]
# Check message content
self.assertTrue(first_com.subject == False and first_com.body == _body_text,
'Posted comment subject is %s and body is %s; should be False and %s' % (first_com.subject, first_com.body, _body_text))
# Message partners = notified people = writer + partner_ids
first_com_pids = [partner.id for partner in first_com.partner_ids]
notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', first_com.id)])
self.assertTrue(len(first_com_pids) == 4, 'There are %s partners linked to the newly posted comment; should be 4' % (len(first_com_pids)))
# Test: mail.message: subject, body inside pre
self.assertTrue(msg.subject == False and msg.body == _msg_body1,
'mail.message subject is %s, body is %s; should be %s and %s' % (msg.subject, msg.body, False, _msg_body1))
# Test: mail.message partners = notified people: group_pigs followers (a, b) + mail.compose.message partner_ids (c, d)
msg_pids = [partner.id for partner in msg.partner_ids]
test_pids = [p_a_id, p_b_id, p_c_id, p_d_id]
notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', msg.id)])
self.assertTrue(len(msg_pids) == 4, 'There are %s partners linked to the newly posted comment; should be 4' % (len(msg_pids)))
self.assertTrue(len(notif_ids) == 4, 'There are %s entries in mail_notification: should be 4' % (len(notif_ids)))
self.assertTrue(all(id in [user_admin.partner_id.id, partner_bert_id, partner_raoul_id, partner_roger_id] for id in first_com_pids),
self.assertTrue(all(id in msg_pids for id in test_pids) and len(msg_pids) == len(test_pids),
'Admin, Bert Raoul and Roger should be the 4 partners of the newly created message')
# Fetch latest created email, that should be the email send to partners
mail_ids = self.mail_mail.search(cr, uid, [], limit=1)
mail = self.mail_mail.browse(cr, uid, mail_ids[0])
mail_emails = tools.email_split(mail.email_to)
# Check email subject, body, and email_to
expected_emails = ['a@a', 'b@b']
self.assertTrue(mail.subject == _mail_subject and _body_text in mail.body,
'Send email subject is \'%s\' and should be %s; body is %s and should contain %s' % (mail.subject, _mail_subject, mail.body, _body_text))
self.assertTrue(all(email in mail_emails for email in expected_emails) and len(mail_emails) == 2,
'Send email emails are %s; should be %s' % (mail_emails, expected_emails))
# Create a reply to the last comment
compose_id = mail_compose.create(cr, uid,
{}, {'mail.compose.message.mode': 'reply', 'default_model': 'mail.thread', 'default_res_id': self.group_pigs_id,
'active_id': first_com.id})
'active_id': msg.id})
compose = mail_compose.browse(cr, uid, compose_id)
# Test: model, res_id, parent_id
self.assertTrue(compose.model == 'mail.group' and compose.res_id == self.group_pigs_id,
'Wizard message has model: %s and res_id:%s; should be mail.group and %s' % (compose.model, compose.res_id, self.group_pigs_id))
self.assertTrue(compose.parent_id.id == first_com.id,
'Wizard parent_id is %d; should be %d' % (compose.parent_id.id, first_com.id))
self.assertEqual(compose.parent_id.id, msg.id,
'Wizard parent_id is %d; should be %d' % (compose.parent_id.id, msg.id))
def test_30_message_read(self):
""" Tests designed for message_read. """
@ -442,5 +565,3 @@ class test_mail(common.TransactionCase):
msg1.refresh()
self.assertEqual(5, len(group_pigs.message_ids), 'group should contain 5 messages')
self.assertEqual(2, len(msg1.child_ids), 'msg1 should have 2 children now')

View File

@ -20,8 +20,8 @@
##############################################################################
import re
import tools
from osv import osv
from osv import fields
from tools.safe_eval import safe_eval as eval
@ -232,7 +232,7 @@ class mail_compose_message(osv.TransientModel):
# default values, according to the wizard options
subject = wizard.subject if wizard.content_subtype == 'html' else False
partner_ids = [(4, partner.id) for partner in wizard.partner_ids]
body = wizard.body if wizard.content_subtype == 'html' else wizard.body_text
body = wizard.body if wizard.content_subtype == 'html' else '<pre>%s</pre>' % tools.ustr(wizard.body_text)
active_model_pool = self.pool.get(wizard.model if wizard.model else 'mail.thread')