summaryrefslogtreecommitdiff
path: root/addons/mail
diff options
context:
space:
mode:
authorsgo@tinyerp.com <>2013-06-05 12:49:05 +0530
committersgo@tinyerp.com <>2013-06-05 12:49:05 +0530
commit6a3cdf718ce4f9bd2749bb75993cdbcfd86d3eb2 (patch)
tree075af0421f75fd36ca9f5cd44551e58ffc73460a /addons/mail
parent143b485baf8adb7936d7784e314ccd405d1b8c14 (diff)
parent5cc8c30adfeccc6db22ebf7487b8e4ebdbe10423 (diff)
[MERGE]sync with trunk
bzr revid: sgo@tinyerp.com-20130605071905-o2ldzc6vxqnoe099
Diffstat (limited to 'addons/mail')
-rw-r--r--addons/mail/data/mail_data.xml6
-rw-r--r--addons/mail/html/index.html178
-rw-r--r--addons/mail/html/mail_illustration.pngbin0 -> 34110 bytes
-rw-r--r--addons/mail/html/mail_sc_00.pngbin0 -> 71427 bytes
-rw-r--r--addons/mail/html/mail_sc_01.pngbin0 -> 23632 bytes
-rw-r--r--addons/mail/html/mail_sc_02.pngbin0 -> 27486 bytes
-rw-r--r--addons/mail/html/mail_sc_03.pngbin0 -> 21784 bytes
-rw-r--r--addons/mail/html/mail_sc_04.pngbin0 -> 92888 bytes
-rw-r--r--addons/mail/html/mail_sc_05.pngbin0 -> 27375 bytes
-rw-r--r--addons/mail/html/mail_sc_06.pngbin0 -> 27375 bytes
-rw-r--r--addons/mail/html/mail_sc_07.pngbin0 -> 100179 bytes
-rw-r--r--addons/mail/html/photo.pngbin0 -> 6289 bytes
-rw-r--r--addons/mail/i18n/ko.po1687
-rw-r--r--addons/mail/mail_alias.py14
-rw-r--r--addons/mail/mail_followers.py15
-rw-r--r--addons/mail/mail_mail.py118
-rw-r--r--addons/mail/mail_mail_view.xml5
-rw-r--r--addons/mail/mail_message.py26
-rw-r--r--addons/mail/mail_message_view.xml3
-rw-r--r--addons/mail/mail_thread.py100
-rw-r--r--addons/mail/mail_thread_view.xml16
-rw-r--r--addons/mail/res_config.py3
-rw-r--r--addons/mail/res_users_view.xml2
-rwxr-xr-x[-rw-r--r--]addons/mail/static/scripts/openerp_mailgate.py0
-rw-r--r--addons/mail/static/src/css/mail.css11
-rw-r--r--[-rwxr-xr-x]addons/mail/static/src/img/email_icon.pngbin924 -> 924 bytes
-rw-r--r--addons/mail/static/src/js/mail.js62
-rw-r--r--addons/mail/static/src/xml/mail.xml4
-rw-r--r--addons/mail/static/src/xml/mail_followers.xml2
-rw-r--r--addons/mail/tests/test_mail_features.py131
-rw-r--r--addons/mail/tests/test_mail_gateway.py103
-rw-r--r--addons/mail/wizard/invite.py2
32 files changed, 2369 insertions, 119 deletions
diff --git a/addons/mail/data/mail_data.xml b/addons/mail/data/mail_data.xml
index 02cfd626768..4e935e4aa88 100644
--- a/addons/mail/data/mail_data.xml
+++ b/addons/mail/data/mail_data.xml
@@ -40,6 +40,12 @@
<field name="args">()</field>
</record>
+ <!-- Catchall Email Alias -->
+ <record id="icp_mail_catchall_alias" model="ir.config_parameter">
+ <field name="key">mail.catchall.alias</field>
+ <field name="value">catchall</field>
+ </record>
+
<!-- Discussion subtype for messaging / Chatter -->
<record id="mt_comment" model="mail.message.subtype">
<field name="name">Discussions</field>
diff --git a/addons/mail/html/index.html b/addons/mail/html/index.html
new file mode 100644
index 00000000000..b564cf3ab1e
--- /dev/null
+++ b/addons/mail/html/index.html
@@ -0,0 +1,178 @@
+<section class="oe_container">
+ <div class="oe_row oe_spaced">
+ <div class="oe_span12">
+ <h2 class="oe_slogan">Enterprise Social Network</h2>
+ <h3 class="oe_slogan">A private social network for your company</h3>
+ </div>
+ <div class="oe_span6">
+ <div class="oe_demo oe_picture oe_screenshot">
+ <a href="https://www.openerp.com/saas_master/demo?lang=en_US&module=crm">
+ <img src="mail_sc_00.png">
+ </a>
+ <div class="oe_demo_footer oe_centeralign">Online Demo</div>
+ </div>
+ </div>
+ <div class="oe_span6">
+ <p class="oe_mt32">
+Connect with experts, follow what interests you, share documents and promote
+best practices. Get work done with effective collaboration across departments,
+geographies, documents and business applications. All of this while decreasing
+email overload.
+
+ </p>
+ <div class="oe_centeralign oe_websiteonly">
+ <a href="http://www.openerp.com/start" class="oe_button oe_big oe_tacky">Start your <span class="oe_emph">free</span> trial</a>
+ </div>
+ </div>
+ </div>
+</section>
+
+<section class="oe_container oe_dark">
+ <div class="oe_row oe_spaced">
+ <h2 class="oe_slogan">Connect with experts</h2>
+ <h3 class="oe_slogan">Get the right information, when you need it</h3>
+ <div class="oe_span6">
+ <p class="oe_mt32">
+Next time you have a question for the marketing, sales, R&amp;D or any other
+department, don't send an email blast-post the question to OpenERP and get
+answers from the right persons.
+ </p>
+ </div>
+ <div class="oe_span6">
+ <div class="oe_row_img oe_centered">
+ <img class="oe_picture oe_screenshot" src="mail_sc_01.png">
+ </div>
+ </div>
+ </div>
+</section>
+
+<section class="oe_container">
+ <div class="oe_row oe_spaced">
+ <h2 class="oe_slogan">Follow what interests you</h2>
+ <h3 class="oe_slogan">Make the information flow across your company</h3>
+ <div class="oe_span6">
+ <div class="oe_row_img oe_centered">
+ <img class="oe_picture" src="mail_sc_02.png">
+ </div>
+ </div>
+ <div class="oe_span6">
+ <p class="oe_mt32">
+Want to get informed about new product features, hot deals, bottlenecks in projects or any other event? Just follow what interests you to get the information you need what you need; no more, no less.
+ </p>
+ </div>
+ </div>
+</section>
+
+
+<section class="oe_container oe_dark">
+ <div class="oe_row oe_spaced">
+ <h2 class="oe_slogan">Get Things Done</h2>
+ <h3 class="oe_slogan">Your inbox is a todo list</h3>
+ <div class="oe_span6">
+ <p class="oe_mt32">
+You can process (not only read) the inbox and easily mark messages for future actions. Start feeling the pleasure of having an empty inbox every day; no more overload of information.
+ </p>
+ </div>
+ <div class="oe_span6">
+ <div class="oe_row_img oe_centered">
+ <img class="oe_picture oe_screenshot" src="mail_sc_03.png">
+ </div>
+ </div>
+ </div>
+</section>
+
+<section class="oe_container">
+ <div class="oe_row oe_spaced">
+ <h2 class="oe_slogan">Promote best practices</h2>
+ <h3 class="oe_slogan">Discussion groups at your fingertips</h3>
+ <div class="oe_span6">
+ <div class="oe_row_img oe_centered">
+ <img class="oe_picture oe_screenshot" src="mail_sc_04.png">
+ </div>
+ </div>
+ <div class="oe_span6">
+ <p class="oe_mt32">
+Cut back on meetings and email chains by working together in groups of interests. Create a group to let people share files, discuss ideas, and vote to promote best practices.
+ </p>
+ </div>
+ </div>
+</section>
+
+<section class="oe_container oe_dark">
+ <div class="oe_row oe_spaced">
+ <h2 class="oe_slogan">Improve Access to Information and Expertise</h2>
+ <h3 class="oe_slogan">Easily find the information you need</h3>
+ <div class="oe_span6">
+ <p class="oe_mt32">
+Break down information silos. Search across your existing systems to find the answers and expertise you need to complete projects quickly.
+ </p>
+ </div>
+ <div class="oe_span6">
+ <div class="oe_row_img oe_centered">
+ <img class="oe_picture oe_screenshot" src="mail_illustration.png">
+ </div>
+ </div>
+ </div>
+</section>
+
+<section class="oe_container">
+ <div class="oe_row oe_spaced">
+ <h2 class="oe_slogan">Collaborate securely</h2>
+ <div class="oe_span6">
+ <div class="oe_row_img oe_centered">
+ <img class="oe_picture oe_screenshot" src="mail_sc_06.png">
+ </div>
+ </div>
+ <div class="oe_span6">
+ <p class="oe_mt32">
+Set the right security policy; public, private or on invitation only -- according to the information sensitivity.
+ </p>
+ </div>
+ </div>
+</section>
+
+
+<section class="oe_container oe_dark">
+ <div class="oe_row oe_spaced">
+ <h2 class="oe_slogan">A Twitter-like Network For Your Company </h2>
+ <div class="oe_span6">
+ <p class="oe_mt32">
+Make every employee feel more connected and engaged with twitter-like features
+for your own company. Follow people, share best practices, 'like' top ideas, etc.
+ </p>
+ </div>
+ <div class="oe_span6">
+ <div class="oe_row_img oe_centered">
+ <img class="oe_picture oe_screenshot" src="mail_sc_07.png">
+ </div>
+ </div>
+ </div>
+</section>
+
+
+<section class="oe_container">
+ <div class="oe_row">
+ <div class="oe_span12">
+ <h2 class="oe_slogan">Trusted by millions worldwide</h2>
+ </div>
+ <div class="oe_span12">
+ <div class="oe_quote">
+ <q>
+ Emails make me waste my time. But I need them. Reading my inbox
+ is the most unproductive task I do on a daily basis. I have to
+ spend one or two full hours a day to process my emails. All the
+ junk flows in the same inbox; spams, information that doesn't
+ matter, quoted answers of quoted answers, etc. At the end of
+ the hour, only 10 emails actually requested an answer from me.
+ Since I use OpenERP, I can do the same job in only 10 minutes!
+ </q>
+ <cite class="oe_cite oe_clearfix">
+ <img class="oe_photo" src="photo.png">
+ <div class="oe_author">Luc de Keyser</div>
+ </cite>
+ </div>
+ </div>
+ </div>
+</section>
+<section class="oe_container oe_separator">
+</section>
diff --git a/addons/mail/html/mail_illustration.png b/addons/mail/html/mail_illustration.png
new file mode 100644
index 00000000000..4fff4837faa
--- /dev/null
+++ b/addons/mail/html/mail_illustration.png
Binary files differ
diff --git a/addons/mail/html/mail_sc_00.png b/addons/mail/html/mail_sc_00.png
new file mode 100644
index 00000000000..3011ef129b5
--- /dev/null
+++ b/addons/mail/html/mail_sc_00.png
Binary files differ
diff --git a/addons/mail/html/mail_sc_01.png b/addons/mail/html/mail_sc_01.png
new file mode 100644
index 00000000000..1b1099f6536
--- /dev/null
+++ b/addons/mail/html/mail_sc_01.png
Binary files differ
diff --git a/addons/mail/html/mail_sc_02.png b/addons/mail/html/mail_sc_02.png
new file mode 100644
index 00000000000..4e59c9d1e0f
--- /dev/null
+++ b/addons/mail/html/mail_sc_02.png
Binary files differ
diff --git a/addons/mail/html/mail_sc_03.png b/addons/mail/html/mail_sc_03.png
new file mode 100644
index 00000000000..dbb14b4da36
--- /dev/null
+++ b/addons/mail/html/mail_sc_03.png
Binary files differ
diff --git a/addons/mail/html/mail_sc_04.png b/addons/mail/html/mail_sc_04.png
new file mode 100644
index 00000000000..b8f47ba2935
--- /dev/null
+++ b/addons/mail/html/mail_sc_04.png
Binary files differ
diff --git a/addons/mail/html/mail_sc_05.png b/addons/mail/html/mail_sc_05.png
new file mode 100644
index 00000000000..251b4ebc676
--- /dev/null
+++ b/addons/mail/html/mail_sc_05.png
Binary files differ
diff --git a/addons/mail/html/mail_sc_06.png b/addons/mail/html/mail_sc_06.png
new file mode 100644
index 00000000000..251b4ebc676
--- /dev/null
+++ b/addons/mail/html/mail_sc_06.png
Binary files differ
diff --git a/addons/mail/html/mail_sc_07.png b/addons/mail/html/mail_sc_07.png
new file mode 100644
index 00000000000..9a33332817e
--- /dev/null
+++ b/addons/mail/html/mail_sc_07.png
Binary files differ
diff --git a/addons/mail/html/photo.png b/addons/mail/html/photo.png
new file mode 100644
index 00000000000..e605e5c6f8e
--- /dev/null
+++ b/addons/mail/html/photo.png
Binary files differ
diff --git a/addons/mail/i18n/ko.po b/addons/mail/i18n/ko.po
new file mode 100644
index 00000000000..6315792f4fc
--- /dev/null
+++ b/addons/mail/i18n/ko.po
@@ -0,0 +1,1687 @@
+# Korean translation for openobject-addons
+# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2012-12-21 17:04+0000\n"
+"PO-Revision-Date: 2013-05-12 07:37+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Korean <ko@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2013-05-13 05:17+0000\n"
+"X-Generator: Launchpad (build 16614)\n"
+
+#. module: mail
+#: view:mail.followers:0
+msgid "Followers Form"
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_publisher_warranty_contract
+msgid "publisher_warranty.contract"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,author_id:0
+#: field:mail.message,author_id:0
+msgid "Author"
+msgstr "작성자"
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Message Details"
+msgstr ""
+
+#. module: mail
+#: help:mail.mail,email_to:0
+msgid "Message recipients"
+msgstr ""
+
+#. module: mail
+#: help:mail.message.subtype,default:0
+msgid "Activated by default when subscribing."
+msgstr ""
+
+#. module: mail
+#: view:mail.message:0
+msgid "Comments"
+msgstr ""
+
+#. module: mail
+#: view:mail.alias:0
+#: view:mail.mail:0
+msgid "Group By..."
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,body:0
+#: help:mail.message,body:0
+msgid "Automatically sanitized HTML contents"
+msgstr ""
+
+#. module: mail
+#: help:mail.alias,alias_name:0
+msgid ""
+"The name of the email alias, e.g. 'jobs' if you want to catch emails for "
+"<jobs@example.my.openerp.com>"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.act_window,name:mail.action_email_compose_message_wizard
+#: view:mail.compose.message:0
+msgid "Compose Email"
+msgstr "메일 작성"
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:132
+#, python-format
+msgid "Add them into recipients and followers"
+msgstr ""
+
+#. module: mail
+#: view:mail.group:0
+msgid "Group Name"
+msgstr "그룹명"
+
+#. module: mail
+#: selection:mail.group,public:0
+msgid "Public"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Body"
+msgstr "본문"
+
+#. module: mail
+#: view:mail.message:0
+msgid "Show messages to read"
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,email_from:0
+#: help:mail.message,email_from:0
+msgid ""
+"Email address of the sender. This field is set when no matching partner is "
+"found for incoming emails."
+msgstr "보내는 사람의 이메일 주소. 이 필드는 수신 메일에서 일치하는 파트너를 찾을 수 없을 때 설정됩니다."
+
+#. module: mail
+#: model:ir.model,name:mail.model_mail_compose_message
+msgid "Email composition wizard"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail_followers.xml:23
+#, python-format
+msgid "Add others"
+msgstr ""
+
+#. module: mail
+#: field:mail.message.subtype,parent_id:0
+msgid "Parent"
+msgstr ""
+
+#. module: mail
+#: field:mail.group,message_unread:0
+#: field:mail.thread,message_unread:0
+#: field:res.partner,message_unread:0
+msgid "Unread Messages"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:296
+#, python-format
+msgid "show"
+msgstr ""
+
+#. module: mail
+#: help:mail.group,group_ids:0
+msgid ""
+"Members of those groups will automatically added as followers. Note that "
+"they will be able to manage their subscription manually if necessary."
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/js/mail.js:1019
+#, python-format
+msgid "Do you really want to delete this message?"
+msgstr ""
+
+#. module: mail
+#: view:mail.message:0
+#: field:mail.notification,read:0
+msgid "Read"
+msgstr ""
+
+#. module: mail
+#: view:mail.group:0
+msgid "Search Groups"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/js/mail_followers.js:159
+#, python-format
+msgid "followers"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/mail_message.py:726
+#, python-format
+msgid "Access Denied"
+msgstr ""
+
+#. module: mail
+#: help:mail.group,image_medium:0
+msgid ""
+"Medium-sized photo of the group. It is automatically resized as a 128x128px "
+"image, with aspect ratio preserved. Use this field in form views or some "
+"kanban views."
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:212
+#, python-format
+msgid "Uploading error"
+msgstr ""
+
+#. module: mail
+#: model:mail.group,name:mail.group_support
+msgid "Support"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/mail_message.py:727
+#, python-format
+msgid ""
+"The requested operation cannot be completed due to security restrictions. "
+"Please contact your system administrator.\n"
+"\n"
+"(Document type: %s, Operation: %s)"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+#: selection:mail.mail,state:0
+msgid "Received"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Thread"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:29
+#, python-format
+msgid "Open the full mail composer"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:29
+#, python-format
+msgid "&ograve"
+msgstr ""
+
+#. module: mail
+#: field:base.config.settings,alias_domain:0
+msgid "Alias Domain"
+msgstr ""
+
+#. module: mail
+#: field:mail.group,group_ids:0
+msgid "Auto Subscription"
+msgstr ""
+
+#. module: mail
+#: field:mail.mail,references:0
+msgid "References"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:206
+#, python-format
+msgid "No messages."
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_mail_group
+msgid "Discussion group"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:98
+#: code:addons/mail/static/src/xml/mail.xml:110
+#, python-format
+msgid "uploading"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail_followers.xml:52
+#, python-format
+msgid "more."
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,type:0
+#: help:mail.message,type:0
+msgid ""
+"Message type: email for email message, notification for system message, "
+"comment for other messages such as user replies"
+msgstr ""
+
+#. module: mail
+#: help:mail.message.subtype,relation_field:0
+msgid ""
+"Field used to link the related model to the subtype model when using "
+"automatic subscription on a related document. The field is used to compute "
+"getattr(related_document.relation_field)."
+msgstr ""
+
+#. module: mail
+#: selection:mail.mail,state:0
+msgid "Cancelled"
+msgstr ""
+
+#. module: mail
+#: field:mail.mail,reply_to:0
+msgid "Reply-To"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/wizard/invite.py:37
+#, python-format
+msgid "<div>You have been invited to follow %s.</div>"
+msgstr ""
+
+#. module: mail
+#: help:mail.group,message_unread:0
+#: help:mail.thread,message_unread:0
+#: help:res.partner,message_unread:0
+msgid "If checked new messages require your attention."
+msgstr ""
+
+#. module: mail
+#: field:mail.group,image_medium:0
+msgid "Medium-sized photo"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.client,name:mail.action_mail_to_me_feeds
+#: model:ir.ui.menu,name:mail.mail_tomefeeds
+msgid "To: me"
+msgstr ""
+
+#. module: mail
+#: field:mail.message.subtype,name:0
+msgid "Message Type"
+msgstr ""
+
+#. module: mail
+#: field:mail.mail,auto_delete:0
+msgid "Auto Delete"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail_followers.xml:12
+#: view:mail.group:0
+#, python-format
+msgid "Unfollow"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:295
+#, python-format
+msgid "show one more message"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/mail_mail.py:74
+#: code:addons/mail/res_users.py:69
+#, python-format
+msgid "Invalid Action!"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:25
+#, python-format
+msgid "User img"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.act_window,name:mail.action_view_mail_mail
+#: model:ir.ui.menu,name:mail.menu_mail_mail
+#: view:mail.mail:0
+#: view:mail.message:0
+msgid "Emails"
+msgstr ""
+
+#. module: mail
+#: field:mail.followers,partner_id:0
+msgid "Related Partner"
+msgstr ""
+
+#. module: mail
+#: help:mail.group,message_summary:0
+#: help:mail.thread,message_summary:0
+#: help:res.partner,message_summary:0
+msgid ""
+"Holds the Chatter summary (number of messages, ...). This summary is "
+"directly in html format in order to be inserted in kanban views."
+msgstr ""
+
+#. module: mail
+#: help:mail.alias,alias_model_id:0
+msgid ""
+"The model (OpenERP Document Kind) to which this alias corresponds. Any "
+"incoming email that does not reply to an existing record will cause the "
+"creation of a new record of this model (e.g. a Project Task)"
+msgstr ""
+
+#. module: mail
+#: field:mail.message.subtype,relation_field:0
+msgid "Relation field"
+msgstr ""
+
+#. module: mail
+#: selection:mail.compose.message,type:0
+#: selection:mail.message,type:0
+msgid "System notification"
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_res_partner
+#: view:mail.mail:0
+msgid "Partner"
+msgstr ""
+
+#. module: mail
+#: model:ir.ui.menu,name:mail.mail_my_stuff
+msgid "Organizer"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,subject:0
+#: field:mail.message,subject:0
+msgid "Subject"
+msgstr ""
+
+#. module: mail
+#: field:mail.wizard.invite,partner_ids:0
+msgid "Partners"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Retry"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,email_from:0
+#: field:mail.mail,email_from:0
+#: field:mail.message,email_from:0
+msgid "From"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+#: view:mail.message.subtype:0
+msgid "Email message"
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_base_config_settings
+msgid "base.config.settings"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:36
+#: view:mail.compose.message:0
+#, python-format
+msgid "Send"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/js/mail_followers.js:155
+#, python-format
+msgid "No followers"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Failed"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail_followers.xml:22
+#: model:ir.actions.act_window,name:mail.action_view_followers
+#: model:ir.ui.menu,name:mail.menu_email_followers
+#: view:mail.followers:0
+#: field:mail.group,message_follower_ids:0
+#: field:mail.thread,message_follower_ids:0
+#: field:res.partner,message_follower_ids:0
+#, python-format
+msgid "Followers"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.client,name:mail.action_mail_archives_feeds
+#: model:ir.ui.menu,name:mail.mail_archivesfeeds
+msgid "Archives"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:97
+#: code:addons/mail/static/src/xml/mail.xml:109
+#, python-format
+msgid "Delete this attachment"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:245
+#: view:mail.mail:0
+#, python-format
+msgid "Reply"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/js/mail_followers.js:157
+#, python-format
+msgid "One follower"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,type:0
+#: field:mail.message,type:0
+msgid "Type"
+msgstr ""
+
+#. module: mail
+#: selection:mail.compose.message,type:0
+#: view:mail.mail:0
+#: selection:mail.message,type:0
+msgid "Email"
+msgstr ""
+
+#. module: mail
+#: field:ir.ui.menu,mail_group_id:0
+msgid "Mail Group"
+msgstr ""
+
+#. module: mail
+#: selection:res.partner,notification_email_send:0
+msgid "Comments and Emails"
+msgstr ""
+
+#. module: mail
+#: field:mail.alias,alias_defaults:0
+msgid "Default Values"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/res_users.py:89
+#, python-format
+msgid "%s has joined the %s network."
+msgstr ""
+
+#. module: mail
+#: help:mail.group,image_small:0
+msgid ""
+"Small-sized photo of the group. It is automatically resized as a 64x64px "
+"image, with aspect ratio preserved. Use this field anywhere a small image is "
+"required."
+msgstr ""
+
+#. module: mail
+#: view:mail.compose.message:0
+#: field:mail.message,partner_ids:0
+msgid "Recipients"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:142
+#, python-format
+msgid "<<<"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:43
+#, python-format
+msgid "Write to the followers of this document..."
+msgstr ""
+
+#. module: mail
+#: field:mail.group,group_public_id:0
+msgid "Authorized Group"
+msgstr ""
+
+#. module: mail
+#: view:mail.group:0
+msgid "Join Group"
+msgstr ""
+
+#. module: mail
+#: help:mail.mail,email_from:0
+msgid "Message sender, taken from user preferences."
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/wizard/invite.py:40
+#, python-format
+msgid "<div>You have been invited to follow a new document.</div>"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,parent_id:0
+#: field:mail.message,parent_id:0
+msgid "Parent Message"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,res_id:0
+#: field:mail.followers,res_id:0
+#: field:mail.message,res_id:0
+#: field:mail.wizard.invite,res_id:0
+msgid "Related Document ID"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.client,help:mail.action_mail_to_me_feeds
+msgid ""
+"<p>\n"
+" <b>No private message.</b>\n"
+" </p><p>\n"
+" This list contains messages sent to you.\n"
+" </p>\n"
+" "
+msgstr ""
+
+#. module: mail
+#: model:mail.group,name:mail.group_rd
+msgid "R&D"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:61
+#, python-format
+msgid "/web/binary/upload_attachment"
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_mail_thread
+msgid "Email Thread"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Advanced"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:244
+#, python-format
+msgid "Move to Inbox"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/wizard/mail_compose_message.py:165
+#, python-format
+msgid "Re:"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,to_read:0
+#: field:mail.message,to_read:0
+msgid "To read"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/res_users.py:69
+#, python-format
+msgid ""
+"You may not create a user. To create new users, you should use the "
+"\"Settings > Users\" menu."
+msgstr ""
+
+#. module: mail
+#: help:mail.followers,res_model:0
+#: help:mail.wizard.invite,res_model:0
+msgid "Model of the followed resource"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:320
+#, python-format
+msgid "like"
+msgstr ""
+
+#. module: mail
+#: view:mail.compose.message:0
+#: view:mail.wizard.invite:0
+msgid "Cancel"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:47
+#, python-format
+msgid "Share with my followers..."
+msgstr ""
+
+#. module: mail
+#: field:mail.notification,partner_id:0
+msgid "Contact"
+msgstr ""
+
+#. module: mail
+#: view:mail.group:0
+msgid ""
+"Only the invited followers can read the\n"
+" discussions on this group."
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_ir_ui_menu
+msgid "ir.ui.menu"
+msgstr ""
+
+#. module: mail
+#: view:mail.message:0
+msgid "Has attachments"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "on"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/mail_message.py:915
+#, python-format
+msgid ""
+"The following partners chosen as recipients for the email have no email "
+"address linked :"
+msgstr ""
+
+#. module: mail
+#: help:mail.alias,alias_defaults:0
+msgid ""
+"A Python dictionary that will be evaluated to provide default values when "
+"creating new records for this alias."
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_mail_message_subtype
+msgid "Message subtypes"
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,notified_partner_ids:0
+#: help:mail.message,notified_partner_ids:0
+msgid ""
+"Partners that have a notification pushing this message in their mailboxes"
+msgstr ""
+
+#. module: mail
+#: selection:mail.compose.message,type:0
+#: view:mail.mail:0
+#: selection:mail.message,type:0
+msgid "Comment"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.client,help:mail.action_mail_inbox_feeds
+msgid ""
+"<p>\n"
+" <b>Good Job!</b> Your inbox is empty.\n"
+" </p><p>\n"
+" Your inbox contains private messages or emails sent to "
+"you\n"
+" as well as information related to documents or people "
+"you\n"
+" follow.\n"
+" </p>\n"
+" "
+msgstr ""
+
+#. module: mail
+#: field:mail.mail,notification:0
+msgid "Is Notification"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:188
+#, python-format
+msgid "Compose a new message"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Send Now"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/mail_mail.py:74
+#, python-format
+msgid ""
+"Unable to send email, please configure the sender's email address or alias."
+msgstr ""
+
+#. module: mail
+#: help:res.users,alias_id:0
+msgid ""
+"Email address internally associated with this user. Incoming emails will "
+"appear in the user's notifications."
+msgstr ""
+
+#. module: mail
+#: field:mail.group,image:0
+msgid "Photo"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:56
+#: code:addons/mail/static/src/xml/mail.xml:191
+#: view:mail.compose.message:0
+#: view:mail.wizard.invite:0
+#, python-format
+msgid "or"
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,vote_user_ids:0
+#: help:mail.message,vote_user_ids:0
+msgid "Users that voted for this message"
+msgstr ""
+
+#. module: mail
+#: help:mail.group,alias_id:0
+msgid ""
+"The email address associated with this group. New emails received will "
+"automatically create new topics."
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Month"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Email Search"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,child_ids:0
+#: field:mail.message,child_ids:0
+msgid "Child Messages"
+msgstr ""
+
+#. module: mail
+#: field:mail.alias,alias_user_id:0
+msgid "Owner"
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_res_users
+msgid "Users"
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_mail_message
+#: field:mail.mail,mail_message_id:0
+#: view:mail.message:0
+#: field:mail.notification,message_id:0
+#: field:mail.wizard.invite,message:0
+msgid "Message"
+msgstr ""
+
+#. module: mail
+#: help:mail.followers,res_id:0
+#: help:mail.wizard.invite,res_id:0
+msgid "Id of the followed resource"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,body:0
+#: field:mail.message,body:0
+msgid "Contents"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.act_window,name:mail.action_view_mail_alias
+#: model:ir.ui.menu,name:mail.mail_alias_menu
+msgid "Aliases"
+msgstr ""
+
+#. module: mail
+#: help:mail.message.subtype,description:0
+msgid ""
+"Description that will be added in the message posted for this subtype. If "
+"void, the name will be added instead."
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,vote_user_ids:0
+#: field:mail.message,vote_user_ids:0
+msgid "Votes"
+msgstr ""
+
+#. module: mail
+#: view:mail.group:0
+msgid "Group"
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,starred:0
+#: help:mail.message,starred:0
+msgid "Current user has a starred notification linked to this message"
+msgstr ""
+
+#. module: mail
+#: field:mail.group,public:0
+msgid "Privacy"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Notification"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/js/mail.js:650
+#, python-format
+msgid "Please complete partner's informations"
+msgstr ""
+
+#. module: mail
+#: view:mail.wizard.invite:0
+msgid "Add Followers"
+msgstr ""
+
+#. module: mail
+#: view:mail.compose.message:0
+msgid "Followers of selected items and"
+msgstr ""
+
+#. module: mail
+#: field:mail.alias,alias_force_thread_id:0
+msgid "Record Thread ID"
+msgstr ""
+
+#. module: mail
+#: model:ir.ui.menu,name:mail.mail_group_root
+msgid "My Groups"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.client,help:mail.action_mail_archives_feeds
+msgid ""
+"<p>\n"
+" No message found and no message sent yet.\n"
+" </p><p>\n"
+" Click on the top-right icon to compose a message. This\n"
+" message will be sent by email if it's an internal "
+"contact.\n"
+" </p>\n"
+" "
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+#: field:mail.mail,state:0
+msgid "Status"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+#: selection:mail.mail,state:0
+msgid "Outgoing"
+msgstr ""
+
+#. module: mail
+#: selection:res.partner,notification_email_send:0
+msgid "All feeds"
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,record_name:0
+#: help:mail.message,record_name:0
+msgid "Name get of the related document."
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.act_window,name:mail.action_view_notifications
+#: model:ir.model,name:mail.model_mail_notification
+#: model:ir.ui.menu,name:mail.menu_email_notifications
+#: field:mail.compose.message,notification_ids:0
+#: view:mail.message:0
+#: field:mail.message,notification_ids:0
+#: view:mail.notification:0
+msgid "Notifications"
+msgstr ""
+
+#. module: mail
+#: view:mail.alias:0
+msgid "Search Alias"
+msgstr ""
+
+#. module: mail
+#: help:mail.alias,alias_force_thread_id:0
+msgid ""
+"Optional ID of a thread (record) to which all incoming messages will be "
+"attached, even if they did not reply to it. If set, this will disable the "
+"creation of new records completely."
+msgstr ""
+
+#. module: mail
+#: help:mail.message.subtype,name:0
+msgid ""
+"Message subtype gives a more precise type on the message, especially for "
+"system notifications. For example, it can be a notification related to a new "
+"record (New), or to a stage change in a process (Stage change). Message "
+"subtypes allow to precisely tune the notifications the user want to receive "
+"on its wall."
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "by"
+msgstr ""
+
+#. module: mail
+#: model:mail.group,name:mail.group_best_sales_practices
+msgid "Best Sales Practices"
+msgstr ""
+
+#. module: mail
+#: selection:mail.group,public:0
+msgid "Selected Group Only"
+msgstr ""
+
+#. module: mail
+#: field:mail.group,message_is_follower:0
+#: field:mail.thread,message_is_follower:0
+#: field:res.partner,message_is_follower:0
+msgid "Is a Follower"
+msgstr ""
+
+#. module: mail
+#: view:mail.alias:0
+#: view:mail.mail:0
+msgid "User"
+msgstr ""
+
+#. module: mail
+#: view:mail.group:0
+msgid "Groups"
+msgstr ""
+
+#. module: mail
+#: view:mail.message:0
+msgid "Messages Search"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,date:0
+#: field:mail.message,date:0
+msgid "Date"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:34
+#, python-format
+msgid "Post"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Extended Filters..."
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:122
+#, python-format
+msgid "To:"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:193
+#, python-format
+msgid "Write to my followers"
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_res_groups
+msgid "Access Groups"
+msgstr ""
+
+#. module: mail
+#: field:mail.message.subtype,default:0
+msgid "Default"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:294
+#, python-format
+msgid "show more message"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:246
+#, python-format
+msgid "Mark as Todo"
+msgstr ""
+
+#. module: mail
+#: help:mail.message.subtype,parent_id:0
+msgid "Parent subtype, used for automatic subscription."
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_mail_wizard_invite
+msgid "Invite wizard"
+msgstr ""
+
+#. module: mail
+#: field:mail.group,message_summary:0
+#: field:mail.thread,message_summary:0
+#: field:res.partner,message_summary:0
+msgid "Summary"
+msgstr ""
+
+#. module: mail
+#: help:mail.message.subtype,res_model:0
+msgid ""
+"Model the subtype applies to. If False, this subtype applies to all models."
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,subtype_id:0
+#: field:mail.followers,subtype_ids:0
+#: field:mail.message,subtype_id:0
+#: view:mail.message.subtype:0
+msgid "Subtype"
+msgstr ""
+
+#. module: mail
+#: view:mail.group:0
+msgid "Group Form"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,starred:0
+#: field:mail.message,starred:0
+#: field:mail.notification,starred:0
+msgid "Starred"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:296
+#, python-format
+msgid "more messages"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/update.py:93
+#, python-format
+msgid "Error"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail_followers.xml:13
+#, python-format
+msgid "Following"
+msgstr ""
+
+#. module: mail
+#: sql_constraint:mail.alias:0
+msgid ""
+"Unfortunately this email alias is already used, please choose a unique one"
+msgstr ""
+
+#. module: mail
+#: help:mail.alias,alias_user_id:0
+msgid ""
+"The owner of records created upon receiving emails on this alias. If this "
+"field is not set the system will attempt to find the right owner based on "
+"the sender (From) address, or will use the Administrator account if no "
+"system user is found for that address."
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail_followers.xml:52
+#, python-format
+msgid "And"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,message_id:0
+#: field:mail.message,message_id:0
+msgid "Message-Id"
+msgstr ""
+
+#. module: mail
+#: help:mail.group,image:0
+msgid ""
+"This field holds the image used as photo for the group, limited to "
+"1024x1024px."
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,attachment_ids:0
+#: view:mail.mail:0
+#: field:mail.message,attachment_ids:0
+msgid "Attachments"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,record_name:0
+#: field:mail.message,record_name:0
+msgid "Message Record Name"
+msgstr ""
+
+#. module: mail
+#: field:mail.mail,email_cc:0
+msgid "Cc"
+msgstr ""
+
+#. module: mail
+#: help:mail.notification,starred:0
+msgid "Starred message that goes into the todo mailbox"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:125
+#: view:mail.compose.message:0
+#, python-format
+msgid "Followers of"
+msgstr ""
+
+#. module: mail
+#: help:mail.mail,auto_delete:0
+msgid "Permanently delete this email after sending it, to save space"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.client,name:mail.action_mail_group_feeds
+msgid "Discussion Group"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:242
+#, python-format
+msgid "Done"
+msgstr ""
+
+#. module: mail
+#: model:mail.message.subtype,name:mail.mt_comment
+msgid "Discussions"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail_followers.xml:11
+#, python-format
+msgid "Follow"
+msgstr ""
+
+#. module: mail
+#: field:mail.group,name:0
+msgid "Name"
+msgstr ""
+
+#. module: mail
+#: model:mail.group,name:mail.group_all_employees
+msgid "Whole Company"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:131
+#: code:addons/mail/static/src/xml/mail.xml:278
+#: view:mail.compose.message:0
+#, python-format
+msgid "and"
+msgstr ""
+
+#. module: mail
+#: help:mail.mail,body_html:0
+msgid "Rich-text/HTML message"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+msgid "Creation Month"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:306
+#, python-format
+msgid "Compose new Message"
+msgstr ""
+
+#. module: mail
+#: field:mail.group,menu_id:0
+msgid "Related Menu"
+msgstr ""
+
+#. module: mail
+#: view:mail.message:0
+msgid "Content"
+msgstr ""
+
+#. module: mail
+#: field:mail.mail,email_to:0
+msgid "To"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,notified_partner_ids:0
+#: field:mail.message,notified_partner_ids:0
+msgid "Notified partners"
+msgstr ""
+
+#. module: mail
+#: help:mail.group,public:0
+msgid ""
+"This group is visible by non members. Invisible groups can add "
+"members through the invite button."
+msgstr ""
+
+#. module: mail
+#: model:mail.group,name:mail.group_board
+msgid "Board meetings"
+msgstr ""
+
+#. module: mail
+#: constraint:mail.alias:0
+msgid ""
+"Invalid expression, it must be a literal python dictionary definition e.g. "
+"\"{'field': 'value'}\""
+msgstr ""
+
+#. module: mail
+#: field:mail.alias,alias_model_id:0
+msgid "Aliased Model"
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,message_id:0
+#: help:mail.message,message_id:0
+msgid "Message unique identifier"
+msgstr ""
+
+#. module: mail
+#: field:mail.group,description:0
+#: field:mail.message.subtype,description:0
+msgid "Description"
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_mail_followers
+msgid "Document Followers"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail_followers.xml:35
+#, python-format
+msgid "Remove this follower"
+msgstr ""
+
+#. module: mail
+#: selection:res.partner,notification_email_send:0
+msgid "Never"
+msgstr ""
+
+#. module: mail
+#: field:mail.mail,mail_server_id:0
+msgid "Outgoing mail server"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/mail_message.py:919
+#, python-format
+msgid "Partners email addresses not found"
+msgstr ""
+
+#. module: mail
+#: view:mail.mail:0
+#: selection:mail.mail,state:0
+msgid "Sent"
+msgstr ""
+
+#. module: mail
+#: field:mail.mail,body_html:0
+msgid "Rich-text Contents"
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,to_read:0
+#: help:mail.message,to_read:0
+msgid "Current user has an unread notification linked to this message"
+msgstr ""
+
+#. module: mail
+#: help:res.partner,notification_email_send:0
+msgid ""
+"Choose in which case you want to receive an email when you receive new feeds."
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.act_window,name:mail.action_view_groups
+#: model:ir.ui.menu,name:mail.mail_allgroups
+msgid "Join a group"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.client,help:mail.action_mail_group_feeds
+msgid ""
+"<p>\n"
+" No message in this group.\n"
+" </p>\n"
+" "
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:213
+#, python-format
+msgid "Please, wait while the file is uploading."
+msgstr ""
+
+#. module: mail
+#: view:mail.group:0
+msgid ""
+"This group is visible by everyone,\n"
+" including your customers if you "
+"installed\n"
+" the portal module."
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:243
+#, python-format
+msgid "Set back to Todo"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:128
+#, python-format
+msgid "this document"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,filter_id:0
+msgid "Filters"
+msgstr ""
+
+#. module: mail
+#: field:res.partner,notification_email_send:0
+msgid "Receive Feeds by Email"
+msgstr ""
+
+#. module: mail
+#: help:base.config.settings,alias_domain:0
+msgid ""
+"If you have setup a catch-all email domain redirected to the OpenERP server, "
+"enter the domain name here."
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.act_window,name:mail.action_view_mail_message
+#: model:ir.ui.menu,name:mail.menu_mail_message
+#: field:mail.group,message_ids:0
+#: view:mail.message:0
+#: field:mail.thread,message_ids:0
+#: field:res.partner,message_ids:0
+msgid "Messages"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:141
+#, python-format
+msgid "others..."
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.client,name:mail.action_mail_star_feeds
+#: model:ir.ui.menu,name:mail.mail_starfeeds
+msgid "To-do"
+msgstr ""
+
+#. module: mail
+#: view:mail.alias:0
+#: field:mail.alias,alias_name:0
+#: field:mail.group,alias_id:0
+#: field:res.users,alias_id:0
+msgid "Alias"
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_mail_mail
+msgid "Outgoing Mails"
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,notification_ids:0
+#: help:mail.message,notification_ids:0
+msgid ""
+"Technical field holding the message notifications. Use notified_partner_ids "
+"to access notified partners."
+msgstr ""
+
+#. module: mail
+#: model:ir.ui.menu,name:mail.mail_feeds
+#: model:ir.ui.menu,name:mail.mail_feeds_main
+msgid "Messaging"
+msgstr ""
+
+#. module: mail
+#: view:mail.alias:0
+#: field:mail.message.subtype,res_model:0
+msgid "Model"
+msgstr ""
+
+#. module: mail
+#: view:mail.message:0
+msgid "Unread"
+msgstr "읽지 않음"
+
+#. module: mail
+#: help:mail.followers,subtype_ids:0
+msgid ""
+"Message subtypes followed, meaning subtypes that will be pushed onto the "
+"user's Wall."
+msgstr ""
+
+#. module: mail
+#: help:mail.group,message_ids:0
+#: help:mail.thread,message_ids:0
+#: help:res.partner,message_ids:0
+msgid "Messages and communication history"
+msgstr ""
+
+#. module: mail
+#: help:mail.mail,references:0
+msgid "Message references, such as identifiers of previous messages"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,composition_mode:0
+msgid "Composition mode"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,model:0
+#: field:mail.followers,res_model:0
+#: field:mail.message,model:0
+#: field:mail.wizard.invite,res_model:0
+msgid "Related Document Model"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:321
+#, python-format
+msgid "unlike"
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,author_id:0
+#: help:mail.message,author_id:0
+msgid ""
+"Author of the message. If not set, email_from may hold an email address that "
+"did not match any partner."
+msgstr ""
+
+#. module: mail
+#: help:mail.mail,email_cc:0
+msgid "Carbon copy message recipients"
+msgstr ""
+
+#. module: mail
+#: field:mail.alias,alias_domain:0
+msgid "Alias domain"
+msgstr ""
+
+#. module: mail
+#: code:addons/mail/update.py:93
+#, python-format
+msgid "Error during communication with the publisher warranty server."
+msgstr ""
+
+#. module: mail
+#: selection:mail.group,public:0
+msgid "Private"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.client,help:mail.action_mail_star_feeds
+msgid ""
+"<p>\n"
+" <b>No todo.</b>\n"
+" </p><p>\n"
+" When you process messages in your inbox, you can mark "
+"some\n"
+" as <i>todo</i>. From this menu, you can process all your "
+"todo.\n"
+" </p>\n"
+" "
+msgstr ""
+
+#. module: mail
+#: selection:mail.mail,state:0
+msgid "Delivery Failed"
+msgstr ""
+
+#. module: mail
+#: field:mail.compose.message,partner_ids:0
+msgid "Additional contacts"
+msgstr ""
+
+#. module: mail
+#: help:mail.compose.message,parent_id:0
+#: help:mail.message,parent_id:0
+msgid "Initial thread message."
+msgstr ""
+
+#. module: mail
+#: model:mail.group,name:mail.group_hr_policies
+msgid "HR Policies"
+msgstr ""
+
+#. module: mail
+#: selection:res.partner,notification_email_send:0
+msgid "Emails only"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.client,name:mail.action_mail_inbox_feeds
+#: model:ir.ui.menu,name:mail.mail_inboxfeeds
+msgid "Inbox"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/xml/mail.xml:58
+#, python-format
+msgid "File"
+msgstr ""
+
+#. module: mail
+#. openerp-web
+#: code:addons/mail/static/src/js/many2many_tags_email.js:63
+#, python-format
+msgid "Please complete partner's informations and Email"
+msgstr ""
+
+#. module: mail
+#: model:ir.actions.act_window,name:mail.action_view_message_subtype
+#: model:ir.ui.menu,name:mail.menu_message_subtype
+msgid "Subtypes"
+msgstr ""
+
+#. module: mail
+#: model:ir.model,name:mail.model_mail_alias
+msgid "Email Aliases"
+msgstr ""
+
+#. module: mail
+#: field:mail.group,image_small:0
+msgid "Small-sized photo"
+msgstr ""
+
+#. module: mail
+#: help:mail.mail,reply_to:0
+msgid "Preferred response address for the message"
+msgstr ""
diff --git a/addons/mail/mail_alias.py b/addons/mail/mail_alias.py
index 8730599ad72..870695e074e 100644
--- a/addons/mail/mail_alias.py
+++ b/addons/mail/mail_alias.py
@@ -139,7 +139,7 @@ class mail_alias(osv.Model):
return new_name
def migrate_to_alias(self, cr, child_model_name, child_table_name, child_model_auto_init_fct,
- alias_id_column, alias_key, alias_prefix = '', alias_force_key = '', alias_defaults = {}, context=None):
+ alias_id_column, alias_key, alias_prefix='', alias_force_key='', alias_defaults={}, context=None):
""" Installation hook to create aliases for all users and avoid constraint errors.
:param child_model_name: model name of the child class (i.e. res.users)
@@ -154,8 +154,10 @@ class mail_alias(osv.Model):
:param alias_defaults: dict, keys = mail.alias columns, values = child
model column name used for default values (i.e. {'job_id': 'id'})
"""
+ if context is None:
+ context = {}
- # disable the unique alias_id not null constraint, to avoid spurious warning during
+ # disable the unique alias_id not null constraint, to avoid spurious warning during
# super.auto_init. We'll reinstall it afterwards.
alias_id_column.required = False
@@ -165,14 +167,14 @@ class mail_alias(osv.Model):
registry = RegistryManager.get(cr.dbname)
mail_alias = registry.get('mail.alias')
child_class_model = registry[child_model_name]
- no_alias_ids = child_class_model.search(cr, SUPERUSER_ID, [('alias_id', '=', False)], context={'active_test':False})
+ no_alias_ids = child_class_model.search(cr, SUPERUSER_ID, [('alias_id', '=', False)], context={'active_test': False})
# Use read() not browse(), to avoid prefetching uninitialized inherited fields
for obj_data in child_class_model.read(cr, SUPERUSER_ID, no_alias_ids, [alias_key]):
- alias_vals = {'alias_name': '%s%s' % (alias_prefix, obj_data[alias_key]) }
+ alias_vals = {'alias_name': '%s%s' % (alias_prefix, obj_data[alias_key])}
if alias_force_key:
alias_vals['alias_force_thread_id'] = obj_data[alias_force_key]
- alias_vals['alias_defaults'] = dict( (k, obj_data[v]) for k, v in alias_defaults.iteritems())
- alias_id = mail_alias.create_unique_alias(cr, SUPERUSER_ID, alias_vals, model_name=child_model_name)
+ alias_vals['alias_defaults'] = dict((k, obj_data[v]) for k, v in alias_defaults.iteritems())
+ alias_id = mail_alias.create_unique_alias(cr, SUPERUSER_ID, alias_vals, model_name=context.get('alias_model_name', child_model_name))
child_class_model.write(cr, SUPERUSER_ID, obj_data['id'], {'alias_id': alias_id})
_logger.info('Mail alias created for %s %s (uid %s)', child_model_name, obj_data[alias_key], obj_data['id'])
diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py
index 152b9704fd7..98e88b664e6 100644
--- a/addons/mail/mail_followers.py
+++ b/addons/mail/mail_followers.py
@@ -90,7 +90,7 @@ class mail_notification(osv.Model):
continue
partner = notification.partner_id
# If partners_to_notify specified: restrict to them
- if partners_to_notify and partner.id not in partners_to_notify:
+ if partners_to_notify is not None and partner.id not in partners_to_notify:
continue
# Do not send to partners without email address defined
if not partner.email:
@@ -135,14 +135,17 @@ class mail_notification(osv.Model):
footer = tools.append_content_to_html(footer, signature, plaintext=False, container_tag='p')
# add company signature
- if user.company_id:
- company = user.company_id.website and "<a style='color:inherit' href='%s'>%s</a>" % (user.company_id.website, user.company_id.name) or user.company_id.name
+ if user.company_id.website:
+ website_url = ('http://%s' % user.company_id.website) if not user.company_id.website.lower().startswith(('http:', 'https:')) \
+ else user.company_id.website
+ company = "<a style='color:inherit' href='%s'>%s</a>" % (website_url, user.company_id.name)
else:
- company = user.name
- signature_company = _('<small>Sent by %(company)s using %(openerp)s.</small>') % {
+ company = user.company_id.name
+ sent_by = _('Sent by %(company)s using %(openerp)s.')
+ signature_company = '<small>%s</small>' % (sent_by % {
'company': company,
'openerp': "<a style='color:inherit' href='https://www.openerp.com/'>OpenERP</a>"
- }
+ })
footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div')
return footer
diff --git a/addons/mail/mail_mail.py b/addons/mail/mail_mail.py
index 3c30a950230..8fab4347d0d 100644
--- a/addons/mail/mail_mail.py
+++ b/addons/mail/mail_mail.py
@@ -27,8 +27,8 @@ from urlparse import urljoin
from openerp import tools
from openerp import SUPERUSER_ID
+from openerp.addons.base.ir.ir_mail_server import MailDeliveryException
from openerp.osv import fields, osv
-from openerp.osv.orm import except_orm
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
@@ -93,31 +93,41 @@ class mail_mail(osv.Model):
""" Return a specific reply_to: alias of the document through message_get_reply_to
or take the email_from
"""
+ # if value specified: directly return it
if values.get('reply_to'):
return values.get('reply_to')
- email_reply_to = False
- # model, res_id: comes from values OR related message
- model = values.get('model')
- res_id = values.get('res_id')
- if values.get('mail_message_id') and (not model or not res_id):
+ mailgateway = True # tells whether the answer will go through the mailgateway, leading to the formatting of reply_to <Followers of ...>
+ ir_config_parameter = self.pool.get("ir.config_parameter")
+ catchall_domain = ir_config_parameter.get_param(cr, uid, "mail.catchall.domain", context=context)
+
+ # model, res_id, email_from, reply_to: comes from values OR related message
+ message = None
+ if values.get('mail_message_id'):
message = self.pool.get('mail.message').browse(cr, uid, values.get('mail_message_id'), context=context)
- if not model:
- model = message.model
- if not res_id:
- res_id = message.res_id
+ model = values.get('model', message and message.model or False)
+ res_id = values.get('res_id', message and message.res_id or False)
+ email_from = values.get('email_from', message and message.email_from or False)
+ email_reply_to = message and message.reply_to or False
# if model and res_id: try to use ``message_get_reply_to`` that returns the document alias
- if model and res_id and hasattr(self.pool[model], 'message_get_reply_to'):
+ if not email_reply_to and model and res_id and hasattr(self.pool[model], 'message_get_reply_to'):
email_reply_to = self.pool[model].message_get_reply_to(cr, uid, [res_id], context=context)[0]
+ # no alias reply_to -> catchall alias
+ if not email_reply_to:
+ catchall_alias = ir_config_parameter.get_param(cr, uid, "mail.catchall.alias", context=context)
+ if catchall_domain and catchall_alias:
+ email_reply_to = '%s@%s' % (catchall_alias, catchall_domain)
# no alias reply_to -> reply_to will be the email_from, only the email part
- if not email_reply_to and values.get('email_from'):
- emails = tools.email_split(values.get('email_from'))
+ if not email_reply_to and email_from:
+ emails = tools.email_split(email_from)
if emails:
email_reply_to = emails[0]
+ if emails[0].split('@')[1] != catchall_domain:
+ mailgateway = False
# format 'Document name <email_address>'
- if email_reply_to and model and res_id:
+ if email_reply_to and model and res_id and mailgateway:
document_name = self.pool[model].name_get(cr, SUPERUSER_ID, [res_id], context=context)[0]
if document_name:
# sanitize document name
@@ -195,6 +205,36 @@ class mail_mail(osv.Model):
self.unlink(cr, SUPERUSER_ID, [mail.id], context=context)
return True
+ #------------------------------------------------------
+ # mail_mail formatting, tools and send mechanism
+ #------------------------------------------------------
+
+ # TODO in 8.0(+): maybe factorize this to enable in modules link generation
+ # independently of mail_mail model
+ # TODO in 8.0(+): factorize doc name sanitized and 'Followers of ...' formatting
+ # because it begins to appear everywhere
+
+ def _get_partner_access_link(self, cr, uid, mail, partner=None, context=None):
+ """ Generate URLs for links in mails:
+ - partner is an user and has read access to the document: direct link to document with model, res_id
+ """
+ if partner and partner.user_ids:
+ base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
+ # the parameters to encode for the query and fragment part of url
+ query = {'db': cr.dbname}
+ fragment = {
+ 'login': partner.user_ids[0].login,
+ 'action': 'mail.action_mail_redirect',
+ }
+ if mail.notification:
+ fragment.update({
+ 'message_id': mail.mail_message_id.id,
+ })
+ url = urljoin(base_url, "?%s#%s" % (urlencode(query), urlencode(fragment)))
+ return _("""<small>Access your messages and documents <a style='color:inherit' href="%s">in OpenERP</a></small>""") % url
+ else:
+ return None
+
def send_get_mail_subject(self, cr, uid, mail, force=False, partner=None, context=None):
""" If subject is void and record_name defined: '<Author> posted on <Resource>'
@@ -202,36 +242,12 @@ class mail_mail(osv.Model):
:param browse_record mail: mail.mail browse_record
:param browse_record partner: specific recipient partner
"""
- if force or (not mail.subject and mail.model and mail.res_id):
+ if (force or not mail.subject) and mail.record_name:
return 'Re: %s' % (mail.record_name)
+ elif (force or not mail.subject) and mail.parent_id and mail.parent_id.subject:
+ return 'Re: %s' % (mail.parent_id.subject)
return mail.subject
- def send_get_mail_body_footer(self, cr, uid, mail, partner=None, context=None):
- """ Return a specific footer for the ir_email body. The main purpose of this method
- is to be inherited by Portal, to add modify the link for signing in, in
- each notification email a partner receives.
- """
- body_footer = ""
- # partner is a user, link to a related document (incentive to install portal)
- if partner and partner.user_ids and mail.model and mail.res_id \
- and self.check_access_rights(cr, partner.user_ids[0].id, 'read', raise_exception=False):
- related_user = partner.user_ids[0]
- try:
- self.pool[mail.model].check_access_rule(cr, related_user.id, [mail.res_id], 'read', context=context)
- base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
- # the parameters to encode for the query and fragment part of url
- query = {'db': cr.dbname}
- fragment = {
- 'login': related_user.login,
- 'model': mail.model,
- 'id': mail.res_id,
- }
- url = urljoin(base_url, "?%s#%s" % (urlencode(query), urlencode(fragment)))
- body_footer = _("""<small>Access this document <a style='color:inherit' href="%s">directly in OpenERP</a></small>""") % url
- except except_orm, e:
- pass
- return body_footer
-
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None):
""" Return a specific ir_email body. The main purpose of this method
is to be inherited to add custom content depending on some module.
@@ -241,9 +257,10 @@ class mail_mail(osv.Model):
"""
body = mail.body_html
- # add footer
- body_footer = self.send_get_mail_body_footer(cr, uid, mail, partner=partner, context=context)
- body = tools.append_content_to_html(body, body_footer, plaintext=False, container_tag='div')
+ # generate footer
+ link = self._get_partner_access_link(cr, uid, mail, partner, context=context)
+ if link:
+ body = tools.append_content_to_html(body, link, plaintext=False, container_tag='div')
return body
def send_get_email_dict(self, cr, uid, mail, partner=None, context=None):
@@ -276,7 +293,7 @@ class mail_mail(osv.Model):
'email_to': email_to,
}
- def send(self, cr, uid, ids, auto_commit=False, context=None):
+ def send(self, cr, uid, ids, auto_commit=False, raise_exception=False, context=None):
""" Sends the selected emails immediately, ignoring their current
state (mails that have already been sent should not be passed
unless they should actually be re-sent).
@@ -287,6 +304,8 @@ class mail_mail(osv.Model):
:param bool auto_commit: whether to force a commit of the mail status
after sending each mail (meant only for scheduler processing);
should never be True during normal transactions (default: False)
+ :param bool raise_exception: whether to raise an exception if the
+ email sending process has failed
:return: True
"""
ir_mail_server = self.pool.get('ir.mail_server')
@@ -332,9 +351,16 @@ class mail_mail(osv.Model):
# see revid:odo@openerp.com-20120622152536-42b2s28lvdv3odyr in 6.1
if mail_sent:
self._postprocess_sent_message(cr, uid, mail, context=context)
- except Exception:
+ except Exception as e:
_logger.exception('failed sending mail.mail %s', mail.id)
mail.write({'state': 'exception'})
+ if raise_exception:
+ if isinstance(e, AssertionError):
+ # get the args of the original error, wrap into a value and throw a MailDeliveryException
+ # that is an except_orm, with name and value as arguments
+ value = '. '.join(e.args)
+ raise MailDeliveryException(_("Mail Delivery Failed"), value)
+ raise
if auto_commit == True:
cr.commit()
diff --git a/addons/mail/mail_mail_view.xml b/addons/mail/mail_mail_view.xml
index 1ff9a2a292e..7384cc24a75 100644
--- a/addons/mail/mail_mail_view.xml
+++ b/addons/mail/mail_mail_view.xml
@@ -6,6 +6,11 @@
<field name="model">mail.mail</field>
<field name="arch" type="xml">
<form string="Email message" version="7.0">
+ <header>
+ <button name="send" string="Send Now" type="object" states='outgoing' class="oe_highlight"/>
+ <button name="mark_outgoing" string="Retry" type="object" states='exception,cancel'/>
+ <button name="cancel" string="Cancel" type="object" states='outgoing'/>
+ </header>
<sheet>
<label for="subject" class="oe_edit_only"/>
<h2><field name="subject"/></h2>
diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py
index defc12a2f73..c30d00f5af7 100644
--- a/addons/mail/mail_message.py
+++ b/addons/mail/mail_message.py
@@ -27,6 +27,7 @@ from openerp import SUPERUSER_ID
from openerp.osv import osv, orm, fields
from openerp.tools import html_email_clean
from openerp.tools.translate import _
+from HTMLParser import HTMLParser
_logger = logging.getLogger(__name__)
@@ -43,6 +44,19 @@ def decode(text):
text = decode_header(text.replace('\r', ''))
return ''.join([tools.ustr(x[0], x[1]) for x in text])
+class MLStripper(HTMLParser):
+ def __init__(self):
+ self.reset()
+ self.fed = []
+ def handle_data(self, d):
+ self.fed.append(d)
+ def get_data(self):
+ return ''.join(self.fed)
+
+def strip_tags(html):
+ s = MLStripper()
+ s.feed(html)
+ return s.get_data()
class mail_message(osv.Model):
""" Messages model: system notification (replacing res.log notifications),
@@ -125,7 +139,7 @@ class mail_message(osv.Model):
ids = [ids]
res = []
for message in self.browse(cr, uid, ids, context=context):
- name = '%s: %s' % (message.subject or '', message.body or '')
+ name = '%s: %s' % (message.subject or '', strip_tags(message.body or '') or '')
res.append((message.id, self._shorten_name(name.lstrip(' :'))))
return res
@@ -236,6 +250,8 @@ class mail_message(osv.Model):
:param bool read: set notification as (un)read
:param bool create_missing: create notifications for missing entries
(i.e. when acting on displayed messages not notified)
+
+ :return number of message mark as read
"""
notification_obj = self.pool.get('mail.notification')
user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
@@ -246,14 +262,16 @@ class mail_message(osv.Model):
# all message have notifications: already set them as (un)read
if len(notif_ids) == len(msg_ids) or not create_missing:
- return notification_obj.write(cr, uid, notif_ids, {'read': read}, context=context)
+ notification_obj.write(cr, uid, notif_ids, {'read': read}, context=context)
+ return len(notif_ids)
# some messages do not have notifications: find which one, create notification, update read status
notified_msg_ids = [notification.message_id.id for notification in notification_obj.browse(cr, uid, notif_ids, context=context)]
to_create_msg_ids = list(set(msg_ids) - set(notified_msg_ids))
for msg_id in to_create_msg_ids:
notification_obj.create(cr, uid, {'partner_id': user_pid, 'read': read, 'message_id': msg_id}, context=context)
- return notification_obj.write(cr, uid, notif_ids, {'read': read}, context=context)
+ notification_obj.write(cr, uid, notif_ids, {'read': read}, context=context)
+ return len(notif_ids)
def set_message_starred(self, cr, uid, msg_ids, starred, create_missing=True, context=None):
""" Set messages as (un)starred. Technically, the notifications related
@@ -743,7 +761,7 @@ class mail_message(osv.Model):
default_starred = context.pop('default_starred', False)
# generate message_id, to redirect answers to the right discussion thread
if not values.get('message_id') and values.get('reply_to'):
- values['message_id'] = tools.generate_tracking_message_id('reply_to-%(model)s' % values)
+ values['message_id'] = tools.generate_tracking_message_id('reply_to')
elif not values.get('message_id') and values.get('res_id') and values.get('model'):
values['message_id'] = tools.generate_tracking_message_id('%(res_id)s-%(model)s' % values)
elif not values.get('message_id'):
diff --git a/addons/mail/mail_message_view.xml b/addons/mail/mail_message_view.xml
index 8f2fb3f1020..02f4ef7fdbe 100644
--- a/addons/mail/mail_message_view.xml
+++ b/addons/mail/mail_message_view.xml
@@ -59,6 +59,9 @@
<field name="type"/>
<field name="author_id"/>
<field name="partner_ids"/>
+ <field name="model"/>
+ <field name="res_id"/>
+ <field name="parent_id"/>
<filter string="To Read"
name="message_unread" help="Show messages to read"
domain="[('to_read', '=', True)]"/>
diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py
index 5ddf412e66b..80df8ad6e99 100644
--- a/addons/mail/mail_thread.py
+++ b/addons/mail/mail_thread.py
@@ -33,7 +33,7 @@ from email.message import Message
from openerp import tools
from openerp import SUPERUSER_ID
from openerp.addons.mail.mail_message import decode
-from openerp.osv import fields, osv
+from openerp.osv import fields, osv, orm
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.translate import _
@@ -449,6 +449,70 @@ class mail_thread(osv.AbstractModel):
ir_attachment_obj.unlink(cr, uid, attach_ids, context=context)
return True
+ def _get_formview_action(self, cr, uid, id, model=None, context=None):
+ """ Return an action to open the document. This method is meant to be
+ overridden in addons that want to give specific view ids for example.
+
+ :param int id: id of the document to open
+ :param string model: specific model that overrides self._name
+ """
+ return {
+ 'type': 'ir.actions.act_window',
+ 'res_model': model or self._name,
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'views': [(False, 'form')],
+ 'target': 'current',
+ 'res_id': id,
+ }
+
+ def _get_inbox_action_xml_id(self, cr, uid, context=None):
+ """ When redirecting towards the Inbox, choose which action xml_id has
+ to be fetched. This method is meant to be inherited, at least in portal
+ because portal users have a different Inbox action than classic users. """
+ return ('mail', 'action_mail_inbox_feeds')
+
+ def message_redirect_action(self, cr, uid, context=None):
+ """ For a given message, return an action that either
+ - opens the form view of the related document if model, res_id, and
+ read access to the document
+ - opens the Inbox with a default search on the conversation if model,
+ res_id
+ - opens the Inbox with context propagated
+
+ """
+ if context is None:
+ context = {}
+
+ # default action is the Inbox action
+ self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
+ act_model, act_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, *self._get_inbox_action_xml_id(cr, uid, context=context))
+ action = self.pool.get(act_model).read(cr, uid, act_id, [])
+
+ # if msg_id specified: try to redirect to the document or fallback on the Inbox
+ msg_id = context.get('params', {}).get('message_id')
+ if not msg_id:
+ return action
+ msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context)
+ if msg.model and msg.res_id:
+ action.update({
+ 'context': {
+ 'search_default_model': msg.model,
+ 'search_default_res_id': msg.res_id,
+ }
+ })
+ if self.pool.get(msg.model).check_access_rights(cr, uid, 'read', raise_exception=False):
+ try:
+ model_obj = self.pool.get(msg.model)
+ model_obj.check_access_rule(cr, uid, [msg.res_id], 'read', context=context)
+ if not hasattr(model_obj, '_get_formview_action'):
+ action = self.pool.get('mail.thread')._get_formview_action(cr, uid, msg.res_id, model=msg.model, context=context)
+ else:
+ action = model_obj._get_formview_action(cr, uid, msg.res_id, context=context)
+ except (osv.except_osv, orm.except_orm):
+ pass
+ return action
+
#------------------------------------------------------
# Email specific
#------------------------------------------------------
@@ -459,7 +523,7 @@ class mail_thread(osv.AbstractModel):
return ["%s@%s" % (record['alias_name'], record['alias_domain'])
if record.get('alias_domain') and record.get('alias_name')
else False
- for record in self.read(cr, uid, ids, ['alias_name', 'alias_domain'], context=context)]
+ for record in self.read(cr, SUPERUSER_ID, ids, ['alias_name', 'alias_domain'], context=context)]
#------------------------------------------------------
# Mail gateway
@@ -1200,19 +1264,35 @@ class mail_thread(osv.AbstractModel):
""" Add partners to the records followers. """
user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
if set(partner_ids) == set([user_pid]):
- self.check_access_rights(cr, uid, 'read')
+ try:
+ self.check_access_rights(cr, uid, 'read')
+ except (osv.except_osv, orm.except_orm):
+ return
else:
self.check_access_rights(cr, uid, 'write')
+ # subscribe partners
self.write(cr, SUPERUSER_ID, ids, {'message_follower_ids': [(4, pid) for pid in partner_ids]}, context=context)
- # if subtypes are not specified (and not set to a void list), fetch default ones
- if subtype_ids is None:
- subtype_obj = self.pool.get('mail.message.subtype')
- subtype_ids = subtype_obj.search(cr, uid, [('default', '=', True), '|', ('res_model', '=', self._name), ('res_model', '=', False)], context=context)
- # update the subscriptions
+
+ # subtype specified: update the subscriptions
fol_obj = self.pool.get('mail.followers')
- fol_ids = fol_obj.search(cr, SUPERUSER_ID, [('res_model', '=', self._name), ('res_id', 'in', ids), ('partner_id', 'in', partner_ids)], context=context)
- fol_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
+ if subtype_ids is not None:
+ fol_ids = fol_obj.search(cr, SUPERUSER_ID, [('res_model', '=', self._name), ('res_id', 'in', ids), ('partner_id', 'in', partner_ids)], context=context)
+ fol_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
+ # no subtypes: default ones for new subscription, do not update existing subscriptions
+ else:
+ # search new subscriptions: subtype_ids is False
+ fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
+ ('res_model', '=', self._name),
+ ('res_id', 'in', ids),
+ ('partner_id', 'in', partner_ids),
+ ('subtype_ids', '=', False)
+ ], context=context)
+ if fol_ids:
+ subtype_obj = self.pool.get('mail.message.subtype')
+ subtype_ids = subtype_obj.search(cr, uid, [('default', '=', True), '|', ('res_model', '=', self._name), ('res_model', '=', False)], context=context)
+ fol_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
+
return True
def message_unsubscribe_users(self, cr, uid, ids, user_ids=None, context=None):
diff --git a/addons/mail/mail_thread_view.xml b/addons/mail/mail_thread_view.xml
index 75c86e4645d..c9c5141d303 100644
--- a/addons/mail/mail_thread_view.xml
+++ b/addons/mail/mail_thread_view.xml
@@ -8,6 +8,7 @@
<field name="context">{
'default_model': 'res.users',
'default_res_id': uid,
+ 'needaction_menu_ref': ['mail.mail_tomefeeds', 'mail.mail_starfeeds']
}</field>
<field name="params" eval="&quot;{
'domain': [
@@ -36,7 +37,8 @@
<field name="context">{
'default_model': 'res.users',
'default_res_id': uid,
- 'search_default_message_unread': True
+ 'search_default_message_unread': True,
+ 'needaction_menu_ref': ['mail.mail_starfeeds', 'mail.mail_inboxfeeds']
}</field>
<field name="params" eval="&quot;{
'domain': [
@@ -87,7 +89,8 @@
<field name="tag">mail.wall</field>
<field name="context">{
'default_model': 'res.users',
- 'default_res_id': uid
+ 'default_res_id': uid,
+ 'needaction_menu_ref': ['mail.mail_tomefeeds', 'mail.mail_starfeeds', 'mail.mail_inboxfeeds']
}</field>
<field name="params" eval="&quot;{
'domain': [
@@ -108,6 +111,15 @@
</field>
</record>
+ <record id="action_mail_redirect" model="ir.actions.server">
+ <field name="name">Mail Redirection (Document / Inbox)</field>
+ <field name="condition">True</field>
+ <field name="model_id" ref="model_mail_thread"/>
+ <field name="code">action = pool.get('mail.thread').message_redirect_action(cr, uid, context)</field>
+ <field name="state">code</field>
+ <field name="type">ir.actions.server</field>
+ </record>
+
<!-- MENU -->
<!-- Top menu item -->
diff --git a/addons/mail/res_config.py b/addons/mail/res_config.py
index 91606e1c720..c19eb4a38ee 100644
--- a/addons/mail/res_config.py
+++ b/addons/mail/res_config.py
@@ -23,11 +23,12 @@ import urlparse
from openerp.osv import osv, fields
+
class project_configuration(osv.TransientModel):
_inherit = 'base.config.settings'
_columns = {
- 'alias_domain' : fields.char('Alias Domain',
+ 'alias_domain': fields.char('Alias Domain',
help="If you have setup a catch-all email domain redirected to "
"the OpenERP server, enter the domain name here."),
}
diff --git a/addons/mail/res_users_view.xml b/addons/mail/res_users_view.xml
index f49ff72194a..1cacadfc898 100644
--- a/addons/mail/res_users_view.xml
+++ b/addons/mail/res_users_view.xml
@@ -26,7 +26,7 @@
<field name="signature" position="before">
<field name="notification_email_send"/>
</field>
- <field name="email" position="after">
+ <field name="signature" position="before">
<field name="alias_domain" invisible="1"/>
<field name="alias_id" readonly="1" required="0" attrs="{'invisible': [('alias_domain', '=', False)]}"/>
</field>
diff --git a/addons/mail/static/scripts/openerp_mailgate.py b/addons/mail/static/scripts/openerp_mailgate.py
index 99ebc8f770b..99ebc8f770b 100644..100755
--- a/addons/mail/static/scripts/openerp_mailgate.py
+++ b/addons/mail/static/scripts/openerp_mailgate.py
diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css
index 6bc086a5b58..958c2bccd5f 100644
--- a/addons/mail/static/src/css/mail.css
+++ b/addons/mail/static/src/css/mail.css
@@ -564,13 +564,6 @@
text-align: center;
width:100%;
}
-.openerp .oe_followers button.oe_invite{
- margin: 5px 0;
- padding: 2px 8px;
- font-size: 12px;
- text-shadow: none;
- width: 100%;
-}
.openerp .oe_followers button.oe_follower.oe_following{
color: white;
background-color: #3465A4;
@@ -624,8 +617,12 @@
margin-top: 12px;
margin-bottom: 4px;
}
+.openerp .oe_followers .oe_invite{
+ float: right;
+}
.openerp .oe_followers .oe_partner {
height: 32px;
+ margin-right: 8px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
diff --git a/addons/mail/static/src/img/email_icon.png b/addons/mail/static/src/img/email_icon.png
index 78c131c0ff2..78c131c0ff2 100755..100644
--- a/addons/mail/static/src/img/email_icon.png
+++ b/addons/mail/static/src/img/email_icon.png
Binary files differ
diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js
index b1a579ba057..8631bc70baa 100644
--- a/addons/mail/static/src/js/mail.js
+++ b/addons/mail/static/src/js/mail.js
@@ -1056,9 +1056,7 @@ openerp.mail = function (session) {
msg.renderElement();
msg.start();
}
- if( self.options.root_thread.__parentedParent.__parentedParent.do_reload_menu_emails ) {
- self.options.root_thread.__parentedParent.__parentedParent.do_reload_menu_emails();
- }
+ self.options.root_thread.MailWidget.do_reload_menu_emails();
});
});
@@ -1198,6 +1196,7 @@ openerp.mail = function (session) {
init: function (parent, datasets, options) {
var self = this;
this._super(parent, options);
+ this.MailWidget = parent.__proto__ == mail.Widget.prototype ? parent : false;
this.domain = options.domain || [];
this.context = _.extend(options.context || {});
@@ -1431,11 +1430,16 @@ openerp.mail = function (session) {
message_fetch_set_read: function (message_list) {
if (! this.context.mail_read_set_read) return;
- this.render_mutex.exec(_.bind(function() {
+ var self = this;
+ this.render_mutex.exec(function() {
msg_ids = _.pluck(message_list, 'id');
- return this.ds_message.call('set_message_read', [
- msg_ids, true, false, this.context]);
- }, this));
+ return self.ds_message.call('set_message_read', [msg_ids, true, false, self.context])
+ .then(function (nb_read) {
+ if (nb_read) {
+ self.options.root_thread.MailWidget.do_reload_menu_emails();
+ }
+ });
+ });
},
/**
@@ -1701,6 +1705,22 @@ openerp.mail = function (session) {
},
/**
+ * create an object "related_menu"
+ * contains the menu widget and the sub menu related of this wall
+ */
+ do_reload_menu_emails: function () {
+ var menu = session.webclient.menu;
+ if (!menu || !menu.current_menu) {
+ return $.when();
+ }
+ return menu.rpc("/web/menu/load_needaction", {'menu_ids': [menu.current_menu]}).done(function(r) {
+ menu.on_needaction_loaded(r);
+ }).then(function () {
+ menu.trigger("need_action_reloaded");
+ });
+ },
+
+ /**
*Create the root thread and display this object in the DOM.
* Call the no_message method then c all the message_fetch method
* of this root thread to display the messages.
@@ -1749,6 +1769,7 @@ openerp.mail = function (session) {
init: function (parent, node) {
this._super.apply(this, arguments);
+ this.ParentViewManager = parent;
this.node = _.clone(node);
this.node.params = _.extend({
'display_indented_thread': -1,
@@ -1768,7 +1789,7 @@ openerp.mail = function (session) {
this.domain = this.node.params && this.node.params.domain || [];
- if (!this.__parentedParent.is_action_enabled('edit')) {
+ if (!this.ParentViewManager.is_action_enabled('edit')) {
this.node.params.show_link = false;
}
},
@@ -1839,12 +1860,20 @@ openerp.mail = function (session) {
*/
init: function (parent, action) {
this._super(parent, action);
+ this.ActionManager = parent;
this.action = _.clone(action);
this.domain = this.action.params.domain || this.action.domain || [];
this.context = _.extend(this.action.params.context || {}, this.action.context || {});
+ // filter some parameters that we will propagate as search_default
this.defaults = {};
+ for (var key in this.action.context.params) {
+ if (_.indexOf(['model', 'res_id'], key) == -1) {
+ continue;
+ }
+ this.context['search_default_' + key] = this.action.context.params[key];
+ }
for (var key in this.context) {
if (key.match(/^search_default_/)) {
this.defaults[key.replace(/^search_default_/, '')] = this.context[key];
@@ -1872,23 +1901,6 @@ openerp.mail = function (session) {
},
/**
- * crete an object "related_menu"
- * contain the menu widget and the the sub menu related of this wall
- */
- do_reload_menu_emails: function () {
- var menu = this.__parentedParent.__parentedParent.menu;
- // return this.rpc("/web/menu/load", {'menu_id': 100}).done(function(r) {
- // _.each(menu.data.data.children, function (val) {
- // if (val.id == 100) {
- // val.children = _.find(r.data.children, function (r_val) {return r_val.id == 100;}).children;
- // }
- // });
- // var r = menu.data;
- // window.setTimeout(function(){menu.do_reload();}, 0);
- // });
- },
-
- /**
* Load the mail.message search view
* @param {Object} defaults ??
*/
diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml
index 7e7d772397a..ab82d650f30 100644
--- a/addons/mail/static/src/xml/mail.xml
+++ b/addons/mail/static/src/xml/mail.xml
@@ -144,7 +144,9 @@
<t t-foreach='widget.recipients' t-as='recipient'>
<label t-attf-title="Add as recipient and follower (reason: #{recipient.reason})">
<input type="checkbox" t-att-checked="recipient.checked ? 'checked' : undefined" t-att-data="recipient.email_address"/>
- <t t-raw="recipient.name"/> (<t t-raw="recipient.email_address"/>)
+ <t t-raw="recipient.name"/>
+ <t t-if="recipient.email_address">(<t t-raw="recipient.email_address"/>)</t>
+ <t t-if="!recipient.email_address">(no email address)</t>
</label>
</t>
</div>
diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml
index f3317223f1d..5ad3ff09bb3 100644
--- a/addons/mail/static/src/xml/mail_followers.xml
+++ b/addons/mail/static/src/xml/mail_followers.xml
@@ -19,7 +19,7 @@
</div>
<div class='oe_follower_title_box'>
<h4 class='oe_follower_title'>Followers</h4>
- <button t-if="widget.view_is_editable" href='#' class="oe_invite">Invite people</button>
+ <a t-if="widget.view_is_editable" href='#' class="oe_invite">Add others</a>
</div>
<div class="oe_follower_list"></div>
</div>
diff --git a/addons/mail/tests/test_mail_features.py b/addons/mail/tests/test_mail_features.py
index 7eea66b3b90..46f4555349d 100644
--- a/addons/mail/tests/test_mail_features.py
+++ b/addons/mail/tests/test_mail_features.py
@@ -19,12 +19,15 @@
#
##############################################################################
+from openerp.addons.mail.mail_mail import mail_mail
+from openerp.addons.mail.mail_thread import mail_thread
from openerp.addons.mail.tests.test_mail_base import TestMailBase
+from openerp.tools import mute_logger
from openerp.tools.mail import html_sanitize
class test_mail(TestMailBase):
-
+
def test_000_alias_setup(self):
""" Test basic mail.alias setup works, before trying to use them for routing """
cr, uid = self.cr, self.uid
@@ -43,7 +46,6 @@ class test_mail(TestMailBase):
self.user_barty = self.res_users.browse(cr, uid, self.user_barty_id)
self.assertEquals(self.user_barty.alias_name, 'b4r+_-_r3wl-', 'Disallowed chars should be replaced by hyphens')
-
def test_00_followers_function_field(self):
""" Tests designed for the many2many function field 'follower_ids'.
We will test to perform writes using the many2many commands 0, 3, 4,
@@ -116,18 +118,66 @@ class test_mail(TestMailBase):
# CASE1: test subscriptions with subtypes
# ----------------------------------------
- # Do: Subscribe Raoul three times (niak niak) through message_subscribe_users
+ # Do: subscribe Raoul, should have default subtypes
+ group_pigs.message_subscribe_users([user_raoul.id])
+ group_pigs.refresh()
+ # Test: 2 followers (Admin and Raoul)
+ follower_ids = [follower.id for follower in group_pigs.message_follower_ids]
+ self.assertEqual(set(follower_ids), set([user_raoul.partner_id.id, user_admin.partner_id.id]),
+ 'message_subscribe: Admin and Raoul should be the only 2 Pigs fans')
+ # Raoul follows default subtypes
+ fol_ids = self.mail_followers.search(cr, uid, [
+ ('res_model', '=', 'mail.group'),
+ ('res_id', '=', self.group_pigs_id),
+ ('partner_id', '=', user_raoul.partner_id.id)
+ ])
+ fol_obj = self.mail_followers.browse(cr, uid, fol_ids)[0]
+ fol_subtype_ids = set([subtype.id for subtype in fol_obj.subtype_ids])
+ self.assertEqual(set(fol_subtype_ids), set(default_group_subtypes),
+ 'message_subscribe: Raoul subscription subtypes are incorrect, should be all default ones')
+
+ # Do: subscribe Raoul with specified new subtypes
+ group_pigs.message_subscribe_users([user_raoul.id], subtype_ids=[mt_mg_nodef])
+ # Test: 2 followers (Admin and Raoul)
+ follower_ids = [follower.id for follower in group_pigs.message_follower_ids]
+ self.assertEqual(set(follower_ids), set([user_raoul.partner_id.id, user_admin.partner_id.id]),
+ 'message_subscribe: Admin and Raoul should be the only 2 Pigs fans')
+ # Test: 2 lines in mail.followers (no duplicate for Raoul)
+ fol_ids = self.mail_followers.search(cr, uid, [
+ ('res_model', '=', 'mail.group'),
+ ('res_id', '=', self.group_pigs_id),
+ ])
+ self.assertEqual(len(fol_ids), 2,
+ 'message_subscribe: subscribing an already-existing follower should not create new entries in mail.followers')
+ # Test: Raoul follows only specified subtypes
+ fol_ids = self.mail_followers.search(cr, uid, [
+ ('res_model', '=', 'mail.group'),
+ ('res_id', '=', self.group_pigs_id),
+ ('partner_id', '=', user_raoul.partner_id.id)
+ ])
+ fol_obj = self.mail_followers.browse(cr, uid, fol_ids)[0]
+ fol_subtype_ids = set([subtype.id for subtype in fol_obj.subtype_ids])
+ self.assertEqual(set(fol_subtype_ids), set([mt_mg_nodef]),
+ 'message_subscribe: Raoul subscription subtypes are incorrect, should be only specified')
+
+ # Do: Subscribe Raoul without specified subtypes: should not erase existing subscription subtypes
group_pigs.message_subscribe_users([user_raoul.id, user_raoul.id])
group_pigs.message_subscribe_users([user_raoul.id])
group_pigs.refresh()
# Test: 2 followers (Admin and Raoul)
follower_ids = [follower.id for follower in group_pigs.message_follower_ids]
- self.assertEqual(set(follower_ids), set([user_raoul.partner_id.id, user_admin.partner_id.id]), 'Admin and Raoul should be the only 2 Pigs fans')
+ self.assertEqual(set(follower_ids), set([user_raoul.partner_id.id, user_admin.partner_id.id]),
+ 'message_subscribe: Admin and Raoul should be the only 2 Pigs fans')
# Test: Raoul follows default subtypes
- fol_ids = self.mail_followers.search(cr, uid, [('res_model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id), ('partner_id', '=', user_raoul.partner_id.id)])
+ fol_ids = self.mail_followers.search(cr, uid, [
+ ('res_model', '=', 'mail.group'),
+ ('res_id', '=', self.group_pigs_id),
+ ('partner_id', '=', user_raoul.partner_id.id)
+ ])
fol_obj = self.mail_followers.browse(cr, uid, fol_ids)[0]
fol_subtype_ids = set([subtype.id for subtype in fol_obj.subtype_ids])
- self.assertEqual(set(fol_subtype_ids), set(default_group_subtypes), 'subscription subtypes are incorrect')
+ self.assertEqual(set(fol_subtype_ids), set([mt_mg_nodef]),
+ 'message_subscribe: Raoul subscription subtypes are incorrect, should be only specified')
# Do: Unsubscribe Raoul twice through message_unsubscribe_users
group_pigs.message_unsubscribe_users([user_raoul.id, user_raoul.id])
@@ -135,6 +185,13 @@ class test_mail(TestMailBase):
# Test: 1 follower (Admin)
follower_ids = [follower.id for follower in group_pigs.message_follower_ids]
self.assertEqual(follower_ids, [user_admin.partner_id.id], 'Admin must be the only Pigs fan')
+ # Test: 1 lines in mail.followers (no duplicate for Raoul)
+ fol_ids = self.mail_followers.search(cr, uid, [
+ ('res_model', '=', 'mail.group'),
+ ('res_id', '=', self.group_pigs_id)
+ ])
+ self.assertEqual(len(fol_ids), 1,
+ 'message_subscribe: group should have only 1 entry in mail.follower for 1 follower')
# Do: subscribe Admin with subtype_ids
group_pigs.message_subscribe_users([uid], [mt_mg_nodef, mt_all_nodef])
@@ -171,6 +228,64 @@ class test_mail(TestMailBase):
self.assertNotIn('First answer, should not be displayed', result, 'Old answer should not be in quote.')
self.assertNotIn('My answer I am propagating', result, 'Thread header content should be in quote.')
+ def test_11_notification_url(self):
+ """ Tests designed to test the URL added in notification emails. """
+ cr, uid, group_pigs = self.cr, self.uid, self.group_pigs
+
+ # Partner data
+ partner_raoul = self.res_partner.browse(cr, uid, self.partner_raoul_id)
+ partner_bert_id = self.res_partner.create(cr, uid, {'name': 'bert'})
+ partner_bert = self.res_partner.browse(cr, uid, partner_bert_id)
+ # Mail data
+ mail_mail_id = self.mail_mail.create(cr, uid, {'state': 'exception'})
+ mail = self.mail_mail.browse(cr, uid, mail_mail_id)
+
+ # Test: link for nobody -> None
+ url = mail_mail._get_partner_access_link(self.mail_mail, cr, uid, mail)
+ self.assertEqual(url, None,
+ 'notification email: mails not send to a specific partner should not have any URL')
+
+ # Test: link for partner -> None
+ url = mail_mail._get_partner_access_link(self.mail_mail, cr, uid, mail, partner=partner_bert)
+ self.assertEqual(url, None,
+ 'notification email: mails send to a not-user partner should not have any URL')
+
+ # Test: link for user -> signin
+ url = mail_mail._get_partner_access_link(self.mail_mail, cr, uid, mail, partner=partner_raoul)
+ self.assertIn('action=mail.action_mail_redirect', url,
+ 'notification email: link should contain the redirect action')
+ self.assertIn('login=%s' % partner_raoul.user_ids[0].login, url,
+ 'notification email: link should contain the user login')
+
+ @mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
+ def test_12_inbox_redirection(self):
+ """ Tests designed to test the inbox redirection of emails notification URLs. """
+ cr, uid, user_admin, group_pigs = self.cr, self.uid, self.user_admin, self.group_pigs
+ model, act_id = self.ir_model_data.get_object_reference(cr, uid, 'mail', 'action_mail_inbox_feeds')
+ # Data: post a message on pigs
+ msg_id = self.group_pigs.message_post(body='My body', partner_ids=[self.partner_bert_id], type='comment', subtype='mail.mt_comment')
+
+ # No specific parameters -> should redirect to Inbox
+ action = mail_thread.message_redirect_action(self.mail_thread, cr, self.user_raoul_id, {'params': {}})
+ self.assertEqual(action.get('type'), 'ir.actions.client',
+ 'URL redirection: action without parameters should redirect to client action Inbox')
+ self.assertEqual(action.get('id'), act_id,
+ 'URL redirection: action without parameters should redirect to client action Inbox')
+
+ # Bert has read access to Pigs -> should redirect to form view of Pigs
+ action = mail_thread.message_redirect_action(self.mail_thread, cr, self.user_raoul_id, {'params': {'message_id': msg_id}})
+ self.assertEqual(action.get('type'), 'ir.actions.act_window',
+ 'URL redirection: action with message_id for read-accredited user should redirect to Pigs')
+ self.assertEqual(action.get('res_id'), group_pigs.id,
+ 'URL redirection: action with message_id for read-accredited user should redirect to Pigs')
+
+ # Bert has no read access to Pigs -> should redirect to Inbox
+ action = mail_thread.message_redirect_action(self.mail_thread, cr, self.user_bert_id, {'params': {'message_id': msg_id}})
+ self.assertEqual(action.get('type'), 'ir.actions.client',
+ 'URL redirection: action without parameters should redirect to client action Inbox')
+ self.assertEqual(action.get('id'), act_id,
+ 'URL redirection: action without parameters should redirect to client action Inbox')
+
def test_20_message_post(self):
""" Tests designed for message_post. """
cr, uid, user_raoul, group_pigs = self.cr, self.uid, self.user_raoul, self.group_pigs
@@ -364,8 +479,8 @@ class test_mail(TestMailBase):
'message_post: notification email sent to more than one email address instead of a precise partner')
self.assertIn(sent_email['email_to'][0], test_emailto,
'message_post: notification email email_to incorrect')
- self.assertEqual(sent_email['reply_to'], '"Followers of Pigs" <r@r>',
- 'message_post: notification email reply_to incorrect: should name Followers of Pigs, and have raoul email')
+ self.assertEqual(sent_email['reply_to'], 'r@r', # was '"Followers of Pigs" <r@r>', but makes no sense
+ 'message_post: notification email reply_to incorrect: should have raoul email')
self.assertEqual(_mail_subject, sent_email['subject'],
'message_post: notification email subject incorrect')
self.assertIn(html_sanitize(_body2), sent_email['body'],
diff --git a/addons/mail/tests/test_mail_gateway.py b/addons/mail/tests/test_mail_gateway.py
index e4269d59d8b..ee166b82dde 100644
--- a/addons/mail/tests/test_mail_gateway.py
+++ b/addons/mail/tests/test_mail_gateway.py
@@ -20,6 +20,7 @@
##############################################################################
from openerp.addons.mail.tests.test_mail_base import TestMailBase
+from openerp.tools import mute_logger
MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com>
To: {to}
@@ -123,6 +124,107 @@ class TestMailgateway(TestMailBase):
self.assertEqual(partner_info['partner_id'], p_b_id,
'mail_thread: message_find_partner_from_emails wrong partner found')
+ def test_05_mail_message_mail_mail(self):
+ """ Tests designed for testing email values based on mail.message, aliases, ... """
+ cr, uid = self.cr, self.uid
+
+ # Data: clean catchall domain
+ param_ids = self.registry('ir.config_parameter').search(cr, uid, [('key', '=', 'mail.catchall.domain')])
+ self.registry('ir.config_parameter').unlink(cr, uid, param_ids)
+
+ # Do: create a mail_message with a reply_to, without message-id
+ msg_id = self.mail_message.create(cr, uid, {'subject': 'Subject', 'body': 'Body', 'reply_to': 'custom@example.com'})
+ msg = self.mail_message.browse(cr, uid, msg_id)
+ # Test: message content
+ self.assertIn('reply_to', msg.message_id,
+ 'mail_message: message_id should be specific to a mail_message with a given reply_to')
+ self.assertEqual('custom@example.com', msg.reply_to,
+ 'mail_message: incorrect reply_to')
+ # Do: create a mail_mail with the previous mail_message and specified reply_to
+ mail_id = self.mail_mail.create(cr, uid, {'mail_message_id': msg_id, 'reply_to': 'other@example.com', 'state': 'cancel'})
+ mail = self.mail_mail.browse(cr, uid, mail_id)
+ # Test: mail_mail content
+ self.assertEqual(mail.reply_to, 'other@example.com',
+ 'mail_mail: reply_to should be equal to the one coming from creation values')
+ # Do: create a mail_mail with the previous mail_message
+ mail_id = self.mail_mail.create(cr, uid, {'mail_message_id': msg_id, 'state': 'cancel'})
+ mail = self.mail_mail.browse(cr, uid, mail_id)
+ # Test: mail_mail content
+ self.assertEqual(mail.reply_to, msg.reply_to,
+ 'mail_mail: reply_to should be equal to the one coming from the mail_message')
+
+ # Do: create a mail_message without a reply_to
+ msg_id = self.mail_message.create(cr, uid, {'subject': 'Subject', 'body': 'Body', 'model': 'mail.group', 'res_id': self.group_pigs_id, 'email_from': False})
+ msg = self.mail_message.browse(cr, uid, msg_id)
+ # Test: message content
+ self.assertIn('mail.group', msg.message_id,
+ 'mail_message: message_id should contain model')
+ self.assertIn('%s' % self.group_pigs_id, msg.message_id,
+ 'mail_message: message_id should contain res_id')
+ self.assertFalse(msg.reply_to,
+ 'mail_message: should not generate a reply_to address when not specified')
+ # Do: create a mail_mail based on the previous mail_message
+ mail_id = self.mail_mail.create(cr, uid, {'mail_message_id': msg_id, 'state': 'cancel'})
+ mail = self.mail_mail.browse(cr, uid, mail_id)
+ # Test: mail_mail content
+ self.assertFalse(mail.reply_to,
+ 'mail_mail: reply_to should not have been guessed')
+ # Update message
+ self.mail_message.write(cr, uid, [msg_id], {'email_from': 'someone@example.com'})
+ msg.refresh()
+ # Do: create a mail_mail based on the previous mail_message
+ mail_id = self.mail_mail.create(cr, uid, {'mail_message_id': msg_id, 'state': 'cancel'})
+ mail = self.mail_mail.browse(cr, uid, mail_id)
+ # Test: mail_mail content
+ self.assertEqual(mail.reply_to, msg.email_from,
+ 'mail_mail: reply_to should equal to mail_message.email_from when having no document or default alias')
+
+ # Data: set catchall domain
+ self.registry('ir.config_parameter').set_param(cr, uid, 'mail.catchall.domain', 'schlouby.fr')
+ self.registry('ir.config_parameter').unlink(cr, uid, self.registry('ir.config_parameter').search(cr, uid, [('key', '=', 'mail.catchall.alias')]))
+
+ # Do: create a mail_mail based on the previous mail_message
+ mail_id = self.mail_mail.create(cr, uid, {'mail_message_id': msg_id, 'state': 'cancel'})
+ mail = self.mail_mail.browse(cr, uid, mail_id)
+ # Test: mail_mail content
+ self.assertEqual(mail.reply_to, '"Followers of Pigs" <group+pigs@schlouby.fr>',
+ 'mail_mail: reply_to should equal the mail.group alias')
+
+ # Update message
+ self.mail_message.write(cr, uid, [msg_id], {'res_id': False, 'email_from': 'someone@schlouby.fr'})
+ msg.refresh()
+ # Do: create a mail_mail based on the previous mail_message
+ mail_id = self.mail_mail.create(cr, uid, {'mail_message_id': msg_id, 'state': 'cancel'})
+ mail = self.mail_mail.browse(cr, uid, mail_id)
+ # Test: mail_mail content
+ self.assertEqual(mail.reply_to, msg.email_from,
+ 'mail_mail: reply_to should equal the mail_message email_from')
+
+ # Data: set catchall alias
+ self.registry('ir.config_parameter').set_param(self.cr, self.uid, 'mail.catchall.alias', 'gateway')
+
+ # Do: create a mail_mail based on the previous mail_message
+ mail_id = self.mail_mail.create(cr, uid, {'mail_message_id': msg_id, 'state': 'cancel'})
+ mail = self.mail_mail.browse(cr, uid, mail_id)
+ # Test: mail_mail content
+ self.assertEqual(mail.reply_to, 'gateway@schlouby.fr',
+ 'mail_mail: reply_to should equal the catchall email alias')
+
+ # Do: create a mail_mail
+ mail_id = self.mail_mail.create(cr, uid, {'state': 'cancel'})
+ mail = self.mail_mail.browse(cr, uid, mail_id)
+ # Test: mail_mail content
+ self.assertEqual(mail.reply_to, 'gateway@schlouby.fr',
+ 'mail_mail: reply_to should equal the catchall email alias')
+
+ # Do: create a mail_mail
+ mail_id = self.mail_mail.create(cr, uid, {'state': 'cancel', 'reply_to': 'someone@example.com'})
+ mail = self.mail_mail.browse(cr, uid, mail_id)
+ # Test: mail_mail content
+ self.assertEqual(mail.reply_to, 'someone@example.com',
+ 'mail_mail: reply_to should equal the rpely_to given to create')
+
+ @mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
def test_10_message_process(self):
""" Testing incoming emails processing. """
cr, uid, user_raoul = self.cr, self.uid, self.user_raoul
@@ -365,6 +467,7 @@ class TestMailgateway(TestMailBase):
self.assertEqual(msg.body, '<pre>\nPlease call me as soon as possible this afternoon!\n\n--\nSylvie\n</pre>',
'message_process: plaintext incoming email incorrectly parsed')
+ @mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
def test_20_thread_parent_resolution(self):
""" Testing parent/child relationships are correctly established when processing incoming mails """
cr, uid = self.cr, self.uid
diff --git a/addons/mail/wizard/invite.py b/addons/mail/wizard/invite.py
index 4ff6584d789..a6bfc34c213 100644
--- a/addons/mail/wizard/invite.py
+++ b/addons/mail/wizard/invite.py
@@ -75,7 +75,7 @@ class invite_wizard(osv.osv_memory):
model_name = ir_model.name_get(cr, uid, model_ids, context=context)[0][1]
# send an email if option checked and if a message exists (do not send void emails)
- if wizard.send_mail and wizard.message:
+ if wizard.send_mail and wizard.message and not wizard.message == '<br>': # when deleting the message, cleditor keeps a <br>
# add signature
# FIXME 8.0: use notification_email_send, send a wall message and let mail handle email notification + message box
signature_company = self.pool.get('mail.notification').get_signature_footer(cr, uid, user_id=uid, res_model=wizard.res_model, res_id=wizard.res_id, context=context)