Discuss

mail
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/19.0/mail
VERSION
VERSION 1.19
CATEGORY
CATEGORYProductivity/Discuss
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo S.A.
MAINTAINERS
MAINTAINERSOdoo S.A.
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Thibault Delavallée, Denis Ledoux, Xavier ALT, David Monjoie, Xavier Morel, Nicolas Martinelli, Nicolas Lempereur, Stefan Rijnhart, Géry Debongnie, Aaron Bohy, Jeremy Kersten, Lucas Perais (lpe), Damien Bouvy, Pierre Masereel, Christophe Monniez, Jorge Pinna Puissant, Jairo Llopis, Lucas Perais, Alexandre Kühn, Julien Castiaux, Xavier-Do, Romeo Fragomeli, Adrien Dieudonné, Paul Morelle, Sébastien Theys, Julien Mougenot, std-odoo, Achraf (abz), Brice bib Bartoletti, Prakash Prajapati, Tiffany Chang (tic), Rémy Voet (ryv), Pierre Rousseau, Gorash, ThanhDodeurOdoo, Mathieu Duckerts-Antoine, Pierre Paridans, abd-msyukyu-odoo, William Braeckman, Romain Estievenart, odoo, Stanislas Sobieski, Miquel Raïch, yhu-odoo, Didier (did), Nicolas Bayet, Jinjiu Liu, Hubert Van De Walle, luvi, Renaud Thiry, Julien Banken, Iván Todorovich, bve-odoo, alsh-odoo, Gaetan Vanden Bergh (gavb), Louis Wicket (wil), tsm-odoo, Maximilien (malb), Victor Piryns (pivi), Thomas Becquevort (thbe), amdi-odoo, Pierre-Yves Dufays, Levi Siuzdak (sile), Dylan Kiss (dyki), Bruno Boi, FrancoisGe, Mayurrajsinh Rathod, Rahul Prajapati, Chong Wang (cwg), Leloup Loïc (lole), Adrien Schoffeniels, Xavier Bol (xbo), omra-odoo, Andrzej(pian), Zelong Lin, Walid (wasa), sesn-odoo, maad-odoo, Deependra Solanki, BHanq, aktr-odoo, Hesham, Youssef Bashandy, Maryam Kia, jorv-odoo, Maxime de Neuville, reka-odoo, “Beekan”, Ricardoalso, vava-odoo, Bruno Boi (boi), Bastien Fafchamps (bafa), Julien Carion (juca), dhba, adsh-odoo, mega, Tanguy Quéguineur, TSO, Alex Kühn, Lopes Marc (loma), nihp-odoo, Chrysanthe (chgo), Adnan Saiyed, Rodolpho Lima, aath-odoo, adch-odoo, Junqi Wu, mano-odoo, Joseph (jcb), thle-odoo, Mathieu Coutant, Elisabeth Dickinson, Xavier Luyckx (xlu), guce, yagp-odoo, haumenphai, rame-odoo, sabr, Antoine Dupuis, Sébastien (blse), Pierre Pulinckx (PIPU), Hesham Saleh, Julien Schwanen, Victor Miguel Armenta Carrillo, quyen, sben-odoo, aych-odoo, Michaël Mattiello, nikj-odoo, Pierre Pulinckx, Bastien PIERRE, Anton Romanova (roan), masm-odoo, K Theja (kthe), zel-odoo, pish-odoo, Panagiotis Kyriakou, plha-odoo, Thomas Josse (THJO), Krzysztof Magusiak (krma), Ajit Singh, Quoc - Pham Ngoc, nees-odoo, Basioni (basm), utma-odoo, Maeva De Keyser (MDEK), sagu-odoo, kdes-odoo, Brett Cutler, pajo, defl, mojem, Giorgio Tocco (gito), Ayush Chauhan (aych), jayp-odoo, akha, romc-odoo, igbe, Tudor-Calin Panzaru (tupan), Laetitia (ldau), Augustin (duau), adip-odoo, shka-odoo, Jérôme Belpaire, ramh, oumaima-aarabe, leclerc-leo, dhrp-odoo, assh-odoo, Bruno BOI, livaios, Kevin Gerard (kege), Louis, nmak-odoo, Akash Parmar, pmah-odoo, Benoit Socias (bso), YoussefM890, Soumya M, saurabh, Omar Khalil (omkha), Séna Nshimiyimana, Atovange, alan-odoo, Kadam Darji, Jason (jaca), Julien (jdeh), Zachary (zavan), ibo-odoo, raja prasad, Farah (ahmfa), akth-odoo, Mehdi Rachico (mera), akus-odoo, ELCO, karygauss03, chpa-odoo, shmn-odoo, Claire Nguyen (clan), Mohamed Ayman, Dylan Provoost, mear-odoo, Haja Ram, Louis Wicket, rsbh-odoo, Joe VanHorn
WEBSITE
WEBSITEhttps://www.odoo.com/app/discuss
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 14:10:20
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web
    - bus
    - web_tour
    - html_editor
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Chat, mail gateway and private channel.
=======================================

Communicate with your colleagues/customers/guest within Odoo.

Discuss/Chat
------------
User-friendly "Discuss" features that allows one 2 one or group communication
(text chat/voice call/video call), invite guests and share documents with
them, all real-time.

Mail gateway
------------
Sending information and documents made simplified. You can send emails
from Odoo itself, and that too with great possibilities. For example,
design a beautiful email template for the invoices, and use the same
for all your customers, no need to do the same exercise every time.

Chatter
-------
Do all the contextual conversation on a document. For example on an
applicant, directly post an update to send email to the applicant,
schedule the next interview call, attach the contract, add HR officer
to the follower list to notify them for important events(with help of
subtypes),...


Retrieve incoming email on POP/IMAP servers.
============================================
Enter the parameters of your POP/IMAP account(s), and any incoming emails on
these accounts will be automatically downloaded into your Odoo system. All
POP3/IMAP-compatible servers are supported, included those that require an
encrypted SSL/TLS connection.
This can be used to easily create email-based workflows for many email-enabled Odoo documents, such as:
----------------------------------------------------------------------------------------------------------
    * CRM Leads/Opportunities
    * CRM Claims
    * Project Issues
    * Project Tasks
    * Human Resource Recruitment (Applicants)
Just install the relevant application, and you can assign any of these document
types (Leads, Project Issues) to your incoming email accounts. New emails will
automatically spawn new documents of the chosen type, so it's a snap to create a
mailbox-to-Odoo integration. Even better: these documents directly act as mini
conversations synchronized by email. You can reply from within Odoo, and the
answers will automatically be collected when they come back, and attached to the
same *conversation* document.
For more specific needs, you may also assign custom-defined actions
(technically: Server Actions) to be triggered for each incoming mail.
    

Code Analysis

Views touched (137)
XML IDNameModelTypeStatus
account_security_alert Alert Security Update ir.ui.view qweb New
discuss_call_history_view_form discuss.call.history.view.form discuss.call.history form New
discuss_call_history_view_tree discuss.call.history.view.list discuss.call.history list New
discuss_channel_invitation_template discuss_channel_invitation_template ir.ui.view qweb New
discuss_channel_member_view_form discuss.channel.member.form discuss.channel.member form New
discuss_channel_member_view_tree discuss.channel.member.list discuss.channel.member list New
discuss_channel_rtc_session_view_form discuss.channel.rtc.session.form discuss.channel.rtc.session form New
discuss_channel_rtc_session_view_search discuss.channel.rtc.session.search discuss.channel.rtc.session search New
discuss_channel_rtc_session_view_tree discuss.channel.rtc.session.list discuss.channel.rtc.session list New
discuss_gif_favorite_view_form discuss.gif.favorite.form discuss.gif.favorite form New
discuss_gif_favorite_view_tree discuss.gif.favorite.list discuss.gif.favorite list New
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
email_template_form email.template.form mail.template form New
email_template_tree email.template.list mail.template list New
field_form_view ir.model.fields field Inherits base.view_model_fields_form
ir_cron_view_form ir.cron.view.form.inherit ir.cron xpath Inherits base.ir_cron_view_form
ir_filters_view_form ir.filters.view.form.inherit ir.filters xpath Inherits base.ir_filters_view_form
ir_filters_view_tree ir.filters.view.tree.inherit ir.filters xpath Inherits base.ir_filters_view_tree
ir_mail_server_view_form ir.mail_server.view.form.inherit.mail ir.mail_server xpath Inherits base.ir_mail_server_form
mail.discuss_channel_view_form discuss.channel.form discuss.channel form New
mail.discuss_channel_view_kanban discuss.channel.kanban discuss.channel kanban New
mail.discuss_channel_view_list discuss.channel.list discuss.channel list New
mail.discuss_channel_view_search discuss.channel.search discuss.channel search New
mail.discuss_channel_view_tree discuss.channel.list discuss.channel list New
mail.discuss_public_channel_template Discuss Public Template ir.ui.view qweb New
mail.message_document_unfollowed mail.message_document_unfollowed ir.ui.view qweb New
mail.public_layout mail.public_layout ir.ui.view qweb New
mail_activity_plan_template_view_form mail.activity.plan.template.view.form mail.activity.plan.template form New
mail_activity_plan_template_view_tree mail.activity.plan.template.view.list mail.activity.plan.template list New
mail_activity_plan_view_form mail.activity.plan.view.form mail.activity.plan form New
mail_activity_plan_view_form_fixed_model mail.activity.plan.view.form.fixed.model mail.activity.plan xpath Inherits mail.mail_activity_plan_view_form
mail_activity_plan_view_kanban mail.activity.plan.view.kanban mail.activity.plan kanban New
mail_activity_plan_view_search mail.activity.plan.view.search mail.activity.plan search New
mail_activity_plan_view_tree mail.activity.plan.view.list mail.activity.plan list New
mail_activity_plan_view_tree_detailed mail.activity.plan.view.list.detailed mail.activity.plan xpath Inherits mail.mail_activity_plan_view_tree
mail_activity_schedule_view_form Activity schedule mail.activity.schedule form New
mail_activity_type_view_form mail.activity.type.view.form mail.activity.type form New
mail_activity_type_view_kanban mail.activity.type.view.kanban mail.activity.type kanban New
mail_activity_type_view_search mail.activity.type.search mail.activity.type search New
mail_activity_type_view_tree mail.activity.type.view.list mail.activity.type list New
mail_activity_view_calendar mail.activity.view.calendar mail.activity calendar New
mail_activity_view_form mail.activity.view.form mail.activity field Inherits mail.mail_activity_view_form_popup
mail_activity_view_form_popup mail.activity.view.form.popup mail.activity form New
mail_activity_view_form_without_record_access mail.activity.view.form.without.record.access mail.activity form New
mail_activity_view_kanban_open_target mail.activity.view.kanban.open.target mail.activity kanban New
mail_activity_view_search mail.activity.view.search mail.activity search New
mail_activity_view_tree mail.activity.view.list mail.activity list New
mail_activity_view_tree_open_target mail.activity.view.list.open.target mail.activity xpath Inherits mail_activity_view_tree
mail_activity_view_tree_without_record_access mail.activity.view.list.without.record.access mail.activity xpath Inherits mail_activity_view_tree
mail_alias_domain_view_form mail.alias.domain.view.form mail.alias.domain form New
mail_alias_domain_view_search mail.alias.domain.view.search mail.alias.domain search New
mail_alias_domain_view_tree mail.alias.domain.view.list mail.alias.domain list New
mail_alias_view_form mail.alias.view.form mail.alias form New
mail_alias_view_search mail.alias.view.search mail.alias search New
mail_alias_view_tree mail.alias.view.list mail.alias list New
mail_attachment_links Attachment links ir.ui.view qweb New
mail_blacklist_remove_view_form mail.blacklist.remove.form mail.blacklist.remove form New
mail_blacklist_view_form mail.blacklist.view.form mail.blacklist form New
mail_blacklist_view_search mail.blacklist.view.search mail.blacklist search New
mail_blacklist_view_tree mail.blacklist.view.list mail.blacklist list New
mail_bounce_alias_security mail_bounce_alias_security ir.ui.view qweb New
mail_bounce_catchall mail_bounce_catchall ir.ui.view qweb New
mail_canned_response_view_form mail.canned.response.form mail.canned.response form New
mail_canned_response_view_kanban mail.canned.response.kanban mail.canned.response kanban New
mail_canned_response_view_search mail.canned.response.view.search mail.canned.response search New
mail_canned_response_view_tree mail.canned.response.list mail.canned.response list New
mail_compose_message_view_form_template_save mail.compose.message.view.form.template.save mail.compose.message form New
mail_followers_edit_form mail.followers.edit.form mail.followers.edit form New
mail_followers_list_edit_form mail.followers.list.edit.form mail.followers.edit data Inherits mail_followers_edit_form
mail_gateway_allowed_view_search mail.gateway.allowed.view.search mail.gateway.allowed search New
mail_gateway_allowed_view_tree mail.gateway.allowed.view.list mail.gateway.allowed list New
mail_guest_view_form mail.guest.form mail.guest form New
mail_guest_view_tree mail.guest.list mail.guest list New
mail_link_preview_view_form mail.link.preview.form mail.link.preview form New
mail_link_preview_view_tree mail.link.preview.list mail.link.preview list New
mail_message_reaction_view_form mail.message.reaction.form mail.message.reaction form New
mail_message_reaction_view_tree mail.message.reaction.list mail.message.reaction list New
mail_message_schedule_view_form mail.message.schedule.view.form mail.message.schedule form New
mail_message_schedule_view_search mail.message.schedule.view.search mail.message.schedule search New
mail_message_schedule_view_tree mail.message.schedule.view.list mail.message.schedule list New
mail_message_subtype_view_search mail.message.subtype.view.search mail.message.subtype search New
mail_message_view_form mail.message.view.form mail.message form New
mail_notification_invite mail_notification_invite ir.ui.view qweb Inherits mail.mail_notification_layout
mail_notification_layout Mail: mail notification layout template ir.ui.view qweb New
mail_notification_layout_with_responsible_signature Mail: mail notification layout with responsible signature (user_id of the record) ir.ui.view qweb Inherits mail.mail_notification_layout
mail_notification_light mail_notification_light ir.ui.view qweb New
mail_notification_multi_invite mail_notification_multi_invite ir.ui.view qweb Inherits mail.mail_notification_invite
mail_notification_view_form mail.notification.view.form mail.notification form New
mail_notification_view_tree mail.notification.view.list mail.notification list New
mail_scheduled_message_view_form mail.scheduled.message.view.form mail.scheduled.message form New
mail_template_preview_view_form mail.template.preview.view.form mail.template.preview form New
mail_template_reset_view_form mail.template.reset.view.form mail.template.reset form New
message_activity_assigned message_activity_assigned ir.ui.view qweb New
message_activity_done message_activity_done ir.ui.view qweb New
message_link_preview_list mail.message.link.preview.list mail.message.link.preview list New
message_notification_limit_email message_notification_limit_email ir.ui.view qweb New
message_notification_out_of_office message_notification_out_of_office ir.ui.view qweb New
message_origin_link message_origin_link ir.ui.view qweb New
message_user_assigned message_user_assigned ir.ui.view qweb New
model_form_view ir.model field Inherits base.view_model_form
model_search_view ir.model field Inherits base.view_model_search
notification_preview notification_preview ir.ui.view qweb New
res_company_view_form res.company.view.form.inherit.mail res.company field Inherits base.view_company_form
res_config_settings_view_form res.config.settings.view.form.inherit.mail res.config.settings div Inherits base_setup.res_config_settings_view_form
res_partner_view_activity res.partner.activity res.partner activity New
res_partner_view_form_inherit_mail res.partner.view.form.inherit.mail res.partner xpath Inherits base.view_partner_form
res_partner_view_kanban_inherit_mail res.partner.view.kanban.inherit.mail res.partner xpath Inherits base.res_partner_kanban_view
res_partner_view_search_inherit_mail res.partner.view.search.inherit.mail res.partner filter Inherits base.view_res_partner_filter
res_partner_view_tree_inherit_mail res.partner.view.list.inherit.mail res.partner xpath Inherits base.view_partner_tree
res_role_view_form res.role.form res.role form New
res_role_view_search res.role.view.search res.role search New
res_role_view_tree res.role.list res.role list New
res_users_settings_view_form res.users.settings.form res.users.settings form New
res_users_settings_view_tree res.users.settings.list res.users.settings list New
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_email_server_form fetchmail.server.form fetchmail.server form New
view_email_server_search fetchmail.server.search fetchmail.server search New
view_email_server_tree fetchmail.server.list fetchmail.server list New
view_email_template_search email.template.search mail.template search New
view_followers_tree mail.followers.list mail.followers list New
view_ice_server_form mail.ice.server.form mail.ice.server form New
view_ice_server_kanban mail.ice.server.kanban mail.ice.server kanban New
view_ice_server_search mail.ice.server.search mail.ice.server search New
view_ice_server_tree mail.ice.server.list mail.ice.server list New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tracking_value_form mail.tracking.value.form mail.tracking.value form New
view_mail_tracking_value_tree mail.tracking.value.list mail.tracking.value list New
view_mail_tree mail.mail.list mail.mail list New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.list mail.message.subtype list New
view_message_tree mail.message.list mail.message list New
view_server_action_form_template ir.actions.server.form ir.actions.server xpath Inherits base.view_server_action_form
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (83)

New fields (0)

No new fields.

Public methods (4)
  • mail_allowed_qweb_expressions(self)
    @api.model
  • mail_get_partner_fields(self)
  • unlink(self)
  • with_user(self, user)
    Override to ensure the guest context is removed as the target user in a with_user should never be considered as being the guest of the outside env.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (5)
  • channel_id Many2one → discuss.channel
    index=True ondelete='cascade' required=True args: 'discuss.channel'
  • duration_hour Float
    compute='_compute_duration_hour'
  • end_dt Datetime
  • start_call_message_id Many2one → mail.message
    index=True args: 'mail.message'
  • start_dt Datetime
    index=True required=True
Public methods (0)

No public methods.

New fields (30)
  • active Boolean
    default=True help='Set active to false to hide the channel without removing it.'
  • avatar_128 Image
    compute='_compute_avatar_128' max_height=128 max_width=128 args: 'Avatar'
  • avatar_cache_key Char
    compute='_compute_avatar_cache_key'
  • call_history_ids One2many → discuss.call.history
    args: 'discuss.call.history', 'channel_id'
  • channel_member_ids One2many → discuss.channel.member
    string='Members' args: 'discuss.channel.member', 'channel_id'
  • channel_name_member_ids One2many → discuss.channel.member
    compute='_compute_channel_name_member_ids' help='Members from which the channel name is computed when the name field is empty.' args: 'discuss.channel.member'
  • channel_partner_ids Many2many → res.partner
    compute='_compute_channel_partner_ids' inverse='_inverse_channel_partner_ids' search='_search_channel_partner_ids' string='Partners' args: 'res.partner'
  • channel_type Selection
    default='channel' help='Chat is private and unique between 2 persons. Group is private among invited persons. Channel can be freely joined (depending on its configuration).' readonly=True required=True string='Channel Type' args: [('chat', 'Chat'), ('channel', 'Channel'), ('group', 'Group')]
  • default_display_mode Selection
    help='Determines how the channel will be displayed by default when opening it from its invitation link. No value means display text (no voice/video).' selection=[('video_full_screen', 'Full screen video')] string='Default Display Mode'
  • description Text
    args: 'Description'
  • from_message_id Many2one → mail.message
    help='The message the channel was created from.' readonly=True args: 'mail.message'
  • group_ids Many2many → res.groups
    help='Members of those groups will automatically added as followers. Note that they will be able to manage their subscription manually if necessary.' string='Auto Subscription' args: 'res.groups'
  • group_public_id Many2one → res.groups
    compute='_compute_group_public_id' readonly=False recursive=True store=True string='Authorized Group' args: 'res.groups'
  • image_128 Image
    max_height=128 max_width=128 args: 'Image'
  • invitation_url Char
    compute='_compute_invitation_url' args: 'Invitation URL'
  • invited_member_ids One2many → discuss.channel.member
    compute='_compute_invited_member_ids' compute_sudo=True args: 'discuss.channel.member'
  • is_editable Boolean
    compute='_compute_is_editable' args: 'Is Editable'
  • is_member Boolean
    compute='_compute_is_member' compute_sudo=True search='_search_is_member' args: 'Is Member'
  • last_interest_dt Datetime
    default=<expr> help='Contains the date and time of the last interesting event that happened in this channel. This updates itself when new message posted.' index=True args: 'Last Interest'
  • member_count Integer
    compute='_compute_member_count' compute_sudo=True string='Member Count'
  • message_count Integer
    compute='_compute_message_count' readonly=True args: '# Messages'
  • name Char
    required=True args: 'Name'
  • parent_channel_id Many2one → discuss.channel
    bypass_search_access=True help='Parent channel' index=True ondelete='cascade' readonly=True args: 'discuss.channel'
  • pinned_message_ids One2many → mail.message
    domain=[('model', '=', 'discuss.channel'), ('pinned_at', '!=', False)] string='Pinned Messages' args: 'mail.message', 'res_id'
  • rtc_session_ids One2many → discuss.channel.rtc.session
    groups='base.group_system' args: 'discuss.channel.rtc.session', 'channel_id'
  • self_member_id Many2one → discuss.channel.member
    compute='_compute_self_member_id' compute_sudo=True args: 'discuss.channel.member'
  • sfu_channel_uuid Char
    groups='base.group_system'
  • sfu_server_url Char
    groups='base.group_system'
  • sub_channel_ids One2many → discuss.channel
    readonly=True string='Sub Channels' args: 'discuss.channel', 'parent_channel_id'
  • uuid Char
    copy=False default=_generate_random_token size=50 args: 'UUID'
Public methods (17)
  • action_unfollow(self)
  • add_members(self, partner_ids=None, guest_ids=None, invite_to_rtc_call=False, post_joined_message=True)
    Adds the given partner_ids and guest_ids as member of self channels.
  • channel_change_description(self, description)
  • channel_fetched(self)
    Broadcast the channel_fetched notification to channel members
  • channel_join(self)
    Shortcut to add the current user as member of self channels. Prefer calling add_members() directly when possible.
  • channel_pin(self, pinned=False)
  • channel_rename(self, name)
  • channel_set_custom_name(self, name)
  • create(self, vals_list)
    @api.model_create_multi
  • execute_command_help(self, **kwargs)
  • execute_command_leave(self, **kwargs)
  • execute_command_who(self, **kwargs)
  • get_mention_suggestions(self, search, limit=8)
    @api.readonly@api.model
    Return 'limit'-first channels' name, channel_type and group_public_id fields such that the name matches a 'search' string. Exclude channels of type chat (DM) and group.
  • invite_by_email(self, emails)
    Send channel invitation emails to a list of email addresses. Existing members' email addresses are ignored. :param emails: List of email addresses to invite. :type emails: list[str]
  • message_post(self, *, message_type='notification', partner_ids=None, **kwargs)
  • set_message_pin(self, message_id, pinned)
    (Un)pin a message on the channel and send a notification to the members. :param message_id: id of the message to be pinned. :param pinned: whether the message should be pinned or unpinned.
  • write(self, vals)

New fields (17)
  • channel_id Many2one → discuss.channel
    bypass_search_access=True ondelete='cascade' required=True args: 'discuss.channel', 'Channel'
  • custom_channel_name Char
    args: 'Custom channel name'
  • custom_notifications Selection
    help='Use default from user settings if not specified. This setting will only be applied to channels.' args: [('all', 'All Messages'), ('mentions', 'Mentions Only'), ('no_notif', 'Nothing')], 'Customized Notifications'
  • fetched_message_id Many2one → mail.message
    index='btree_not_null' string='Last Fetched' args: 'mail.message'
  • guest_id Many2one → mail.guest
    index=True ondelete='cascade' args: 'mail.guest', 'Guest'
  • is_pinned Boolean
    compute='_compute_is_pinned' search='_search_is_pinned' args: 'Is pinned on the interface'
  • is_self Boolean
    compute='_compute_is_self' search='_search_is_self'
  • last_interest_dt Datetime
    default=<expr> help='Contains the date and time of the last interesting event that happened in this channel for this user. This includes: creating, joining, pinning' index=True args: 'Last Interest'
  • last_seen_dt Datetime
    args: 'Last seen date'
  • message_unread_counter Integer
    compute='_compute_message_unread' compute_sudo=True args: 'Unread Messages Counter'
  • mute_until_dt Datetime
    help='If set, the member will not receive notifications from the channel until this date.' args: 'Mute notifications until'
  • new_message_separator Integer
    default=0 help='Message id before which the separator should be displayed' required=True
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner', 'Partner'
  • rtc_inviting_session_id Many2one → discuss.channel.rtc.session
    string='Ringing session' args: 'discuss.channel.rtc.session'
  • rtc_session_ids One2many → discuss.channel.rtc.session
    comodel_name='discuss.channel.rtc.session' inverse_name='channel_member_id' string='RTC Sessions'
  • seen_message_id Many2one → mail.message
    index='btree_not_null' string='Last Seen' args: 'mail.message'
  • unpin_dt Datetime
    help='Contains the date and time when the channel was unpinned by the user.' index=True args: 'Unpin date'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (9)
  • channel_id Many2one → discuss.channel
    index='btree_not_null' readonly=True related='channel_member_id.channel_id' store=True args: 'discuss.channel'
  • channel_member_id Many2one → discuss.channel.member
    ondelete='cascade' required=True args: 'discuss.channel.member'
  • guest_id Many2one → mail.guest
    related='channel_member_id.guest_id' args: 'mail.guest'
  • is_camera_on Boolean
    string='Is sending user video'
  • is_deaf Boolean
    string='Has disabled incoming sound'
  • is_muted Boolean
    string='Is microphone muted'
  • is_screen_sharing_on Boolean
    string='Is sharing the screen'
  • partner_id Many2one → res.partner
    index=True related='channel_member_id.partner_id' store=True string='Partner' args: 'res.partner'
  • write_date Datetime
    index=True args: 'Last Updated On'
Public methods (3)
  • action_disconnect(self)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)

New fields (1)
  • tenor_gif_id Char
    required=True args: 'GIF id from Tenor'
Public methods (0)

No public methods.

New fields (1)
  • attachment_id Many2one → ir.attachment
    bypass_search_access=True copy=False index=True ondelete='cascade' args: 'ir.attachment'
Public methods (0)

No public methods.

New fields (20)
  • active Boolean
    default=True args: 'Active'
  • attach Boolean
    default=True help='Whether attachments should be downloaded. If not enabled, incoming emails will be stripped of any attachments before being processed' args: 'Keep Attachments'
  • configuration Text
    readonly=True args: 'Configuration'
  • date Datetime
    readonly=True string='Last Fetch Date'
  • error_date Datetime
    help='Date of last failure, reset on success.' readonly=True string='Last Error Date'
  • error_message Text
    readonly=True string='Last Error Message'
  • is_ssl Boolean
    help='Connections are encrypted with SSL/TLS through a dedicated port (default: IMAPS=993, POP3S=995)' args: 'SSL/TLS'
  • message_ids One2many → mail.mail
    readonly=True string='Messages' args: 'mail.mail', 'fetchmail_server_id'
  • name Char
    required=True args: 'Name'
  • object_id Many2one → ir.model
    help='Process each incoming mail as part of a conversation corresponding to this document type. This will create new documents for new conversations, or attach follow-up emails to the existing conversations (documents).' string='Create a New Record' args: 'ir.model'
  • original Boolean
    help='Whether a full original copy of each email should be kept for reference and attached to each processed message. This will usually double the size of your message database.' args: 'Keep Original'
  • password Char
  • port Integer
  • priority Integer
    default=5 help='Defines the order of processing, lower values mean higher priority' readonly=False string='Server Priority'
  • script Char
    default='/mail/static/scripts/odoo-mailgate.py' readonly=True
  • server Char
    help='Hostname or IP of the mail server' readonly=False string='Server Name'
  • server_type Selection
    default='imap' index=True required=True string='Server Type' args: [('imap', 'IMAP Server'), ('pop', 'POP Server'), ('local', 'Local Server')]
  • server_type_info Text
    compute='_compute_server_type_info' args: 'Server Type Info'
  • state Selection
    copy=False default='draft' index=True readonly=True string='Status' args: [('draft', 'Not Confirmed'), ('done', 'Confirmed')]
  • user Char
    readonly=False string='Username'
Public methods (7)
  • button_confirm_login(self)
  • create(self, vals_list)
    @api.model_create_multi
  • fetch_mail(self)
    Action to fetch the mail from the current server.
  • onchange_server_type(self)
    @api.onchange('server_type', 'is_ssl', 'object_id')
  • set_draft(self)
  • unlink(self)
  • write(self, vals)

New fields (1)
  • view_mode Selection
    ondelete={'activity': 'cascade'} selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (23)
  • activity_date_deadline_range Integer
    compute='_compute_activity_info' readonly=False store=True string='Due Date In'
  • activity_date_deadline_range_type Selection
    compute='_compute_activity_info' readonly=False store=True string='Due type' args: [('days', 'Days'), ('weeks', 'Weeks'), ('months', 'Months')]
  • activity_note Html
    compute='_compute_activity_info' readonly=False store=True args: 'Note'
  • activity_summary Char
    compute='_compute_activity_info' readonly=False store=True args: 'Title'
  • activity_type_id Many2one → mail.activity.type
    compute='_compute_activity_info' domain="['|', ('res_model', '=', False), ('res_model', '=', model_name)]" ondelete='restrict' readonly=False store=True string='Activity Type' args: 'mail.activity.type'
  • activity_user_field_name Char
    compute='_compute_activity_user_info' readonly=False store=True args: 'User Field'
  • activity_user_id Many2one → res.users
    compute='_compute_activity_user_info' readonly=False store=True string='Responsible' args: 'res.users'
  • activity_user_type Selection
    compute='_compute_activity_info' help="Use 'Specific User' to always assign the same user on the next activity. Use 'Dynamic User' to specify the field name of the user to choose on the record." readonly=False store=True string='User Type' args: [('specific', 'Specific User'), ('generic', 'Dynamic User (based on record)')]
  • crud_model_id Many2one
    tracking=True
  • evaluation_type Selection
    tracking=True
  • followers_partner_field_name Char
    compute='_compute_followers_info' readonly=False store=True string='Followers Field'
  • followers_type Selection
    compute='_compute_followers_type' help="\n - Specific Followers: select specific contacts to add/remove from record's followers.\n - Dynamic Followers: all contacts of the chosen record's field will be added/removed from followers.\n " readonly=False selection=[('specific', 'Specific Followers'), ('generic', 'Dynamic Followers')] store=True string='Followers Type'
  • link_field_id Many2one
    tracking=True
  • mail_post_autofollow Boolean
    compute='_compute_mail_post_autofollow' readonly=False store=True args: 'Subscribe Recipients'
  • mail_post_method Selection
    compute='_compute_mail_post_method' readonly=False selection=[('email', 'Email'), ('comment', 'Message'), ('note', 'Note')] store=True string='Send Email As'
  • model_id Many2one
    tracking=True
  • name Char
    tracking=True
  • partner_ids Many2many → res.partner
    compute='_compute_followers_info' readonly=False store=True args: 'res.partner'
  • state Selection
    ondelete={'mail_post': 'cascade', 'followers': 'cascade', 'remove_followers': 'cascade', 'next_activity': 'cascade'} selection_add=[('next_activity', 'Create Activity'), ('mail_post', 'Send Email'), ('followers', 'Add Followers'), ('remove_followers', 'Remove Followers'), ('code')] tracking=True
  • template_id Many2one → mail.template
    compute='_compute_template_id' domain="[('model_id', '=', model_id)]" ondelete='set null' readonly=False store=True args: 'mail.template', 'Email Template'
  • update_path Char
    tracking=True
  • value Text
    tracking=True
  • webhook_url Char
    tracking=True
Public methods (0)

No public methods.

New fields (2)
  • has_thumbnail Boolean
    compute='_compute_has_thumbnail'
  • thumbnail Image
Public methods (1)
  • register_as_main_attachment(self, force=True)
    Registers this attachment as the main one of the model it is attached to. :param bool force: if set, the method always updates the existing main attachment otherwise it only sets the main attachment if there is none.

New fields (1)
  • voice_ids One2many → discuss.voice.metadata
    args: 'discuss.voice.metadata', 'attachment_id'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • set_param(self, key, value)
    @api.model
  • write(self, vals)

New fields (4)
  • interval_number Integer
    tracking=True
  • interval_type Selection
    tracking=True
  • priority Integer
    tracking=True
  • user_id Many2one
    tracking=True
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • session_info(self)
    Override to add the current user data (partner or guest) if applicable.

New fields (4)
  • mail_template_ids One2many → mail.template
    comodel_name='mail.template' inverse_name='mail_server_id' readonly=True string='Mail template using this mail server'
  • owner_limit_count Integer
    copy=False args: 'Owner Limit Count'
  • owner_limit_time Datetime
    copy=False args: 'Owner Limit Time'
  • owner_user_id Many2one → res.users
    copy=False args: 'res.users', 'Owner'
Public methods (0)

No public methods.

New fields (3)
  • is_mail_activity Boolean
    default=False string='Has Mail Activity'
  • is_mail_blacklist Boolean
    default=False string='Has Mail Blacklist'
  • is_mail_thread Boolean
    default=False string='Has Mail Thread'
Public methods (2)
  • unlink(self)
    Delete mail data (followers, messages, activities) associated with the models being deleted.
  • write(self, vals)

New fields (1)
  • tracking Integer
    help='If set every modification done to this field is tracked. Value is used to order tracking values.' string='Enable Ordered Tracking'
Public methods (1)
  • unlink(self)
    When unlinking fields populate tracking value table with relevant information. That way if a field is removed (custom tracked, migration or any other reason) we keep the tracking and its relevant information. Do it only when unlinking fields so that we don't duplicate field information for most tracking.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (1)
  • type Selection
    selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (25)
  • active Boolean
    default=True
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_decoration Selection
    readonly=True related='activity_type_id.decoration_type'
  • activity_type_id Many2one → mail.activity.type
    default=_default_activity_type domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" ondelete='restrict' string='Activity Type' args: 'mail.activity.type'
  • attachment_ids Many2many → ir.attachment
    bypass_search_access=True string='Attachments' args: 'ir.attachment', 'activity_attachment_rel', 'activity_id', 'attachment_id'
  • automated Boolean
    help='Indicates this activity has been created automatically and not by any user.' readonly=True args: 'Automated activity'
  • can_write Boolean
    compute='_compute_can_write'
  • chaining_type Selection
    readonly=True related='activity_type_id.chaining_type'
  • date_deadline Date
    default=fields.Date.context_today index=True required=True args: 'Due Date'
  • date_done Date
    compute='_compute_date_done' store=True args: 'Done Date'
  • feedback Text
    args: 'Feedback'
  • has_recommended_activities Boolean
    compute='_compute_has_recommended_activities' args: 'Next activities available'
  • icon Char
    readonly=True related='activity_type_id.icon' args: 'Icon'
  • mail_template_ids Many2many
    readonly=True related='activity_type_id.mail_template_ids'
  • note Html
    sanitize_style=True args: 'Note'
  • previous_activity_type_id Many2one → mail.activity.type
    readonly=True string='Previous Activity Type' args: 'mail.activity.type'
  • recommended_activity_type_id Many2one → mail.activity.type
    string='Recommended Activity Type' args: 'mail.activity.type'
  • res_id Many2oneReference
    index=True model_field='res_model' string='Related Document ID'
  • res_model Char
    index=True precompute=True readonly=True related='res_model_id.model' store=True args: 'Related Document Model'
  • res_model_id Many2one → ir.model
    index=True ondelete='cascade' required=False args: 'ir.model', 'Document Model'
  • res_name Char
    compute='_compute_res_name' compute_sudo=True readonly=True store=True args: 'Document Name'
  • state Selection
    compute='_compute_state' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned'), ('done', 'Done')], 'State'
  • summary Char
    args: 'Summary'
  • user_id Many2one → res.users
    index=True ondelete='cascade' required=False args: 'res.users', 'Assigned to'
  • user_tz Selection
    related='user_id.tz' store=True string='Timezone'
Public methods (18)
  • action_cancel(self)
  • action_close_dialog(self)
    @api.readonly
  • action_done(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_done_redirect_to_other(self)
    Mark activity as done and return action mail.mail_activity_without_access_action. Goal: Unless "keep done" activity is enabled, when marking an activity as done, the activity is deleted and can no more be displayed. To overcome this, we return an action that will launch the list view displaying the activities corresponding to the active_ids from the context (i.e.: the remaining "other activities"). If the right context is not available, we recompute the activities to display.
  • action_done_schedule_next(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_feedback(self, feedback=False, attachment_ids=None)
  • action_feedback_schedule_next(self, feedback=False, attachment_ids=None)
  • action_notify(self)
  • action_open_document(self)
    @api.readonly
    Opens the related record based on the model and ID, or activity if user has no access to the related record.
  • action_reschedule_nextweek(self)
  • action_reschedule_today(self)
  • action_reschedule_tomorrow(self)
  • activity_format(self)
    @api.readonly
  • create(self, vals_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • get_activity_data(self, res_model, domain, limit=None, offset=0, fetch_done=False)
    @api.readonly@api.model
    Get aggregate data about records and their activities. The goal is to fetch and compute aggregated data about records and their activities to display them in the activity views and the chatter. For example, the activity view displays it as a table with columns and rows being respectively the activity_types and the activity_res_ids, and the grouped_activities being the table entries with the aggregated data. :param str res_model: model of the records to fetch :param list domain: record search domain :param int limit: maximum number of records to fetch :param int offset: offset of the first record to fetch :param bool fetch_done: determines if "done" activities are integrated in the aggregated data or not. :returns: {'activity_types': dict of activity type info {id: int, name: str, mail_template: list of {id:int, name:str}} 'activity_res_ids': list<int> of record id ordered by closest date (deadline for ongoing activities, and done date for done activities) 'grouped_activities': dict<dict> res_id -> activity_type_id -> aggregated info as: count_by_state dict: mapping state to count (ex.: 'planned': 2) ids list: activity ids for the res_id and activity_type_id reporting_date str: aggregated date of the related activities as oldest deadline of ongoing activities if there are any or most recent date done of completed activities state dict: aggregated state of the related activities user_assigned_ids list: activity responsible id ordered by closest deadline of the related activities attachments_info: dict with information about the attachments {'count': int, 'most_recent_id': int, 'most_recent_name': str} } :rtype: dict
  • unlink(self)
  • write(self, vals)

New fields (10)
  • activity_date_deadline Date
    compute='_compute_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_activity_date_deadline' store=False args: 'Next Activity Deadline'
  • activity_exception_decoration Selection
    compute='_compute_activity_exception_type' help='Type of the exception activity on record.' search='_search_activity_exception_decoration' args: [('warning', 'Alert'), ('danger', 'Error')]
  • activity_exception_icon Char
    compute='_compute_activity_exception_type' help='Icon to indicate an exception activity.' args: 'Icon'
  • activity_ids One2many → mail.activity
    bypass_search_access=True groups='base.group_user' args: 'mail.activity', 'res_id', 'Activities'
  • activity_state Selection
    compute='_compute_activity_state' groups='base.group_user' help='Status based on activities\nOverdue: Due date is already passed\nToday: Activity date is today\nPlanned: Future activities.' search='_search_activity_state' string='Activity State' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')]
  • activity_summary Char
    groups='base.group_user' readonly=False related='activity_ids.summary' search='_search_activity_summary' args: 'Next Activity Summary'
  • activity_type_icon Char
    related='activity_ids.icon' args: 'Activity Type Icon'
  • activity_type_id Many2one → mail.activity.type
    groups='base.group_user' readonly=False related='activity_ids.activity_type_id' search='_search_activity_type_id' args: 'mail.activity.type', 'Next Activity Type'
  • activity_user_id Many2one → res.users
    compute='_compute_activity_user_id' groups='base.group_user' readonly=True search='_search_activity_user_id' args: 'res.users', 'Responsible User'
  • my_activity_date_deadline Date
    compute='_compute_my_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_my_activity_date_deadline' args: 'My Activity Deadline'
Public methods (9)
  • action_reschedule_my_next_nextweek(self)
  • action_reschedule_my_next_today(self)
  • action_reschedule_my_next_tomorrow(self)
  • activity_feedback(self, act_type_xmlids, user_id=None, feedback=None, attachment_ids=None, only_automated=True)
    Set activities as done, limiting to some activity types and optionally to a given user.
  • activity_reschedule(self, act_type_xmlids, user_id=None, date_deadline=None, new_user_id=None, only_automated=True)
    Reschedule some automated activities. Activities to reschedule are selected based on type xml ids and optionally by user. Purpose is to be able to * update the deadline to date_deadline; * update the responsible to new_user_id;
  • activity_schedule(self, act_type_xmlid='', date_deadline=None, summary='', note='', **act_values)
    Schedule an activity on each record of the current record set. This method allow to provide as parameter act_type_xmlid. This is an xml_id of activity type instead of directly giving an activity_type_id. It is useful to avoid having various "env.ref" in the code and allow to let the mixin handle access rights. Note that unless specified otherwise in act_values, the activities created will have their "automated" field set to True. :param date_deadline: the day the activity must be scheduled on the timezone of the user must be considered to set the correct deadline
  • activity_search(self, act_type_xmlids='', user_id=None, additional_domain=None, only_automated=True)
    Search automated activities on current record set, given a list of activity types xml IDs. It is useful when dealing with specific types involved in automatic activities management. :param act_type_xmlids: list of activity types xml IDs :param user_id: if set, restrict to activities of that user_id; :param additional_domain: if set, filter on that domain; :param only_automated: if unset, search for all activities, not only automated ones;
  • activity_send_mail(self, template_id)
    Automatically send an email based on the given mail.template, given its ID.
  • activity_unlink(self, act_type_xmlids, user_id=None, only_automated=True)
    Unlink activities, limiting to some activity types and optionally to a given user.

New fields (8)
  • active Boolean
    default=True
  • company_id Many2one → res.company
    default=<expr> args: 'res.company'
  • has_user_on_demand Boolean
    compute='_compute_has_user_on_demand' args: 'Has on demand responsible'
  • name Char
    required=True args: 'Name'
  • res_model Selection
    help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' required=True selection=_get_model_selection string='Model'
  • res_model_id Many2one → ir.model
    compute='_compute_res_model_id' compute_sudo=True ondelete='cascade' precompute=True readonly=False required=True store=True string='Applies to' args: 'ir.model'
  • steps_count Integer
    compute='_compute_steps_count'
  • template_ids One2many → mail.activity.plan.template
    copy=True string='Activities' args: 'mail.activity.plan.template', 'plan_id'
Public methods (1)
  • copy_data(self, default=None)

New fields (14)
  • activity_type_id Many2one → mail.activity.type
    default=<expr> domain="['|', ('res_model', '=', False), '&', ('res_model', '!=', False), ('res_model', '=', parent.res_model)]" ondelete='restrict' required=True args: 'mail.activity.type', 'Activity Type'
  • company_id Many2one
    related='plan_id.company_id'
  • delay_count Integer
    default=0 help='Number of days/week/month before executing the action after or before the scheduled plan date.' args: 'Interval'
  • delay_from Selection
    default='before_plan_date' required=True string='Trigger' args: [('before_plan_date', 'Before Plan Date'), ('after_plan_date', 'After Plan Date')]
  • delay_unit Selection
    default='days' help='Unit of delay' required=True string='Delay units' args: [('days', 'days'), ('weeks', 'weeks'), ('months', 'months')]
  • icon Char
    readonly=True related='activity_type_id.icon' args: 'Icon'
  • next_activity_ids Many2many → mail.activity.type
    compute='_compute_next_activity_ids' readonly=False store=True string='Next Activities' args: 'mail.activity.type'
  • note Html
    compute='_compute_note' readonly=False store=True args: 'Note'
  • plan_id Many2one → mail.activity.plan
    index=True ondelete='cascade' required=True string='Plan' args: 'mail.activity.plan'
  • res_model Selection
    related='plan_id.res_model'
  • responsible_id Many2one → res.users
    check_company=True compute='_compute_responsible_id' readonly=False store=True args: 'res.users', 'Assigned to'
  • responsible_type Selection
    compute='_compute_responsible_type' default='on_demand' readonly=False required=True store=True string='Assignment' args: [('on_demand', 'Ask at launch'), ('other', 'Default user')]
  • sequence Integer
    default=10
  • summary Char
    compute='_compute_summary' readonly=False store=True args: 'Summary'
Public methods (0)

No public methods.

New fields (22)
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_type_id Many2one → mail.activity.type
    compute='_compute_activity_type_id' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" ondelete='set null' readonly=False store=True string='Activity Type' args: 'mail.activity.type'
  • activity_user_id Many2one → res.users
    compute='_compute_activity_user_id' readonly=False store=True args: 'res.users', 'Assigned to'
  • chaining_type Selection
    readonly=True related='activity_type_id.chaining_type'
  • company_id Many2one → res.company
    compute='_compute_company_id' required=False args: 'res.company', 'Company'
  • date_deadline Date
    compute='_compute_date_deadline' readonly=False store=True args: 'Due Date'
  • error Html
    compute='_compute_error'
  • has_error Boolean
    compute='_compute_error'
  • has_warning Boolean
    compute='_compute_error'
  • is_batch_mode Boolean
    compute='_compute_is_batch_mode' args: 'Use in batch'
  • note Html
    compute='_compute_note' readonly=False sanitize_style=True store=True args: 'Note'
  • plan_available_ids Many2many → mail.activity.plan
    compute='_compute_plan_available_ids' compute_sudo=True store=True args: 'mail.activity.plan'
  • plan_date Date
    compute='_compute_plan_date' readonly=False store=True args: 'Plan Date'
  • plan_has_user_on_demand Boolean
    related='plan_id.has_user_on_demand'
  • plan_id Many2one → mail.activity.plan
    compute='_compute_plan_id' domain="[('id', 'in', plan_available_ids)]" readonly=False store=True args: 'mail.activity.plan'
  • plan_on_demand_user_id Many2one → res.users
    default=<expr> help='Choose assignation for activities with on demand assignation.' args: 'res.users', 'Assigned To'
  • plan_schedule_line_ids One2many → mail.activity.schedule.line
    compute='_compute_plan_schedule_line_ids' string='Schedule Lines' args: 'mail.activity.schedule.line', 'activity_schedule_id'
  • res_ids Text
    compute='_compute_res_ids' precompute=True readonly=False store=True args: 'Document IDs'
  • res_model Char
    readonly=False required=False args: 'Model'
  • res_model_id Many2one → ir.model
    compute='_compute_res_model_id' compute_sudo=True ondelete='cascade' precompute=True readonly=False required=False store=True string='Applies to' args: 'ir.model'
  • summary Char
    compute='_compute_summary' readonly=False store=True args: 'Summary'
  • warning Html
    compute='_compute_error'
Public methods (5)
  • action_schedule_activities(self)
  • action_schedule_activities_done(self)
  • action_schedule_plan(self)
  • default_get(self, fields)
    @api.model
  • get_model_options(self)
    @api.readonly@api.model
    Return a list of valid models for a user to define an activity on.

New fields (4)
  • activity_schedule_id Many2one → mail.activity.schedule
    ondelete='cascade' required=True string='Activity Schedule' args: 'mail.activity.schedule'
  • line_date_deadline Date
    args: 'Date Deadline'
  • line_description Char
    args: 'Line Description'
  • responsible_user_id Many2one → res.users
    string='Responsible User' args: 'res.users'
Public methods (0)

No public methods.

New fields (22)
  • active Boolean
    default=True
  • category Selection
    default='default' help='Actions may trigger specific behavior like opening calendar view or automatically mark as done when a document is uploaded' string='Action' args: [('default', 'None'), ('upload_file', 'Upload Document'), ('phonecall', 'Phonecall')]
  • chaining_type Selection
    default='suggest' required=True string='Chaining Type' args: [('suggest', 'Suggest Next Activity'), ('trigger', 'Trigger Next Activity')]
  • create_uid Many2one → res.users
    index=True args: 'res.users'
  • decoration_type Selection
    help='Change the background color of the related activities of this type.' string='Decoration Type' args: [('warning', 'Alert'), ('danger', 'Error')]
  • default_note Html
    string='Default Note' translate=True
  • default_user_id Many2one → res.users
    string='Default User' args: 'res.users'
  • delay_count Integer
    default=0 help='Number of days/week/month before executing the action. It allows to plan the action deadline.' args: 'Schedule'
  • delay_from Selection
    default='previous_activity' help='Type of delay' required=True string='Delay Type' args: [('current_date', 'after previous activity completion date'), ('previous_activity', 'after previous activity deadline')]
  • delay_label Char
    compute='_compute_delay_label'
  • delay_unit Selection
    default='days' help='Unit of delay' required=True string='Delay units' args: [('days', 'days'), ('weeks', 'weeks'), ('months', 'months')]
  • icon Char
    help='Font awesome icon e.g. fa-tasks' args: 'Icon'
  • initial_res_model Selection
    compute='_compute_initial_res_model' help='Technical field to keep track of the model at the start of editing to support UX related behaviour' selection=_get_model_selection store=False string='Initial model'
  • mail_template_ids Many2many → mail.template
    string='Email templates' args: 'mail.template'
  • name Char
    required=True translate=True args: 'Name'
  • previous_type_ids Many2many → mail.activity.type
    domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" string='Preceding Activities' args: 'mail.activity.type', 'mail_activity_rel', 'recommended_id', 'activity_id'
  • res_model Selection
    help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' selection=_get_model_selection string='Model'
  • res_model_change Boolean
    default=False store=False string='Model has change'
  • sequence Integer
    default=10 args: 'Sequence'
  • suggested_next_type_ids Many2many → mail.activity.type
    compute='_compute_suggested_next_type_ids' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" help='Suggest these activities once the current one is marked as done.' inverse='_inverse_suggested_next_type_ids' readonly=False store=True string='Suggest' args: 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id'
  • summary Char
    translate=True args: 'Default Summary'
  • triggered_next_type_id Many2one → mail.activity.type
    compute='_compute_triggered_next_type_id' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" help='Automatically schedule this activity once the current one is marked as done.' inverse='_inverse_triggered_next_type_id' ondelete='restrict' readonly=False store=True string='Trigger' args: 'mail.activity.type'
Public methods (3)
  • action_archive(self)
  • unlink(self)
    When removing an activity type, put activities into a Todo.
  • write(self, vals)

New fields (13)
  • alias_bounced_content Html
    help='If set, this content will automatically be sent out to unauthorized users instead of the default message.' translate=True args: 'Custom Bounced Message'
  • alias_contact Selection
    default='everyone' help='Policy to post a message on the document using the mailgateway.\n- everyone: everyone can post\n- partners: only authenticated partners\n- followers: only followers of the related document or members of following channels\n' required=True string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_defaults Text
    default='{}' help='A Python dictionary that will be evaluated to provide default values when creating new records for this alias.' required=True args: 'Default Values'
  • alias_domain Char
    related='alias_domain_id.name' args: 'Alias domain name'
  • alias_domain_id Many2one → mail.alias.domain
    default=<expr> ondelete='restrict' string='Alias Domain' args: 'mail.alias.domain'
  • alias_force_thread_id Integer
    help='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.' args: 'Record Thread ID'
  • alias_full_name Char
    compute='_compute_alias_full_name' index='btree_not_null' store=True args: 'Alias Email'
  • alias_incoming_local Boolean
    default=False args: 'Local-part based incoming detection'
  • alias_model_id Many2one → ir.model
    domain="[('field_id.name', '=', 'message_ids')]" help='The model (Odoo 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)' ondelete='cascade' required=True args: 'ir.model', 'Aliased Model'
  • alias_name Char
    copy=False help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>" args: 'Alias Name'
  • alias_parent_model_id Many2one → ir.model
    help='Parent model holding the alias. The model holding the alias reference is not necessarily the model given by alias_model_id (example: project (parent_model) and task (model))' args: 'ir.model', 'Parent Model'
  • alias_parent_thread_id Integer
    help='ID of the parent record holding the alias (example: project holding the task creation alias)' args: 'Parent Record Thread ID'
  • alias_status Selection
    compute='_compute_alias_status' help='Alias status assessed on the last message received.' store=True args: [('not_tested', 'Not Tested'), ('valid', 'Valid'), ('invalid', 'Invalid')]
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
    Creates mail.alias records according to the values provided in ``vals`` but sanitize 'alias_name' by replacing certain unsafe characters; set default alias domain if not given. :raise UserError: if given (alias_name, alias_domain_id) already exists or if there are duplicates in given vals_list;
  • open_document(self)
  • open_parent_document(self)
  • write(self, vals)
    Raise UserError with a meaningful message instead of letting the uniqueness constraint raise an SQL error. To check uniqueness we have to rebuild pairs of names / domains to validate, taking into account that a void alias_domain_id is acceptable (but also raises for uniqueness).

New fields (9)
  • bounce_alias Char
    default='bounce' help="Local-part of email used for Return-Path used when emails bounce e.g. 'bounce' in 'bounce@example.com'" required=True args: 'Bounce Alias'
  • bounce_email Char
    compute='_compute_bounce_email' args: 'Bounce Email'
  • catchall_alias Char
    default='catchall' help="Local-part of email used for Reply-To to catch answers e.g. 'catchall' in 'catchall@example.com'" required=True args: 'Catchall Alias'
  • catchall_email Char
    compute='_compute_catchall_email' args: 'Catchall Email'
  • company_ids One2many → res.company
    help='Companies using this domain as default for sending mails' string='Companies' args: 'res.company', 'alias_domain_id'
  • default_from Char
    default='notifications' help="Default from when it does not match outgoing server filters. Can be either a local-part e.g. 'notifications' either a complete email address e.g. 'notifications@example.com' to override all outgoing emails." args: 'Default From Alias'
  • default_from_email Char
    compute='_compute_default_from_email' args: 'Default From'
  • name Char
    help="Email domain e.g. 'example.com' in 'odoo@example.com'" required=True args: 'Name'
  • sequence Integer
    default=10
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
    Sanitize bounce_alias / catchall_alias / default_from
  • write(self, vals)
    Sanitize name / bounce_alias / catchall_alias / default_from

New fields (3)
  • alias_defaults Text
    inherited=True
  • alias_id Many2one
    required=True
  • alias_name Char
    inherited=True
Public methods (0)

No public methods.

New fields (6)
  • alias_defaults Text
    related='alias_id.alias_defaults'
  • alias_domain Char
    related='alias_id.alias_domain' args: 'Alias Domain Name'
  • alias_domain_id Many2one → mail.alias.domain
    readonly=False related='alias_id.alias_domain_id' string='Alias Domain' args: 'mail.alias.domain'
  • alias_email Char
    compute='_compute_alias_email' search='_search_alias_email' args: 'Email Alias'
  • alias_id Many2one → mail.alias
    copy=False ondelete='restrict' required=False string='Alias' args: 'mail.alias'
  • alias_name Char
    readonly=False related='alias_id.alias_name'
Public methods (4)
  • copy_data(self, default=None)
  • create(self, vals_list)
    @api.model_create_multi
    Create aliases using sudo if an alias is required, notably if its name is given.
  • unlink(self)
    Delete the given records, and cascade-delete their corresponding alias.
  • write(self, vals)
    Split writable fields of mail.alias and other fields alias fields will write with sudo and the other normally. Also handle alias_domain_id update. If alias does not exist and we try to set a name, create the alias automatically.

New fields (2)
  • active Boolean
    default=True tracking=2
  • email Char
    help='This field is case insensitive.' index='trigram' required=True string='Email Address' tracking=1
Public methods (4)
  • action_add(self)
  • create(self, vals_list)
    @api.model_create_multi
  • mail_action_blacklist_remove(self)
  • write(self, vals)

New fields (2)
  • email Char
    name='Email' readonly=True required=True
  • reason Char
    name='Reason'
Public methods (1)
  • action_unblacklist_apply(self)

New fields (6)
  • group_ids Many2many → res.groups
    domain=<expr> string='Authorized Groups' args: 'res.groups'
  • is_editable Boolean
    compute='_compute_is_editable' string='Determines if the canned response can be edited by the current user'
  • is_shared Boolean
    compute='_compute_is_shared' store=True string='Determines if the canned_response is currently shared with other users'
  • last_used Datetime
    help='Last time this canned_response was used' args: 'Last Used'
  • source Char
    help="Canned response that will automatically be substituted with longer content in your messages. Type '::' followed by the name of your shortcut (e.g. ::hello) to use in your messages." index='trigram' required=True args: 'Shortcut'
  • substitution Text
    help='Content that will automatically replace the shortcut of your choosing. This content can still be adapted before sending your message.' required=True args: 'Substitution'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (39)
  • attachment_ids Many2many → ir.attachment
    bypass_search_access=True compute='_compute_attachment_ids' readonly=False store=True string='Attachments' args: 'ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id'
  • author_id Many2one → res.partner
    compute='_compute_authorship' compute_sudo=False help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' readonly=False store=True string='Author' args: 'res.partner'
  • auto_delete Boolean
    compute='_compute_auto_delete' compute_sudo=False help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." readonly=False store=True args: 'Delete Emails'
  • auto_delete_keep_log Boolean
    compute='_compute_auto_delete_keep_log' help='Keep a copy of the email content if emails are removed (mass mailing only)' readonly=False store=True args: 'Keep Message Copy'
  • body Html
    compute='_compute_body' readonly=False render_engine='qweb' render_options={'post_process': True} sanitize_style=True store=True args: 'Contents'
  • composition_batch Boolean
    compute='_compute_composition_batch' args: 'Batch composition'
  • composition_comment_option Selection
    string='Comment Options' args: [('reply_all', 'Reply-All'), ('forward', 'Forward')]
  • composition_mode Selection
    default='comment' selection=[('comment', 'Post on a document'), ('mass_mail', 'Email Mass Mailing')] string='Composition mode'
  • email_add_signature Boolean
    compute='_compute_email_add_signature' readonly=False store=True args: 'Add signature'
  • email_from Char
    compute='_compute_authorship' compute_sudo=False help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' readonly=False store=True args: 'From'
  • email_layout_xmlid Char
    compute='_compute_email_layout_xmlid' compute_sudo=False copy=False readonly=False store=True args: 'Email Notification Layout'
  • force_send Boolean
    compute='_compute_force_send' readonly=False store=True args: 'Send mailing or notifications directly'
  • mail_activity_type_id Many2one → mail.activity.type
    ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_server_id Many2one → ir.mail_server
    compute='_compute_mail_server_id' compute_sudo=False readonly=False store=True string='Outgoing mail server' args: 'ir.mail_server'
  • message_type Selection
    default='comment' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' required=True args: [('auto_comment', 'Automated Targeted Notification'), ('comment', 'Comment'), ('notification', 'System notification')], 'Type'
  • model Char
    compute='_compute_model' readonly=False store=True args: 'Related Document Model'
  • model_is_thread Boolean
    compute='_compute_model_is_thread' args: 'Thread-Enabled'
  • notified_bcc_contains_share Boolean
    compute='_compute_notified_bcc_contains_share' args: 'Is an external partner follower of the document?'
  • notify_author Boolean
    compute='_compute_notify_author' readonly=False store=True
  • notify_author_mention Boolean
    compute='_compute_notify_author_mention' readonly=False store=True
  • notify_skip_followers Boolean
    compute='_compute_notify_skip_followers' readonly=False store=True
  • parent_id Many2one → mail.message
    ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    compute='_compute_partner_ids' readonly=False store=True args: 'res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional Contacts'
  • partner_ids_all_have_email Boolean
    compute='_compute_partner_ids_all_have_email'
  • record_alias_domain_id Many2one → mail.alias.domain
    compute='_compute_record_environment' readonly=False store=True args: 'mail.alias.domain', 'Alias Domain'
  • record_company_id Many2one → res.company
    compute='_compute_record_environment' readonly=False store=True args: 'res.company', 'Company'
  • reply_to Char
    compute='_compute_reply_to' compute_sudo=False help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' readonly=False store=True args: 'Reply To'
  • reply_to_force_new Boolean
    compute='_compute_reply_to_force_new' help='Manage answers as new incoming emails instead of replies going to the same thread.' readonly=False store=True string='Considers answers as new thread'
  • reply_to_mode Selection
    compute='_compute_reply_to_mode' help='Original Discussion: Answers go in the original document discussion thread. \n Another Email Address: Answers go to the email address mentioned in the tracking message-id instead of original document discussion thread. \n This has an impact on the generated message-id.' inverse='_inverse_reply_to_mode' string='Replies' args: [('update', 'Store email and replies in the chatter of each record'), ('new', 'Collect replies on a specific email address')]
  • res_domain Text
    args: 'Active domain'
  • res_domain_user_id Many2one → res.users
    help='Used as context used to evaluate composer domain' string='Responsible' args: 'res.users'
  • res_ids Text
    compute='_compute_res_ids' readonly=False store=True args: 'Related Document IDs'
  • scheduled_date Char
    compute='_compute_scheduled_date' compute_sudo=False help='In comment mode: if set, postpone notifications sending. In mass mail mode: if sent, send emails after that date. This date is considered as being in UTC timezone.' readonly=False store=True args: 'Scheduled Date'
  • subject Char
    compute='_compute_subject' readonly=False store=True args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    compute='_compute_subtype_id' ondelete='set null' readonly=False store=True args: 'mail.message.subtype', 'Subtype'
  • subtype_is_log Boolean
    compute='_compute_subtype_is_log' args: 'Is a log'
  • template_id Many2one → mail.template
    domain="[('model', '=', model), '|', ('user_id','=', False), ('user_id', '=', uid)]" args: 'mail.template', 'Use template'
  • template_name Char
    args: 'Template Name'
  • use_exclusion_list Boolean
    copy=False default=True help='Prevent sending messages to blacklisted contacts. Disable only when absolutely necessary.' args: 'Use Exclusion List'
Public methods (6)
  • action_schedule_message(self)
  • action_send_mail(self)
    Used for action button that do not accept arguments.
  • cancel_save_template(self)
    Restore old subject when canceling the 'save as template' action as it was erased to let user give a more custom input.
  • create_mail_template(self)
    creates a mail template with the current mail composer's fields
  • default_get(self, fields)
    @api.model
    Handle composition mode and contextual computation, until moving to computed fields. Support active_model / active_id(s) as valid default values, as this comes from standard web client usage. Note that supporting active_ids through composer is still done, as we may have to give a huge list of IDs that won't fit into res_ids field.
  • open_template_creation_wizard(self)
    hit save as template button: opens a wizard that prompts for the template's subject. `create_mail_template` is called when saving the new wizard.

New fields (7)
  • body Html
    compute='_compute_body' compute_sudo=False readonly=False render_engine='qweb' render_options={'post_process': True} sanitize='email_outgoing' store=True args: 'Contents'
  • body_has_template_value Boolean
    compute='_compute_body_has_template_value' args: 'Body content is the same as the template'
  • can_edit_body Boolean
    compute='_compute_can_edit_body' args: 'Can Edit Body'
  • is_mail_template_editor Boolean
    compute='_compute_is_mail_template_editor' args: 'Is Editor'
  • lang Char
    compute='_compute_lang' compute_sudo=False precompute=True readonly=False store=True
  • subject Char
    compute='_compute_subject' compute_sudo=False readonly=False store=True args: 'Subject'
  • template_id Many2one → mail.template
    domain="[('model', '=', render_model)]" args: 'mail.template', 'Mail Template'
Public methods (0)

No public methods.

New fields (7)
  • email Char
    related='partner_id.email' args: 'Email'
  • is_active Boolean
    related='partner_id.active' args: 'Is Active'
  • name Char
    related='partner_id.name' args: 'Name'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' required=True string='Related Partner' args: 'res.partner'
  • res_id Many2oneReference
    help='Id of the followed resource' index=True model_field='res_model' args: 'Related Document ID'
  • res_model Char
    index=True required=True args: 'Related Document Model Name'
  • subtype_ids Many2many → mail.message.subtype
    help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall." string='Subtype' args: 'mail.message.subtype'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (6)
  • message Html
    args: 'Message'
  • notify Boolean
    default=False args: 'Notify Recipients'
  • operation Selection
    default='add' required=True string='Operation' args: [('add', 'Add'), ('remove', 'Remove')]
  • partner_ids Many2many → res.partner
    required=True string='Followers' args: 'res.partner'
  • res_ids Char
    help='Ids of the followed resources' args: 'Related Document IDs'
  • res_model Char
    help='Model of the followed resource' required=True args: 'Related Document Model'
Public methods (1)
  • edit_followers(self)

New fields (2)
  • email Char
    required=True args: 'Email Address'
  • email_normalized Char
    compute='_compute_email_normalized' index=True store=True string='Normalized Email'
Public methods (1)
  • get_empty_list_help(self, help_message)
    @api.model

New fields (10)
  • access_token Char
    copy=False default=<expr> groups='base.group_system' readonly=True required=True string='Access Token'
  • channel_ids Many2many → discuss.channel
    column1='guest_id' column2='channel_id' comodel_name='discuss.channel' copy=False relation='discuss_channel_member' string='Channels'
  • country_id Many2one → res.country
    comodel_name='res.country' string='Country'
  • email Char
  • im_status Char
    compute='_compute_im_status' compute_sudo=True args: 'IM Status'
  • lang Selection
    selection=_lang_get string='Language'
  • name Char
    required=True string='Name'
  • offline_since Datetime
    compute='_compute_im_status' compute_sudo=True args: 'Offline since'
  • presence_ids One2many → mail.presence
    groups='base.group_system' args: 'mail.presence', 'guest_id'
  • timezone Selection
    selection=_tz_get string='Timezone'
Public methods (0)

No public methods.

New fields (4)
  • credential Char
  • server_type Selection
    default='stun' required=True string='Type' args: [('stun', 'stun:'), ('turn', 'turn:')]
  • uri Char
    required=True args: 'URI'
  • username Char
Public methods (0)

No public methods.

New fields (10)
  • create_date Datetime
    index=True
  • image_mimetype Char
    args: 'Image MIME type'
  • message_link_preview_ids One2many → mail.message.link.preview
    groups='base.group_erp_manager' args: 'mail.message.link.preview', 'link_preview_id'
  • og_description Text
    args: 'Description'
  • og_image Char
    args: 'Image'
  • og_mimetype Char
    args: 'MIME type'
  • og_site_name Char
    args: 'Site name'
  • og_title Char
    args: 'Title'
  • og_type Char
    args: 'Type'
  • source_url Char
    required=True args: 'URL'
Public methods (0)

No public methods.

New fields (19)
  • auto_delete Boolean
    help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_content Html
    compute='_compute_body_content' sanitize=True search='_search_body_content' args: 'Rich-text Contents'
  • body_html Text
    help='Rich-text/HTML message' args: 'Text Contents'
  • email_cc Char
    help='Carbon copy message recipients' args: 'Cc'
  • email_to Text
    help='Message recipients (emails)' args: 'To'
  • failure_reason Text
    copy=False help='Failure reason. This is usually the exception thrown by the email server, stored to ease the debugging of mailing issues.' readonly=True args: 'Failure Reason'
  • failure_type Selection
    selection=[('unknown', 'Unknown error'), ('mail_spam', 'Detected As Spam'), ('mail_email_invalid', 'Invalid email address'), ('mail_email_missing', 'Missing email'), ('mail_from_invalid', 'Invalid from address'), ('mail_from_missing', 'Missing from address'), ('mail_smtp', 'Connection failed (outgoing mail server problem)'), ('mail_bl', 'Blacklisted Address'), ('mail_optout', 'Opted Out'), ('mail_dup', 'Duplicated Email')] string='Failure type'
  • fetchmail_server_id Many2one → fetchmail.server
    index='btree_not_null' readonly=True args: 'fetchmail.server', 'Inbound Mail Server'
  • headers Text
    copy=False args: 'Headers'
  • is_notification Boolean
    help='Mail has been created to notify people of an existing mail.message' args: 'Notification Email'
  • mail_message_id Many2one → mail.message
    bypass_search_access=True index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • mail_message_id_int Integer
    compute='_compute_mail_message_id_int' compute_sudo=True
  • message_type Selection
    default='email_outgoing' inherited=True related='mail_message_id.message_type'
  • recipient_ids Many2many → res.partner
    context={'active_test': False} string='To (Partners)' args: 'res.partner'
  • references Text
    help='Message references, such as identifiers of previous messages' readonly=True args: 'References'
  • restricted_attachment_count Integer
    compute='_compute_restricted_attachments' args: 'Restricted attachments'
  • scheduled_date Datetime
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. Unless a timezone is specified, it is considered as being in UTC timezone.' args: 'Scheduled Send Date'
  • state Selection
    copy=False default='outgoing' readonly=True args: [('outgoing', 'Outgoing'), ('sent', 'Sent'), ('received', 'Received'), ('exception', 'Delivery Failed'), ('cancel', 'Cancelled')], 'Status'
  • unrestricted_attachment_ids Many2many → ir.attachment
    compute='_compute_restricted_attachments' inverse='_inverse_unrestricted_attachment_ids' string='Unrestricted Attachments' args: 'ir.attachment'
Public methods (12)
  • action_open_document(self)
    Opens the related record based on the model and ID
  • action_retry(self)
  • action_send_and_close(self)
    An action sending the selected mail and redirecting to mail.mail list view.
  • cancel(self)
  • create(self, vals_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • mark_outgoing(self)
  • process_email_queue(self, email_ids=(), batch_size=1000)
    @api.model
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! A maximum of 1K MailMail (configurable using 'mail.mail.queue.batch.size' optional ICP) are fetched in order to keep time under control. :param list email_ids: optional list of emails ids to send. If given only scheduled and outgoing emails within this ids list are sent;
  • send(self, auto_commit=False, raise_exception=False, post_send_callback=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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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 :param post_send_callback: an optional function, called as ``post_send_callback(ids, force=False)``, with the mail ids that have been sent; calls with redundant ids are possible :return: True
  • send_after_commit(self)
    Queues the email to be sent after the commit of the current cursor. Useful to send an email only if a transaction is successful.
  • unlink(self)
  • write(self, vals)

New fields (43)
  • attachment_ids Many2many → ir.attachment
    bypass_search_access=True string='Attachments' args: 'ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id'
  • author_avatar Binary
    depends=['author_id'] readonly=False related='author_id.avatar_128' args: "Author's avatar"
  • author_guest_id Many2one → mail.guest
    comodel_name='mail.guest' string='Guest'
  • author_id Many2one → res.partner
    help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True ondelete='set null' args: 'res.partner', 'Author'
  • body Html
    default='' sanitize_style=True args: 'Contents'
  • child_ids One2many → mail.message
    args: 'mail.message', 'parent_id', 'Child Messages'
  • date Datetime
    default=fields.Datetime.now args: 'Date'
  • email_add_signature Boolean
    default=True
  • email_from Char
    help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • email_layout_xmlid Char
    copy=False args: 'Layout'
  • has_error Boolean
    compute='_compute_has_error' search='_search_has_error' args: 'Has error'
  • incoming_email_cc Char
    args: 'Emails Cc'
  • incoming_email_to Text
    args: 'Emails To'
  • is_current_user_or_guest_author Boolean
    compute='_compute_is_current_user_or_guest_author'
  • is_internal Boolean
    help='Hide to public / portal users, independently from subtype configuration.' args: 'Employee Only'
  • linked_message_ids Many2many → mail.message
    compute='_compute_linked_message_ids' args: 'mail.message'
  • mail_activity_type_id Many2one → mail.activity.type
    index='btree_not_null' ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_ids One2many → mail.mail
    groups='base.group_system' string='Mails' args: 'mail.mail', 'mail_message_id'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_id Char
    copy=False help='Message unique identifier' index='btree' readonly=True args: 'Message-Id'
  • message_link_preview_ids One2many → mail.message.link.preview
    groups='base.group_erp_manager' args: 'mail.message.link.preview', 'message_id'
  • message_type Selection
    default='comment' help="Used to categorize message generator\n'email': generated by an incoming email e.g. mailgateway\n'comment': generated by user input e.g. through discuss or composer\n'email_outgoing': generated by a mailing\n'notification': generated by system e.g. tracking messages\n'auto_comment': generated by automated notification mechanism e.g. acknowledgment\n'user_notification': generated for a specific recipient" required=True args: [('email', 'Incoming Email'), ('comment', 'Comment'), ('email_outgoing', 'Outgoing Email'), ('notification', 'System notification'), ('auto_comment', 'Automated Targeted Notification'), ('out_of_office', 'Out-of-office Message'), ('user_notification', 'User Specific Notification')], 'Type'
  • model Char
    args: 'Related Document Model'
  • needaction Boolean
    compute='_compute_needaction' search='_search_needaction' args: 'Need Action'
  • notification_ids One2many → mail.notification
    bypass_search_access=True copy=False depends=['notified_partner_ids'] args: 'mail.notification', 'mail_message_id', 'Notifications'
  • notified_partner_ids Many2many → res.partner
    context={'active_test': False} copy=False depends=['notification_ids'] string='Partners with Need Action' args: 'res.partner', 'mail_notification'
  • outgoing_email_to Char
    args: 'emails To'
  • parent_id Many2one → mail.message
    index='btree_not_null' ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    context={'active_test': False} string='Recipients' args: 'res.partner'
  • pinned_at Datetime
    help='Datetime at which the message has been pinned' args: 'Pinned'
  • preview Char
    compute='_compute_preview' help='The text-only beginning of the body used as email preview.' args: 'Preview'
  • reaction_ids One2many → mail.message.reaction
    groups='base.group_system' string='Reactions' args: 'mail.message.reaction', 'message_id'
  • record_alias_domain_id Many2one → mail.alias.domain
    ondelete='set null' args: 'mail.alias.domain', 'Alias Domain'
  • record_company_id Many2one → res.company
    ondelete='set null' args: 'res.company', 'Company'
  • record_name Char
    compute='_compute_record_name' store=False args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • reply_to_force_new Boolean
    help='If true, answers do not go in the original document discussion thread. Instead, it will check for the reply_to in tracking message-id and redirected accordingly. This has an impact on the generated message-id.' args: 'No threading for answers'
  • res_id Many2oneReference
    model_field='model' args: 'Related Document ID'
  • starred Boolean
    compute='_compute_starred' compute_sudo=False help='Current user has a starred notification linked to this message' search='_search_starred' args: 'Starred'
  • starred_partner_ids Many2many → res.partner
    string='Favorited By' args: 'res.partner', 'mail_message_res_partner_starred_rel'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • tracking_value_ids One2many → mail.tracking.value
    groups='base.group_system' help='Tracked values are stored in a separate model. This field allow to reconstruct the tracking and to generate statistics on the model.' string='Tracking values' args: 'mail.tracking.value', 'mail_message_id'
Public methods (13)
  • action_open_document(self)
    Opens the related record based on the model and ID
  • copy_data(self, default=None)
    Make is symmetric to read, to avoid spurious issues with recordsets differences.
  • create(self, vals_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • export_data(self, fields_to_export)
  • fetch(self, field_names=None)
  • mark_all_as_read(self, domain=None)
    @api.model
  • read(self, fields=None, load='_classic_read')
    Override to explicitely call check_access(), that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_done(self)
    Remove the needaction from messages for the current partner.
  • toggle_message_starred(self)
    Toggle messages as (un)starred. Technically, the notifications related to uid are set to (un)starred.
  • unlink(self)
  • unstar_all(self)
    @api.model
    Unstar messages for the current partner.
  • write(self, vals)

New fields (2)
  • call_history_ids One2many → discuss.call.history
    args: 'discuss.call.history', 'start_call_message_id'
  • channel_id Many2one → discuss.channel
    compute='_compute_channel_id' args: 'discuss.channel'
Public methods (0)

No public methods.

New fields (5)
  • author_id Many2one
    related='message_id.author_id'
  • is_hidden Boolean
  • link_preview_id Many2one → mail.link.preview
    index=True ondelete='cascade' required=True args: 'mail.link.preview'
  • message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message'
  • sequence Integer
    args: 'Sequence'
Public methods (0)

No public methods.

New fields (4)
  • content Char
    readonly=True required=True string='Content'
  • guest_id Many2one → mail.guest
    comodel_name='mail.guest' ondelete='cascade' readonly=True string='Reacting Guest'
  • message_id Many2one → mail.message
    comodel_name='mail.message' index=True ondelete='cascade' readonly=True required=True string='Message'
  • partner_id Many2one → res.partner
    comodel_name='res.partner' ondelete='cascade' readonly=True string='Reacting Partner'
Public methods (0)

No public methods.

New fields (3)
  • mail_message_id Many2one → mail.message
    ondelete='cascade' required=True string='Message' args: 'mail.message'
  • notification_parameters Text
    args: 'Notification Parameter'
  • scheduled_datetime Datetime
    help='Datetime at which notification should be sent.' required=True args: 'Scheduled Send Date'
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • force_send(self)
    Launch notification process independently from the expected date.

New fields (10)
  • default Boolean
    default=True help='Activated by default when subscribing.' args: 'Default'
  • description Text
    help='Description that will be added in the message posted for this subtype. If void, the name will be added instead.' prefetch=True translate=True args: 'Description'
  • hidden Boolean
    help='Hide the subtype in the follower options' args: 'Hidden'
  • internal Boolean
    help='Messages with internal subtypes will be visible only by employees, aka members of base_user group' args: 'Internal Only'
  • name Char
    help='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.' required=True translate=True args: 'Message Type'
  • parent_id Many2one → mail.message.subtype
    help='Parent subtype, used for automatic subscription. This field is not correctly named. For example on a project, the parent_id of project subtypes refers to task-related subtypes.' ondelete='set null' string='Parent' args: 'mail.message.subtype'
  • relation_field Char
    help='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).' args: 'Relation field'
  • res_model Char
    help='Model the subtype applies to. If False, this subtype applies to all models.' args: 'Model'
  • sequence Integer
    default=1 help='Used to order subtypes.' args: 'Sequence'
  • track_recipients Boolean
    help='Whether to display all the recipients or only the important ones.' args: 'Track Recipients'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • default_subtypes(self, model_name)
    @api.model
    Retrieve the default subtypes (all, internal, external) for the given model.
  • unlink(self)
  • write(self, vals)

New fields (5)
  • body Html
    help='String received from the translation request.' required=True sanitize_style=True args: 'Translation Body'
  • create_date Datetime
    index=True
  • message_id Many2one → mail.message
    ondelete='cascade' required=True args: 'mail.message', 'Message'
  • source_lang Char
    help='Result of the language detection based on its content.' required=True args: 'Source Language'
  • target_lang Char
    help='Shortened language code used as the target for the translation request.' required=True args: 'Target Language'
Public methods (0)

No public methods.

New fields (11)
  • author_id Many2one → res.partner
    ondelete='set null' args: 'res.partner', 'Author'
  • failure_reason Text
    copy=False args: 'Failure reason'
  • failure_type Selection
    selection=[('unknown', 'Unknown error'), ('mail_bounce', 'Bounce'), ('mail_spam', 'Detected As Spam'), ('mail_email_invalid', 'Invalid email address'), ('mail_email_missing', 'Missing email address'), ('mail_from_invalid', 'Invalid from address'), ('mail_from_missing', 'Missing from address'), ('mail_smtp', 'Connection failed (outgoing mail server problem)'), ('mail_bl', 'Blacklisted Address'), ('mail_optout', 'Opted Out'), ('mail_dup', 'Duplicated Email')] string='Failure type'
  • is_read Boolean
    index=True args: 'Is Read'
  • mail_email_address Char
    help='Recipient email address'
  • mail_mail_id Many2one → mail.mail
    help='Optional mail_mail ID. Used mainly to optimize searches.' index=True args: 'mail.mail', 'Mail'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification_status Selection
    default='ready' index=True string='Status' args: [('ready', 'Ready to Send'), ('process', 'Processing'), ('pending', 'Sent'), ('sent', 'Delivered'), ('bounce', 'Bounced'), ('exception', 'Exception'), ('canceled', 'Cancelled')]
  • notification_type Selection
    default='inbox' index=True required=True string='Notification Type' args: [('inbox', 'Inbox'), ('email', 'Email')]
  • read_date Datetime
    copy=False args: 'Read Date'
  • res_partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner', 'Recipient'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • format_failure_reason(self)
  • write(self, vals)

New fields (5)
  • guest_id Many2one → mail.guest
    ondelete='cascade' args: 'mail.guest', 'Guest'
  • last_poll Datetime
    default=<expr> args: 'Last Poll'
  • last_presence Datetime
    default=<expr> args: 'Last Presence'
  • status Selection
    default='offline' args: [('online', 'Online'), ('away', 'Away'), ('offline', 'Offline')], 'IM Status'
  • user_id Many2one → res.users
    ondelete='cascade' args: 'res.users', 'Users'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (2)
  • mail_push_device_id Many2one → mail.push.device
    ondelete='cascade' required=True string='devices' args: 'mail.push.device'
  • payload Text
Public methods (0)

No public methods.

New fields (4)
  • endpoint Char
    required=True string='Browser endpoint'
  • expiration_time Datetime
    string='Expiration Token Date'
  • keys Char
    help="It's refer to browser keys used by the notification: \n- p256dh: It's the subscription public key generated by the browser. The browser will \n keep the private key secret and use it for decrypting the payload\n- auth: The auth value should be treated as a secret and not shared outside of Odoo" required=True string='Browser keys'
  • partner_id Many2one → res.partner
    default=<expr> index=True required=True string='Partner' args: 'res.partner'
Public methods (3)
  • get_web_push_vapid_public_key(self)
    @api.model
  • register_devices(self, **kw)
    @api.model
  • unregister_devices(self, **kw)
    @api.model

New fields (2)
  • lang Char
    help="Optional translation language (ISO code) to select when sending out an email. If not set, the main partner's language will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. {{ object.partner_id.lang }}." args: 'Language'
  • render_model Char
    compute='_compute_render_model' store=False args: 'Rendering Model'
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, vals)

New fields (12)
  • attachment_ids Many2many → ir.attachment
    bypass_search_access=True string='Attachments' args: 'ir.attachment', 'scheduled_message_attachment_rel', 'scheduled_message_id', 'attachment_id'
  • author_id Many2one → res.partner
    required=True args: 'res.partner', 'Author'
  • body Html
    sanitize_style=True args: 'Contents'
  • composition_comment_option Selection
    string='Comment Options' args: [('reply_all', 'Reply-All'), ('forward', 'Forward')]
  • is_note Boolean
    default=False help='If the message will be posted as a Note.' args: 'Is a note'
  • model Char
    required=True args: 'Related Document Model'
  • notification_parameters Text
    args: 'Notification parameters'
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • res_id Many2oneReference
    model_field='model' required=True args: 'Related Document Id'
  • scheduled_date Datetime
    required=True args: 'Scheduled Date'
  • send_context Json
    args: 'Sending Context'
  • subject Char
    args: 'Subject'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
  • open_edit_form(self)
  • post_message(self)
  • unlink(self)
  • write(self, vals)

New fields (26)
  • active Boolean
    default=True
  • attachment_ids Many2many → ir.attachment
    bypass_search_access=True string='Attachments' args: 'ir.attachment', 'email_template_attachment_rel', 'email_template_id', 'attachment_id'
  • auto_delete Boolean
    default=True help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_html Html
    prefetch=True render_engine='qweb' render_options={'post_process': True} sanitize='email_outgoing' translate=True args: 'Body'
  • can_write Boolean
    compute='_compute_can_write' help='The current user can edit the template.'
  • description Text
    help="This field is used for internal description of the template's usage." translate=True args: 'Template Description'
  • email_cc Char
    help='Carbon copy recipients (placeholders may be used here)' args: 'Cc'
  • email_from Char
    help="Sender address (placeholders may be used here). If not set, the default value will be the author's email alias if configured, or email address." args: 'Send From'
  • email_layout_xmlid Char
    copy=False args: 'Email Notification Layout'
  • email_to Char
    help='Comma-separated recipient addresses (placeholders may be used here)' args: 'To (Emails)'
  • has_dynamic_reports Boolean
    compute='_compute_has_dynamic_reports'
  • has_mail_server Boolean
    compute='_compute_has_mail_server'
  • is_template_editor Boolean
    compute='_compute_is_template_editor'
  • mail_server_id Many2one → ir.mail_server
    help='Optional preferred server for outgoing mails. If not set, the highest priority one will be used.' index='btree_not_null' readonly=False args: 'ir.mail_server', 'Outgoing Mail Server'
  • model Char
    index=True readonly=True related='model_id.model' store=True args: 'Related Document Model'
  • model_id Many2one → ir.model
    domain=_get_non_abstract_models_domain ondelete='cascade' args: 'ir.model', 'Applies to'
  • name Char
    translate=True args: 'Name'
  • partner_to Char
    help='Comma-separated ids of recipient partners (placeholders may be used here)' args: 'To (Partners)'
  • ref_ir_act_window Many2one → ir.actions.act_window
    copy=False help='Sidebar action to make this template available on records of the related document model' readonly=True args: 'ir.actions.act_window', 'Sidebar action'
  • reply_to Char
    help='Email address to which replies will be redirected when sending emails in mass; only used when the reply is not logged in the original discussion thread.' args: 'Reply To'
  • report_template_ids Many2many → ir.actions.report
    column1='mail_template_id' column2='ir_actions_report_id' domain="[('model', '=', model)]" relation='mail_template_ir_actions_report_rel' string='Dynamic Reports' args: 'ir.actions.report'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. You can use dynamic expression.' args: 'Scheduled Date'
  • subject Char
    help='Subject (placeholders may be used here)' prefetch=True translate=True args: 'Subject'
  • template_category Selection
    compute='_compute_template_category' search='_search_template_category' args: [('base_template', 'Base Template'), ('hidden_template', 'Hidden Template'), ('custom_template', 'Custom Template')]
  • use_default_to Boolean
    default=True help='Default recipients of the record:\n- partner (using id on a partner or the partner_id field) OR\n- email (using email_from or email field)' args: 'Default Recipients'
  • user_id Many2one → res.users
    domain="[('share', '=', False)]" string='Owner' args: 'res.users'
Public methods (11)
  • action_open_mail_preview(self)
  • copy(self, default=None)
  • copy_data(self, default=None)
  • create(self, vals_list)
    @api.model_create_multi
  • create_action(self)
  • default_get(self, fields)
    @api.model
  • send_mail(self, res_id, force_send=False, raise_exception=False, email_values=None, email_layout_xmlid=False)
    Generates a new mail.mail. Template is rendered on record given by res_id and model coming from template. :param int res_id: id of the record to render the template :param bool force_send: send email immediately; otherwise use the mail queue (recommended); :param dict email_values: update generated mail with those values to further customize the mail; :param str email_layout_xmlid: optional notification layout to encapsulate the generated email; :returns: id of the mail.mail that was created
  • send_mail_batch(self, res_ids, force_send=False, raise_exception=False, email_values=None, email_layout_xmlid=False)
    Generates new mail.mails. Batch version of 'send_mail'.' :param list res_ids: IDs of modelrecords on which template will be rendered :returns: newly created mail.mail
  • unlink(self)
  • unlink_action(self)
  • write(self, vals)

New fields (17)
  • attachment_ids Many2many → ir.attachment
    compute='_compute_mail_template_fields' string='Attachments' args: 'ir.attachment'
  • body_html Html
    compute='_compute_mail_template_fields' sanitize=False args: 'Body'
  • email_cc Char
    compute='_compute_mail_template_fields' help='Carbon copy recipients' args: 'Cc'
  • email_from Char
    compute='_compute_mail_template_fields' help='Sender address' args: 'From'
  • email_to Char
    compute='_compute_mail_template_fields' help='Comma-separated recipient addresses' args: 'To'
  • error_msg Char
    compute='_compute_mail_template_fields' args: 'Error Message'
  • has_attachments Boolean
    compute='_compute_has_attachments'
  • has_several_languages_installed Boolean
    compute='_compute_has_several_languages_installed'
  • lang Selection
    string='Template Preview Language' args: _selection_languages
  • mail_template_id Many2one → mail.template
    required=True string='Related Mail Template' args: 'mail.template'
  • model_id Many2one → ir.model
    related='mail_template_id.model_id' string='Targeted model' args: 'ir.model'
  • no_record Boolean
    compute='_compute_no_record' args: 'No Record'
  • partner_ids Many2many → res.partner
    compute='_compute_mail_template_fields' string='Recipients' args: 'res.partner'
  • reply_to Char
    compute='_compute_mail_template_fields' help='Preferred response address' args: 'Reply-To'
  • resource_ref Reference
    compute='_compute_resource_ref' compute_sudo=False readonly=False selection='_selection_target_model' store=True string='Record'
  • scheduled_date Char
    compute='_compute_mail_template_fields' help='The queue manager will send the email after the date' args: 'Scheduled Date'
  • subject Char
    compute='_compute_mail_template_fields' args: 'Subject'
Public methods (0)

No public methods.

New fields (1)
  • template_ids Many2many → mail.template
    args: 'mail.template'
Public methods (1)
  • reset_template(self)

New fields (10)
  • has_message Boolean
    compute='_compute_has_message' search='_search_has_message' store=False
  • message_attachment_count Integer
    compute='_compute_message_attachment_count' groups='base.group_user' args: 'Attachment Count'
  • message_follower_ids One2many → mail.followers
    groups='base.group_user' string='Followers' args: 'mail.followers', 'res_id'
  • message_has_error Boolean
    compute='_compute_message_has_error' help='If checked, some messages have a delivery error.' search='_search_message_has_error' args: 'Message Delivery error'
  • message_has_error_counter Integer
    compute='_compute_message_has_error' help='Number of messages with delivery error' args: 'Number of errors'
  • message_ids One2many → mail.message
    bypass_search_access=True domain=<expr> string='Messages' args: 'mail.message', 'res_id'
  • message_is_follower Boolean
    compute='_compute_message_is_follower' search='_search_message_is_follower' args: 'Is Follower'
  • message_needaction Boolean
    compute='_compute_message_needaction' help='If checked, new messages require your attention.' search='_search_message_needaction' args: 'Action Needed'
  • message_needaction_counter Integer
    compute='_compute_message_needaction' help='Number of messages requiring action' args: 'Number of Actions'
  • message_partner_ids Many2many → res.partner
    comodel_name='res.partner' compute='_compute_message_partner_ids' groups='base.group_user' inverse='_inverse_message_partner_ids' search='_search_message_partner_ids' string='Followers (Partners)'
Public methods (20)
  • copy_data(self, default=None)
  • create(self, vals_list)
    @api.model_create_multi
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • get_empty_list_help(self, help_message)
    @api.model
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • get_views(self, views, options=None)
    @api.model
  • message_change_thread(self, new_thread, new_parent_message=False)
    Transfer the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : my_lead.message_change_thread(my_project_task) will transfer the context of the thread of my_lead to my_project_task
  • message_get_followers(self, after=None, limit=100, filter_recipients=False)
    @api.readonly
  • message_mail_with_source(self, source_ref, *, render_values=None, message_type='notification', auto_commit=False, **kwargs)
    Send a mass mail on self, using an external source to render part of the content. It can be either a 'mail.template', either a view used to render the body using QWeb. SPOILER: this method currently calls a composer in a loop when using a view even if it is suboptimal. This is due to current composer implementation.. This will be cleaned soon to optimize mass mailing through mail.thread and lessen usage of composer itself. Default values * subtype_id: will be False, forced by composer in mass mode; :param record/str source_ref: reference to a source for rendering. It can be one of * a MailTemplate record. It will be used to render the various message values (body, subject, recipients, ...). It should behave like using the mail composer with a template; * an IrUIView record. It will be used to render the content (body). Other fields are left to the caller and/or default values computation; * an XmlID of a MailTemplate or of an IrUiView: see above; :param dict render_values: additional rendering values for qweb context; :param str message_type: one of 'notification' or 'comment'; :param bool auto_commit: auto commit after each batch of emails sent (see ``MailComposer._action_send_mail()``); :param dict kwargs: additional values given to the 'mail.compose.message' creation; :return: created mail.mail records, as sudo
  • message_new(self, msg_dict, custom_values=None)
    @api.model
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :rtype: int :return: the id of the newly created thread object
  • message_notify(self, *, body='', subject=False, author_id=None, email_from=None, model=False, res_id=False, subtype_xmlid=None, subtype_id=False, partner_ids=False, attachments=None, attachment_ids=None, **kwargs)
    Shortcut allowing to notify partners of messages that should not be displayed on a document. It pushes notifications on inbox or by email depending on the user configuration, like other notifications. Default values * subtype_id: if not given, fallback on ``note`` to be consistent with what message_post does; :param str body: body of the message, usually raw HTML that will be sanitized :param str subject: subject of the message :param int author_id: optional ID of partner record being the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param str email_from: from address of the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param str model: when invoked on MailThread directly, this method allows to push a notification on a given record (allows to notify on not thread-enabled records); :param int res_id: defines the record in combination with model; :param str subtype_xmlid: optional xml id of a mail.message.subtype to fetch, will force value of subtype_id; :param int subtype_id: subtype_id of the message, used mainly for followers notification mechanism; :param list(int) partner_ids: partner_ids to notify in addition to partners computed based on subtype / followers matching; :param list(tuple(str,str), tuple(str,str, dict)) attachments : list of attachment tuples in the form ``(name,content)`` or ``(name,content, info)`` where content is NOT base64 encoded; :param list attachment_ids: list of existing attachments to link to this message Should not be a list of commands. Attachment records attached to mail composer will be attached to the related document. Extra keyword arguments will be used either * as default column values for the new mail.message record if they match mail.message fields; * propagated to notification methods if not; :return: posted mail.message records
  • message_parse(self, message, save_original=False)
    @api.model
    Parses an email.message.Message representing an RFC-2822 email and returns a generic dict holding the message details. Note that partner finding is delegated to a post processing as it is better done using gateway record as context e.g. to check for followers, ... see '_message_parse_post_process'. :param message: email to parse :type message: email.message.Message :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'email_from': from, 'to': to + delivered-to, 'cc': cc, 'recipients': delivered-to + to + cc + resent-to + resent-cc, 'body': unified_body, 'references': references, 'in_reply_to': in-reply-to, 'is_bounce': True if it has been detected as a bounce email 'parent_id': parent mail.message based on in_reply_to or references, 'is_internal': answer to an internal message (note), 'date': date, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_post(self, *, body='', subject=None, message_type='notification', email_from=None, author_id=None, parent_id=False, subtype_xmlid=None, subtype_id=False, partner_ids=None, outgoing_email_to=False, incoming_email_to=False, incoming_email_cc=False, attachments=None, attachment_ids=None, body_is_html=False, **kwargs)
    Post a new message in an existing thread, returning the new mail.message. :param str|Markup body: body of the message, str content will be escaped, Markup for html body :param str subject: subject of the message :param str message_type: see mail_message.message_type field. Can be anything but user_notification, reserved for message_notify :param str email_from: from address of the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param int author_id: optional ID of partner record being the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param int parent_id: handle thread formation :param str subtype_xmlid: optional xml id of a mail.message.subtype to fetch, will force value of subtype_id; :param int subtype_id: subtype_id of the message, used mainly for followers notification mechanism; :param list(int) partner_ids: partner_ids to notify in addition to partners computed based on subtype / followers matching; :param str outgoing_email_to: comma-separated list of emails to notify in addition to partner_ids. Experimental support as of Odoo v19; :param str incoming_email_to: comma-separated list of emails, already notified by incoming email; :param str incoming_email_cc: comma-separated list of emails, already notified by incoming email; :param list(tuple(str,str), tuple(str,str, dict)) attachments : list of attachment tuples in the form ``(name,content)`` or ``(name,content, info)`` where content is NOT base64 encoded; :param list attachment_ids: list of existing attachments to link to this message Should not be a list of commands. Attachment records attached to mail composer will be attached to the related document. :param bool body_is_html: indicates body should be threated as HTML even if str to be used only for RPC calls Extra keyword arguments will be used either * as default column values for the new mail.message record if they match mail.message fields; * propagated to notification methods if not; :return: newly create mail.message record
  • message_post_with_source(self, source_ref, *, render_values=None, message_type='notification', subtype_xmlid=False, subtype_id=False, **kwargs)
    Post a message on each record of self, using a view to render the body using QWeb. Default values * subtype_id: if not given, fallback on ``note`` to be consistent with what message_post does; :param record/str source_ref: reference to a source for rendering. It can be one of * a MailTemplate record. It will be used to render the various message values (body, subject, recipients, ...). It should behave like using the mail composer with a template; * an IrUIView record. It will be used to render the content (body). Other fields are left to the caller and/or default values computation; * an XmlID of a MailTemplate or of an IrUiView: see above :param dict render_values: additional rendering values for qweb context; :param str message_type: one of 'notification' or 'comment'; :param str subtype_xmlid: optional xml id of a mail.message.subtype to fetch, will force value of subtype_id; :param int subtype_id: subtype_id of the message, used mainly for followers notification mechanism; :param dict kwargs: additional values given to the 'mail.compose.message' creation; :return: posted mail.message records
  • message_process(self, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None)
    @api.model
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). :param str model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: str | xmlrpclib.Binary :param custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :type custom_values: dict | None :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None)
    @api.model
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: * if the message replies to an existing thread by having a Message-Id that matches an existing mail_message.message_id, we take the original message model/thread_id pair and ignore custom_value as no creation will take place; * look for a mail.alias entry matching the message recipients and use the corresponding model, thread_id, custom_values and user_id. This could lead to a thread update or creation depending on the alias; * fallback on provided ``model``, ``thread_id`` and ``custom_values``; * raise an exception as no route has been found :param str message: an email.message instance :param dict message_dict: dictionary holding parsed message variables :param str model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param custom_values: dictionary mapping field names to default values to be passed to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :type custom_values: dict[str, Any] | None :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of routes [(model, thread_id, custom_values, user_id, alias)] :raises: ValueError, TypeError
  • message_subscribe(self, partner_ids=None, subtype_ids=None)
    Main public API to add followers to a record set. Its main purpose is to perform access rights checks before calling ``_message_subscribe``.
  • message_unsubscribe(self, partner_ids=None)
    Remove partners from the records followers.
  • message_update(self, msg_dict, update_vals=None)
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • notify_cancel_by_type(self, notification_type)
    @api.model
    Subclasses must call this method and then * either call the standard implementation _notify_cancel_by_type_generic * or implements their own logic
  • unlink(self)
    Override unlink to delete (scheduled) messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • write(self, vals)

New fields (3)
  • email_normalized Char
    compute='_compute_email_normalized' compute_sudo=True help='This field is used to search on email address as the primary email field can contain more than strictly an email address.' store=True string='Normalized Email'
  • is_blacklisted Boolean
    compute='_compute_is_blacklisted' compute_sudo=True groups='base.group_user' help="If the email address is on the blacklist, the contact won't receive mass mailing anymore, from any list" search='_search_is_blacklisted' store=False string='Blacklist'
  • message_bounce Integer
    default=0 help='Counter of the number of bounced emails for this contact' args: 'Bounce'
Public methods (1)
  • mail_action_blacklist_remove(self)

New fields (1)
  • email_cc Char
    args: 'Email cc'
Public methods (2)
  • message_new(self, msg_dict, custom_values=None)
    @api.model
  • message_update(self, msg_dict, update_vals=None)

New fields (1)
  • message_main_attachment_id Many2one → ir.attachment
    comodel_name='ir.attachment' copy=False index='btree_not_null' string='Main Attachment'
Public methods (0)

No public methods.

New fields (3)
  • duration_tracking Json
    compute='_compute_duration_tracking' help='JSON that maps ids from a many2one field to seconds spent' string='Status time'
  • is_rotting Boolean
    compute='_compute_rotting' search='_search_is_rotting' args: 'Rotting'
  • rotting_days Integer
    compute='_compute_rotting' help='Day count since this resource was last updated' args: 'Days Rotting'
Public methods (0)

No public methods.

New fields (14)
  • currency_id Many2one → res.currency
    help='Used to display the currency when tracking monetary values' ondelete='set null' readonly=True args: 'res.currency', 'Currency'
  • field_id Many2one → ir.model.fields
    index=True ondelete='set null' readonly=True required=False args: 'ir.model.fields'
  • field_info Json
    args: 'Removed field information'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message ID'
  • new_value_char Char
    readonly=True args: 'New Value Char'
  • new_value_datetime Datetime
    readonly=True args: 'New Value Datetime'
  • new_value_float Float
    readonly=True args: 'New Value Float'
  • new_value_integer Integer
    readonly=True args: 'New Value Integer'
  • new_value_text Text
    readonly=True args: 'New Value Text'
  • old_value_char Char
    readonly=True args: 'Old Value Char'
  • old_value_datetime Datetime
    readonly=True args: 'Old Value DateTime'
  • old_value_float Float
    readonly=True args: 'Old Value Float'
  • old_value_integer Integer
    readonly=True args: 'Old Value Integer'
  • old_value_text Text
    readonly=True args: 'Old Value Text'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cron_mode=True)
    Send a message to Odoo's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (9)
  • alias_domain_id Many2one → mail.alias.domain
    default=<expr> index='btree_not_null' string='Email Domain' args: 'mail.alias.domain'
  • bounce_email Char
    compute='_compute_bounce' string='Bounce Email'
  • bounce_formatted Char
    compute='_compute_bounce' string='Bounce'
  • catchall_email Char
    compute='_compute_catchall' string='Catchall Email'
  • catchall_formatted Char
    compute='_compute_catchall' string='Catchall'
  • default_from_email Char
    readonly=True related='alias_domain_id.default_from_email' string='Default From'
  • email_formatted Char
    compute='_compute_email_formatted' compute_sudo=True string='Formatted Email'
  • email_primary_color Char
    default='#FFFFFF' readonly=False args: 'Email Button Text'
  • email_secondary_color Char
    default='#875A7B' readonly=False args: 'Email Button Color'
Public methods (0)

No public methods.

New fields (16)
  • alias_domain_id Many2one → mail.alias.domain
    help='If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.' readonly=False related='company_id.alias_domain_id' args: 'mail.alias.domain', 'Alias Domain'
  • email_primary_color Char
    readonly=False related='company_id.email_primary_color'
  • email_secondary_color Char
    readonly=False related='company_id.email_secondary_color'
  • external_email_server_default Boolean
    config_parameter='base_setup.default_external_email_server' args: 'Use Custom Email Servers'
  • fail_counter Integer
    compute='_compute_fail_counter' args: 'Fail Mail'
  • google_translate_api_key Char
    config_parameter='mail.google_translate_api_key' help='A valid Google API key is required to enable message translation. https://cloud.google.com/translate/docs/setup' args: 'Message Translation API Key'
  • module_google_gmail Boolean
    args: 'Support Gmail Authentication'
  • module_microsoft_outlook Boolean
    args: 'Support Outlook Authentication'
  • restrict_template_rendering Boolean
    config_parameter='mail.restrict.template.rendering' help='Users will still be able to render templates.\nHowever only Mail Template Editors will be able to create new dynamic templates or modify existing ones.' args: 'Restrict Template Rendering'
  • sfu_server_key Char
    config_parameter='mail.sfu_server_key' help='Base64 encoded key' args: 'SFU Server key'
  • sfu_server_url Char
    config_parameter='mail.sfu_server_url' args: 'SFU Server URL'
  • tenor_api_key Char
    config_parameter='discuss.klipy_api_key' help='Add a Klipy GIF API key to enable GIFs support. https://docs.klipy.com/getting-started\nIf you were using a Tenor GIF API key (service shutdown on June 30, 2026), please replace it here with a Klipy GIF API key' args: 'Klipy API key'
  • twilio_account_sid Char
    config_parameter='mail.twilio_account_sid' args: 'Account SID'
  • twilio_account_token Char
    config_parameter='mail.twilio_account_token' args: 'Account Auth Token'
  • use_sfu_server Boolean
    config_parameter='mail.use_sfu_server' help='If you want to setup SFU server for large group calls.' args: 'Use SFU server'
  • use_twilio_rtc_servers Boolean
    config_parameter='mail.use_twilio_rtc_servers' help='If you want to use twilio as TURN/STUN server provider' args: 'Use Twilio ICE servers'
Public methods (2)
  • open_email_layout(self)
  • open_mail_templates(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals)

New fields (9)
  • contact_address_inline Char
    compute='_compute_contact_address_inline' string='Inlined Complete Address' tracking=True
  • email Char
    tracking=1
  • im_status Char
    compute='_compute_im_status' compute_sudo=True args: 'IM Status'
  • name Char
    tracking=1
  • offline_since Datetime
    compute='_compute_im_status' compute_sudo=True args: 'Offline since'
  • parent_id Many2one
    tracking=3
  • phone Char
    tracking=2
  • user_id Many2one
    tracking=4
  • vat Char
    tracking=5
Public methods (2)
  • find_or_create(self, email, assert_valid_email=False)
    @api.model
    Override to use the email_normalized field.
  • get_mention_suggestions(self, search, limit=8)
    @api.readonly@api.model
    Return 'limit'-first partners' such that the name or email matches a 'search' string. Prioritize partners that are also (internal) users, and then extend the research to all partners. The return format is a list of partner data (as per returned by `_to_store()`).

New fields (4)
  • channel_ids Many2many → discuss.channel
    copy=False string='Channels' args: 'discuss.channel', 'discuss_channel_member', 'partner_id', 'channel_id'
  • channel_member_ids One2many → discuss.channel.member
    args: 'discuss.channel.member', 'partner_id'
  • is_in_call Boolean
    compute='_compute_is_in_call' groups='base.group_system'
  • rtc_session_ids One2many → discuss.channel.rtc.session
    args: 'discuss.channel.rtc.session', 'partner_id'
Public methods (2)
  • get_mention_suggestions_from_channel(self, channel_id, search, limit=8)
    @api.readonly@api.model
    Return 'limit'-first partners' such that the name or email matches a 'search' string. Prioritize partners that are also (internal) users, and then extend the research to all partners. Only members of the given channel are returned. The return format is a list of partner data (as per returned by `_to_store()`).
  • search_for_channel_invite(self, search_term, channel_id=None, limit=30)
    @api.readonly@api.model
    Returns partners matching search_term that can be invited to a channel. - If `channel_id` is specified, only partners that can actually be invited to the channel are returned (not already members, and in accordance to the channel configuration). - If no matching partners are found and the search term is a valid email address, then the method may return `selectable_email` as a fallback direct email invite, provided that the channel allows invites by email.

New fields (2)
  • name Char
    required=True
  • user_ids Many2many → res.users
    relation='res_role_res_users_rel' string='Users' args: 'res.users'
Public methods (0)

No public methods.

New fields (13)
  • can_edit_role Boolean
    compute='_compute_can_edit_role'
  • has_external_mail_server Boolean
    compute='_compute_has_external_mail_server'
  • im_status Char
    compute='_compute_im_status' compute_sudo=True args: 'IM Status'
  • is_out_of_office Boolean
    compute='_compute_is_out_of_office' args: 'Out of Office'
  • manual_im_status Selection
    string='IM status manually set by the user' args: [('away', 'Away'), ('busy', 'Do Not Disturb'), ('offline', 'Offline')]
  • notification_type Selection
    compute='_compute_notification_type' default='email' help='Policy on how to handle Chatter notifications:\n- By Emails: notifications are sent to your email address\n- In Odoo: notifications appear in your Odoo Inbox' inverse='_inverse_notification_type' required=True store=True args: [('email', 'By Emails'), ('inbox', 'In Odoo')], 'Notification'
  • out_of_office_from Datetime
  • out_of_office_message Html
    args: 'Vacation Responder'
  • out_of_office_to Datetime
  • outgoing_mail_server_id Many2one → ir.mail_server
    compute='_compute_outgoing_mail_server_id' groups='base.group_user' args: 'ir.mail_server', 'Outgoing Mail Server'
  • outgoing_mail_server_type Selection
    compute='_compute_outgoing_mail_server_id' default='default' groups='base.group_user' required=True args: [('default', 'Default')], 'Outgoing Mail Server Type'
  • presence_ids One2many → mail.presence
    groups='base.group_system' args: 'mail.presence', 'user_id'
  • role_ids Many2many → res.role
    help='Users are notified whenever one of their roles is @-mentioned in a conversation.' relation='res_role_res_users_rel' string='User Roles' args: 'res.role'
Public methods (7)
  • SELF_READABLE_FIELDS(self)
    @property
  • SELF_WRITEABLE_FIELDS(self)
    @property
  • action_archive(self)
  • action_setup_outgoing_mail_server(self, server_type)
    @api.model
    Configure the outgoing mail servers.
  • action_test_outgoing_mail_server(self)
    @api.model
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, vals)

New fields (1)
  • is_in_call Boolean
    related='partner_id.is_in_call' args: 'Is in call'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (7)
  • channel_notifications Selection
    help='This setting will only be applied to channels. Mentions only if not specified.' args: [('all', 'All Messages'), ('no_notif', 'Nothing')], 'Channel Notifications'
  • is_discuss_sidebar_category_channel_open Boolean
    default=True string='Is discuss sidebar category channel open?'
  • is_discuss_sidebar_category_chat_open Boolean
    default=True string='Is discuss sidebar category chat open?'
  • push_to_talk_key Char
    help='String formatted to represent a key with modifiers following this pattern: shift.ctrl.alt.key, e.g: truthy.1.true.b' string='Push-To-Talk shortcut'
  • use_push_to_talk Boolean
    default=False string='Use the push to talk feature'
  • voice_active_duration Integer
    default=200 help='How long the audio broadcast will remain active after passing the volume threshold' string='Duration of voice activity in ms'
  • volume_settings_ids One2many → res.users.settings.volumes
    string='Volumes of other partners' args: 'res.users.settings.volumes', 'user_setting_id'
Public methods (2)
  • set_res_users_settings(self, new_settings)
  • set_volume_setting(self, partner_id, volume, guest_id=None)
    Saves the volume of a guest or a partner. Either partner_id or guest_id must be specified. :param float volume: the selected volume between 0 and 1 :param int partner_id: :param int guest_id:

New fields (4)
  • guest_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner'
  • user_setting_id Many2one → res.users.settings
    index=True ondelete='cascade' required=True args: 'res.users.settings'
  • volume Float
    default=0.5 help='Ranges between 0.0 and 1.0, scale depends on the browser implementation'
Public methods (0)

No public methods.

New fields (1)
  • template_fs Char
    copy=False help='File from where the template originates. Used to reset broken template.' string='Template Filename'
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • reset_template(self)
    Resets the Template with values given in source file. We ignore the case of template being overridden in another modules because it is extremely less likely to happen. This method also tries to reset the translation terms for the current user lang (all langs are not supported due to costly file operation).
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/18.0/mail
VERSION
VERSION 1.18
CATEGORY
CATEGORYProductivity/Discuss
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Martin Trigaux, Olivier Dony, Thibault Delavallée, Denis Ledoux, Xavier Morel, Nicolas Martinelli, Nicolas Lempereur, Thibault Francois, Stefan Rijnhart, Géry Debongnie, Aaron Bohy, Jeremy Kersten, Lucas Perais (lpe), Damien Bouvy, Yannick Tivisse, qsm-odoo, Odoo Online, Pierre Masereel, Laurent Smet, Christophe Monniez, Jorge Pinna Puissant, Jairo Llopis, Lucas Perais, Alexandre Kühn, Julien Castiaux, Xavier-Do, Victor Feyens, Adrien Dieudonné, Paul Morelle, Sébastien Theys, Julien Mougenot, Samuel Degueldre, std-odoo, Achraf (abz), Nasreddin Boulif (bon), Prakash Prajapati, Tiffany Chang (tic), Rémy Voet (ryv), Pierre Rousseau, Gorash, ThanhDodeurOdoo, Mathieu Duckerts-Antoine, Pierre Paridans, abd-msyukyu-odoo, bit-odoo, Romain Estievenart, odoo, Stanislas Sobieski, Miquel Raïch, william-andre, Sébastien Alix, Didier (did), Krzysztof Magusiak, Florian Charlier, Nicolas Bayet, Hubert Van De Walle, Mathieu Walravens, luvi, Achraf, Renaud Thiry, Julien Banken, Vincent Larcin, Ipsita Borisagar, Weblate, bve-odoo, damr, Thomas Lefebvre (thle), alsh-odoo, Gaetan Vanden Bergh (gavb), Louis Wicket (wil), tsm-odoo, nda, Victor Piryns (pivi), Yash Vaishnav, Thomas Becquevort (thbe), miad-odoo, amdi-odoo, Simon Genin (ges), Pierre-Yves Dufays, pash-odoo, Levi Siuzdak (sile), Maruan Aguerdouh (magm), Dylan Kiss (dyki), Bruno Boi, Antoine (ande), FrancoisGe, Mayurrajsinh Rathod, Rahul Prajapati, Chong Wang (cwg), Leloup Loïc (lole), Adrien Schoffeniels, Hugo Carlier (Huca), Xavier Bol (xbo), Brieuc-brd, Alessandro Caldonazzi (alca), Nguyễn Đại Dương, adda-odoo, Mahdi Cheikh Rouhou (macr), Noe Antoine, omra-odoo, Andrzej(pian), Zelong Lin, Walid (wasa), sesn-odoo, maad-odoo, Deependra Solanki, stefanorigano (SRI), BHanq, dane@odoo.com, Hesham, Mattis Megevand, Mélanie, Youssef Bashandy, OmarAbosamaha, lase@odoo.com, bary, Maryam Kia, jorv-odoo, mizosoft, Guillaume-gdi, yosa-odoo, “Beekan”, Ruben Gomes (rugo), Carlos Roca, Ricardoalso, vava-odoo, Bastien Fafchamps (bafa), Julien Carion (juca), dhba, kcv-odoo, adsh-odoo, mega, Tanguy Quéguineur, TSO, Alex Kühn, Lopes Marc (loma), Martin Trigaux (mat), duongnguyen-viindoo, nihp-odoo, Shubham Thanki, Chrysanthe (chgo), Rodolpho Lima, aath-odoo, adch-odoo, sami odoo, Louis (wil), Aungkokolin1997, Junqi Wu, mano-odoo, aamo-odoo, thle-odoo, Mathieu Coutant, Xavier Luyckx (xlu), guce, haumenphai, rame-odoo, Mohammad Abdulmoneim, Antoine (anso), sabr, LauraCForgeFlow, Pierre Pulinckx (PIPU), Hesham Saleh, Julien Schwanen, Victor Miguel Armenta Carrillo, quyen, dija-odoo, Maira Salazar (srma), st-yes, khsr-odoo, Khushi, aych-odoo, Michaël Mattiello, Pierre Pulinckx (pipu), Pierre Pulinckx, fdardenne, Bastien PIERRE, zel-odoo, John Kirkwood (kij), kusi-odoo, pish-odoo, plha-odoo, Krzysztof Magusiak (krma), Mahdi Alijani (malj), Ajit Singh, Christopher Rogos, Quoc - Pham Ngoc, nees-odoo, sagu-odoo, mjvi-odoo, defl, mojem, dise-odoo, Giorgio Tocco (gito), Ayush Chauhan (aych), jayp-odoo, bsra-odoo, igbe, Tudor-Calin Panzaru (tupan), adip-odoo, shka-odoo, Killian Frappart, Jérôme Belpaire, ramh, kmdi-odoo, EL Alaoui Yassine, assh-odoo, gito-odoo, livaios, scho-odoo, Kevin Gerard (kege), Louis, nmak-odoo, Akash Parmar, Shubham Patel, hossamelgendy1, pmah-odoo, Benoit Socias (bso), Soumya M, saurabh, tegu-odoo, Séna Nshimiyimana, Atovange, Tina, Kadam Darji, Jason (jaca), akth-odoo, akus-odoo, Adrien Didot
WEBSITE
WEBSITEhttps://www.odoo.com/app/discuss
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 01:25:57
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web
    - bus
    - web_tour
    - html_editor
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Chat, mail gateway and private channel.
=======================================

Communicate with your colleagues/customers/guest within Odoo.

Discuss/Chat
------------
User-friendly "Discuss" features that allows one 2 one or group communication
(text chat/voice call/video call), invite guests and share documents with
them, all real-time.

Mail gateway
------------
Sending information and documents made simplified. You can send emails
from Odoo itself, and that too with great possibilities. For example,
design a beautiful email template for the invoices, and use the same
for all your customers, no need to do the same exercise every time.

Chatter
-------
Do all the contextual conversation on a document. For example on an
applicant, directly post an update to send email to the applicant,
schedule the next interview call, attach the contract, add HR officer
to the follower list to notify them for important events(with help of
subtypes),...


Retrieve incoming email on POP/IMAP servers.
============================================
Enter the parameters of your POP/IMAP account(s), and any incoming emails on
these accounts will be automatically downloaded into your Odoo system. All
POP3/IMAP-compatible servers are supported, included those that require an
encrypted SSL/TLS connection.
This can be used to easily create email-based workflows for many email-enabled Odoo documents, such as:
----------------------------------------------------------------------------------------------------------
    * CRM Leads/Opportunities
    * CRM Claims
    * Project Issues
    * Project Tasks
    * Human Resource Recruitment (Applicants)
Just install the relevant application, and you can assign any of these document
types (Leads, Project Issues) to your incoming email accounts. New emails will
automatically spawn new documents of the chosen type, so it's a snap to create a
mailbox-to-Odoo integration. Even better: these documents directly act as mini
conversations synchronized by email. You can reply from within Odoo, and the
answers will automatically be collected when they come back, and attached to the
same *conversation* document.
For more specific needs, you may also assign custom-defined actions
(technically: Server Actions) to be triggered for each incoming mail.
    

Code Analysis

Views touched (123)
XML IDNameModelTypeStatus
account_security_setting_update account_security_setting_update ir.ui.view qweb New
discuss_channel_member_view_form discuss.channel.member.form discuss.channel.member form New
discuss_channel_member_view_tree discuss.channel.member.list discuss.channel.member list New
discuss_channel_rtc_session_view_form discuss.channel.rtc.session.form discuss.channel.rtc.session form New
discuss_channel_rtc_session_view_search discuss.channel.rtc.session.search discuss.channel.rtc.session search New
discuss_channel_rtc_session_view_tree discuss.channel.rtc.session.list discuss.channel.rtc.session list New
discuss_gif_favorite_view_form discuss.gif.favorite.form discuss.gif.favorite form New
discuss_gif_favorite_view_tree discuss.gif.favorite.list discuss.gif.favorite list New
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
email_template_form email.template.form mail.template form New
email_template_tree email.template.list mail.template list New
field_form_view ir.model.fields field Inherits base.view_model_fields_form
mail.discuss_channel_view_form discuss.channel.form discuss.channel form New
mail.discuss_channel_view_kanban discuss.channel.kanban discuss.channel kanban New
mail.discuss_channel_view_search discuss.channel.search discuss.channel search New
mail.discuss_channel_view_tree discuss.channel.list discuss.channel list New
mail.discuss_public_channel_template Discuss Public Template ir.ui.view qweb New
mail.message_document_unfollowed mail.message_document_unfollowed ir.ui.view qweb New
mail.public_layout mail.public_layout ir.ui.view qweb New
mail_activity_plan_template_view_form mail.activity.plan.template.view.form mail.activity.plan.template form New
mail_activity_plan_template_view_tree mail.activity.plan.template.view.list mail.activity.plan.template list New
mail_activity_plan_view_form mail.activity.plan.view.form mail.activity.plan form New
mail_activity_plan_view_form_fixed_model mail.activity.plan.view.form.fixed.model mail.activity.plan xpath Inherits mail.mail_activity_plan_view_form
mail_activity_plan_view_kanban mail.activity.plan.view.kanban mail.activity.plan kanban New
mail_activity_plan_view_search mail.activity.plan.view.search mail.activity.plan search New
mail_activity_plan_view_tree mail.activity.plan.view.list mail.activity.plan list New
mail_activity_plan_view_tree_detailed mail.activity.plan.view.list.detailed mail.activity.plan xpath Inherits mail.mail_activity_plan_view_tree
mail_activity_schedule_view_form Activity schedule mail.activity.schedule form New
mail_activity_type_form_inherit mail.activity.type.form.inherit mail.activity.type xpath Inherits mail.mail_activity_type_view_form
mail_activity_type_view_form mail.activity.type.view.form mail.activity.type form New
mail_activity_type_view_kanban mail.activity.type.view.kanban mail.activity.type kanban New
mail_activity_type_view_search mail.activity.type.search mail.activity.type search New
mail_activity_type_view_tree mail.activity.type.view.list mail.activity.type list New
mail_activity_view_calendar mail.activity.view.calendar mail.activity calendar New
mail_activity_view_form mail.activity.view.form mail.activity field Inherits mail.mail_activity_view_form_popup
mail_activity_view_form_popup mail.activity.view.form.popup mail.activity form New
mail_activity_view_form_without_record_access mail.activity.view.form.without.record.access mail.activity form New
mail_activity_view_kanban_open_target mail.activity.view.kanban.open.target mail.activity kanban New
mail_activity_view_search mail.activity.view.search mail.activity search New
mail_activity_view_tree mail.activity.view.list mail.activity list New
mail_activity_view_tree_open_target mail.activity.view.list.open.target mail.activity xpath Inherits mail_activity_view_tree
mail_activity_view_tree_without_record_access mail.activity.view.list.without.record.access mail.activity xpath Inherits mail_activity_view_tree
mail_alias_domain_view_form mail.alias.domain.view.form mail.alias.domain form New
mail_alias_domain_view_search mail.alias.domain.view.search mail.alias.domain search New
mail_alias_domain_view_tree mail.alias.domain.view.list mail.alias.domain list New
mail_alias_view_form mail.alias.view.form mail.alias form New
mail_alias_view_search mail.alias.view.search mail.alias search New
mail_alias_view_tree mail.alias.view.list mail.alias list New
mail_attachment_links Attachment links ir.ui.view qweb New
mail_blacklist_remove_view_form mail.blacklist.remove.form mail.blacklist.remove form New
mail_blacklist_view_form mail.blacklist.view.form mail.blacklist form New
mail_blacklist_view_search mail.blacklist.view.search mail.blacklist search New
mail_blacklist_view_tree mail.blacklist.view.list mail.blacklist list New
mail_bounce_alias_security mail_bounce_alias_security ir.ui.view qweb New
mail_bounce_catchall mail_bounce_catchall ir.ui.view qweb New
mail_canned_response_view_form mail.canned.response.form mail.canned.response form New
mail_canned_response_view_search mail.canned.response.view.search mail.canned.response search New
mail_canned_response_view_tree mail.canned.response.list mail.canned.response list New
mail_compose_message_view_form_template_save mail.compose.message.view.form.template.save mail.compose.message form New
mail_gateway_allowed_view_search mail.gateway.allowed.view.search mail.gateway.allowed search New
mail_gateway_allowed_view_tree mail.gateway.allowed.view.list mail.gateway.allowed list New
mail_guest_view_form mail.guest.form mail.guest form New
mail_guest_view_tree mail.guest.list mail.guest list New
mail_link_preview_view_form mail.link.preview.form mail.link.preview form New
mail_link_preview_view_tree mail.link.preview.list mail.link.preview list New
mail_message_reaction_view_form mail.message.reaction.form mail.message.reaction form New
mail_message_reaction_view_tree mail.message.reaction.list mail.message.reaction list New
mail_message_schedule_view_form mail.message.schedule.view.form mail.message.schedule form New
mail_message_schedule_view_search mail.message.schedule.view.search mail.message.schedule search New
mail_message_schedule_view_tree mail.message.schedule.view.list mail.message.schedule list New
mail_message_subtype_view_search mail.message.subtype.view.search mail.message.subtype search New
mail_message_view_form mail.message.view.form mail.message form New
mail_notification_invite mail_notification_invite ir.ui.view qweb Inherits mail.mail_notification_layout
mail_notification_layout Mail: mail notification layout template ir.ui.view qweb New
mail_notification_layout_with_responsible_signature Mail: mail notification layout with responsible signature (user_id of the record) ir.ui.view qweb Inherits mail.mail_notification_layout
mail_notification_light mail_notification_light ir.ui.view qweb New
mail_notification_view_form mail.notification.view.form mail.notification form New
mail_notification_view_tree mail.notification.view.list mail.notification list New
mail_resend_message_view_form mail.resend.message.view.form mail.resend.message form New
mail_resend_partner_view_form mail.resend.partner.view.form mail.resend.partner form New
mail_scheduled_message_view_form mail.scheduled.message.view.form mail.scheduled.message form New
mail_template_preview_view_form mail.template.preview.view.form mail.template.preview form New
mail_template_reset_view_form mail.template.reset.view.form mail.template.reset form New
mail_template_view_form_confirm_delete mail.template.view.form.confirm.delete mail.template form New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
message_activity_assigned message_activity_assigned ir.ui.view qweb New
message_activity_done message_activity_done ir.ui.view qweb New
message_notification_limit_email message_notification_limit_email ir.ui.view qweb New
message_origin_link message_origin_link ir.ui.view qweb New
message_user_assigned message_user_assigned ir.ui.view qweb New
model_form_view ir.model field Inherits base.view_model_form
model_search_view ir.model field Inherits base.view_model_search
notification_preview notification_preview ir.ui.view qweb New
res_company_view_form res.company.view.form.inherit.mail res.company field Inherits base.view_company_form
res_config_settings_view_form res.config.settings.view.form.inherit.mail res.config.settings div Inherits base_setup.res_config_settings_view_form
res_partner_view_activity res.partner.activity res.partner activity New
res_partner_view_form_inherit_mail res.partner.view.form.inherit.mail res.partner xpath Inherits base.view_partner_form
res_partner_view_kanban_inherit_mail res.partner.view.kanban.inherit.mail res.partner xpath Inherits base.res_partner_kanban_view
res_partner_view_search_inherit_mail res.partner.view.search.inherit.mail res.partner filter Inherits base.view_res_partner_filter
res_partner_view_tree_inherit_mail res.partner.view.list.inherit.mail res.partner xpath Inherits base.view_partner_tree
res_users_settings_view_form res.users.settings.form res.users.settings form New
res_users_settings_view_tree res.users.settings.list res.users.settings list New
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_email_server_form fetchmail.server.form fetchmail.server form New
view_email_server_search fetchmail.server.search fetchmail.server search New
view_email_server_tree fetchmail.server.list fetchmail.server list New
view_email_template_search email.template.search mail.template search New
view_followers_tree mail.followers.list mail.followers list New
view_ice_server_form mail.ice.server.form mail.ice.server form New
view_ice_server_tree mail.ice.server.list mail.ice.server list New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tracking_value_form mail.tracking.value.form mail.tracking.value form New
view_mail_tracking_value_tree mail.tracking.value.list mail.tracking.value list New
view_mail_tree mail.mail.list mail.mail list New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.list mail.message.subtype list New
view_message_tree mail.message.list mail.message list New
view_server_action_form_template ir.actions.server.form ir.actions.server xpath Inherits base.view_server_action_form
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (81)

New fields (0)

No new fields.

Public methods (1)
  • mail_allowed_qweb_expressions(self)
    @api.model

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (1)
  • guest_id Many2one → mail.guest
    ondelete='cascade' args: 'mail.guest', 'Guest'
Public methods (1)
  • init(self)

New fields (26)
  • active Boolean
    default=True help='Set active to false to hide the channel without removing it.'
  • allow_public_upload Boolean
    default=False
  • avatar_128 Image
    compute='_compute_avatar_128' max_height=128 max_width=128 args: 'Avatar'
  • avatar_cache_key Char
    compute='_compute_avatar_cache_key'
  • channel_member_ids One2many → discuss.channel.member
    string='Members' args: 'discuss.channel.member', 'channel_id'
  • channel_partner_ids Many2many → res.partner
    compute='_compute_channel_partner_ids' inverse='_inverse_channel_partner_ids' search='_search_channel_partner_ids' string='Partners' args: 'res.partner'
  • channel_type Selection
    default='channel' help='Chat is private and unique between 2 persons. Group is private among invited persons. Channel can be freely joined (depending on its configuration).' readonly=True required=True string='Channel Type' args: [('chat', 'Chat'), ('channel', 'Channel'), ('group', 'Group')]
  • default_display_mode Selection
    help='Determines how the channel will be displayed by default when opening it from its invitation link. No value means display text (no voice/video).' selection=[('video_full_screen', 'Full screen video')] string='Default Display Mode'
  • description Text
    args: 'Description'
  • from_message_id Many2one → mail.message
    help='The message the channel was created from.' readonly=True args: 'mail.message'
  • group_ids Many2many → res.groups
    help='Members of those groups will automatically added as followers. Note that they will be able to manage their subscription manually if necessary.' string='Auto Subscription' args: 'res.groups'
  • group_public_id Many2one → res.groups
    compute='_compute_group_public_id' readonly=False store=True string='Authorized Group' args: 'res.groups'
  • image_128 Image
    max_height=128 max_width=128 args: 'Image'
  • invitation_url Char
    compute='_compute_invitation_url' args: 'Invitation URL'
  • is_editable Boolean
    compute='_compute_is_editable' args: 'Is Editable'
  • is_member Boolean
    compute='_compute_is_member' search='_search_is_member' args: 'Is Member'
  • last_interest_dt Datetime
    help='Contains the date and time of the last interesting event that happened in this channel. This updates itself when new message posted.' index=True args: 'Last Interest'
  • member_count Integer
    compute='_compute_member_count' compute_sudo=True string='Member Count'
  • name Char
    required=True args: 'Name'
  • parent_channel_id Many2one → discuss.channel
    auto_join=True help='Parent channel' index=True ondelete='cascade' readonly=True args: 'discuss.channel'
  • pinned_message_ids One2many → mail.message
    domain=[('model', '=', 'discuss.channel'), ('pinned_at', '!=', False)] string='Pinned Messages' args: 'mail.message', 'res_id'
  • rtc_session_ids One2many → discuss.channel.rtc.session
    groups='base.group_system' args: 'discuss.channel.rtc.session', 'channel_id'
  • sfu_channel_uuid Char
    groups='base.group_system'
  • sfu_server_url Char
    groups='base.group_system'
  • sub_channel_ids One2many → discuss.channel
    readonly=True string='Sub Channels' args: 'discuss.channel', 'parent_channel_id'
  • uuid Char
    copy=False default=_generate_random_token size=50 args: 'UUID'
Public methods (20)
  • action_unfollow(self)
  • add_members(self, partner_ids=None, guest_ids=None, invite_to_rtc_call=False, open_chat_window=False, post_joined_message=True)
    Adds the given partner_ids and guest_ids as member of self channels.
  • channel_change_description(self, description)
  • channel_create(self, name, group_id)
    @api.model@api.returns('self', <expr>)
    Create a channel and add the current partner, broadcast it (to make the user directly listen to it when polling) :param name : the name of the channel to create :param group_id : the group allowed to join the channel. :return dict : channel header
  • channel_fetched(self)
    Broadcast the channel_fetched notification to channel members
  • channel_get(self, partners_to, pin=True, force_open=False)
    @api.model@api.returns('self', <expr>)
    Get the canonical private channel between some partners, create it if needed. To reuse an old channel (conversation), this one must be private, and contains only the given partners. :param partners_to : list of res.partner ids to add to the conversation :param pin : True if getting the channel should pin it for the current user :param force_open : True if getting the channel should open it for the current user :returns: channel_info of the created or existing channel :rtype: dict
  • channel_join(self)
    Shortcut to add the current user as member of self channels. Prefer calling add_members() directly when possible.
  • channel_pin(self, pinned=False)
  • channel_rename(self, name)
  • channel_set_custom_name(self, name)
  • create(self, vals_list)
    @api.model_create_multi
  • create_group(self, partners_to, default_display_mode=False, name='')
    @api.model@api.returns('self', <expr>)
    Creates a group channel. :param partners_to : list of res.partner ids to add to the conversation :param str default_display_mode: how the channel will be displayed by default :param str name: group name. default name is computed client side from the list of members if no name is set :returns: channel_info of the created channel :rtype: dict
  • execute_command_help(self, **kwargs)
  • execute_command_leave(self, **kwargs)
  • execute_command_who(self, **kwargs)
  • get_mention_suggestions(self, search, limit=8)
    @api.readonly@api.model
    Return 'limit'-first channels' id, name, channel_type and authorizedGroupFullName fields such that the name matches a 'search' string. Exclude channels of type chat (DM) and group.
  • init(self)
  • message_post(self, *, message_type='notification', **kwargs)
    @api.returns('mail.message', <expr>)
  • set_message_pin(self, message_id, pinned)
    (Un)pin a message on the channel and send a notification to the members. :param message_id: id of the message to be pinned. :param pinned: whether the message should be pinned or unpinned.
  • write(self, vals)

New fields (18)
  • channel_id Many2one → discuss.channel
    auto_join=True ondelete='cascade' required=True args: 'discuss.channel', 'Channel'
  • custom_channel_name Char
    args: 'Custom channel name'
  • custom_notifications Selection
    help='Use default from user settings if not specified. This setting will only be applied to channels.' args: [('all', 'All Messages'), ('mentions', 'Mentions Only'), ('no_notif', 'Nothing')], 'Customized Notifications'
  • fetched_message_id Many2one → mail.message
    index='btree_not_null' string='Last Fetched' args: 'mail.message'
  • fold_state Selection
    default='closed' string='Conversation Fold State' args: [('open', 'Open'), ('folded', 'Folded'), ('closed', 'Closed')]
  • guest_id Many2one → mail.guest
    index=True ondelete='cascade' args: 'mail.guest', 'Guest'
  • is_pinned Boolean
    compute='_compute_is_pinned' search='_search_is_pinned' args: 'Is pinned on the interface'
  • is_self Boolean
    compute='_compute_is_self' search='_search_is_self'
  • last_interest_dt Datetime
    default=fields.Datetime.now help='Contains the date and time of the last interesting event that happened in this channel for this user. This includes: creating, joining, pinning' index=True args: 'Last Interest'
  • last_seen_dt Datetime
    args: 'Last seen date'
  • message_unread_counter Integer
    compute='_compute_message_unread' compute_sudo=True args: 'Unread Messages Counter'
  • mute_until_dt Datetime
    help='If set, the member will not receive notifications from the channel until this date.' args: 'Mute notifications until'
  • new_message_separator Integer
    default=0 help='Message id before which the separator should be displayed' required=True
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner', 'Partner'
  • rtc_inviting_session_id Many2one → discuss.channel.rtc.session
    string='Ringing session' args: 'discuss.channel.rtc.session'
  • rtc_session_ids One2many → discuss.channel.rtc.session
    comodel_name='discuss.channel.rtc.session' inverse_name='channel_member_id' string='RTC Sessions'
  • seen_message_id Many2one → mail.message
    index='btree_not_null' string='Last Seen' args: 'mail.message'
  • unpin_dt Datetime
    help='Contains the date and time when the channel was unpinned by the user.' index=True args: 'Unpin date'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
  • init(self)
  • set_custom_notifications(self, custom_notifications)
  • unlink(self)
  • write(self, vals)

New fields (9)
  • channel_id Many2one → discuss.channel
    readonly=True related='channel_member_id.channel_id' store=True args: 'discuss.channel'
  • channel_member_id Many2one → discuss.channel.member
    ondelete='cascade' required=True args: 'discuss.channel.member'
  • guest_id Many2one → mail.guest
    related='channel_member_id.guest_id' args: 'mail.guest'
  • is_camera_on Boolean
    string='Is sending user video'
  • is_deaf Boolean
    string='Has disabled incoming sound'
  • is_muted Boolean
    string='Is microphone muted'
  • is_screen_sharing_on Boolean
    string='Is sharing the screen'
  • partner_id Many2one → res.partner
    related='channel_member_id.partner_id' string='Partner' args: 'res.partner'
  • write_date Datetime
    index=True args: 'Last Updated On'
Public methods (3)
  • action_disconnect(self)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)

New fields (1)
  • tenor_gif_id Char
    required=True args: 'GIF id from Tenor'
Public methods (0)

No public methods.

New fields (1)
  • attachment_id Many2one → ir.attachment
    auto_join=True copy=False index=True ondelete='cascade' args: 'ir.attachment'
Public methods (0)

No public methods.

New fields (18)
  • active Boolean
    default=True args: 'Active'
  • attach Boolean
    default=True help='Whether attachments should be downloaded. If not enabled, incoming emails will be stripped of any attachments before being processed' args: 'Keep Attachments'
  • configuration Text
    readonly=True args: 'Configuration'
  • date Datetime
    readonly=True string='Last Fetch Date'
  • is_ssl Boolean
    help='Connections are encrypted with SSL/TLS through a dedicated port (default: IMAPS=993, POP3S=995)' args: 'SSL/TLS'
  • message_ids One2many → mail.mail
    readonly=True string='Messages' args: 'mail.mail', 'fetchmail_server_id'
  • name Char
    required=True args: 'Name'
  • object_id Many2one → ir.model
    help='Process each incoming mail as part of a conversation corresponding to this document type. This will create new documents for new conversations, or attach follow-up emails to the existing conversations (documents).' string='Create a New Record' args: 'ir.model'
  • original Boolean
    help='Whether a full original copy of each email should be kept for reference and attached to each processed message. This will usually double the size of your message database.' args: 'Keep Original'
  • password Char
  • port Integer
  • priority Integer
    default=5 help='Defines the order of processing, lower values mean higher priority' readonly=False string='Server Priority'
  • script Char
    default='/mail/static/scripts/odoo-mailgate.py' readonly=True
  • server Char
    help='Hostname or IP of the mail server' readonly=False string='Server Name'
  • server_type Selection
    default='imap' index=True required=True string='Server Type' args: [('imap', 'IMAP Server'), ('pop', 'POP Server'), ('local', 'Local Server')]
  • server_type_info Text
    compute='_compute_server_type_info' args: 'Server Type Info'
  • state Selection
    copy=False default='draft' index=True readonly=True string='Status' args: [('draft', 'Not Confirmed'), ('done', 'Confirmed')]
  • user Char
    readonly=False string='Username'
Public methods (8)
  • button_confirm_login(self)
  • connect(self, allow_archived=False)
    :param bool allow_archived: by default (False), an exception is raised when calling this method on an archived record. It can be set to True for testing so that the exception is no longer raised.
  • create(self, vals_list)
    @api.model_create_multi
  • fetch_mail(self, raise_exception=True)
    WARNING: meant for cron usage only - will commit() after each email!
  • onchange_server_type(self)
    @api.onchange('server_type', 'is_ssl', 'object_id')
  • set_draft(self)
  • unlink(self)
  • write(self, values)

New fields (1)
  • view_mode Selection
    ondelete={'activity': 'cascade'} selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (13)
  • activity_date_deadline_range Integer
    compute='_compute_activity_info' readonly=False store=True string='Due Date In'
  • activity_date_deadline_range_type Selection
    compute='_compute_activity_info' readonly=False store=True string='Due type' args: [('days', 'Days'), ('weeks', 'Weeks'), ('months', 'Months')]
  • activity_note Html
    compute='_compute_activity_info' readonly=False store=True args: 'Note'
  • activity_summary Char
    compute='_compute_activity_info' readonly=False store=True args: 'Title'
  • activity_type_id Many2one → mail.activity.type
    compute='_compute_activity_type_id' domain="['|', ('res_model', '=', False), ('res_model', '=', model_name)]" ondelete='restrict' readonly=False store=True string='Activity Type' args: 'mail.activity.type'
  • activity_user_field_name Char
    compute='_compute_activity_info' readonly=False store=True args: 'User Field'
  • activity_user_id Many2one → res.users
    compute='_compute_activity_info' readonly=False store=True string='Responsible' args: 'res.users'
  • activity_user_type Selection
    compute='_compute_activity_info' help="Use 'Specific User' to always assign the same user on the next activity. Use 'Dynamic User' to specify the field name of the user to choose on the record." readonly=False store=True string='User Type' args: [('specific', 'Specific User'), ('generic', 'Dynamic User (based on record)')]
  • mail_post_autofollow Boolean
    compute='_compute_mail_post_autofollow' readonly=False store=True args: 'Subscribe Recipients'
  • mail_post_method Selection
    compute='_compute_mail_post_method' readonly=False selection=[('email', 'Email'), ('comment', 'Message'), ('note', 'Note')] store=True string='Send Email As'
  • partner_ids Many2many → res.partner
    compute='_compute_partner_ids' readonly=False store=True args: 'res.partner'
  • state Selection
    ondelete={'mail_post': 'cascade', 'followers': 'cascade', 'remove_followers': 'cascade', 'next_activity': 'cascade'} selection_add=[('next_activity', 'Create Activity'), ('mail_post', 'Send Email'), ('followers', 'Add Followers'), ('remove_followers', 'Remove Followers'), ('object_create')]
  • template_id Many2one → mail.template
    compute='_compute_template_id' domain="[('model_id', '=', model_id)]" ondelete='set null' readonly=False store=True args: 'mail.template', 'Email Template'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • register_as_main_attachment(self, force=True)
    Registers this attachment as the main one of the model it is attached to. :param bool force: if set, the method always updates the existing main attachment otherwise it only sets the main attachment if there is none.

New fields (1)
  • voice_ids One2many → discuss.voice.metadata
    args: 'discuss.voice.metadata', 'attachment_id'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • set_param(self, key, value)
    @api.model
  • write(self, vals)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • session_info(self)
    Override to add the current user data (partner or guest) if applicable.

New fields (1)
  • mail_template_ids One2many → mail.template
    comodel_name='mail.template' inverse_name='mail_server_id' readonly=True string='Mail template using this mail server'
Public methods (0)

No public methods.

New fields (3)
  • is_mail_activity Boolean
    default=False string='Has Mail Activity'
  • is_mail_blacklist Boolean
    default=False string='Has Mail Blacklist'
  • is_mail_thread Boolean
    default=False string='Has Mail Thread'
Public methods (2)
  • unlink(self)
    Delete mail data (followers, messages, activities) associated with the models being deleted.
  • write(self, vals)

New fields (1)
  • tracking Integer
    help='If set every modification done to this field is tracked. Value is used to order tracking values.' string='Enable Ordered Tracking'
Public methods (1)
  • unlink(self)
    When unlinking fields populate tracking value table with relevant information. That way if a field is removed (custom tracked, migration or any other reason) we keep the tracking and its relevant information. Do it only when unlinking fields so that we don't duplicate field information for most tracking.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (1)
  • type Selection
    selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (25)
  • active Boolean
    default=True
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_decoration Selection
    readonly=True related='activity_type_id.decoration_type'
  • activity_type_id Many2one → mail.activity.type
    default=_default_activity_type domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" ondelete='restrict' string='Activity Type' args: 'mail.activity.type'
  • attachment_ids Many2many → ir.attachment
    string='Attachments' args: 'ir.attachment', 'activity_attachment_rel', 'activity_id', 'attachment_id'
  • automated Boolean
    help='Indicates this activity has been created automatically and not by any user.' readonly=True args: 'Automated activity'
  • can_write Boolean
    compute='_compute_can_write'
  • chaining_type Selection
    readonly=True related='activity_type_id.chaining_type'
  • date_deadline Date
    default=fields.Date.context_today index=True required=True args: 'Due Date'
  • date_done Date
    compute='_compute_date_done' store=True args: 'Done Date'
  • has_recommended_activities Boolean
    compute='_compute_has_recommended_activities' args: 'Next activities available'
  • icon Char
    readonly=True related='activity_type_id.icon' args: 'Icon'
  • mail_template_ids Many2many
    readonly=True related='activity_type_id.mail_template_ids'
  • note Html
    sanitize_style=True args: 'Note'
  • previous_activity_type_id Many2one → mail.activity.type
    readonly=True string='Previous Activity Type' args: 'mail.activity.type'
  • recommended_activity_type_id Many2one → mail.activity.type
    string='Recommended Activity Type' args: 'mail.activity.type'
  • request_partner_id Many2one → res.partner
    string='Requesting Partner' args: 'res.partner'
  • res_id Many2oneReference
    index=True model_field='res_model' string='Related Document ID'
  • res_model Char
    index=True precompute=True readonly=True related='res_model_id.model' store=True args: 'Related Document Model'
  • res_model_id Many2one → ir.model
    index=True ondelete='cascade' required=True args: 'ir.model', 'Document Model'
  • res_name Char
    compute='_compute_res_name' compute_sudo=True readonly=True store=True args: 'Document Name'
  • state Selection
    compute='_compute_state' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned'), ('done', 'Done')], 'State'
  • summary Char
    args: 'Summary'
  • user_id Many2one → res.users
    default=<expr> index=True ondelete='cascade' required=True args: 'res.users', 'Assigned to'
  • user_tz Selection
    related='user_id.tz' store=True string='Timezone'
Public methods (16)
  • action_cancel(self)
  • action_close_dialog(self)
    @api.readonly
  • action_done(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_done_redirect_to_other(self)
    Mark activity as done and return action mail.mail_activity_without_access_action. Goal: Unless "keep done" activity is enabled, when marking an activity as done, the activity is deleted and can no more be displayed. To overcome this, we return an action that will launch the list view displaying the activities corresponding to the active_ids from the context (i.e.: the remaining "other activities"). If the right context is not available, we recompute the activities to display.
  • action_done_schedule_next(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_feedback(self, feedback=False, attachment_ids=None)
  • action_feedback_schedule_next(self, feedback=False, attachment_ids=None)
  • action_notify(self)
  • action_open_document(self)
    @api.readonly
    Opens the related record based on the model and ID, or activity if user has no access to the related record.
  • action_snooze(self)
  • activity_format(self)
    @api.readonly
  • create(self, vals_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • get_activity_data(self, res_model, domain, limit=None, offset=0, fetch_done=False)
    @api.readonly@api.model
    Get aggregate data about records and their activities. The goal is to fetch and compute aggregated data about records and their activities to display them in the activity views and the chatter. For example, the activity view displays it as a table with columns and rows being respectively the activity_types and the activity_res_ids, and the grouped_activities being the table entries with the aggregated data. :param str res_model: model of the records to fetch :param list domain: record search domain :param int limit: maximum number of records to fetch :param int offset: offset of the first record to fetch :param bool fetch_done: determines if "done" activities are integrated in the aggregated data or not. :return dict: {'activity_types': dict of activity type info {id: int, name: str, mail_template: list of {id:int, name:str}, keep_done: bool} 'activity_res_ids': list<int> of record id ordered by closest date (deadline for ongoing activities, and done date for done activities) 'grouped_activities': dict<dict> res_id -> activity_type_id -> aggregated info as: count_by_state dict: mapping state to count (ex.: 'planned': 2) ids list: activity ids for the res_id and activity_type_id reporting_date str: aggregated date of the related activities as oldest deadline of ongoing activities if there are any or most recent date done of completed activities state dict: aggregated state of the related activities user_assigned_ids list: activity responsible id ordered by closest deadline of the related activities attachments_info: dict with information about the attachments {'count': int, 'most_recent_id': int, 'most_recent_name': str} }
  • unlink(self)
  • write(self, values)

New fields (10)
  • activity_date_deadline Date
    compute='_compute_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_activity_date_deadline' store=False args: 'Next Activity Deadline'
  • activity_exception_decoration Selection
    compute='_compute_activity_exception_type' help='Type of the exception activity on record.' search='_search_activity_exception_decoration' args: [('warning', 'Alert'), ('danger', 'Error')]
  • activity_exception_icon Char
    compute='_compute_activity_exception_type' help='Icon to indicate an exception activity.' args: 'Icon'
  • activity_ids One2many → mail.activity
    auto_join=True groups='base.group_user' args: 'mail.activity', 'res_id', 'Activities'
  • activity_state Selection
    compute='_compute_activity_state' groups='base.group_user' help='Status based on activities\nOverdue: Due date is already passed\nToday: Activity date is today\nPlanned: Future activities.' search='_search_activity_state' string='Activity State' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')]
  • activity_summary Char
    groups='base.group_user' readonly=False related='activity_ids.summary' search='_search_activity_summary' args: 'Next Activity Summary'
  • activity_type_icon Char
    related='activity_ids.icon' args: 'Activity Type Icon'
  • activity_type_id Many2one → mail.activity.type
    groups='base.group_user' readonly=False related='activity_ids.activity_type_id' search='_search_activity_type_id' args: 'mail.activity.type', 'Next Activity Type'
  • activity_user_id Many2one → res.users
    compute='_compute_activity_user_id' groups='base.group_user' readonly=True search='_search_activity_user_id' args: 'res.users', 'Responsible User'
  • my_activity_date_deadline Date
    compute='_compute_my_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_my_activity_date_deadline' args: 'My Activity Deadline'
Public methods (9)
  • activity_feedback(self, act_type_xmlids, user_id=None, feedback=None, attachment_ids=None)
    Set activities as done, limiting to some activity types and optionally to a given user.
  • activity_reschedule(self, act_type_xmlids, user_id=None, date_deadline=None, new_user_id=None)
    Reschedule some automated activities. Activities to reschedule are selected based on type xml ids and optionally by user. Purpose is to be able to * update the deadline to date_deadline; * update the responsible to new_user_id;
  • activity_schedule(self, act_type_xmlid='', date_deadline=None, summary='', note='', **act_values)
    Schedule an activity on each record of the current record set. This method allow to provide as parameter act_type_xmlid. This is an xml_id of activity type instead of directly giving an activity_type_id. It is useful to avoid having various "env.ref" in the code and allow to let the mixin handle access rights. Note that unless specified otherwise in act_values, the activities created will have their "automated" field set to True. :param date_deadline: the day the activity must be scheduled on the timezone of the user must be considered to set the correct deadline
  • activity_search(self, act_type_xmlids='', user_id=None, additional_domain=None)
    Search automated activities on current record set, given a list of activity types xml IDs. It is useful when dealing with specific types involved in automatic activities management. :param act_type_xmlids: list of activity types xml IDs :param user_id: if set, restrict to activities of that user_id; :param additional_domain: if set, filter on that domain;
  • activity_send_mail(self, template_id)
    Automatically send an email based on the given mail.template, given its ID.
  • activity_unlink(self, act_type_xmlids, user_id=None)
    Unlink activities, limiting to some activity types and optionally to a given user.
  • toggle_active(self)
    Before archiving the record we should also remove its ongoing activities. Otherwise they stay in the systray and concerning archived records it makes no sense.
  • unlink(self)
    Override unlink to delete records activities through (res_model, res_id).
  • write(self, vals)

New fields (8)
  • active Boolean
    default=True
  • company_id Many2one → res.company
    default=<expr> args: 'res.company'
  • has_user_on_demand Boolean
    compute='_compute_has_user_on_demand' args: 'Has on demand responsible'
  • name Char
    required=True args: 'Name'
  • res_model Selection
    help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' required=True selection=_get_model_selection string='Model'
  • res_model_id Many2one → ir.model
    compute='_compute_res_model_id' compute_sudo=True ondelete='cascade' precompute=True readonly=False required=True store=True string='Applies to' args: 'ir.model'
  • steps_count Integer
    compute='_compute_steps_count'
  • template_ids One2many → mail.activity.plan.template
    copy=True string='Activities' args: 'mail.activity.plan.template', 'plan_id'
Public methods (1)
  • copy_data(self, default=None)

New fields (13)
  • activity_type_id Many2one → mail.activity.type
    default=<expr> domain="['|', ('res_model', '=', False), '&', ('res_model', '!=', False), ('res_model', '=', parent.res_model)]" ondelete='restrict' required=True args: 'mail.activity.type', 'Activity Type'
  • company_id Many2one
    related='plan_id.company_id'
  • delay_count Integer
    default=0 help='Number of days/week/month before executing the action after or before the scheduled plan date.' args: 'Interval'
  • delay_from Selection
    default='before_plan_date' required=True string='Trigger' args: [('before_plan_date', 'Before Plan Date'), ('after_plan_date', 'After Plan Date')]
  • delay_unit Selection
    default='days' help='Unit of delay' required=True string='Delay units' args: [('days', 'days'), ('weeks', 'weeks'), ('months', 'months')]
  • icon Char
    readonly=True related='activity_type_id.icon' args: 'Icon'
  • note Html
    compute='_compute_note' readonly=False store=True args: 'Note'
  • plan_id Many2one → mail.activity.plan
    ondelete='cascade' required=True string='Plan' args: 'mail.activity.plan'
  • res_model Selection
    related='plan_id.res_model'
  • responsible_id Many2one → res.users
    check_company=True compute='_compute_responsible_id' readonly=False store=True args: 'res.users', 'Assigned to'
  • responsible_type Selection
    compute='_compute_responsible_type' default='on_demand' readonly=False required=True store=True string='Assignment' args: [('on_demand', 'Ask at launch'), ('other', 'Default user')]
  • sequence Integer
    default=10
  • summary Char
    compute='_compute_summary' readonly=False store=True args: 'Summary'
Public methods (0)

No public methods.

New fields (20)
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_type_id Many2one → mail.activity.type
    compute='_compute_activity_type_id' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" ondelete='set null' readonly=False store=True string='Activity Type' args: 'mail.activity.type'
  • activity_user_id Many2one → res.users
    compute='_compute_activity_user_id' readonly=False store=True args: 'res.users', 'Assigned to'
  • chaining_type Selection
    readonly=True related='activity_type_id.chaining_type'
  • company_id Many2one → res.company
    compute='_compute_company_id' required=True args: 'res.company', 'Company'
  • date_deadline Date
    compute='_compute_date_deadline' readonly=False store=True args: 'Due Date'
  • error Html
    compute='_compute_error'
  • has_error Boolean
    compute='_compute_error'
  • is_batch_mode Boolean
    compute='_compute_is_batch_mode' args: 'Use in batch'
  • note Html
    compute='_compute_note' readonly=False sanitize_style=True store=True args: 'Note'
  • plan_available_ids Many2many → mail.activity.plan
    compute='_compute_plan_available_ids' compute_sudo=True store=True args: 'mail.activity.plan'
  • plan_date Date
    compute='_compute_plan_date' readonly=False store=True args: 'Plan Date'
  • plan_has_user_on_demand Boolean
    related='plan_id.has_user_on_demand'
  • plan_id Many2one → mail.activity.plan
    compute='_compute_plan_id' domain="[('id', 'in', plan_available_ids)]" readonly=False store=True args: 'mail.activity.plan'
  • plan_on_demand_user_id Many2one → res.users
    default=<expr> help='Choose assignation for activities with on demand assignation.' args: 'res.users', 'Assigned To'
  • plan_summary Html
    compute='_compute_plan_summary'
  • res_ids Text
    compute='_compute_res_ids' precompute=True readonly=True store=True args: 'Document IDs'
  • res_model Char
    readonly=True required=True args: 'Model'
  • res_model_id Many2one → ir.model
    compute='_compute_res_model_id' compute_sudo=True ondelete='cascade' precompute=True readonly=False required=True store=True string='Applies to' args: 'ir.model'
  • summary Char
    compute='_compute_summary' readonly=False store=True args: 'Summary'
Public methods (5)
  • action_schedule_activities(self)
  • action_schedule_activities_done(self)
  • action_schedule_activities_done_and_schedule(self)
  • action_schedule_plan(self)
  • default_get(self, fields_list)
    @api.model

New fields (23)
  • active Boolean
    default=True
  • category Selection
    default='default' help='Actions may trigger specific behavior like opening calendar view or automatically mark as done when a document is uploaded' string='Action' args: [('default', 'None'), ('upload_file', 'Upload Document'), ('phonecall', 'Phonecall')]
  • chaining_type Selection
    default='suggest' required=True string='Chaining Type' args: [('suggest', 'Suggest Next Activity'), ('trigger', 'Trigger Next Activity')]
  • create_uid Many2one → res.users
    index=True args: 'res.users'
  • decoration_type Selection
    help='Change the background color of the related activities of this type.' string='Decoration Type' args: [('warning', 'Alert'), ('danger', 'Error')]
  • default_note Html
    string='Default Note' translate=True
  • default_user_id Many2one → res.users
    string='Default User' args: 'res.users'
  • delay_count Integer
    default=0 help='Number of days/week/month before executing the action. It allows to plan the action deadline.' args: 'Schedule'
  • delay_from Selection
    default='previous_activity' help='Type of delay' required=True string='Delay Type' args: [('current_date', 'after completion date'), ('previous_activity', 'after previous activity deadline')]
  • delay_label Char
    compute='_compute_delay_label'
  • delay_unit Selection
    default='days' help='Unit of delay' required=True string='Delay units' args: [('days', 'days'), ('weeks', 'weeks'), ('months', 'months')]
  • icon Char
    help='Font awesome icon e.g. fa-tasks' args: 'Icon'
  • initial_res_model Selection
    compute='_compute_initial_res_model' help='Technical field to keep track of the model at the start of editing to support UX related behaviour' selection=_get_model_selection store=False string='Initial model'
  • keep_done Boolean
    help='Keep activities marked as done in the activity view' string='Keep Done'
  • mail_template_ids Many2many → mail.template
    string='Email templates' args: 'mail.template'
  • name Char
    required=True translate=True args: 'Name'
  • previous_type_ids Many2many → mail.activity.type
    domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" string='Preceding Activities' args: 'mail.activity.type', 'mail_activity_rel', 'recommended_id', 'activity_id'
  • res_model Selection
    help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' selection=_get_model_selection string='Model'
  • res_model_change Boolean
    default=False store=False string='Model has change'
  • sequence Integer
    default=10 args: 'Sequence'
  • suggested_next_type_ids Many2many → mail.activity.type
    compute='_compute_suggested_next_type_ids' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" help='Suggest these activities once the current one is marked as done.' inverse='_inverse_suggested_next_type_ids' readonly=False store=True string='Suggest' args: 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id'
  • summary Char
    translate=True args: 'Default Summary'
  • triggered_next_type_id Many2one → mail.activity.type
    compute='_compute_triggered_next_type_id' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" help='Automatically schedule this activity once the current one is marked as done.' inverse='_inverse_triggered_next_type_id' ondelete='restrict' readonly=False store=True string='Trigger' args: 'mail.activity.type'
Public methods (2)
  • action_archive(self)
  • write(self, values)

New fields (14)
  • alias_bounced_content Html
    help='If set, this content will automatically be sent out to unauthorized users instead of the default message.' translate=True args: 'Custom Bounced Message'
  • alias_contact Selection
    default='everyone' help='Policy to post a message on the document using the mailgateway.\n- everyone: everyone can post\n- partners: only authenticated partners\n- followers: only followers of the related document or members of following channels\n' required=True string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_defaults Text
    default='{}' help='A Python dictionary that will be evaluated to provide default values when creating new records for this alias.' required=True args: 'Default Values'
  • alias_domain Char
    related='alias_domain_id.name' args: 'Alias domain name'
  • alias_domain_id Many2one → mail.alias.domain
    default=<expr> ondelete='restrict' string='Alias Domain' args: 'mail.alias.domain'
  • alias_force_thread_id Integer
    help='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.' args: 'Record Thread ID'
  • alias_full_name Char
    compute='_compute_alias_full_name' index='btree_not_null' store=True args: 'Alias Email'
  • alias_incoming_local Boolean
    default=False args: 'Local-part based incoming detection'
  • alias_model_id Many2one → ir.model
    domain="[('field_id.name', '=', 'message_ids')]" help='The model (Odoo 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)' ondelete='cascade' required=True args: 'ir.model', 'Aliased Model'
  • alias_name Char
    copy=False help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>" args: 'Alias Name'
  • alias_parent_model_id Many2one → ir.model
    help='Parent model holding the alias. The model holding the alias reference is not necessarily the model given by alias_model_id (example: project (parent_model) and task (model))' args: 'ir.model', 'Parent Model'
  • alias_parent_thread_id Integer
    help='ID of the parent record holding the alias (example: project holding the task creation alias)' args: 'Parent Record Thread ID'
  • alias_status Selection
    compute='_compute_alias_status' help='Alias status assessed on the last message received.' store=True args: [('not_tested', 'Not Tested'), ('valid', 'Valid'), ('invalid', 'Invalid')]
  • display_name Char
    compute='_compute_display_name' search='_search_display_name' string='Display Name'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
    Creates mail.alias records according to the values provided in ``vals`` but sanitize 'alias_name' by replacing certain unsafe characters; set default alias domain if not given. :raise UserError: if given (alias_name, alias_domain_id) already exists or if there are duplicates in given vals_list;
  • init(self)
    Make sure there aren't multiple records for the same name and alias domain. Not in _sql_constraint because COALESCE is not supported for PostgreSQL constraint.
  • open_document(self)
  • open_parent_document(self)
  • write(self, vals)
    Raise UserError with a meaningful message instead of letting the uniqueness constraint raise an SQL error. To check uniqueness we have to rebuild pairs of names / domains to validate, taking into account that a void alias_domain_id is acceptable (but also raises for uniqueness).

New fields (9)
  • bounce_alias Char
    default='bounce' help="Local-part of email used for Return-Path used when emails bounce e.g. 'bounce' in 'bounce@example.com'" required=True args: 'Bounce Alias'
  • bounce_email Char
    compute='_compute_bounce_email' args: 'Bounce Email'
  • catchall_alias Char
    default='catchall' help="Local-part of email used for Reply-To to catch answers e.g. 'catchall' in 'catchall@example.com'" required=True args: 'Catchall Alias'
  • catchall_email Char
    compute='_compute_catchall_email' args: 'Catchall Email'
  • company_ids One2many → res.company
    help='Companies using this domain as default for sending mails' string='Companies' args: 'res.company', 'alias_domain_id'
  • default_from Char
    default='notifications' help="Default from when it does not match outgoing server filters. Can be either a local-part e.g. 'notifications' either a complete email address e.g. 'notifications@example.com' to override all outgoing emails." args: 'Default From Alias'
  • default_from_email Char
    compute='_compute_default_from_email' args: 'Default From'
  • name Char
    help="Email domain e.g. 'example.com' in 'odoo@example.com'" required=True args: 'Name'
  • sequence Integer
    default=10
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
    Sanitize bounce_alias / catchall_alias / default_from
  • write(self, vals)
    Sanitize name / bounce_alias / catchall_alias / default_from

New fields (3)
  • alias_defaults Text
    inherited=True
  • alias_id Many2one
    required=True
  • alias_name Char
    inherited=True
Public methods (0)

No public methods.

New fields (6)
  • alias_defaults Text
    related='alias_id.alias_defaults'
  • alias_domain Char
    related='alias_id.alias_domain' args: 'Alias Domain Name'
  • alias_domain_id Many2one → mail.alias.domain
    readonly=False related='alias_id.alias_domain_id' string='Alias Domain' args: 'mail.alias.domain'
  • alias_email Char
    compute='_compute_alias_email' search='_search_alias_email' args: 'Email Alias'
  • alias_id Many2one → mail.alias
    copy=False ondelete='restrict' required=False string='Alias' args: 'mail.alias'
  • alias_name Char
    readonly=False related='alias_id.alias_name'
Public methods (4)
  • copy_data(self, default=None)
  • create(self, vals_list)
    @api.model_create_multi
    Create aliases using sudo if an alias is required, notably if its name is given.
  • unlink(self)
    Delete the given records, and cascade-delete their corresponding alias.
  • write(self, vals)
    Split writable fields of mail.alias and other fields alias fields will write with sudo and the other normally. Also handle alias_domain_id update. If alias does not exist and we try to set a name, create the alias automatically.

New fields (2)
  • active Boolean
    default=True tracking=2
  • email Char
    help='This field is case insensitive.' index='trigram' required=True string='Email Address' tracking=1
Public methods (4)
  • action_add(self)
  • create(self, values)
    @api.model_create_multi
  • mail_action_blacklist_remove(self)
  • write(self, values)

New fields (2)
  • email Char
    name='Email' readonly=True required=True
  • reason Char
    name='Reason'
Public methods (1)
  • action_unblacklist_apply(self)

New fields (7)
  • description Char
    args: 'Description'
  • group_ids Many2many → res.groups
    string='Authorized Groups' args: 'res.groups'
  • is_editable Boolean
    compute='_compute_is_editable' string='Determines if the canned response can be edited by the current user'
  • is_shared Boolean
    compute='_compute_is_shared' store=True string='Determines if the canned_response is currently shared with other users'
  • last_used Datetime
    help='Last time this canned_response was used' args: 'Last Used'
  • source Char
    help="Canned response that will automatically be substituted with longer content in your messages. Type ':' followed by the name of your shortcut (e.g. :hello) to use in your messages." index='trigram' required=True args: 'Shortcut'
  • substitution Text
    help='Content that will automatically replace the shortcut of your choosing. This content can still be adapted before sending your message.' required=True args: 'Substitution'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (34)
  • attachment_ids Many2many → ir.attachment
    compute='_compute_attachment_ids' readonly=False store=True string='Attachments' args: 'ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id'
  • author_id Many2one → res.partner
    compute='_compute_authorship' compute_sudo=False help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' readonly=False store=True string='Author' args: 'res.partner'
  • auto_delete Boolean
    compute='_compute_auto_delete' compute_sudo=False help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." readonly=False store=True args: 'Delete Emails'
  • auto_delete_keep_log Boolean
    compute='_compute_auto_delete_keep_log' help='Keep a copy of the email content if emails are removed (mass mailing only)' readonly=False store=True args: 'Keep Message Copy'
  • body Html
    compute='_compute_body' readonly=False render_engine='qweb' render_options={'post_process': True} sanitize_style=True store=True args: 'Contents'
  • composition_batch Boolean
    compute='_compute_composition_batch' args: 'Batch composition'
  • composition_mode Selection
    default='comment' selection=[('comment', 'Post on a document'), ('mass_mail', 'Email Mass Mailing')] string='Composition mode'
  • email_add_signature Boolean
    compute='_compute_email_add_signature' readonly=False store=True args: 'Add signature'
  • email_from Char
    compute='_compute_authorship' compute_sudo=False help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' readonly=False store=True args: 'From'
  • email_layout_xmlid Char
    compute='_compute_email_layout_xmlid' compute_sudo=False copy=False readonly=False store=True args: 'Email Notification Layout'
  • force_send Boolean
    compute='_compute_force_send' readonly=False store=True args: 'Send mailing or notifications directly'
  • mail_activity_type_id Many2one → mail.activity.type
    ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_server_id Many2one → ir.mail_server
    compute='_compute_mail_server_id' compute_sudo=False readonly=False store=True string='Outgoing mail server' args: 'ir.mail_server'
  • message_type Selection
    default='comment' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' required=True args: [('auto_comment', 'Automated Targeted Notification'), ('comment', 'Comment'), ('notification', 'System notification')], 'Type'
  • model Char
    compute='_compute_model' readonly=False store=True args: 'Related Document Model'
  • model_is_thread Boolean
    compute='_compute_model_is_thread' args: 'Thread-Enabled'
  • parent_id Many2one → mail.message
    ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    compute='_compute_partner_ids' readonly=False store=True args: 'res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional Contacts'
  • record_alias_domain_id Many2one → mail.alias.domain
    compute='_compute_record_environment' readonly=False store=True args: 'mail.alias.domain', 'Alias Domain'
  • record_company_id Many2one → res.company
    compute='_compute_record_environment' readonly=False store=True args: 'res.company', 'Company'
  • record_name Char
    compute='_compute_record_name' readonly=False store=True args: 'Record Name'
  • reply_to Char
    compute='_compute_reply_to' compute_sudo=False help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' readonly=False store=True args: 'Reply To'
  • reply_to_force_new Boolean
    compute='_compute_reply_to_force_new' help='Manage answers as new incoming emails instead of replies going to the same thread.' readonly=False store=True string='Considers answers as new thread'
  • reply_to_mode Selection
    compute='_compute_reply_to_mode' help='Original Discussion: Answers go in the original document discussion thread. \n Another Email Address: Answers go to the email address mentioned in the tracking message-id instead of original document discussion thread. \n This has an impact on the generated message-id.' inverse='_inverse_reply_to_mode' string='Replies' args: [('update', 'Store email and replies in the chatter of each record'), ('new', 'Collect replies on a specific email address')]
  • res_domain Text
    args: 'Active domain'
  • res_domain_user_id Many2one → res.users
    help='Used as context used to evaluate composer domain' string='Responsible' args: 'res.users'
  • res_ids Text
    compute='_compute_res_ids' readonly=False store=True args: 'Related Document IDs'
  • scheduled_date Char
    compute='_compute_scheduled_date' compute_sudo=False help='In comment mode: if set, postpone notifications sending. In mass mail mode: if sent, send emails after that date. This date is considered as being in UTC timezone.' readonly=False store=True args: 'Scheduled Date'
  • subject Char
    compute='_compute_subject' readonly=False store=True args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    compute='_compute_subtype_id' ondelete='set null' readonly=False store=True args: 'mail.message.subtype', 'Subtype'
  • subtype_is_log Boolean
    compute='_compute_subtype_is_log' args: 'Is a log'
  • template_id Many2one → mail.template
    domain="[('model', '=', model), '|', ('user_id','=', False), ('user_id', '=', uid)]" args: 'mail.template', 'Use template'
  • template_name Char
    args: 'Template Name'
  • use_exclusion_list Boolean
    default=True args: 'Check Exclusion List'
Public methods (6)
  • action_schedule_message(self, scheduled_date=False)
  • action_send_mail(self)
    Used for action button that do not accept arguments.
  • cancel_save_template(self)
    Restore old subject when canceling the 'save as template' action as it was erased to let user give a more custom input.
  • create_mail_template(self)
    creates a mail template with the current mail composer's fields
  • default_get(self, fields_list)
    @api.model
    Handle composition mode and contextual computation, until moving to computed fields. Support active_model / active_id(s) as valid default values, as this comes from standard web client usage. Note that supporting active_ids through composer is still done, as we may have to give a huge list of IDs that won't fit into res_ids field.
  • open_template_creation_wizard(self)
    hit save as template button: opens a wizard that prompts for the template's subject. `create_mail_template` is called when saving the new wizard.

New fields (7)
  • body Html
    compute='_compute_body' compute_sudo=False readonly=False render_engine='qweb' render_options={'post_process': True} sanitize='email_outgoing' store=True args: 'Contents'
  • body_has_template_value Boolean
    compute='_compute_body_has_template_value' args: 'Body content is the same as the template'
  • can_edit_body Boolean
    compute='_compute_can_edit_body' args: 'Can Edit Body'
  • is_mail_template_editor Boolean
    compute='_compute_is_mail_template_editor' args: 'Is Editor'
  • lang Char
    compute='_compute_lang' compute_sudo=False precompute=True readonly=False store=True
  • subject Char
    compute='_compute_subject' compute_sudo=False readonly=False store=True args: 'Subject'
  • template_id Many2one → mail.template
    domain="[('model', '=', render_model)]" args: 'mail.template', 'Mail Template'
Public methods (0)

No public methods.

New fields (7)
  • email Char
    related='partner_id.email' args: 'Email'
  • is_active Boolean
    related='partner_id.active' args: 'Is Active'
  • name Char
    related='partner_id.name' args: 'Name'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' required=True string='Related Partner' args: 'res.partner'
  • res_id Many2oneReference
    help='Id of the followed resource' index=True model_field='res_model' args: 'Related Document ID'
  • res_model Char
    index=True required=True args: 'Related Document Model Name'
  • subtype_ids Many2many → mail.message.subtype
    help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall." string='Subtype' args: 'mail.message.subtype'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (2)
  • email Char
    required=True args: 'Email Address'
  • email_normalized Char
    compute='_compute_email_normalized' index=True store=True string='Normalized Email'
Public methods (1)
  • get_empty_list_help(self, help_message)
    @api.model

New fields (7)
  • access_token Char
    copy=False default=<expr> groups='base.group_system' readonly=True required=True string='Access Token'
  • channel_ids Many2many → discuss.channel
    column1='guest_id' column2='channel_id' comodel_name='discuss.channel' copy=False relation='discuss_channel_member' string='Channels'
  • country_id Many2one → res.country
    comodel_name='res.country' string='Country'
  • im_status Char
    compute='_compute_im_status' args: 'IM Status'
  • lang Selection
    selection=_lang_get string='Language'
  • name Char
    required=True string='Name'
  • timezone Selection
    selection=_tz_get string='Timezone'
Public methods (0)

No public methods.

New fields (4)
  • credential Char
  • server_type Selection
    default='stun' required=True string='Type' args: [('stun', 'stun:'), ('turn', 'turn:')]
  • uri Char
    required=True args: 'URI'
  • username Char
Public methods (0)

No public methods.

New fields (11)
  • create_date Datetime
    index=True
  • image_mimetype Char
    args: 'Image MIME type'
  • is_hidden Boolean
  • message_id Many2one → mail.message
    index=True ondelete='cascade' string='Message' args: 'mail.message'
  • og_description Text
    args: 'Description'
  • og_image Char
    args: 'Image'
  • og_mimetype Char
    args: 'MIME type'
  • og_site_name Char
    args: 'Site name'
  • og_title Char
    args: 'Title'
  • og_type Char
    args: 'Type'
  • source_url Char
    required=True args: 'URL'
Public methods (0)

No public methods.

New fields (19)
  • auto_delete Boolean
    help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_content Html
    compute='_compute_body_content' sanitize=True search='_search_body_content' args: 'Rich-text Contents'
  • body_html Text
    help='Rich-text/HTML message' args: 'Text Contents'
  • email_cc Char
    help='Carbon copy message recipients' args: 'Cc'
  • email_to Text
    help='Message recipients (emails)' args: 'To'
  • failure_reason Text
    copy=False help='Failure reason. This is usually the exception thrown by the email server, stored to ease the debugging of mailing issues.' readonly=True args: 'Failure Reason'
  • failure_type Selection
    selection=[('unknown', 'Unknown error'), ('mail_email_invalid', 'Invalid email address'), ('mail_email_missing', 'Missing email'), ('mail_from_invalid', 'Invalid from address'), ('mail_from_missing', 'Missing from address'), ('mail_smtp', 'Connection failed (outgoing mail server problem)'), ('mail_bl', 'Blacklisted Address'), ('mail_optout', 'Opted Out'), ('mail_dup', 'Duplicated Email')] string='Failure type'
  • fetchmail_server_id Many2one → fetchmail.server
    readonly=True args: 'fetchmail.server', 'Inbound Mail Server'
  • headers Text
    copy=False args: 'Headers'
  • is_notification Boolean
    help='Mail has been created to notify people of an existing mail.message' args: 'Notification Email'
  • mail_message_id Many2one → mail.message
    auto_join=True index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • mail_message_id_int Integer
    compute='_compute_mail_message_id_int' compute_sudo=True
  • message_type Selection
    default='email_outgoing' inherited=True related='mail_message_id.message_type'
  • recipient_ids Many2many → res.partner
    context={'active_test': False} string='To (Partners)' args: 'res.partner'
  • references Text
    help='Message references, such as identifiers of previous messages' readonly=True args: 'References'
  • restricted_attachment_count Integer
    compute='_compute_restricted_attachments' args: 'Restricted attachments'
  • scheduled_date Datetime
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. Unless a timezone is specified, it is considered as being in UTC timezone.' args: 'Scheduled Send Date'
  • state Selection
    copy=False default='outgoing' readonly=True args: [('outgoing', 'Outgoing'), ('sent', 'Sent'), ('received', 'Received'), ('exception', 'Delivery Failed'), ('cancel', 'Cancelled')], 'Status'
  • unrestricted_attachment_ids Many2many → ir.attachment
    compute='_compute_restricted_attachments' inverse='_inverse_unrestricted_attachment_ids' string='Unrestricted Attachments' args: 'ir.attachment'
Public methods (12)
  • action_open_document(self)
    Opens the related record based on the model and ID
  • action_retry(self)
  • cancel(self)
  • create(self, values_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • fields_get(self, *args, **kwargs)
    @api.model
  • mark_outgoing(self)
  • process_email_queue(self, ids=None, batch_size=1000)
    @api.model
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! A maximum of 1K MailMail (configurable using 'mail.mail.queue.batch.size' optional ICP) are fetched in order to keep time under control. :param list ids: optional list of emails ids to send. If given only scheduled and outgoing emails within this ids list are sent; :param dict context: if a 'filters' key is present in context, this value will be used as an additional filter to further restrict the outgoing messages to send (by default all 'outgoing' 'scheduled' messages are sent).
  • send(self, auto_commit=False, raise_exception=False, post_send_callback=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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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 :param post_send_callback: an optional function, called as ``post_send_callback(ids, force=False)``, with the mail ids that have been sent; calls with redundant ids are possible :return: True
  • send_after_commit(self)
    Queues the email to be sent after the commit of the current cursor. Useful to send an email only if a transaction is successful.
  • unlink(self)
  • write(self, vals)

New fields (39)
  • attachment_ids Many2many → ir.attachment
    string='Attachments' args: 'ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id'
  • author_avatar Binary
    depends=['author_id'] readonly=False related='author_id.avatar_128' args: "Author's avatar"
  • author_guest_id Many2one → mail.guest
    comodel_name='mail.guest' string='Guest'
  • author_id Many2one → res.partner
    help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True ondelete='set null' args: 'res.partner', 'Author'
  • body Html
    default='' sanitize_style=True args: 'Contents'
  • child_ids One2many → mail.message
    args: 'mail.message', 'parent_id', 'Child Messages'
  • date Datetime
    default=fields.Datetime.now args: 'Date'
  • email_add_signature Boolean
    default=True
  • email_from Char
    help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • email_layout_xmlid Char
    copy=False args: 'Layout'
  • has_error Boolean
    compute='_compute_has_error' search='_search_has_error' args: 'Has error'
  • is_current_user_or_guest_author Boolean
    compute='_compute_is_current_user_or_guest_author'
  • is_internal Boolean
    help='Hide to public / portal users, independently from subtype configuration.' args: 'Employee Only'
  • link_preview_ids One2many → mail.link.preview
    groups='base.group_erp_manager' string='Link Previews' args: 'mail.link.preview', 'message_id'
  • mail_activity_type_id Many2one → mail.activity.type
    index='btree_not_null' ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_ids One2many → mail.mail
    groups='base.group_system' string='Mails' args: 'mail.mail', 'mail_message_id'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_id Char
    copy=False help='Message unique identifier' index='btree' readonly=True args: 'Message-Id'
  • message_type Selection
    default='comment' help="Used to categorize message generator\n'email': generated by an incoming email e.g. mailgateway\n'comment': generated by user input e.g. through discuss or composer\n'email_outgoing': generated by a mailing\n'notification': generated by system e.g. tracking messages\n'auto_comment': generated by automated notification mechanism e.g. acknowledgment\n'user_notification': generated for a specific recipient" required=True args: [('email', 'Incoming Email'), ('comment', 'Comment'), ('email_outgoing', 'Outgoing Email'), ('notification', 'System notification'), ('auto_comment', 'Automated Targeted Notification'), ('user_notification', 'User Specific Notification')], 'Type'
  • model Char
    args: 'Related Document Model'
  • needaction Boolean
    compute='_compute_needaction' search='_search_needaction' args: 'Need Action'
  • notification_ids One2many → mail.notification
    auto_join=True copy=False depends=['notified_partner_ids'] args: 'mail.notification', 'mail_message_id', 'Notifications'
  • notified_partner_ids Many2many → res.partner
    context={'active_test': False} copy=False depends=['notification_ids'] string='Partners with Need Action' args: 'res.partner', 'mail_notification'
  • parent_id Many2one → mail.message
    index='btree_not_null' ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    context={'active_test': False} string='Recipients' args: 'res.partner'
  • pinned_at Datetime
    help='Datetime at which the message has been pinned' args: 'Pinned'
  • preview Char
    compute='_compute_preview' help='The text-only beginning of the body used as email preview.' args: 'Preview'
  • reaction_ids One2many → mail.message.reaction
    groups='base.group_system' string='Reactions' args: 'mail.message.reaction', 'message_id'
  • record_alias_domain_id Many2one → mail.alias.domain
    ondelete='set null' args: 'mail.alias.domain', 'Alias Domain'
  • record_company_id Many2one → res.company
    ondelete='set null' args: 'res.company', 'Company'
  • record_name Char
    args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • reply_to_force_new Boolean
    help='If true, answers do not go in the original document discussion thread. Instead, it will check for the reply_to in tracking message-id and redirected accordingly. This has an impact on the generated message-id.' args: 'No threading for answers'
  • res_id Many2oneReference
    model_field='model' args: 'Related Document ID'
  • starred Boolean
    compute='_compute_starred' compute_sudo=False help='Current user has a starred notification linked to this message' search='_search_starred' args: 'Starred'
  • starred_partner_ids Many2many → res.partner
    string='Favorited By' args: 'res.partner', 'mail_message_res_partner_starred_rel'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • tracking_value_ids One2many → mail.tracking.value
    groups='base.group_system' help='Tracked values are stored in a separate model. This field allow to reconstruct the tracking and to generate statistics on the model.' string='Tracking values' args: 'mail.tracking.value', 'mail_message_id'
Public methods (15)
  • action_open_document(self)
    Opens the related record based on the model and ID
  • copy_data(self, default=None)
    Make is symmetric to read, to avoid spurious issues with recordsets differences.
  • create(self, values_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • export_data(self, fields_to_export)
  • fetch(self, field_names)
  • init(self)
  • is_thread_message(self, vals=None)
  • mark_all_as_read(self, domain=None)
    @api.model
  • read(self, fields=None, load='_classic_read')
    Override to explicitely call check_access(), that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_done(self)
    Remove the needaction from messages for the current partner.
  • toggle_message_starred(self)
    Toggle messages as (un)starred. Technically, the notifications related to uid are set to (un)starred.
  • unlink(self)
  • unstar_all(self)
    @api.model
    Unstar messages for the current partner.
  • write(self, vals)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (4)
  • content Char
    readonly=True required=True string='Content'
  • guest_id Many2one → mail.guest
    comodel_name='mail.guest' ondelete='cascade' readonly=True string='Reacting Guest'
  • message_id Many2one → mail.message
    comodel_name='mail.message' ondelete='cascade' readonly=True required=True string='Message'
  • partner_id Many2one → res.partner
    comodel_name='res.partner' ondelete='cascade' readonly=True string='Reacting Partner'
Public methods (1)
  • init(self)

New fields (3)
  • mail_message_id Many2one → mail.message
    ondelete='cascade' required=True string='Message' args: 'mail.message'
  • notification_parameters Text
    args: 'Notification Parameter'
  • scheduled_datetime Datetime
    help='Datetime at which notification should be sent.' required=True args: 'Scheduled Send Date'
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • force_send(self)
    Launch notification process independently from the expected date.

New fields (10)
  • default Boolean
    default=True help='Activated by default when subscribing.' args: 'Default'
  • description Text
    help='Description that will be added in the message posted for this subtype. If void, the name will be added instead.' prefetch=True translate=True args: 'Description'
  • hidden Boolean
    help='Hide the subtype in the follower options' args: 'Hidden'
  • internal Boolean
    help='Messages with internal subtypes will be visible only by employees, aka members of base_user group' args: 'Internal Only'
  • name Char
    help='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.' required=True translate=True args: 'Message Type'
  • parent_id Many2one → mail.message.subtype
    help='Parent subtype, used for automatic subscription. This field is not correctly named. For example on a project, the parent_id of project subtypes refers to task-related subtypes.' ondelete='set null' string='Parent' args: 'mail.message.subtype'
  • relation_field Char
    help='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).' args: 'Relation field'
  • res_model Char
    help='Model the subtype applies to. If False, this subtype applies to all models.' args: 'Model'
  • sequence Integer
    default=1 help='Used to order subtypes.' args: 'Sequence'
  • track_recipients Boolean
    help='Whether to display all the recipients or only the important ones.' args: 'Track Recipients'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • default_subtypes(self, model_name)
    @api.model
    Retrieve the default subtypes (all, internal, external) for the given model.
  • unlink(self)
  • write(self, vals)

New fields (5)
  • body Html
    help='String received from the translation request.' required=True sanitize_style=True args: 'Translation Body'
  • create_date Datetime
    index=True
  • message_id Many2one → mail.message
    ondelete='cascade' required=True args: 'mail.message', 'Message'
  • source_lang Char
    help='Result of the language detection based on its content.' required=True args: 'Source Language'
  • target_lang Char
    help='Shortened language code used as the target for the translation request.' required=True args: 'Target Language'
Public methods (1)
  • init(self)

New fields (10)
  • author_id Many2one → res.partner
    ondelete='set null' args: 'res.partner', 'Author'
  • failure_reason Text
    copy=False args: 'Failure reason'
  • failure_type Selection
    selection=[('unknown', 'Unknown error'), ('mail_bounce', 'Bounce'), ('mail_email_invalid', 'Invalid email address'), ('mail_email_missing', 'Missing email address'), ('mail_from_invalid', 'Invalid from address'), ('mail_from_missing', 'Missing from address'), ('mail_smtp', 'Connection failed (outgoing mail server problem)')] string='Failure type'
  • is_read Boolean
    index=True args: 'Is Read'
  • mail_mail_id Many2one → mail.mail
    help='Optional mail_mail ID. Used mainly to optimize searches.' index=True args: 'mail.mail', 'Mail'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification_status Selection
    default='ready' index=True string='Status' args: [('ready', 'Ready to Send'), ('process', 'Processing'), ('pending', 'Sent'), ('sent', 'Delivered'), ('bounce', 'Bounced'), ('exception', 'Exception'), ('canceled', 'Cancelled')]
  • notification_type Selection
    default='inbox' index=True required=True string='Notification Type' args: [('inbox', 'Inbox'), ('email', 'Email')]
  • read_date Datetime
    copy=False args: 'Read Date'
  • res_partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner', 'Recipient'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • format_failure_reason(self)
  • init(self)
  • write(self, vals)

New fields (2)
  • mail_push_device_id Many2one → mail.push.device
    ondelete='cascade' required=True string='devices' args: 'mail.push.device'
  • payload Text
Public methods (0)

No public methods.

New fields (4)
  • endpoint Char
    required=True string='Browser endpoint'
  • expiration_time Datetime
    string='Expiration Token Date'
  • keys Char
    help="It's refer to browser keys used by the notification: \n- p256dh: It's the subscription public key generated by the browser. The browser will \n keep the private key secret and use it for decrypting the payload\n- auth: The auth value should be treated as a secret and not shared outside of Odoo" required=True string='Browser keys'
  • partner_id Many2one → res.partner
    default=<expr> index=True required=True string='Partner' args: 'res.partner'
Public methods (3)
  • get_web_push_vapid_public_key(self)
    @api.model
  • register_devices(self, **kw)
    @api.model
  • unregister_devices(self, **kw)
    @api.model

New fields (2)
  • lang Char
    help='Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. {{ object.partner_id.lang }}.' args: 'Language'
  • render_model Char
    compute='_compute_render_model' store=False args: 'Rendering Model'
Public methods (2)
  • create(self, values_list)
    @api.model_create_multi
  • write(self, vals)

New fields (6)
  • can_cancel Boolean
    compute='_compute_can_cancel'
  • can_resend Boolean
    compute='_compute_can_resend'
  • mail_message_id Many2one → mail.message
    readonly=True args: 'mail.message', 'Message'
  • notification_ids Many2many → mail.notification
    readonly=True string='Notifications' args: 'mail.notification'
  • partner_ids One2many → mail.resend.partner
    string='Recipients' args: 'mail.resend.partner', 'resend_wizard_id'
  • partner_readonly Boolean
    compute='_compute_partner_readonly'
Public methods (3)
  • cancel_mail_action(self)
  • default_get(self, fields)
    @api.model
  • resend_mail_action(self)
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (9)
  • email Char
    readonly=False related='partner_id.email' related_sudo=False string='Email Address'
  • failure_reason Text
    related='notification_id.failure_reason' args: 'Failure Reason'
  • message Char
    string='Error message'
  • name Char
    readonly=False related='partner_id.name' related_sudo=False string='Recipient Name'
  • notification_id Many2one → mail.notification
    ondelete='cascade' required=True string='Notification' args: 'mail.notification'
  • partner_id Many2one → res.partner
    related='notification_id.res_partner_id' string='Partner' args: 'res.partner'
  • partner_readonly Boolean
    related='resend_wizard_id.partner_readonly' args: 'Partner Readonly'
  • resend Boolean
    default=True string='Try Again'
  • resend_wizard_id Many2one → mail.resend.message
    string='Resend wizard' args: 'mail.resend.message'
Public methods (3)
  • action_open_record(self)
  • action_open_resend_partner(self)
  • action_resend(self)

New fields (10)
  • attachment_ids Many2many → ir.attachment
    string='Attachments' args: 'ir.attachment', 'scheduled_message_attachment_rel', 'scheduled_message_id', 'attachment_id'
  • author_id Many2one → res.partner
    required=True args: 'res.partner', 'Author'
  • body Html
    sanitize_style=True args: 'Contents'
  • is_note Boolean
    default=False help='If the message will be posted as a Note.' args: 'Is a note'
  • model Char
    required=True args: 'Related Document Model'
  • notification_parameters Text
    args: 'Notification parameters'
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • res_id Many2oneReference
    model_field='model' required=True args: 'Related Document Id'
  • scheduled_date Datetime
    required=True args: 'Scheduled Date'
  • subject Char
    args: 'Subject'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
  • open_edit_form(self)
  • post_message(self)
  • unlink(self)
  • write(self, vals)

New fields (24)
  • active Boolean
    default=True
  • attachment_ids Many2many → ir.attachment
    help='You may attach files to this template, to be added to all emails created from this template' args: 'ir.attachment', 'email_template_attachment_rel', 'email_template_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    default=True help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_html Html
    prefetch=True render_engine='qweb' render_options={'post_process': True} sanitize='email_outgoing' translate=True args: 'Body'
  • can_write Boolean
    compute='_compute_can_write' help='The current user can edit the template.'
  • description Text
    help="This field is used for internal description of the template's usage." translate=True args: 'Template Description'
  • email_cc Char
    help='Carbon copy recipients (placeholders may be used here)' args: 'Cc'
  • email_from Char
    help="Sender address (placeholders may be used here). If not set, the default value will be the author's email alias if configured, or email address." args: 'From'
  • email_layout_xmlid Char
    copy=False args: 'Email Notification Layout'
  • email_to Char
    help='Comma-separated recipient addresses (placeholders may be used here)' args: 'To (Emails)'
  • is_template_editor Boolean
    compute='_compute_is_template_editor'
  • mail_server_id Many2one → ir.mail_server
    help='Optional preferred server for outgoing mails. If not set, the highest priority one will be used.' readonly=False args: 'ir.mail_server', 'Outgoing Mail Server'
  • model Char
    index=True readonly=True related='model_id.model' store=True args: 'Related Document Model'
  • model_id Many2one → ir.model
    ondelete='cascade' args: 'ir.model', 'Applies to'
  • name Char
    translate=True args: 'Name'
  • partner_to Char
    help='Comma-separated ids of recipient partners (placeholders may be used here)' args: 'To (Partners)'
  • ref_ir_act_window Many2one → ir.actions.act_window
    copy=False help='Sidebar action to make this template available on records of the related document model' readonly=True args: 'ir.actions.act_window', 'Sidebar action'
  • reply_to Char
    help='Email address to which replies will be redirected when sending emails in mass; only used when the reply is not logged in the original discussion thread.' args: 'Reply To'
  • report_template_ids Many2many → ir.actions.report
    column1='mail_template_id' column2='ir_actions_report_id' domain="[('model', '=', model)]" relation='mail_template_ir_actions_report_rel' string='Dynamic Reports' args: 'ir.actions.report'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. You can use dynamic expression.' args: 'Scheduled Date'
  • subject Char
    help='Subject (placeholders may be used here)' prefetch=True translate=True args: 'Subject'
  • template_category Selection
    compute='_compute_template_category' search='_search_template_category' args: [('base_template', 'Base Template'), ('hidden_template', 'Hidden Template'), ('custom_template', 'Custom Template')]
  • use_default_to Boolean
    help='Default recipients of the record:\n- partner (using id on a partner or the partner_id field) OR\n- email (using email_from or email field)' args: 'Default recipients'
  • user_id Many2one → res.users
    domain="[('share', '=', False)]" help='The template belongs to this user' string='User' args: 'res.users'
Public methods (12)
  • cancel_unlink(self)
  • copy(self, default=None)
  • copy_data(self, default=None)
  • create(self, vals_list)
    @api.model_create_multi
  • create_action(self)
  • default_get(self, fields)
    @api.model
  • open_delete_confirmation_modal(self)
  • send_mail(self, res_id, force_send=False, raise_exception=False, email_values=None, email_layout_xmlid=False)
    Generates a new mail.mail. Template is rendered on record given by res_id and model coming from template. :param int res_id: id of the record to render the template :param bool force_send: send email immediately; otherwise use the mail queue (recommended); :param dict email_values: update generated mail with those values to further customize the mail; :param str email_layout_xmlid: optional notification layout to encapsulate the generated email; :returns: id of the mail.mail that was created
  • send_mail_batch(self, res_ids, force_send=False, raise_exception=False, email_values=None, email_layout_xmlid=False)
    @api.returns('self', <expr>)
    Generates new mail.mails. Batch version of 'send_mail'.' :param list res_ids: IDs of modelrecords on which template will be rendered :returns: newly created mail.mail
  • unlink(self)
  • unlink_action(self)
  • write(self, vals)

New fields (15)
  • attachment_ids Many2many → ir.attachment
    compute='_compute_mail_template_fields' args: 'ir.attachment', 'Attachments'
  • body_html Html
    compute='_compute_mail_template_fields' sanitize=False args: 'Body'
  • email_cc Char
    compute='_compute_mail_template_fields' help='Carbon copy recipients' args: 'Cc'
  • email_from Char
    compute='_compute_mail_template_fields' help='Sender address' args: 'From'
  • email_to Char
    compute='_compute_mail_template_fields' help='Comma-separated recipient addresses' args: 'To'
  • error_msg Char
    compute='_compute_mail_template_fields' args: 'Error Message'
  • lang Selection
    string='Template Preview Language' args: _selection_languages
  • mail_template_id Many2one → mail.template
    required=True string='Related Mail Template' args: 'mail.template'
  • model_id Many2one → ir.model
    related='mail_template_id.model_id' string='Targeted model' args: 'ir.model'
  • no_record Boolean
    compute='_compute_no_record' args: 'No Record'
  • partner_ids Many2many → res.partner
    compute='_compute_mail_template_fields' string='Recipients' args: 'res.partner'
  • reply_to Char
    compute='_compute_mail_template_fields' help='Preferred response address' args: 'Reply-To'
  • resource_ref Reference
    compute='_compute_resource_ref' compute_sudo=False readonly=False selection='_selection_target_model' store=True string='Record'
  • scheduled_date Char
    compute='_compute_mail_template_fields' help='The queue manager will send the email after the date' args: 'Scheduled Date'
  • subject Char
    compute='_compute_mail_template_fields' args: 'Subject'
Public methods (0)

No public methods.

New fields (1)
  • template_ids Many2many → mail.template
    args: 'mail.template'
Public methods (1)
  • reset_template(self)

New fields (10)
  • has_message Boolean
    compute='_compute_has_message' search='_search_has_message' store=False
  • message_attachment_count Integer
    compute='_compute_message_attachment_count' groups='base.group_user' args: 'Attachment Count'
  • message_follower_ids One2many → mail.followers
    groups='base.group_user' string='Followers' args: 'mail.followers', 'res_id'
  • message_has_error Boolean
    compute='_compute_message_has_error' help='If checked, some messages have a delivery error.' search='_search_message_has_error' args: 'Message Delivery error'
  • message_has_error_counter Integer
    compute='_compute_message_has_error' help='Number of messages with delivery error' args: 'Number of errors'
  • message_ids One2many → mail.message
    auto_join=True domain=<expr> string='Messages' args: 'mail.message', 'res_id'
  • message_is_follower Boolean
    compute='_compute_message_is_follower' search='_search_message_is_follower' args: 'Is Follower'
  • message_needaction Boolean
    compute='_compute_message_needaction' help='If checked, new messages require your attention.' search='_search_message_needaction' args: 'Action Needed'
  • message_needaction_counter Integer
    compute='_compute_message_needaction' help='Number of messages requiring action' args: 'Number of Actions'
  • message_partner_ids Many2many → res.partner
    comodel_name='res.partner' compute='_compute_message_partner_ids' groups='base.group_user' inverse='_inverse_message_partner_ids' search='_search_message_partner_ids' string='Followers (Partners)'
Public methods (20)
  • copy_data(self, default=None)
  • create(self, vals_list)
    @api.model_create_multi
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • get_empty_list_help(self, help_message)
    @api.model
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • get_views(self, views, options=None)
    @api.model
  • message_change_thread(self, new_thread, new_parent_message=False)
    Transfer the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : my_lead.message_change_thread(my_project_task) will transfer the context of the thread of my_lead to my_project_task
  • message_get_followers(self, after=None, limit=100, filter_recipients=False)
    @api.readonly
  • message_mail_with_source(self, source_ref, render_values=None, message_type='notification', auto_commit=False, **kwargs)
    Send a mass mail on self, using an external source to render part of the content. It can be either a 'mail.template', either a view used to render the body using QWeb. SPOILER: this method currently calls a composer in a loop when using a view even if it is suboptimal. This is due to current composer implementation.. This will be cleaned soon to optimize mass mailing through mail.thread and lessen usage of composer itself. Default values * subtype_id: will be False, forced by composer in mass mode; :param record/str source_ref: reference to a source for rendering. It can be one of * a MailTemplate record. It will be used to render the various message values (body, subject, recipients, ...). It should behave like using the mail composer with a template; * an IrUIView record. It will be used to render the content (body). Other fields are left to the caller and/or default values computation; * an XmlID of a MailTemplate or of an IrUiView: see above; :param dict render_values: additional rendering values for qweb context; :param str message_type: one of 'notification' or 'comment'; :param bool auto_commit: auto commit after each batch of emails sent (see ``MailComposer._action_send_mail()``); :param dict kwargs: additional values given to the 'mail.compose.message' creation; :return: created mail.mail records, as sudo
  • message_new(self, msg_dict, custom_values=None)
    @api.model
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :rtype: int :return: the id of the newly created thread object
  • message_notify(self, *, body='', subject=False, author_id=None, email_from=None, model=False, res_id=False, subtype_xmlid=None, subtype_id=False, partner_ids=False, attachments=None, attachment_ids=None, **kwargs)
    @api.returns('mail.message', <expr>)
    Shortcut allowing to notify partners of messages that should not be displayed on a document. It pushes notifications on inbox or by email depending on the user configuration, like other notifications. Default values * subtype_id: if not given, fallback on ``note`` to be consistent with what message_post does; :param str body: body of the message, usually raw HTML that will be sanitized :param str subject: subject of the message :param int author_id: optional ID of partner record being the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param str email_from: from address of the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param str model: when invoked on MailThread directly, this method allows to push a notification on a given record (allows to notify on not thread-enabled records); :param int res_id: defines the record in combination with model; :param str subtype_xmlid: optional xml id of a mail.message.subtype to fetch, will force value of subtype_id; :param int subtype_id: subtype_id of the message, used mainly for followers notification mechanism; :param list(int) partner_ids: partner_ids to notify in addition to partners computed based on subtype / followers matching; :param list(tuple(str,str), tuple(str,str, dict)) attachments : list of attachment tuples in the form ``(name,content)`` or ``(name,content, info)`` where content is NOT base64 encoded; :param list attachment_ids: list of existing attachments to link to this message Should not be a list of commands. Attachment records attached to mail composer will be attached to the related document. Extra keyword arguments will be used either * as default column values for the new mail.message record if they match mail.message fields; * propagated to notification methods if not; :return: posted mail.message records
  • message_parse(self, message, save_original=False)
    @api.model
    Parses an email.message.Message representing an RFC-2822 email and returns a generic dict holding the message details. :param message: email to parse :type message: email.message.Message :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'email_from': from, 'to': to + delivered-to, 'cc': cc, 'recipients': delivered-to + to + cc + resent-to + resent-cc, 'partner_ids': partners found based on recipients emails, 'body': unified_body, 'references': references, 'in_reply_to': in-reply-to, 'is_bounce': True if it has been detected as a bounce email 'parent_id': parent mail.message based on in_reply_to or references, 'is_internal': answer to an internal message (note), 'date': date, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_post(self, *, body='', subject=None, message_type='notification', email_from=None, author_id=None, parent_id=False, subtype_xmlid=None, subtype_id=False, partner_ids=None, attachments=None, attachment_ids=None, body_is_html=False, **kwargs)
    @api.returns('mail.message', <expr>)
    Post a new message in an existing thread, returning the new mail.message. :param str|Markup body: body of the message, str content will be escaped, Markup for html body :param str subject: subject of the message :param str message_type: see mail_message.message_type field. Can be anything but user_notification, reserved for message_notify :param str email_from: from address of the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param int author_id: optional ID of partner record being the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param int parent_id: handle thread formation :param str subtype_xmlid: optional xml id of a mail.message.subtype to fetch, will force value of subtype_id; :param int subtype_id: subtype_id of the message, used mainly for followers notification mechanism; :param list(int) partner_ids: partner_ids to notify in addition to partners computed based on subtype / followers matching; :param list(tuple(str,str), tuple(str,str, dict)) attachments : list of attachment tuples in the form ``(name,content)`` or ``(name,content, info)`` where content is NOT base64 encoded; :param list attachment_ids: list of existing attachments to link to this message Should not be a list of commands. Attachment records attached to mail composer will be attached to the related document. :param bool body_is_html: indicates body should be threated as HTML even if str to be used only for RPC calls Extra keyword arguments will be used either * as default column values for the new mail.message record if they match mail.message fields; * propagated to notification methods if not; :return record: newly create mail.message
  • message_post_with_source(self, source_ref, render_values=None, message_type='notification', subtype_xmlid=False, subtype_id=False, **kwargs)
    Post a message on each record of self, using a view to render the body using QWeb. Default values * subtype_id: if not given, fallback on ``note`` to be consistent with what message_post does; :param record/str source_ref: reference to a source for rendering. It can be one of * a MailTemplate record. It will be used to render the various message values (body, subject, recipients, ...). It should behave like using the mail composer with a template; * an IrUIView record. It will be used to render the content (body). Other fields are left to the caller and/or default values computation; * an XmlID of a MailTemplate or of an IrUiView: see above :param dict render_values: additional rendering values for qweb context; :param str message_type: one of 'notification' or 'comment'; :param str subtype_xmlid: optional xml id of a mail.message.subtype to fetch, will force value of subtype_id; :param int subtype_id: subtype_id of the message, used mainly for followers notification mechanism; :param dict kwargs: additional values given to the 'mail.compose.message' creation; :return: posted mail.message records
  • message_process(self, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None)
    @api.model
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: string or xmlrpclib.Binary :type dict custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None)
    @api.model
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: * if the message replies to an existing thread by having a Message-Id that matches an existing mail_message.message_id, we take the original message model/thread_id pair and ignore custom_value as no creation will take place; * look for a mail.alias entry matching the message recipients and use the corresponding model, thread_id, custom_values and user_id. This could lead to a thread update or creation depending on the alias; * fallback on provided ``model``, ``thread_id`` and ``custom_values``; * raise an exception as no route has been found :param string message: an email.message instance :param dict message_dict: dictionary holding parsed message variables :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :type dict custom_values: optional dictionary of default field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of routes [(model, thread_id, custom_values, user_id, alias)] :raises: ValueError, TypeError
  • message_subscribe(self, partner_ids=None, subtype_ids=None)
    Main public API to add followers to a record set. Its main purpose is to perform access rights checks before calling ``_message_subscribe``.
  • message_unsubscribe(self, partner_ids=None)
    Remove partners from the records followers.
  • message_update(self, msg_dict, update_vals=None)
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • notify_cancel_by_type(self, notification_type)
    @api.model
    Subclasses must call this method and then * either call the standard implementation _notify_cancel_by_type_generic * or implements their own logic
  • unlink(self)
    Override unlink to delete (scheduled) messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • write(self, values)

New fields (3)
  • email_normalized Char
    compute='_compute_email_normalized' compute_sudo=True help='This field is used to search on email address as the primary email field can contain more than strictly an email address.' store=True string='Normalized Email'
  • is_blacklisted Boolean
    compute='_compute_is_blacklisted' compute_sudo=True groups='base.group_user' help="If the email address is on the blacklist, the contact won't receive mass mailing anymore, from any list" search='_search_is_blacklisted' store=False string='Blacklist'
  • message_bounce Integer
    default=0 help='Counter of the number of bounced emails for this contact' args: 'Bounce'
Public methods (1)
  • mail_action_blacklist_remove(self)

New fields (1)
  • email_cc Char
    args: 'Email cc'
Public methods (2)
  • message_new(self, msg_dict, custom_values=None)
    @api.model
  • message_update(self, msg_dict, update_vals=None)
    Adds cc email to self.email_cc while trying to keep email as raw as possible but unique

New fields (1)
  • message_main_attachment_id Many2one → ir.attachment
    comodel_name='ir.attachment' copy=False index='btree_not_null' string='Main Attachment'
Public methods (0)

No public methods.

New fields (1)
  • duration_tracking Json
    compute='_compute_duration_tracking' help='JSON that maps ids from a many2one field to seconds spent' string='Status time'
Public methods (0)

No public methods.

New fields (14)
  • currency_id Many2one → res.currency
    help='Used to display the currency when tracking monetary values' ondelete='set null' readonly=True args: 'res.currency', 'Currency'
  • field_id Many2one → ir.model.fields
    index=True ondelete='set null' readonly=True required=False args: 'ir.model.fields'
  • field_info Json
    args: 'Removed field information'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message ID'
  • new_value_char Char
    readonly=True args: 'New Value Char'
  • new_value_datetime Datetime
    readonly=True args: 'New Value Datetime'
  • new_value_float Float
    readonly=True args: 'New Value Float'
  • new_value_integer Integer
    readonly=True args: 'New Value Integer'
  • new_value_text Text
    readonly=True args: 'New Value Text'
  • old_value_char Char
    readonly=True args: 'Old Value Char'
  • old_value_datetime Datetime
    readonly=True args: 'Old Value DateTime'
  • old_value_float Float
    readonly=True args: 'Old Value Float'
  • old_value_integer Integer
    readonly=True args: 'Old Value Integer'
  • old_value_text Text
    readonly=True args: 'Old Value Text'
Public methods (0)

No public methods.

New fields (5)
  • message Html
    args: 'Message'
  • notify Boolean
    default=False args: 'Notify Recipients'
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' required=True args: 'Related Document Model'
Public methods (1)
  • add_followers(self)

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cron_mode=True)
    Send a message to Odoo's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (10)
  • alias_domain_id Many2one → mail.alias.domain
    default=<expr> string='Email Domain' args: 'mail.alias.domain'
  • alias_domain_name Char
    readonly=True related='alias_domain_id.name' store=True args: 'Alias Domain Name'
  • bounce_email Char
    compute='_compute_bounce' string='Bounce Email'
  • bounce_formatted Char
    compute='_compute_bounce' string='Bounce'
  • catchall_email Char
    compute='_compute_catchall' string='Catchall Email'
  • catchall_formatted Char
    compute='_compute_catchall' string='Catchall'
  • default_from_email Char
    readonly=True related='alias_domain_id.default_from_email' string='Default From'
  • email_formatted Char
    compute='_compute_email_formatted' compute_sudo=True string='Formatted Email'
  • email_primary_color Char
    compute='_compute_email_primary_color' readonly=False store=True args: 'Email Header Color'
  • email_secondary_color Char
    compute='_compute_email_secondary_color' readonly=False store=True args: 'Email Button Color'
Public methods (0)

No public methods.

New fields (17)
  • alias_domain_id Many2one → mail.alias.domain
    help='If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.' readonly=False related='company_id.alias_domain_id' args: 'mail.alias.domain', 'Alias Domain'
  • email_primary_color Char
    readonly=False related='company_id.email_primary_color'
  • email_secondary_color Char
    readonly=False related='company_id.email_secondary_color'
  • external_email_server_default Boolean
    config_parameter='base_setup.default_external_email_server' args: 'Use Custom Email Servers'
  • fail_counter Integer
    compute='_compute_fail_counter' args: 'Fail Mail'
  • google_translate_api_key Char
    config_parameter='mail.google_translate_api_key' help='A valid Google API key is required to enable message translation. https://cloud.google.com/translate/docs/setup' args: 'Message Translation API Key'
  • module_google_gmail Boolean
    args: 'Support Gmail Authentication'
  • module_microsoft_outlook Boolean
    args: 'Support Outlook Authentication'
  • restrict_template_rendering Boolean
    config_parameter='mail.restrict.template.rendering' help='Users will still be able to render templates.\nHowever only Mail Template Editors will be able to create new dynamic templates or modify existing ones.' args: 'Restrict Template Rendering'
  • sfu_server_key Char
    config_parameter='mail.sfu_server_key' help='Base64 encoded key' args: 'SFU Server key'
  • sfu_server_url Char
    config_parameter='mail.sfu_server_url' args: 'SFU Server URL'
  • tenor_api_key Char
    config_parameter='discuss.klipy_api_key' help='Add a Klipy GIF API key to enable GIFs support. https://docs.klipy.com/getting-started\nIf you were using a Tenor GIF API key (service shutdown on June 30, 2026), please replace it here with a Klipy GIF API key' args: 'Klipy API key'
  • tenor_content_filter Selection
    config_parameter='discuss.tenor_content_filter' default='low' help='https://docs.klipy.com/migrate-from-tenor/content-filtering' string='Klipy content filter' args: [('high', 'High'), ('medium', 'Medium'), ('low', 'Low'), ('off', 'Off')]
  • tenor_gif_limit Integer
    config_parameter='discuss.tenor_gif_limit' default=8 help='Fetch up to the specified number of GIF.' string='Klipy GIF limits'
  • twilio_account_sid Char
    config_parameter='mail.twilio_account_sid' args: 'Twilio Account SID'
  • twilio_account_token Char
    config_parameter='mail.twilio_account_token' args: 'Twilio Account Auth Token'
  • use_twilio_rtc_servers Boolean
    config_parameter='mail.use_twilio_rtc_servers' help='If you want to use twilio as TURN/STUN server provider' args: 'Use Twilio ICE servers'
Public methods (2)
  • open_email_layout(self)
  • open_mail_templates(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals)

New fields (8)
  • contact_address_inline Char
    compute='_compute_contact_address_inline' string='Inlined Complete Address' tracking=True
  • email Char
    tracking=1
  • name Char
    tracking=1
  • parent_id Many2one
    tracking=3
  • phone Char
    tracking=2
  • starred_message_ids Many2many → mail.message
    args: 'mail.message', 'mail_message_res_partner_starred_rel'
  • user_id Many2one
    tracking=4
  • vat Char
    tracking=5
Public methods (3)
  • find_or_create(self, email, assert_valid_email=False)
    @api.model@api.returns('self', <expr>)
    Override to use the email_normalized field.
  • get_mention_suggestions(self, search, limit=8)
    @api.readonly@api.model
    Return 'limit'-first partners' such that the name or email matches a 'search' string. Prioritize partners that are also (internal) users, and then extend the research to all partners. The return format is a list of partner data (as per returned by `_to_store()`).
  • im_search(self, name, limit=20, excluded_ids=None)
    @api.readonly@api.model
    Search partner with a name and return its id, name and im_status. Note : the user must be logged :param name : the partner name to search :param limit : the limit of result to return :param excluded_ids : the ids of excluded partners

New fields (1)
  • channel_ids Many2many → discuss.channel
    copy=False string='Channels' args: 'discuss.channel', 'discuss_channel_member', 'partner_id', 'channel_id'
Public methods (2)
  • get_mention_suggestions_from_channel(self, channel_id, search, limit=8)
    @api.readonly@api.model
    Return 'limit'-first partners' such that the name or email matches a 'search' string. Prioritize partners that are also (internal) users, and then extend the research to all partners. Only members of the given channel are returned. The return format is a list of partner data (as per returned by `_to_store()`).
  • search_for_channel_invite(self, search_term, channel_id=None, limit=30)
    @api.readonly@api.model
    Returns partners matching search_term that can be invited to a channel. If the channel_id is specified, only partners that can actually be invited to the channel are returned (not already members, and in accordance to the channel configuration).

New fields (1)
  • notification_type Selection
    compute='_compute_notification_type' default='email' help='Policy on how to handle Chatter notifications:\n- Handle by Emails: notifications are sent to your email address\n- Handle in Odoo: notifications appear in your Odoo Inbox' inverse='_inverse_notification_type' required=True store=True args: [('email', 'Handle by Emails'), ('inbox', 'Handle in Odoo')], 'Notification'
Public methods (5)
  • SELF_READABLE_FIELDS(self)
    @property
  • SELF_WRITEABLE_FIELDS(self)
    @property
  • action_archive(self)
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, vals)

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (8)
  • channel_notifications Selection
    help='This setting will only be applied to channels. Mentions only if not specified.' args: [('all', 'All Messages'), ('no_notif', 'Nothing')], 'Channel Notifications'
  • is_discuss_sidebar_category_channel_open Boolean
    default=True string='Is discuss sidebar category channel open?'
  • is_discuss_sidebar_category_chat_open Boolean
    default=True string='Is discuss sidebar category chat open?'
  • mute_until_dt Datetime
    help='If set, the user will not receive notifications from all the channels until this date.' index=True string='Mute notifications until'
  • push_to_talk_key Char
    help='String formatted to represent a key with modifiers following this pattern: shift.ctrl.alt.key, e.g: truthy.1.true.b' string='Push-To-Talk shortcut'
  • use_push_to_talk Boolean
    default=False string='Use the push to talk feature'
  • voice_active_duration Integer
    default=200 help='How long the audio broadcast will remain active after passing the volume threshold' string='Duration of voice activity in ms'
  • volume_settings_ids One2many → res.users.settings.volumes
    string='Volumes of other partners' args: 'res.users.settings.volumes', 'user_setting_id'
Public methods (3)
  • set_custom_notifications(self, custom_notifications)
  • set_res_users_settings(self, new_settings)
  • set_volume_setting(self, partner_id, volume, guest_id=None)
    Saves the volume of a guest or a partner. Either partner_id or guest_id must be specified. :param float volume: the selected volume between 0 and 1 :param int partner_id: :param int guest_id:

New fields (4)
  • guest_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner'
  • user_setting_id Many2one → res.users.settings
    index=True ondelete='cascade' required=True args: 'res.users.settings'
  • volume Float
    default=0.5 help='Ranges between 0.0 and 1.0, scale depends on the browser implementation'
Public methods (1)
  • init(self)

New fields (1)
  • template_fs Char
    copy=False help='File from where the template originates. Used to reset broken template.' string='Template Filename'
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • reset_template(self)
    Resets the Template with values given in source file. We ignore the case of template being overridden in another modules because it is extremely less likely to happen. This method also tries to reset the translation terms for the current user lang (all langs are not supported due to costly file operation).
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/17.0/mail
VERSION
VERSION 1.15
CATEGORY
CATEGORYProductivity/Discuss
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Martin Trigaux, Thibault Delavallée, Denis Ledoux, Fabien Meghazi, Xavier ALT, Xavier Morel, Nicolas Lempereur, Thibault Francois, Stefan Rijnhart, Géry Debongnie, Aaron Bohy, Jeremy Kersten, GitHub, Lucas Perais (lpe), Damien Bouvy, Barad Mahendra, Yannick Tivisse, qsm-odoo, Odoo Online, Pierre Masereel, Romain Derie, Laurent Smet, Christophe Monniez, Jorge Pinna Puissant, Jairo Llopis, Denis Vermylen, Lucas Perais, Alexandre Kühn, Julien Castiaux, Aurélien Warnon, Xavier-Do, Romeo Fragomeli, Victor Feyens, Adrien Dieudonné, Paul Morelle, Sébastien Theys, Joseph Caburnay, Julien Mougenot, svs-odoo, Samuel Degueldre, Alvaro Fuentes, std-odoo, Achraf (abz), Carlos Lopez, Ivan Yelizariev, Nasreddin Boulif (bon), Prakash Prajapati, Tiffany Chang (tic), Rémy Voet (ryv), Pierre Rousseau, Thanh Dodeur, Gorash, ThanhDodeurOdoo, Mathieu Duckerts-Antoine, Pierre Paridans, Yenthe666, abd-msyukyu-odoo, William Braeckman, bit-odoo, Romain Estievenart, Xavier BOL (xbo), Benoit Socias, Stanislas Sobieski, Hubert Van de Walle (huvw), Miquel Raïch, Sylvain Francis, william-andre, Julien Van Roy, MerlinGuillaume, yhu-odoo, Didier (did), Antoine Guenet, Florian Charlier, Patrick Hoste, Louis Baudoux, Walid HANNICHE (waha), Yolann Sabaux, Abdelouahab (abla), Nicolas Bayet, Aurelien van Delft (avd), Hubert Van De Walle, Mathieu Walravens, luvi, Achraf, Valentin Chevalier, Renaud Thiry, Julien Banken, Vincent Larcin, Ipsita Borisagar, Stanislas Gueniffey, niyasraphy, bve-odoo, jorv, damr, mehjabinfarsana, Archana Vaghasiya, alsh-odoo, Gaetan Vanden Bergh (gavb), Andro Gvivradze, Pedram (PEBR), Louis Wicket (wil), tsm-odoo, nda, Maximilien (malb), Victor Piryns (pivi), Shawcker, Thomas Becquevort (thbe), miad-odoo, amdi-odoo, Tom De Caluwé, Simon Genin (ges), Pierre-Yves Dufays, Om Rabara, duongnguyen, Levi Siuzdak (sile), Maruan Aguerdouh (magm), Dylan Kiss (dyki), Sébastien Geelen (sge), Bruno Boi, Antoine (ande), flvr-odoo, FrancoisGe, Michael (mcm), Mayurrajsinh Rathod, Rahul Prajapati, Chong Wang (cwg), Odoo, Leloup Loïc (lole), Thomas Josse (thjo), Kartik Chavda, Hugo Carlier (Huca), Xavier Bol (xbo), Brieuc-brd, micheledic, Alessandro Caldonazzi (alca), Nguyễn Đại Dương, Mahdi Cheikh Rouhou (macr), Noe Antoine, Andrzej(pian), Zelong Lin, Walid (wasa), sesn-odoo, maad-odoo, Jay Savaliya, BHanq, dane@odoo.com, Adam Heinz, Mattis Megevand, Youssef Bashandy, Mathieu (mcou), lase@odoo.com, bary, Maryam Kia, jorv-odoo, mizosoft, yosa-odoo, “Beekan”, jugj-odoo, vava-odoo, Adrien Minne (adrm), Julien Carion (juca), kcv-odoo, adsh-odoo, Tanguy Quéguineur, TSO, Alex Kühn, Martin Trigaux (mat), Chrysanthe (chgo), aath-odoo, shsa-odoo, Louis (wil), mano-odoo, thle-odoo, Mathieu Coutant, Elisabeth Dickinson, Pratik Raval (PRRA), Xavier Luyckx (xlu), haumenphai, Mohammad Abdulmoneim, Antoine (anso), sabr, Pierre Pulinckx (PIPU), quyen, Nemael, Khushi, Pierre Pulinckx (pipu), fdardenne, Bastien PIERRE, joda-odoo, zel-odoo, John Kirkwood (kij), Aditya Sharma, Quoc - Pham Ngoc, Pulinckx Pierre (PIPU), sagu-odoo, nsirjacobs, defl, Giorgio Tocco (gito), Ayush Chauhan (aych), jayp-odoo, bsra-odoo, Tudor-Calin Panzaru (tupan), ramh, kmdi-odoo, Soncrits, EL Alaoui Yassine, assh-odoo, gito-odoo, livaios, scho-odoo, Kevin Gerard (kege), Louis, nmak-odoo, Akash Parmar, Shubham Patel, hossamelgendy1, pmah-odoo, Benoit Socias (bso), JocelynVN
WEBSITE
WEBSITEhttps://www.odoo.com/app/discuss
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 01:02:08
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web
    - bus
    - web_tour
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Chat, mail gateway and private channel.
=======================================

Communicate with your colleagues/customers/guest within Odoo.

Discuss/Chat
------------
User-friendly "Discuss" features that allows one 2 one or group communication
(text chat/voice call/video call), invite guests and share documents with
them, all real-time.

Mail gateway
------------
Sending information and documents made simplified. You can send emails
from Odoo itself, and that too with great possibilities. For example,
design a beautiful email template for the invoices, and use the same
for all your customers, no need to do the same exercise every time.

Chatter
-------
Do all the contextual conversation on a document. For example on an
applicant, directly post an update to send email to the applicant,
schedule the next interview call, attach the contract, add HR officer
to the follower list to notify them for important events(with help of
subtypes),...


Retrieve incoming email on POP/IMAP servers.
============================================
Enter the parameters of your POP/IMAP account(s), and any incoming emails on
these accounts will be automatically downloaded into your Odoo system. All
POP3/IMAP-compatible servers are supported, included those that require an
encrypted SSL/TLS connection.
This can be used to easily create email-based workflows for many email-enabled Odoo documents, such as:
----------------------------------------------------------------------------------------------------------
    * CRM Leads/Opportunities
    * CRM Claims
    * Project Issues
    * Project Tasks
    * Human Resource Recruitment (Applicants)
Just install the relevant application, and you can assign any of these document
types (Leads, Project Issues) to your incoming email accounts. New emails will
automatically spawn new documents of the chosen type, so it's a snap to create a
mailbox-to-Odoo integration. Even better: these documents directly act as mini
conversations synchronized by email. You can reply from within Odoo, and the
answers will automatically be collected when they come back, and attached to the
same *conversation* document.
For more specific needs, you may also assign custom-defined actions
(technically: Server Actions) to be triggered for each incoming mail.
    

Code Analysis

Views touched (114)
XML IDNameModelTypeStatus
account_security_setting_update account_security_setting_update ir.ui.view qweb New
discuss_channel_member_view_form discuss.channel.member.form discuss.channel.member form New
discuss_channel_member_view_tree discuss.channel.member.tree discuss.channel.member tree New
discuss_channel_rtc_session_view_form discuss.channel.rtc.session.form discuss.channel.rtc.session form New
discuss_channel_rtc_session_view_search discuss.channel.rtc.session.search discuss.channel.rtc.session search New
discuss_channel_rtc_session_view_tree discuss.channel.rtc.session.tree discuss.channel.rtc.session tree New
discuss_gif_favorite_view_form discuss.gif.favorite.form discuss.gif.favorite form New
discuss_gif_favorite_view_tree discuss.gif.favorite.tree discuss.gif.favorite tree New
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
email_template_form email.template.form mail.template form New
email_template_tree email.template.tree mail.template tree New
field_form_view ir.model.fields field Inherits base.view_model_fields_form
mail.discuss_channel_view_form discuss.channel.form discuss.channel form New
mail.discuss_channel_view_kanban discuss.channel.kanban discuss.channel kanban New
mail.discuss_channel_view_search discuss.channel.search discuss.channel search New
mail.discuss_channel_view_tree discuss.channel.tree discuss.channel tree New
mail.discuss_public_channel_template Discuss Public Template ir.ui.view qweb New
mail.message_document_unfollowed mail.message_document_unfollowed ir.ui.view qweb New
mail.public_layout mail.public_layout ir.ui.view qweb New
mail_activity_plan_template_view_form mail.activity.plan.template.view.form mail.activity.plan.template form New
mail_activity_plan_template_view_tree mail.activity.plan.template.view.tree mail.activity.plan.template tree New
mail_activity_plan_view_form mail.activity.plan.view.form mail.activity.plan form New
mail_activity_plan_view_form_fixed_model mail.activity.plan.view.form.fixed.model mail.activity.plan xpath Inherits mail.mail_activity_plan_view_form
mail_activity_plan_view_search mail.activity.plan.view.search mail.activity.plan search New
mail_activity_plan_view_tree mail.activity.plan.view.tree mail.activity.plan tree New
mail_activity_schedule_view_form Activity schedule mail.activity.schedule form New
mail_activity_type_form_inherit mail.activity.type.form.inherit mail.activity.type xpath Inherits mail.mail_activity_type_view_form
mail_activity_type_view_form mail.activity.type.view.form mail.activity.type form New
mail_activity_type_view_search mail.activity.type.search mail.activity.type search New
mail_activity_type_view_tree mail.activity.type.view.tree mail.activity.type tree New
mail_activity_view_calendar mail.activity.view.calendar mail.activity calendar New
mail_activity_view_form mail.activity.view.form mail.activity field Inherits mail.mail_activity_view_form_popup
mail_activity_view_form_popup mail.activity.view.form.popup mail.activity form New
mail_activity_view_form_without_record_access mail.activity.view.form.without.record.access mail.activity form New
mail_activity_view_search mail.activity.view.search mail.activity search New
mail_activity_view_tree mail.activity.view.tree mail.activity tree New
mail_activity_view_tree_without_record_access mail.activity.view.tree.without.record.access mail.activity xpath Inherits mail_activity_view_tree
mail_alias_domain_view_form mail.alias.domain.view.form mail.alias.domain form New
mail_alias_domain_view_search mail.alias.domain.view.search mail.alias.domain search New
mail_alias_domain_view_tree mail.alias.domain.view.tree mail.alias.domain tree New
mail_alias_view_form mail.alias.view.form mail.alias form New
mail_alias_view_search mail.alias.view.search mail.alias search New
mail_alias_view_tree mail.alias.view.tree mail.alias tree New
mail_blacklist_remove_view_form mail.blacklist.remove.form mail.blacklist.remove form New
mail_blacklist_view_form mail.blacklist.view.form mail.blacklist form New
mail_blacklist_view_search mail.blacklist.view.search mail.blacklist search New
mail_blacklist_view_tree mail.blacklist.view.tree mail.blacklist tree New
mail_bounce_alias_security mail_bounce_alias_security ir.ui.view qweb New
mail_bounce_catchall mail_bounce_catchall ir.ui.view qweb New
mail_compose_message_view_form_template_save mail.compose.message.view.form.template.save mail.compose.message form New
mail_gateway_allowed_view_search mail.gateway.allowed.view.search mail.gateway.allowed search New
mail_gateway_allowed_view_tree mail.gateway.allowed.view.tree mail.gateway.allowed tree New
mail_guest_view_form mail.guest.form mail.guest form New
mail_guest_view_tree mail.guest.tree mail.guest tree New
mail_link_preview_view_form mail.link.preview.form mail.link.preview form New
mail_link_preview_view_tree mail.link.preview.tree mail.link.preview tree New
mail_message_reaction_view_form mail.message.reaction.form mail.message.reaction form New
mail_message_reaction_view_tree mail.message.reaction.tree mail.message.reaction tree New
mail_message_schedule_view_form mail.message.schedule.view.form mail.message.schedule form New
mail_message_schedule_view_search mail.message.schedule.view.search mail.message.schedule search New
mail_message_schedule_view_tree mail.message.schedule.view.tree mail.message.schedule tree New
mail_message_view_form mail.message.view.form mail.message form New
mail_notification_layout Mail: mail notification layout template ir.ui.view qweb New
mail_notification_layout_with_responsible_signature Mail: mail notification layout with responsible signature (user_id of the record) ir.ui.view qweb Inherits mail.mail_notification_layout
mail_notification_light mail_notification_light ir.ui.view qweb New
mail_notification_view_form mail.notification.view.form mail.notification form New
mail_notification_view_tree mail.notification.view.tree mail.notification tree New
mail_resend_message_view_form mail.resend.message.view.form mail.resend.message form New
mail_resend_partner_view_form mail.resend.partner.view.form mail.resend.partner form New
mail_shortcode_view_form mail.shortcode.form mail.shortcode form New
mail_shortcode_view_search mail.shortcode.search mail.shortcode search New
mail_shortcode_view_tree mail.shortcode.tree mail.shortcode tree New
mail_template_preview_view_form mail.template.preview.view.form mail.template.preview form New
mail_template_reset_view_form mail.template.reset.view.form mail.template.reset form New
mail_template_view_form_confirm_delete mail.template.view.form.confirm.delete mail.template form New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
message_activity_assigned message_activity_assigned ir.ui.view qweb New
message_activity_done message_activity_done ir.ui.view qweb New
message_notification_limit_email message_notification_limit_email ir.ui.view qweb New
message_origin_link message_origin_link ir.ui.view qweb New
message_user_assigned message_user_assigned ir.ui.view qweb New
model_form_view ir.model field Inherits base.view_model_form
model_search_view ir.model field Inherits base.view_model_search
notification_preview notification_preview ir.ui.view qweb New
res_company_view_form res.company.view.form.inherit.mail res.company field Inherits base.view_company_form
res_config_settings_view_form res.config.settings.view.form.inherit.mail res.config.settings div Inherits base_setup.res_config_settings_view_form
res_partner_view_activity res.partner.activity res.partner activity New
res_partner_view_form_inherit_mail res.partner.view.form.inherit.mail res.partner xpath Inherits base.view_partner_form
res_partner_view_kanban_inherit_mail res.partner.view.kanban.inherit.mail res.partner field Inherits base.res_partner_kanban_view
res_partner_view_search_inherit_mail res.partner.view.search.inherit.mail res.partner filter Inherits base.view_res_partner_filter
res_partner_view_tree_inherit_mail res.partner.view.tree.inherit.mail res.partner xpath Inherits base.view_partner_tree
res_users_settings_view_form res.users.settings.form res.users.settings form New
res_users_settings_view_tree res.users.settings.tree res.users.settings tree New
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_email_server_form fetchmail.server.form fetchmail.server form New
view_email_server_search fetchmail.server.search fetchmail.server search New
view_email_server_tree fetchmail.server.list fetchmail.server tree New
view_email_template_search email.template.search mail.template search New
view_followers_tree mail.followers.tree mail.followers tree New
view_ice_server_form mail.ice.server.form mail.ice.server form New
view_ice_server_tree mail.ice.server.tree mail.ice.server tree New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tracking_value_form mail.tracking.value.form mail.tracking.value form New
view_mail_tracking_value_tree mail.tracking.value.tree mail.tracking.value tree New
view_mail_tree mail.mail.tree mail.mail tree New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.tree mail.message.subtype tree New
view_message_tree mail.message.tree mail.message tree New
view_server_action_form_template ir.actions.server.form ir.actions.server xpath Inherits base.view_server_action_form
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (81)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (1)
  • guest_id Many2one → mail.guest
    ondelete='cascade' args: 'mail.guest', 'Guest'
Public methods (1)
  • init(self)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (22)
  • active Boolean
    default=True help='Set active to false to hide the channel without removing it.'
  • allow_public_upload Boolean
    default=False
  • avatar_128 Image
    compute='_compute_avatar_128' max_height=128 max_width=128 args: 'Avatar'
  • channel_member_ids One2many → discuss.channel.member
    string='Members' args: 'discuss.channel.member', 'channel_id'
  • channel_partner_ids Many2many → res.partner
    compute='_compute_channel_partner_ids' inverse='_inverse_channel_partner_ids' search='_search_channel_partner_ids' string='Partners' args: 'res.partner'
  • channel_type Selection
    default='channel' help='Chat is private and unique between 2 persons. Group is private among invited persons. Channel can be freely joined (depending on its configuration).' readonly=True required=True string='Channel Type' args: [('chat', 'Chat'), ('channel', 'Channel'), ('group', 'Group')]
  • default_display_mode Selection
    help='Determines how the channel will be displayed by default when opening it from its invitation link. No value means display text (no voice/video).' selection=[('video_full_screen', 'Full screen video')] string='Default Display Mode'
  • description Text
    args: 'Description'
  • group_ids Many2many → res.groups
    help='Members of those groups will automatically added as followers. Note that they will be able to manage their subscription manually if necessary.' string='Auto Subscription' args: 'res.groups'
  • group_public_id Many2one → res.groups
    compute='_compute_group_public_id' readonly=False store=True string='Authorized Group' args: 'res.groups'
  • image_128 Image
    max_height=128 max_width=128 args: 'Image'
  • invitation_url Char
    compute='_compute_invitation_url' args: 'Invitation URL'
  • is_chat Boolean
    compute='_compute_is_chat' string='Is a chat'
  • is_editable Boolean
    compute='_compute_is_editable' args: 'Is Editable'
  • is_member Boolean
    compute='_compute_is_member' search='_search_is_member' args: 'Is Member'
  • member_count Integer
    compute='_compute_member_count' compute_sudo=True string='Member Count'
  • name Char
    required=True args: 'Name'
  • pinned_message_ids One2many → mail.message
    domain=[('model', '=', 'discuss.channel'), ('pinned_at', '!=', False)] string='Pinned Messages' args: 'mail.message', 'res_id'
  • rtc_session_ids One2many → discuss.channel.rtc.session
    groups='base.group_system' args: 'discuss.channel.rtc.session', 'channel_id'
  • sfu_channel_uuid Char
    groups='base.group_system'
  • sfu_server_url Char
    groups='base.group_system'
  • uuid Char
    copy=False default=_generate_random_token size=50 args: 'UUID'
Public methods (23)
  • action_unfollow(self)
  • add_members(self, partner_ids=None, guest_ids=None, invite_to_rtc_call=False, open_chat_window=False, post_joined_message=True)
    Adds the given partner_ids and guest_ids as member of self channels.
  • channel_change_description(self, description)
  • channel_create(self, name, group_id)
    @api.model@api.returns('self', <expr>)
    Create a channel and add the current partner, broadcast it (to make the user directly listen to it when polling) :param name : the name of the channel to create :param group_id : the group allowed to join the channel. :return dict : channel header
  • channel_fetch_preview(self)
    Return the last message of the given channels
  • channel_fetched(self)
    Broadcast the channel_fetched notification to channel members
  • channel_fold(self, state=None, state_count=0)
    Update the fold_state of the given session. In order to syncronize web browser tabs, the change will be broadcast to themselves (the current user channel). Note: the user need to be logged :param state : the new status of the session for the current user.
  • channel_get(self, partners_to, pin=True)
    @api.model@api.returns('self', <expr>)
    Get the canonical private channel between some partners, create it if needed. To reuse an old channel (conversation), this one must be private, and contains only the given partners. :param partners_to : list of res.partner ids to add to the conversation :param pin : True if getting the channel should pin it for the current user :returns: channel_info of the created or existing channel :rtype: dict
  • channel_join(self)
    Shortcut to add the current user as member of self channels. Prefer calling add_members() directly when possible.
  • channel_pin(self, pinned=False)
  • channel_rename(self, name)
  • channel_set_custom_name(self, name)
  • create(self, vals_list)
    @api.model_create_multi
  • create_group(self, partners_to, default_display_mode=False, name='')
    @api.model@api.returns('self', <expr>)
    Creates a group channel. :param partners_to : list of res.partner ids to add to the conversation :param str default_display_mode: how the channel will be displayed by default :param str name: group name. default name is computed client side from the list of members if no name is set :returns: channel_info of the created channel :rtype: dict
  • execute_command_help(self, **kwargs)
  • execute_command_leave(self, **kwargs)
  • execute_command_who(self, **kwargs)
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first channels' id, name, channel_type and authorizedGroupFullName fields such that the name matches a 'search' string. Exclude channels of type chat (DM) and group.
  • init(self)
  • load_more_members(self, known_member_ids)
  • message_post(self, *, message_type='notification', **kwargs)
    @api.returns('mail.message', <expr>)
  • set_message_pin(self, message_id, pinned)
    (Un)pin a message on the channel and send a notification to the members. :param message_id: id of the message to be pinned. :param pinned: whether the message should be pinned or unpinned.
  • write(self, vals)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (17)
  • channel_id Many2one → discuss.channel
    auto_join=True ondelete='cascade' required=True args: 'discuss.channel', 'Channel'
  • custom_channel_name Char
    args: 'Custom channel name'
  • custom_notifications Selection
    help='All Messages if not specified' args: [('mentions', 'Mentions Only'), ('no_notif', 'Nothing')], 'Customized Notifications'
  • fetched_message_id Many2one → mail.message
    index='btree_not_null' string='Last Fetched' args: 'mail.message'
  • fold_state Selection
    default='open' string='Conversation Fold State' args: [('open', 'Open'), ('folded', 'Folded'), ('closed', 'Closed')]
  • guest_id Many2one → mail.guest
    index=True ondelete='cascade' args: 'mail.guest', 'Guest'
  • is_minimized Boolean
    args: 'Conversation is minimized'
  • is_pinned Boolean
    default=True args: 'Is pinned on the interface'
  • is_self Boolean
    compute='_compute_is_self' search='_search_is_self'
  • last_interest_dt Datetime
    default=fields.Datetime.now help='Contains the date and time of the last interesting event that happened in this channel for this partner. This includes: creating, joining, pinning, and new message posted.' args: 'Last Interest'
  • last_seen_dt Datetime
    args: 'Last seen date'
  • message_unread_counter Integer
    compute='_compute_message_unread' compute_sudo=True args: 'Unread Messages Counter'
  • mute_until_dt Datetime
    help='If set, the member will not receive notifications from the channel until this date.' args: 'Mute notifications until'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner', 'Partner'
  • rtc_inviting_session_id Many2one → discuss.channel.rtc.session
    string='Ringing session' args: 'discuss.channel.rtc.session'
  • rtc_session_ids One2many → discuss.channel.rtc.session
    comodel_name='discuss.channel.rtc.session' inverse_name='channel_member_id' string='RTC Sessions'
  • seen_message_id Many2one → mail.message
    index='btree_not_null' string='Last Seen' args: 'mail.message'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • init(self)
  • unlink(self)
  • write(self, vals)

New fields (9)
  • channel_id Many2one → discuss.channel
    readonly=True related='channel_member_id.channel_id' store=True args: 'discuss.channel'
  • channel_member_id Many2one → discuss.channel.member
    ondelete='cascade' required=True args: 'discuss.channel.member'
  • guest_id Many2one → mail.guest
    related='channel_member_id.guest_id' args: 'mail.guest'
  • is_camera_on Boolean
    string='Is sending user video'
  • is_deaf Boolean
    string='Has disabled incoming sound'
  • is_muted Boolean
    string='Is microphone muted'
  • is_screen_sharing_on Boolean
    string='Is sharing the screen'
  • partner_id Many2one → res.partner
    related='channel_member_id.partner_id' string='Partner' args: 'res.partner'
  • write_date Datetime
    index=True args: 'Last Updated On'
Public methods (3)
  • action_disconnect(self)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)

New fields (1)
  • tenor_gif_id Char
    required=True args: 'GIF id from Tenor'
Public methods (0)

No public methods.

New fields (1)
  • attachment_id Many2one → ir.attachment
    auto_join=True copy=False index=True ondelete='cascade' args: 'ir.attachment'
Public methods (0)

No public methods.

New fields (18)
  • active Boolean
    default=True args: 'Active'
  • attach Boolean
    default=True help='Whether attachments should be downloaded. If not enabled, incoming emails will be stripped of any attachments before being processed' args: 'Keep Attachments'
  • configuration Text
    readonly=True args: 'Configuration'
  • date Datetime
    readonly=True string='Last Fetch Date'
  • is_ssl Boolean
    help='Connections are encrypted with SSL/TLS through a dedicated port (default: IMAPS=993, POP3S=995)' args: 'SSL/TLS'
  • message_ids One2many → mail.mail
    readonly=True string='Messages' args: 'mail.mail', 'fetchmail_server_id'
  • name Char
    required=True args: 'Name'
  • object_id Many2one → ir.model
    help='Process each incoming mail as part of a conversation corresponding to this document type. This will create new documents for new conversations, or attach follow-up emails to the existing conversations (documents).' string='Create a New Record' args: 'ir.model'
  • original Boolean
    help='Whether a full original copy of each email should be kept for reference and attached to each processed message. This will usually double the size of your message database.' args: 'Keep Original'
  • password Char
  • port Integer
  • priority Integer
    default=5 help='Defines the order of processing, lower values mean higher priority' readonly=False string='Server Priority'
  • script Char
    default='/mail/static/scripts/odoo-mailgate.py' readonly=True
  • server Char
    help='Hostname or IP of the mail server' readonly=False string='Server Name'
  • server_type Selection
    default='imap' index=True required=True string='Server Type' args: [('imap', 'IMAP Server'), ('pop', 'POP Server'), ('local', 'Local Server')]
  • server_type_info Text
    compute='_compute_server_type_info' args: 'Server Type Info'
  • state Selection
    copy=False default='draft' index=True readonly=True string='Status' args: [('draft', 'Not Confirmed'), ('done', 'Confirmed')]
  • user Char
    readonly=False string='Username'
Public methods (8)
  • button_confirm_login(self)
  • connect(self, allow_archived=False)
    :param bool allow_archived: by default (False), an exception is raised when calling this method on an archived record. It can be set to True for testing so that the exception is no longer raised.
  • create(self, vals_list)
    @api.model_create_multi
  • fetch_mail(self)
    WARNING: meant for cron usage only - will commit() after each email!
  • onchange_server_type(self)
    @api.onchange('server_type', 'is_ssl', 'object_id')
  • set_draft(self)
  • unlink(self)
  • write(self, values)

New fields (1)
  • view_mode Selection
    ondelete={'activity': 'cascade'} selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (13)
  • activity_date_deadline_range Integer
    compute='_compute_activity_info' readonly=False store=True string='Due Date In'
  • activity_date_deadline_range_type Selection
    compute='_compute_activity_info' default='days' readonly=False store=True string='Due type' args: [('days', 'Days'), ('weeks', 'Weeks'), ('months', 'Months')]
  • activity_note Html
    compute='_compute_activity_info' readonly=False store=True args: 'Note'
  • activity_summary Char
    compute='_compute_activity_info' readonly=False store=True args: 'Title'
  • activity_type_id Many2one → mail.activity.type
    compute='_compute_activity_type_id' domain="['|', ('res_model', '=', False), ('res_model', '=', model_name)]" ondelete='restrict' readonly=False store=True string='Activity Type' args: 'mail.activity.type'
  • activity_user_field_name Char
    compute='_compute_activity_info' readonly=False store=True args: 'User Field'
  • activity_user_id Many2one → res.users
    compute='_compute_activity_info' readonly=False store=True string='Responsible' args: 'res.users'
  • activity_user_type Selection
    compute='_compute_activity_info' help="Use 'Specific User' to always assign the same user on the next activity. Use 'Dynamic User' to specify the field name of the user to choose on the record." readonly=False store=True string='User Type' args: [('specific', 'Specific User'), ('generic', 'Dynamic User (based on record)')]
  • mail_post_autofollow Boolean
    compute='_compute_mail_post_autofollow' readonly=False store=True args: 'Subscribe Recipients'
  • mail_post_method Selection
    compute='_compute_mail_post_method' readonly=False selection=[('email', 'Email'), ('comment', 'Message'), ('note', 'Note')] store=True string='Send Email As'
  • partner_ids Many2many → res.partner
    compute='_compute_partner_ids' readonly=False store=True args: 'res.partner'
  • state Selection
    ondelete={'mail_post': 'cascade', 'followers': 'cascade', 'remove_followers': 'cascade', 'next_activity': 'cascade'} selection_add=[('next_activity', 'Create Activity'), ('mail_post', 'Send Email'), ('followers', 'Add Followers'), ('remove_followers', 'Remove Followers'), ('object_create')]
  • template_id Many2one → mail.template
    compute='_compute_template_id' domain="[('model_id', '=', model_id)]" ondelete='set null' readonly=False store=True args: 'mail.template', 'Email Template'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • register_as_main_attachment(self, force=True)
    Registers this attachment as the main one of the model it is attached to. :param bool force: if set, the method always updates the existing main attachment otherwise it only sets the main attachment if there is none.

New fields (1)
  • voice_ids One2many → discuss.voice.metadata
    args: 'discuss.voice.metadata', 'attachment_id'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • set_param(self, key, value)
    @api.model
  • write(self, vals)

New fields (0)

No new fields.

Public methods (1)
  • session_info(self)

New fields (1)
  • mail_template_ids One2many → mail.template
    comodel_name='mail.template' inverse_name='mail_server_id' readonly=True string='Mail template using this mail server'
Public methods (0)

No public methods.

New fields (3)
  • is_mail_activity Boolean
    default=False string='Has Mail Activity'
  • is_mail_blacklist Boolean
    default=False string='Has Mail Blacklist'
  • is_mail_thread Boolean
    default=False string='Has Mail Thread'
Public methods (2)
  • unlink(self)
    Delete mail data (followers, messages, activities) associated with the models being deleted.
  • write(self, vals)

New fields (1)
  • tracking Integer
    help='If set every modification done to this field is tracked. Value is used to order tracking values.' string='Enable Ordered Tracking'
Public methods (1)
  • unlink(self)
    When unlinking fields populate tracking value table with relevant information. That way if a field is removed (custom tracked, migration or any other reason) we keep the tracking and its relevant information. Do it only when unlinking fields so that we don't duplicate field information for most tracking.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (1)
  • type Selection
    selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (24)
  • active Boolean
    default=True
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_decoration Selection
    readonly=True related='activity_type_id.decoration_type'
  • activity_type_id Many2one → mail.activity.type
    default=_default_activity_type domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" ondelete='restrict' string='Activity Type' args: 'mail.activity.type'
  • attachment_ids Many2many → ir.attachment
    string='Attachments' args: 'ir.attachment', 'activity_attachment_rel', 'activity_id', 'attachment_id'
  • automated Boolean
    help='Indicates this activity has been created automatically and not by any user.' readonly=True args: 'Automated activity'
  • can_write Boolean
    compute='_compute_can_write'
  • chaining_type Selection
    readonly=True related='activity_type_id.chaining_type'
  • date_deadline Date
    default=fields.Date.context_today index=True required=True args: 'Due Date'
  • date_done Date
    compute='_compute_date_done' store=True args: 'Done Date'
  • has_recommended_activities Boolean
    compute='_compute_has_recommended_activities' args: 'Next activities available'
  • icon Char
    readonly=True related='activity_type_id.icon' args: 'Icon'
  • mail_template_ids Many2many
    readonly=True related='activity_type_id.mail_template_ids'
  • note Html
    sanitize_style=True args: 'Note'
  • previous_activity_type_id Many2one → mail.activity.type
    readonly=True string='Previous Activity Type' args: 'mail.activity.type'
  • recommended_activity_type_id Many2one → mail.activity.type
    string='Recommended Activity Type' args: 'mail.activity.type'
  • request_partner_id Many2one → res.partner
    string='Requesting Partner' args: 'res.partner'
  • res_id Many2oneReference
    index=True model_field='res_model' string='Related Document ID'
  • res_model Char
    index=True precompute=True readonly=True related='res_model_id.model' store=True args: 'Related Document Model'
  • res_model_id Many2one → ir.model
    index=True ondelete='cascade' required=True args: 'ir.model', 'Document Model'
  • res_name Char
    compute='_compute_res_name' compute_sudo=True readonly=True store=True args: 'Document Name'
  • state Selection
    compute='_compute_state' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned'), ('done', 'Done')], 'State'
  • summary Char
    args: 'Summary'
  • user_id Many2one → res.users
    default=<expr> index=True ondelete='cascade' required=True args: 'res.users', 'Assigned to'
Public methods (13)
  • action_close_dialog(self)
  • action_done(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_done_schedule_next(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_feedback(self, feedback=False, attachment_ids=None)
  • action_feedback_schedule_next(self, feedback=False, attachment_ids=None)
  • action_notify(self)
  • action_open_document(self)
    Opens the related record based on the model and ID
  • activity_format(self)
  • create(self, vals_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • get_activity_data(self, res_model, domain, limit=None, offset=0, fetch_done=False)
    @api.model
    Get aggregate data about records and their activities. The goal is to fetch and compute aggregated data about records and their activities to display them in the activity views and the chatter. For example, the activity view displays it as a table with columns and rows being respectively the activity_types and the activity_res_ids, and the grouped_activities being the table entries with the aggregated data. :param str res_model: model of the records to fetch :param list domain: record search domain :param int limit: maximum number of records to fetch :param int offset: offset of the first record to fetch :param bool fetch_done: determines if "done" activities are integrated in the aggregated data or not. :return dict: {'activity_types': dict of activity type info {id: int, name: str, mail_template: list of {id:int, name:str}, keep_done: bool} 'activity_res_ids': list<int> of record id ordered by closest date (deadline for ongoing activities, and done date for done activities) 'grouped_activities': dict<dict> res_id -> activity_type_id -> aggregated info as: count_by_state dict: mapping state to count (ex.: 'planned': 2) ids list: activity ids for the res_id and activity_type_id reporting_date str: aggregated date of the related activities as oldest deadline of ongoing activities if there are any or most recent date done of completed activities state dict: aggregated state of the related activities user_assigned_ids list: activity responsible id ordered by closest deadline of the related activities attachments_info: dict with information about the attachments {'count': int, 'most_recent_id': int, 'most_recent_name': str} }
  • unlink(self)
  • write(self, values)

New fields (10)
  • activity_date_deadline Date
    compute='_compute_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_activity_date_deadline' store=False args: 'Next Activity Deadline'
  • activity_exception_decoration Selection
    compute='_compute_activity_exception_type' help='Type of the exception activity on record.' search='_search_activity_exception_decoration' args: [('warning', 'Alert'), ('danger', 'Error')]
  • activity_exception_icon Char
    compute='_compute_activity_exception_type' help='Icon to indicate an exception activity.' args: 'Icon'
  • activity_ids One2many → mail.activity
    auto_join=True groups='base.group_user' args: 'mail.activity', 'res_id', 'Activities'
  • activity_state Selection
    compute='_compute_activity_state' groups='base.group_user' help='Status based on activities\nOverdue: Due date is already passed\nToday: Activity date is today\nPlanned: Future activities.' search='_search_activity_state' string='Activity State' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')]
  • activity_summary Char
    groups='base.group_user' readonly=False related='activity_ids.summary' search='_search_activity_summary' args: 'Next Activity Summary'
  • activity_type_icon Char
    related='activity_ids.icon' args: 'Activity Type Icon'
  • activity_type_id Many2one → mail.activity.type
    groups='base.group_user' readonly=False related='activity_ids.activity_type_id' search='_search_activity_type_id' args: 'mail.activity.type', 'Next Activity Type'
  • activity_user_id Many2one → res.users
    compute='_compute_activity_user_id' groups='base.group_user' readonly=True search='_search_activity_user_id' args: 'res.users', 'Responsible User'
  • my_activity_date_deadline Date
    compute='_compute_my_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_my_activity_date_deadline' args: 'My Activity Deadline'
Public methods (9)
  • activity_feedback(self, act_type_xmlids, user_id=None, feedback=None, attachment_ids=None)
    Set activities as done, limiting to some activity types and optionally to a given user.
  • activity_reschedule(self, act_type_xmlids, user_id=None, date_deadline=None, new_user_id=None)
    Reschedule some automated activities. Activities to reschedule are selected based on type xml ids and optionally by user. Purpose is to be able to * update the deadline to date_deadline; * update the responsible to new_user_id;
  • activity_schedule(self, act_type_xmlid='', date_deadline=None, summary='', note='', **act_values)
    Schedule an activity on each record of the current record set. This method allow to provide as parameter act_type_xmlid. This is an xml_id of activity type instead of directly giving an activity_type_id. It is useful to avoid having various "env.ref" in the code and allow to let the mixin handle access rights. Note that unless specified otherwise in act_values, the activities created will have their "automated" field set to True. :param date_deadline: the day the activity must be scheduled on the timezone of the user must be considered to set the correct deadline
  • activity_search(self, act_type_xmlids='', user_id=None, additional_domain=None)
    Search automated activities on current record set, given a list of activity types xml IDs. It is useful when dealing with specific types involved in automatic activities management. :param act_type_xmlids: list of activity types xml IDs :param user_id: if set, restrict to activities of that user_id; :param additional_domain: if set, filter on that domain;
  • activity_send_mail(self, template_id)
    Automatically send an email based on the given mail.template, given its ID.
  • activity_unlink(self, act_type_xmlids, user_id=None)
    Unlink activities, limiting to some activity types and optionally to a given user.
  • toggle_active(self)
    Before archiving the record we should also remove its ongoing activities. Otherwise they stay in the systray and concerning archived records it makes no sense.
  • unlink(self)
    Override unlink to delete records activities through (res_model, res_id).
  • write(self, vals)

New fields (9)
  • active Boolean
    default=True
  • assignation_summary Html
    compute='_compute_assignation_summary' args: 'Plan Summary'
  • company_id Many2one → res.company
    default=<expr> args: 'res.company'
  • has_user_on_demand Boolean
    compute='_compute_has_user_on_demand' args: 'Has on demand responsible'
  • name Char
    required=True args: 'Name'
  • res_model Selection
    help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' required=True selection=_get_model_selection string='Model'
  • res_model_id Many2one → ir.model
    compute='_compute_res_model_id' compute_sudo=True ondelete='cascade' precompute=True readonly=False required=True store=True string='Applies to' args: 'ir.model'
  • steps_count Integer
    compute='_compute_steps_count'
  • template_ids One2many → mail.activity.plan.template
    string='Activities' args: 'mail.activity.plan.template', 'plan_id'
Public methods (0)

No public methods.

New fields (9)
  • activity_type_id Many2one → mail.activity.type
    default=<expr> domain="['|', ('res_model', '=', False), '&', ('res_model', '!=', False), ('res_model', '=', parent.res_model)]" ondelete='restrict' required=True args: 'mail.activity.type', 'Activity Type'
  • company_id Many2one
    related='plan_id.company_id'
  • note Html
    args: 'Note'
  • plan_id Many2one → mail.activity.plan
    ondelete='cascade' required=True string='Plan' args: 'mail.activity.plan'
  • res_model Selection
    related='plan_id.res_model'
  • responsible_id Many2one → res.users
    check_company=True compute='_compute_responsible_id' readonly=False store=True args: 'res.users', 'Assigned to'
  • responsible_type Selection
    default='on_demand' required=True string='Assignment' args: [('on_demand', 'Ask at launch'), ('other', 'Default user')]
  • sequence Integer
    default=10
  • summary Char
    compute='_compute_summary' readonly=False store=True args: 'Summary'
Public methods (0)

No public methods.

New fields (20)
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_type_id Many2one → mail.activity.type
    compute='_compute_activity_type_id' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" ondelete='set null' readonly=False store=True string='Activity Type' args: 'mail.activity.type'
  • activity_user_id Many2one → res.users
    compute='_compute_activity_user_id' readonly=False store=True args: 'res.users', 'Assigned to'
  • chaining_type Selection
    readonly=True related='activity_type_id.chaining_type'
  • company_id Many2one → res.company
    compute='_compute_company_id' required=True args: 'res.company', 'Company'
  • date_deadline Date
    compute='_compute_date_deadline' readonly=False store=True args: 'Due Date'
  • error Html
    compute='_compute_error'
  • has_error Boolean
    compute='_compute_error'
  • is_batch_mode Boolean
    compute='_compute_is_batch_mode' args: 'Use in batch'
  • note Html
    compute='_compute_note' readonly=False sanitize_style=True store=True args: 'Note'
  • plan_assignation_summary Html
    related='plan_id.assignation_summary'
  • plan_available_ids Many2many → mail.activity.plan
    compute='_compute_plan_available_ids' compute_sudo=True store=True args: 'mail.activity.plan'
  • plan_date_deadline Date
    compute='_compute_plan_date_deadline' readonly=False store=True args: 'Plan Date'
  • plan_has_user_on_demand Boolean
    related='plan_id.has_user_on_demand'
  • plan_id Many2one → mail.activity.plan
    compute='_compute_plan_id' domain="[('id', 'in', plan_available_ids)]" readonly=False store=True args: 'mail.activity.plan'
  • plan_on_demand_user_id Many2one → res.users
    default=<expr> help='Choose assignation for activities with on demand assignation.' args: 'res.users', 'Assigned To'
  • res_ids Text
    compute='_compute_res_ids' precompute=True readonly=True store=True args: 'Document IDs'
  • res_model Char
    readonly=True required=True args: 'Model'
  • res_model_id Many2one → ir.model
    compute='_compute_res_model_id' compute_sudo=True ondelete='cascade' precompute=True readonly=False required=True store=True string='Applies to' args: 'ir.model'
  • summary Char
    compute='_compute_summary' readonly=False store=True args: 'Summary'
Public methods (5)
  • action_schedule_activities(self)
  • action_schedule_activities_done(self)
  • action_schedule_activities_done_and_schedule(self)
  • action_schedule_plan(self)
  • default_get(self, fields_list)
    @api.model

New fields (23)
  • active Boolean
    default=True
  • category Selection
    default='default' help='Actions may trigger specific behavior like opening calendar view or automatically mark as done when a document is uploaded' string='Action' args: [('default', 'None'), ('upload_file', 'Upload Document'), ('phonecall', 'Phonecall')]
  • chaining_type Selection
    default='suggest' required=True string='Chaining Type' args: [('suggest', 'Suggest Next Activity'), ('trigger', 'Trigger Next Activity')]
  • create_uid Many2one → res.users
    index=True args: 'res.users'
  • decoration_type Selection
    help='Change the background color of the related activities of this type.' string='Decoration Type' args: [('warning', 'Alert'), ('danger', 'Error')]
  • default_note Html
    string='Default Note' translate=True
  • default_user_id Many2one → res.users
    string='Default User' args: 'res.users'
  • delay_count Integer
    default=0 help='Number of days/week/month before executing the action. It allows to plan the action deadline.' args: 'Schedule'
  • delay_from Selection
    default='previous_activity' help='Type of delay' required=True string='Delay Type' args: [('current_date', 'after completion date'), ('previous_activity', 'after previous activity deadline')]
  • delay_label Char
    compute='_compute_delay_label'
  • delay_unit Selection
    default='days' help='Unit of delay' required=True string='Delay units' args: [('days', 'days'), ('weeks', 'weeks'), ('months', 'months')]
  • icon Char
    help='Font awesome icon e.g. fa-tasks' args: 'Icon'
  • initial_res_model Selection
    compute='_compute_initial_res_model' help='Technical field to keep track of the model at the start of editing to support UX related behaviour' selection=_get_model_selection store=False string='Initial model'
  • keep_done Boolean
    help='Keep activities marked as done in the activity view' string='Keep Done'
  • mail_template_ids Many2many → mail.template
    string='Email templates' args: 'mail.template'
  • name Char
    required=True translate=True args: 'Name'
  • previous_type_ids Many2many → mail.activity.type
    domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" string='Preceding Activities' args: 'mail.activity.type', 'mail_activity_rel', 'recommended_id', 'activity_id'
  • res_model Selection
    help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' selection=_get_model_selection string='Model'
  • res_model_change Boolean
    default=False store=False string='Model has change'
  • sequence Integer
    default=10 args: 'Sequence'
  • suggested_next_type_ids Many2many → mail.activity.type
    compute='_compute_suggested_next_type_ids' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" help='Suggest these activities once the current one is marked as done.' inverse='_inverse_suggested_next_type_ids' readonly=False store=True string='Suggest' args: 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id'
  • summary Char
    translate=True args: 'Default Summary'
  • triggered_next_type_id Many2one → mail.activity.type
    compute='_compute_triggered_next_type_id' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" help='Automatically schedule this activity once the current one is marked as done.' inverse='_inverse_triggered_next_type_id' ondelete='restrict' readonly=False store=True string='Trigger' args: 'mail.activity.type'
Public methods (1)
  • write(self, values)

New fields (14)
  • alias_bounced_content Html
    help='If set, this content will automatically be sent out to unauthorized users instead of the default message.' translate=True args: 'Custom Bounced Message'
  • alias_contact Selection
    default='everyone' help='Policy to post a message on the document using the mailgateway.\n- everyone: everyone can post\n- partners: only authenticated partners\n- followers: only followers of the related document or members of following channels\n' required=True string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_defaults Text
    default='{}' help='A Python dictionary that will be evaluated to provide default values when creating new records for this alias.' required=True args: 'Default Values'
  • alias_domain Char
    related='alias_domain_id.name' args: 'Alias domain name'
  • alias_domain_id Many2one → mail.alias.domain
    default=<expr> ondelete='restrict' string='Alias Domain' args: 'mail.alias.domain'
  • alias_force_thread_id Integer
    help='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.' args: 'Record Thread ID'
  • alias_full_name Char
    compute='_compute_alias_full_name' index='btree_not_null' store=True args: 'Alias Email'
  • alias_incoming_local Boolean
    default=False args: 'Local-part based incoming detection'
  • alias_model_id Many2one → ir.model
    domain="[('field_id.name', '=', 'message_ids')]" help='The model (Odoo 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)' ondelete='cascade' required=True args: 'ir.model', 'Aliased Model'
  • alias_name Char
    copy=False help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>" args: 'Alias Name'
  • alias_parent_model_id Many2one → ir.model
    help='Parent model holding the alias. The model holding the alias reference is not necessarily the model given by alias_model_id (example: project (parent_model) and task (model))' args: 'ir.model', 'Parent Model'
  • alias_parent_thread_id Integer
    help='ID of the parent record holding the alias (example: project holding the task creation alias)' args: 'Parent Record Thread ID'
  • alias_status Selection
    compute='_compute_alias_status' help='Alias status assessed on the last message received.' store=True args: [('not_tested', 'Not Tested'), ('valid', 'Valid'), ('invalid', 'Invalid')]
  • display_name Char
    compute='_compute_display_name' string='Display Name'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
    Creates mail.alias records according to the values provided in ``vals`` but sanitize 'alias_name' by replacing certain unsafe characters; set default alias domain if not given. :raise UserError: if given (alias_name, alias_domain_id) already exists or if there are duplicates in given vals_list;
  • init(self)
    Make sure there aren't multiple records for the same name and alias domain. Not in _sql_constraint because COALESCE is not supported for PostgreSQL constraint.
  • open_document(self)
  • open_parent_document(self)
  • write(self, vals)
    Raise UserError with a meaningful message instead of letting the uniqueness constraint raise an SQL error. To check uniqueness we have to rebuild pairs of names / domains to validate, taking into account that a void alias_domain_id is acceptable (but also raises for uniqueness).

New fields (9)
  • bounce_alias Char
    default='bounce' help="Local-part of email used for Return-Path used when emails bounce e.g. 'bounce' in 'bounce@example.com'" required=True args: 'Bounce Alias'
  • bounce_email Char
    compute='_compute_bounce_email' args: 'Bounce Email'
  • catchall_alias Char
    default='catchall' help="Local-part of email used for Reply-To to catch answers e.g. 'catchall' in 'catchall@example.com'" required=True args: 'Catchall Alias'
  • catchall_email Char
    compute='_compute_catchall_email' args: 'Catchall Email'
  • company_ids One2many → res.company
    help='Companies using this domain as default for sending mails' string='Companies' args: 'res.company', 'alias_domain_id'
  • default_from Char
    default='notifications' help="Default from when it does not match outgoing server filters. Can be either a local-part e.g. 'notifications' either a complete email address e.g. 'notifications@example.com' to override all outgoing emails." args: 'Default From Alias'
  • default_from_email Char
    compute='_compute_default_from_email' args: 'Default From'
  • name Char
    help="Email domain e.g. 'example.com' in 'odoo@example.com'" required=True args: 'Name'
  • sequence Integer
    default=10
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
    Sanitize bounce_alias / catchall_alias / default_from
  • write(self, vals)
    Sanitize bounce_alias / catchall_alias / default_from

New fields (3)
  • alias_defaults Text
    inherited=True
  • alias_id Many2one
    required=True
  • alias_name Char
    inherited=True
Public methods (0)

No public methods.

New fields (6)
  • alias_defaults Text
    related='alias_id.alias_defaults'
  • alias_domain Char
    related='alias_id.alias_domain' args: 'Alias Domain Name'
  • alias_domain_id Many2one → mail.alias.domain
    readonly=False related='alias_id.alias_domain_id' string='Alias Domain' args: 'mail.alias.domain'
  • alias_email Char
    compute='_compute_alias_email' search='_search_alias_email' args: 'Email Alias'
  • alias_id Many2one → mail.alias
    copy=False ondelete='restrict' required=False string='Alias' args: 'mail.alias'
  • alias_name Char
    readonly=False related='alias_id.alias_name'
Public methods (4)
  • copy_data(self, default=None)
    @api.returns(None, <expr>)
  • create(self, vals_list)
    @api.model_create_multi
    Create aliases using sudo if an alias is required, notably if its name is given.
  • unlink(self)
    Delete the given records, and cascade-delete their corresponding alias.
  • write(self, vals)
    Split writable fields of mail.alias and other fields alias fields will write with sudo and the other normally. Also handle alias_domain_id update. If alias does not exist and we try to set a name, create the alias automatically.

New fields (2)
  • active Boolean
    default=True tracking=2
  • email Char
    help='This field is case insensitive.' index='trigram' required=True string='Email Address' tracking=1
Public methods (4)
  • action_add(self)
  • create(self, values)
    @api.model_create_multi
  • mail_action_blacklist_remove(self)
  • write(self, values)

New fields (2)
  • email Char
    name='Email' readonly=True required=True
  • reason Char
    name='Reason'
Public methods (1)
  • action_unblacklist_apply(self)

New fields (33)
  • attachment_ids Many2many → ir.attachment
    compute='_compute_attachment_ids' readonly=False store=True string='Attachments' args: 'ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id'
  • author_id Many2one → res.partner
    compute='_compute_authorship' compute_sudo=False help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' readonly=False store=True string='Author' args: 'res.partner'
  • auto_delete Boolean
    compute='_compute_auto_delete' compute_sudo=False help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." readonly=False store=True args: 'Delete Emails'
  • auto_delete_keep_log Boolean
    compute='_compute_auto_delete_keep_log' help='Keep a copy of the email content if emails are removed (mass mailing only)' readonly=False store=True args: 'Keep Message Copy'
  • body Html
    compute='_compute_body' readonly=False render_engine='qweb' render_options={'post_process': True} sanitize_style=True store=True args: 'Contents'
  • composition_batch Boolean
    compute='_compute_composition_batch' args: 'Batch composition'
  • composition_mode Selection
    default='comment' selection=[('comment', 'Post on a document'), ('mass_mail', 'Email Mass Mailing')] string='Composition mode'
  • email_add_signature Boolean
    compute='_compute_email_add_signature' readonly=False store=True args: 'Add signature'
  • email_from Char
    compute='_compute_authorship' compute_sudo=False help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' readonly=False store=True args: 'From'
  • email_layout_xmlid Char
    compute='_compute_email_layout_xmlid' compute_sudo=False copy=False readonly=False store=True args: 'Email Notification Layout'
  • force_send Boolean
    compute='_compute_force_send' readonly=False store=True args: 'Send mailing or notifications directly'
  • mail_activity_type_id Many2one → mail.activity.type
    ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_server_id Many2one → ir.mail_server
    compute='_compute_mail_server_id' compute_sudo=False readonly=False store=True string='Outgoing mail server' args: 'ir.mail_server'
  • message_type Selection
    default='comment' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' required=True args: [('auto_comment', 'Automated Targeted Notification'), ('comment', 'Comment'), ('notification', 'System notification')], 'Type'
  • model Char
    compute='_compute_model' readonly=False store=True args: 'Related Document Model'
  • model_is_thread Boolean
    compute='_compute_model_is_thread' args: 'Thread-Enabled'
  • parent_id Many2one → mail.message
    ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    compute='_compute_partner_ids' readonly=False store=True args: 'res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional Contacts'
  • record_alias_domain_id Many2one → mail.alias.domain
    compute='_compute_record_environment' readonly=False store=True args: 'mail.alias.domain', 'Alias Domain'
  • record_company_id Many2one → res.company
    compute='_compute_record_environment' readonly=False store=True args: 'res.company', 'Company'
  • record_name Char
    compute='_compute_record_name' readonly=False store=True args: 'Record Name'
  • reply_to Char
    compute='_compute_reply_to' compute_sudo=False help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' readonly=False store=True args: 'Reply To'
  • reply_to_force_new Boolean
    compute='_compute_reply_to_force_new' help='Manage answers as new incoming emails instead of replies going to the same thread.' readonly=False store=True string='Considers answers as new thread'
  • reply_to_mode Selection
    compute='_compute_reply_to_mode' help='Original Discussion: Answers go in the original document discussion thread. \n Another Email Address: Answers go to the email address mentioned in the tracking message-id instead of original document discussion thread. \n This has an impact on the generated message-id.' inverse='_inverse_reply_to_mode' string='Replies' args: [('update', 'Store email and replies in the chatter of each record'), ('new', 'Collect replies on a specific email address')]
  • res_domain Text
    args: 'Active domain'
  • res_domain_user_id Many2one → res.users
    help='Used as context used to evaluate composer domain' string='Responsible' args: 'res.users'
  • res_ids Text
    compute='_compute_res_ids' readonly=False store=True args: 'Related Document IDs'
  • scheduled_date Char
    compute='_compute_scheduled_date' compute_sudo=False help='In comment mode: if set, postpone notifications sending. In mass mail mode: if sent, send emails after that date. This date is considered as being in UTC timezone.' readonly=False store=True args: 'Scheduled Date'
  • subject Char
    compute='_compute_subject' readonly=False store=True args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    compute='_compute_subtype_id' ondelete='set null' readonly=False store=True args: 'mail.message.subtype', 'Subtype'
  • subtype_is_log Boolean
    compute='_compute_subtype_is_log' args: 'Is a log'
  • template_id Many2one → mail.template
    domain="[('model', '=', model), '|', ('user_id','=', False), ('user_id', '=', uid)]" args: 'mail.template', 'Use template'
  • use_exclusion_list Boolean
    default=True args: 'Check Exclusion List'
Public methods (5)
  • action_send_mail(self)
    Used for action button that do not accept arguments.
  • cancel_save_template(self)
    Restore old subject when canceling the 'save as template' action as it was erased to let user give a more custom input.
  • create_mail_template(self)
    creates a mail template with the current mail composer's fields
  • default_get(self, fields_list)
    @api.model
    Handle composition mode and contextual computation, until moving to computed fields. Support active_model / active_id(s) as valid default values, as this comes from standard web client usage. Note that supporting active_ids through composer is still done, as we may have to give a huge list of IDs that won't fit into res_ids field.
  • open_template_creation_wizard(self)
    hit save as template button: opens a wizard that prompts for the template's subject. `create_mail_template` is called when saving the new wizard.

New fields (7)
  • body Html
    compute='_compute_body' compute_sudo=False readonly=False render_engine='qweb' render_options={'post_process': True} sanitize=False store=True args: 'Contents'
  • body_has_template_value Boolean
    compute='_compute_body_has_template_value' args: 'Body content is the same as the template'
  • can_edit_body Boolean
    compute='_compute_can_edit_body' args: 'Can Edit Body'
  • is_mail_template_editor Boolean
    compute='_compute_is_mail_template_editor' args: 'Is Editor'
  • lang Char
    compute='_compute_lang' compute_sudo=False precompute=True readonly=False store=True
  • subject Char
    compute='_compute_subject' compute_sudo=False readonly=False store=True args: 'Subject'
  • template_id Many2one → mail.template
    domain="[('model', '=', render_model)]" args: 'mail.template', 'Mail Template'
Public methods (0)

No public methods.

New fields (7)
  • email Char
    related='partner_id.email' args: 'Email'
  • is_active Boolean
    related='partner_id.active' args: 'Is Active'
  • name Char
    related='partner_id.name' args: 'Name'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' required=True string='Related Partner' args: 'res.partner'
  • res_id Many2oneReference
    help='Id of the followed resource' index=True model_field='res_model' args: 'Related Document ID'
  • res_model Char
    index=True required=True args: 'Related Document Model Name'
  • subtype_ids Many2many → mail.message.subtype
    help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall." string='Subtype' args: 'mail.message.subtype'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (2)
  • email Char
    required=True args: 'Email Address'
  • email_normalized Char
    compute='_compute_email_normalized' index=True store=True string='Normalized Email'
Public methods (1)
  • get_empty_list_help(self, help_message)
    @api.model

New fields (7)
  • access_token Char
    copy=False default=<expr> groups='base.group_system' readonly=True required=True string='Access Token'
  • channel_ids Many2many → discuss.channel
    column1='guest_id' column2='channel_id' comodel_name='discuss.channel' copy=False relation='discuss_channel_member' string='Channels'
  • country_id Many2one → res.country
    comodel_name='res.country' string='Country'
  • im_status Char
    compute='_compute_im_status' args: 'IM Status'
  • lang Selection
    selection=_lang_get string='Language'
  • name Char
    required=True string='Name'
  • timezone Selection
    selection=_tz_get string='Timezone'
Public methods (0)

No public methods.

New fields (4)
  • credential Char
  • server_type Selection
    default='stun' required=True string='Type' args: [('stun', 'stun:'), ('turn', 'turn:')]
  • uri Char
    required=True args: 'URI'
  • username Char
Public methods (0)

No public methods.

New fields (10)
  • create_date Datetime
    index=True
  • image_mimetype Char
    args: 'Image MIME type'
  • message_id Many2one → mail.message
    index=True ondelete='cascade' required=True string='Message' args: 'mail.message'
  • og_description Text
    args: 'Description'
  • og_image Char
    args: 'Image'
  • og_mimetype Char
    args: 'MIME type'
  • og_site_name Char
    args: 'Site name'
  • og_title Char
    args: 'Title'
  • og_type Char
    args: 'Type'
  • source_url Char
    required=True args: 'URL'
Public methods (0)

No public methods.

New fields (19)
  • auto_delete Boolean
    help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_content Html
    compute='_compute_body_content' sanitize=True search='_search_body_content' args: 'Rich-text Contents'
  • body_html Text
    help='Rich-text/HTML message' args: 'Text Contents'
  • email_cc Char
    help='Carbon copy message recipients' args: 'Cc'
  • email_to Text
    help='Message recipients (emails)' args: 'To'
  • failure_reason Text
    copy=False help='Failure reason. This is usually the exception thrown by the email server, stored to ease the debugging of mailing issues.' readonly=True args: 'Failure Reason'
  • failure_type Selection
    selection=[('unknown', 'Unknown error'), ('mail_email_invalid', 'Invalid email address'), ('mail_email_missing', 'Missing email'), ('mail_from_invalid', 'Invalid from address'), ('mail_from_missing', 'Missing from address'), ('mail_smtp', 'Connection failed (outgoing mail server problem)'), ('mail_bl', 'Blacklisted Address'), ('mail_optout', 'Opted Out'), ('mail_dup', 'Duplicated Email')] string='Failure type'
  • fetchmail_server_id Many2one → fetchmail.server
    readonly=True args: 'fetchmail.server', 'Inbound Mail Server'
  • headers Text
    copy=False args: 'Headers'
  • is_notification Boolean
    help='Mail has been created to notify people of an existing mail.message' args: 'Notification Email'
  • mail_message_id Many2one → mail.message
    auto_join=True index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • mail_message_id_int Integer
    compute='_compute_mail_message_id_int' compute_sudo=True
  • message_type Selection
    default='email_outgoing' inherited=True related='mail_message_id.message_type'
  • recipient_ids Many2many → res.partner
    context={'active_test': False} string='To (Partners)' args: 'res.partner'
  • references Text
    help='Message references, such as identifiers of previous messages' readonly=True args: 'References'
  • restricted_attachment_count Integer
    compute='_compute_restricted_attachments' args: 'Restricted attachments'
  • scheduled_date Datetime
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. Unless a timezone is specified, it is considered as being in UTC timezone.' args: 'Scheduled Send Date'
  • state Selection
    copy=False default='outgoing' readonly=True args: [('outgoing', 'Outgoing'), ('sent', 'Sent'), ('received', 'Received'), ('exception', 'Delivery Failed'), ('cancel', 'Cancelled')], 'Status'
  • unrestricted_attachment_ids Many2many → ir.attachment
    compute='_compute_restricted_attachments' inverse='_inverse_unrestricted_attachment_ids' string='Unrestricted Attachments' args: 'ir.attachment'
Public methods (11)
  • action_open_document(self)
    Opens the related record based on the model and ID
  • action_retry(self)
  • cancel(self)
  • create(self, values_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • fields_get(self, *args, **kwargs)
    @api.model
  • mark_outgoing(self)
  • process_email_queue(self, ids=None)
    @api.model
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! A maximum of 10K MailMail (configurable using 'mail.mail.queue.batch.size' optional ICP) are fetched in order to keep time under control. :param list ids: optional list of emails ids to send. If given only scheduled and outgoing emails within this ids list are sent; :param dict context: if a 'filters' key is present in context, this value will be used as an additional filter to further restrict the outgoing messages to send (by default all 'outgoing' 'scheduled' messages are sent).
  • send(self, auto_commit=False, raise_exception=False)
    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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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
  • unlink(self)
  • write(self, vals)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (40)
  • attachment_ids Many2many → ir.attachment
    string='Attachments' args: 'ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id'
  • author_avatar Binary
    depends=['author_id'] readonly=False related='author_id.avatar_128' args: "Author's avatar"
  • author_guest_id Many2one → mail.guest
    comodel_name='mail.guest' string='Guest'
  • author_id Many2one → res.partner
    help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True ondelete='set null' args: 'res.partner', 'Author'
  • body Html
    default='' sanitize_style=True args: 'Contents'
  • child_ids One2many → mail.message
    args: 'mail.message', 'parent_id', 'Child Messages'
  • date Datetime
    default=fields.Datetime.now args: 'Date'
  • description Char
    compute='_compute_description' help='Message description: either the subject, or the beginning of the body' args: 'Short description'
  • email_add_signature Boolean
    default=True
  • email_from Char
    help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • email_layout_xmlid Char
    copy=False args: 'Layout'
  • has_error Boolean
    compute='_compute_has_error' search='_search_has_error' args: 'Has error'
  • is_current_user_or_guest_author Boolean
    compute='_compute_is_current_user_or_guest_author'
  • is_internal Boolean
    help='Hide to public / portal users, independently from subtype configuration.' args: 'Employee Only'
  • link_preview_ids One2many → mail.link.preview
    groups='base.group_erp_manager' string='Link Previews' args: 'mail.link.preview', 'message_id'
  • mail_activity_type_id Many2one → mail.activity.type
    index='btree_not_null' ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_ids One2many → mail.mail
    groups='base.group_system' string='Mails' args: 'mail.mail', 'mail_message_id'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_id Char
    copy=False help='Message unique identifier' index='btree' readonly=True args: 'Message-Id'
  • message_type Selection
    default='comment' help="Used to categorize message generator\n'email': generated by an incoming email e.g. mailgateway\n'comment': generated by user input e.g. through discuss or composer\n'email_outgoing': generated by a mailing\n'notification': generated by system e.g. tracking messages\n'auto_comment': generated by automated notification mechanism e.g. acknowledgment\n'user_notification': generated for a specific recipient" required=True args: [('email', 'Incoming Email'), ('comment', 'Comment'), ('email_outgoing', 'Outgoing Email'), ('notification', 'System notification'), ('auto_comment', 'Automated Targeted Notification'), ('user_notification', 'User Specific Notification')], 'Type'
  • model Char
    args: 'Related Document Model'
  • needaction Boolean
    compute='_compute_needaction' search='_search_needaction' args: 'Need Action'
  • notification_ids One2many → mail.notification
    auto_join=True copy=False depends=['notified_partner_ids'] args: 'mail.notification', 'mail_message_id', 'Notifications'
  • notified_partner_ids Many2many → res.partner
    context={'active_test': False} copy=False depends=['notification_ids'] string='Partners with Need Action' args: 'res.partner', 'mail_notification'
  • parent_id Many2one → mail.message
    index='btree_not_null' ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    context={'active_test': False} string='Recipients' args: 'res.partner'
  • pinned_at Datetime
    help='Datetime at which the message has been pinned' args: 'Pinned'
  • preview Char
    compute='_compute_preview' help='The text-only beginning of the body used as email preview.' args: 'Preview'
  • reaction_ids One2many → mail.message.reaction
    groups='base.group_system' string='Reactions' args: 'mail.message.reaction', 'message_id'
  • record_alias_domain_id Many2one → mail.alias.domain
    ondelete='set null' args: 'mail.alias.domain', 'Alias Domain'
  • record_company_id Many2one → res.company
    ondelete='set null' args: 'res.company', 'Company'
  • record_name Char
    args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • reply_to_force_new Boolean
    help='If true, answers do not go in the original document discussion thread. Instead, it will check for the reply_to in tracking message-id and redirected accordingly. This has an impact on the generated message-id.' args: 'No threading for answers'
  • res_id Many2oneReference
    model_field='model' args: 'Related Document ID'
  • starred Boolean
    compute='_compute_starred' compute_sudo=False help='Current user has a starred notification linked to this message' search='_search_starred' args: 'Starred'
  • starred_partner_ids Many2many → res.partner
    string='Favorited By' args: 'res.partner', 'mail_message_res_partner_starred_rel'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • tracking_value_ids One2many → mail.tracking.value
    groups='base.group_system' help='Tracked values are stored in a separate model. This field allow to reconstruct the tracking and to generate statistics on the model.' string='Tracking values' args: 'mail.tracking.value', 'mail_message_id'
Public methods (17)
  • action_open_document(self)
    Opens the related record based on the model and ID
  • check_access_rule(self, operation)
    Access rules of mail.message: - read: if - author_id == pid, uid is the author OR - create_uid == uid, uid is the creator OR - uid is in the recipients (partner_ids) OR - uid has been notified (needaction) OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id (private message) OR - pid in message_follower_ids if model, res_id OR - uid can read the parent OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid is in the recipients (partner_ids) OR - uid has write or create access on the related document if model, res_id - otherwise: raise - unlink: if - uid has write or create access on the related document - otherwise: raise Specific case: non employee users cannot see internal messages (aka logs): 'is_internal' flag on message, 'internal' flag on subtype.
  • copy_data(self, default=None)
    Make is symmetric to read, to avoid spurious issues with recordsets differences.
  • create(self, values_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • export_data(self, fields_to_export)
  • fetch(self, field_names)
  • init(self)
  • is_thread_message(self, vals=None)
  • mark_all_as_read(self, domain=None)
    @api.model
  • message_format(self, format_reply=True, msg_vals=None)
    Get the message values in the format for web client. Since message values can be broadcasted, computed fields MUST NOT BE READ and broadcasted. :param msg_vals: dictionary of values used to create the message. If given it may be used to access values related to ``message`` without accessing it directly. It lessens query count in some optimized use cases by avoiding access message content in db; :returns list(dict). Example : { 'body': HTML content of the message 'model': u'res.partner', 'record_name': u'Agrolait', 'attachments': [ { 'file_type_icon': u'webimage', 'id': 45, 'name': u'sample.png', 'filename': u'sample.png' } ], 'needaction_partner_ids': [], # list of partner ids 'res_id': 7, 'trackingValues': [ { 'changedField': "Customer", 'id': 2965, 'fieldName': 'partner_id', 'fieldType': 'char', 'newValue': { 'currencyId': "", 'value': "Axelor", ], 'oldValue': { 'currencyId': "", 'value': "", ], } ], 'author_id': (3, u'Administrator'), 'email_from': 'sacha@pokemon.com' # email address or False 'subtype_id': (1, u'Discussions'), 'date': '2015-06-30 08:22:33', 'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner convert_to_read 'message_type': u'comment', 'id': 59, 'subject': False 'is_note': True # only if the message is a note (subtype == note) 'is_discussion': False # only if the message is a discussion (subtype == discussion) 'parentMessage': {...}, # formatted message that this message is a reply to. Only present if format_reply is True }
  • read(self, fields=None, load='_classic_read')
    Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_done(self)
    Remove the needaction from messages for the current partner.
  • toggle_message_starred(self)
    Toggle messages as (un)starred. Technically, the notifications related to uid are set to (un)starred.
  • unlink(self)
  • unstar_all(self)
    @api.model
    Unstar messages for the current partner.
  • write(self, vals)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (4)
  • content Char
    readonly=True required=True string='Content'
  • guest_id Many2one → mail.guest
    comodel_name='mail.guest' ondelete='cascade' readonly=True string='Reacting Guest'
  • message_id Many2one → mail.message
    comodel_name='mail.message' ondelete='cascade' readonly=True required=True string='Message'
  • partner_id Many2one → res.partner
    comodel_name='res.partner' ondelete='cascade' readonly=True string='Reacting Partner'
Public methods (1)
  • init(self)

New fields (3)
  • mail_message_id Many2one → mail.message
    ondelete='cascade' required=True string='Message' args: 'mail.message'
  • notification_parameters Text
    args: 'Notification Parameter'
  • scheduled_datetime Datetime
    help='Datetime at which notification should be sent.' required=True args: 'Scheduled Send Date'
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • force_send(self)
    Launch notification process independently from the expected date.

New fields (10)
  • default Boolean
    default=True help='Activated by default when subscribing.' args: 'Default'
  • description Text
    help='Description that will be added in the message posted for this subtype. If void, the name will be added instead.' prefetch=True translate=True args: 'Description'
  • hidden Boolean
    help='Hide the subtype in the follower options' args: 'Hidden'
  • internal Boolean
    help='Messages with internal subtypes will be visible only by employees, aka members of base_user group' args: 'Internal Only'
  • name Char
    help='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.' required=True translate=True args: 'Message Type'
  • parent_id Many2one → mail.message.subtype
    help='Parent subtype, used for automatic subscription. This field is not correctly named. For example on a project, the parent_id of project subtypes refers to task-related subtypes.' ondelete='set null' string='Parent' args: 'mail.message.subtype'
  • relation_field Char
    help='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).' args: 'Relation field'
  • res_model Char
    help='Model the subtype applies to. If False, this subtype applies to all models.' args: 'Model'
  • sequence Integer
    default=1 help='Used to order subtypes.' args: 'Sequence'
  • track_recipients Boolean
    help='Whether to display all the recipients or only the important ones.' args: 'Track Recipients'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • default_subtypes(self, model_name)
    @api.model
    Retrieve the default subtypes (all, internal, external) for the given model.
  • unlink(self)
  • write(self, vals)

New fields (5)
  • body Html
    help='String received from the translation request.' required=True sanitize_style=True args: 'Translation Body'
  • create_date Datetime
    index=True
  • message_id Many2one → mail.message
    ondelete='cascade' required=True args: 'mail.message', 'Message'
  • source_lang Char
    help='Result of the language detection based on its content.' required=True args: 'Source Language'
  • target_lang Char
    help='Shortened language code used as the target for the translation request.' required=True args: 'Target Language'
Public methods (1)
  • init(self)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (10)
  • author_id Many2one → res.partner
    ondelete='set null' args: 'res.partner', 'Author'
  • failure_reason Text
    copy=False args: 'Failure reason'
  • failure_type Selection
    selection=[('unknown', 'Unknown error'), ('mail_bounce', 'Bounce'), ('mail_email_invalid', 'Invalid email address'), ('mail_email_missing', 'Missing email address'), ('mail_from_invalid', 'Invalid from address'), ('mail_from_missing', 'Missing from address'), ('mail_smtp', 'Connection failed (outgoing mail server problem)')] string='Failure type'
  • is_read Boolean
    index=True args: 'Is Read'
  • mail_mail_id Many2one → mail.mail
    help='Optional mail_mail ID. Used mainly to optimize searches.' index=True args: 'mail.mail', 'Mail'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification_status Selection
    default='ready' index=True string='Status' args: [('ready', 'Ready to Send'), ('process', 'Processing'), ('pending', 'Sent'), ('sent', 'Delivered'), ('bounce', 'Bounced'), ('exception', 'Exception'), ('canceled', 'Canceled')]
  • notification_type Selection
    default='inbox' index=True required=True string='Notification Type' args: [('inbox', 'Inbox'), ('email', 'Email')]
  • read_date Datetime
    copy=False args: 'Read Date'
  • res_partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner', 'Recipient'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • format_failure_reason(self)
  • init(self)
  • write(self, vals)

New fields (2)
  • payload Text
  • user_device Many2one → mail.partner.device
    ondelete='cascade' required=True string='devices' args: 'mail.partner.device'
Public methods (0)

No public methods.

New fields (4)
  • endpoint Char
    required=True string='Browser endpoint'
  • expiration_time Datetime
    string='Expiration Token Date'
  • keys Char
    help="It's refer to browser keys used by the notification: \n- p256dh: It's the subscription public key generated by the browser. The browser will \n keep the private key secret and use it for decrypting the payload\n- auth: The auth value should be treated as a secret and not shared outside of Odoo" required=True string='Browser keys'
  • partner_id Many2one → res.partner
    default=<expr> index=True required=True string='Partner' args: 'res.partner'
Public methods (3)
  • get_web_push_vapid_public_key(self)
    @api.model
  • register_devices(self, **kw)
    @api.model
  • unregister_devices(self, **kw)
    @api.model

New fields (2)
  • lang Char
    help='Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. {{ object.partner_id.lang }}.' args: 'Language'
  • render_model Char
    compute='_compute_render_model' store=False args: 'Rendering Model'
Public methods (2)
  • create(self, values_list)
    @api.model_create_multi
  • write(self, vals)

New fields (6)
  • can_cancel Boolean
    compute='_compute_can_cancel'
  • can_resend Boolean
    compute='_compute_can_resend'
  • mail_message_id Many2one → mail.message
    readonly=True args: 'mail.message', 'Message'
  • notification_ids Many2many → mail.notification
    readonly=True string='Notifications' args: 'mail.notification'
  • partner_ids One2many → mail.resend.partner
    string='Recipients' args: 'mail.resend.partner', 'resend_wizard_id'
  • partner_readonly Boolean
    compute='_compute_partner_readonly'
Public methods (3)
  • cancel_mail_action(self)
  • default_get(self, fields)
    @api.model
  • resend_mail_action(self)
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (9)
  • email Char
    readonly=False related='partner_id.email' related_sudo=False string='Email Address'
  • failure_reason Text
    related='notification_id.failure_reason' args: 'Failure Reason'
  • message Char
    string='Error message'
  • name Char
    readonly=False related='partner_id.name' related_sudo=False string='Recipient Name'
  • notification_id Many2one → mail.notification
    ondelete='cascade' required=True string='Notification' args: 'mail.notification'
  • partner_id Many2one → res.partner
    related='notification_id.res_partner_id' string='Partner' args: 'res.partner'
  • partner_readonly Boolean
    related='resend_wizard_id.partner_readonly' args: 'Partner Readonly'
  • resend Boolean
    default=True string='Try Again'
  • resend_wizard_id Many2one → mail.resend.message
    string='Resend wizard' args: 'mail.resend.message'
Public methods (3)
  • action_open_record(self)
  • action_open_resend_partner(self)
  • action_resend(self)

New fields (4)
  • description Char
    args: 'Description'
  • last_used Datetime
    help='Last time this shortcode was used' args: 'Last Used'
  • source Char
    help="Shortcut that will automatically be substituted with longer content in your messages. Type ':' followed by the name of your shortcut (e.g. :hello) to use in your messages." index='trigram' required=True args: 'Shortcut'
  • substitution Text
    help='Content that will automatically replace the shortcut of your choosing. This content can still be adapted before sending your message.' required=True args: 'Substitution'
Public methods (0)

No public methods.

New fields (24)
  • active Boolean
    default=True
  • attachment_ids Many2many → ir.attachment
    help='You may attach files to this template, to be added to all emails created from this template' args: 'ir.attachment', 'email_template_attachment_rel', 'email_template_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    default=True help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_html Html
    prefetch=True render_engine='qweb' render_options={'post_process': True} sanitize=False translate=True args: 'Body'
  • can_write Boolean
    compute='_compute_can_write' help='The current user can edit the template.'
  • description Text
    help="This field is used for internal description of the template's usage." translate=True args: 'Template description'
  • email_cc Char
    help='Carbon copy recipients (placeholders may be used here)' args: 'Cc'
  • email_from Char
    help="Sender address (placeholders may be used here). If not set, the default value will be the author's email alias if configured, or email address." args: 'From'
  • email_layout_xmlid Char
    copy=False args: 'Email Notification Layout'
  • email_to Char
    help='Comma-separated recipient addresses (placeholders may be used here)' args: 'To (Emails)'
  • is_template_editor Boolean
    compute='_compute_is_template_editor'
  • mail_server_id Many2one → ir.mail_server
    help='Optional preferred server for outgoing mails. If not set, the highest priority one will be used.' readonly=False args: 'ir.mail_server', 'Outgoing Mail Server'
  • model Char
    index=True readonly=True related='model_id.model' store=True args: 'Related Document Model'
  • model_id Many2one → ir.model
    ondelete='cascade' args: 'ir.model', 'Applies to'
  • name Char
    translate=True args: 'Name'
  • partner_to Char
    help='Comma-separated ids of recipient partners (placeholders may be used here)' args: 'To (Partners)'
  • ref_ir_act_window Many2one → ir.actions.act_window
    copy=False help='Sidebar action to make this template available on records of the related document model' readonly=True args: 'ir.actions.act_window', 'Sidebar action'
  • reply_to Char
    help='Email address to which replies will be redirected when sending emails in mass; only used when the reply is not logged in the original discussion thread.' args: 'Reply To'
  • report_template_ids Many2many → ir.actions.report
    column1='mail_template_id' column2='ir_actions_report_id' domain="[('model', '=', model)]" relation='mail_template_ir_actions_report_rel' string='Dynamic Reports' args: 'ir.actions.report'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. You can use dynamic expression.' args: 'Scheduled Date'
  • subject Char
    help='Subject (placeholders may be used here)' prefetch=True translate=True args: 'Subject'
  • template_category Selection
    compute='_compute_template_category' search='_search_template_category' args: [('base_template', 'Base Template'), ('hidden_template', 'Hidden Template'), ('custom_template', 'Custom Template')]
  • use_default_to Boolean
    help='Default recipients of the record:\n- partner (using id on a partner or the partner_id field) OR\n- email (using email_from or email field)' args: 'Default recipients'
  • user_id Many2one → res.users
    domain="[('share', '=', False)]" help='The template belongs to this user' string='User' args: 'res.users'
Public methods (11)
  • cancel_unlink(self)
  • copy(self, default=None)
    @api.returns('self', <expr>)
  • create(self, vals_list)
    @api.model_create_multi
  • create_action(self)
  • default_get(self, fields)
    @api.model
  • open_delete_confirmation_modal(self)
  • send_mail(self, res_id, force_send=False, raise_exception=False, email_values=None, email_layout_xmlid=False)
    Generates a new mail.mail. Template is rendered on record given by res_id and model coming from template. :param int res_id: id of the record to render the template :param bool force_send: send email immediately; otherwise use the mail queue (recommended); :param dict email_values: update generated mail with those values to further customize the mail; :param str email_layout_xmlid: optional notification layout to encapsulate the generated email; :returns: id of the mail.mail that was created
  • send_mail_batch(self, res_ids, force_send=False, raise_exception=False, email_values=None, email_layout_xmlid=False)
    @api.returns('self', <expr>)
    Generates new mail.mails. Batch version of 'send_mail'.' :param list res_ids: IDs of modelrecords on which template will be rendered :returns: newly created mail.mail
  • unlink(self)
  • unlink_action(self)
  • write(self, vals)

New fields (15)
  • attachment_ids Many2many → ir.attachment
    compute='_compute_mail_template_fields' args: 'ir.attachment', 'Attachments'
  • body_html Html
    compute='_compute_mail_template_fields' sanitize=False args: 'Body'
  • email_cc Char
    compute='_compute_mail_template_fields' help='Carbon copy recipients' args: 'Cc'
  • email_from Char
    compute='_compute_mail_template_fields' help='Sender address' args: 'From'
  • email_to Char
    compute='_compute_mail_template_fields' help='Comma-separated recipient addresses' args: 'To'
  • error_msg Char
    compute='_compute_mail_template_fields' args: 'Error Message'
  • lang Selection
    string='Template Preview Language' args: _selection_languages
  • mail_template_id Many2one → mail.template
    required=True string='Related Mail Template' args: 'mail.template'
  • model_id Many2one → ir.model
    related='mail_template_id.model_id' string='Targeted model' args: 'ir.model'
  • no_record Boolean
    compute='_compute_no_record' args: 'No Record'
  • partner_ids Many2many → res.partner
    compute='_compute_mail_template_fields' string='Recipients' args: 'res.partner'
  • reply_to Char
    compute='_compute_mail_template_fields' help='Preferred response address' args: 'Reply-To'
  • resource_ref Reference
    compute='_compute_resource_ref' compute_sudo=False readonly=False selection='_selection_target_model' store=True string='Record'
  • scheduled_date Char
    compute='_compute_mail_template_fields' help='The queue manager will send the email after the date' args: 'Scheduled Date'
  • subject Char
    compute='_compute_mail_template_fields' args: 'Subject'
Public methods (0)

No public methods.

New fields (1)
  • template_ids Many2many → mail.template
    args: 'mail.template'
Public methods (1)
  • reset_template(self)

New fields (10)
  • has_message Boolean
    compute='_compute_has_message' search='_search_has_message' store=False
  • message_attachment_count Integer
    compute='_compute_message_attachment_count' groups='base.group_user' args: 'Attachment Count'
  • message_follower_ids One2many → mail.followers
    groups='base.group_user' string='Followers' args: 'mail.followers', 'res_id'
  • message_has_error Boolean
    compute='_compute_message_has_error' help='If checked, some messages have a delivery error.' search='_search_message_has_error' args: 'Message Delivery error'
  • message_has_error_counter Integer
    compute='_compute_message_has_error' help='Number of messages with delivery error' args: 'Number of errors'
  • message_ids One2many → mail.message
    auto_join=True domain=<expr> string='Messages' args: 'mail.message', 'res_id'
  • message_is_follower Boolean
    compute='_compute_message_is_follower' search='_search_message_is_follower' args: 'Is Follower'
  • message_needaction Boolean
    compute='_compute_message_needaction' help='If checked, new messages require your attention.' search='_search_message_needaction' args: 'Action Needed'
  • message_needaction_counter Integer
    compute='_compute_message_needaction' help='Number of messages requiring action' args: 'Number of Actions'
  • message_partner_ids Many2many → res.partner
    comodel_name='res.partner' compute='_compute_message_partner_ids' groups='base.group_user' inverse='_inverse_message_partner_ids' search='_search_message_partner_ids' string='Followers (Partners)'
Public methods (19)
  • copy_data(self, default=None)
  • create(self, vals_list)
    @api.model_create_multi
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • get_empty_list_help(self, help_message)
    @api.model
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • message_change_thread(self, new_thread, new_parent_message=False)
    Transfer the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : my_lead.message_change_thread(my_project_task) will transfer the context of the thread of my_lead to my_project_task
  • message_get_followers(self, after=None, limit=100, filter_recipients=False)
  • message_mail_with_source(self, source_ref, render_values=None, message_type='notification', auto_commit=False, **kwargs)
    Send a mass mail on self, using an external source to render part of the content. It can be either a 'mail.template', either a view used to render the body using QWeb. SPOILER: this method currently calls a composer in a loop when using a view even if it is suboptimal. This is due to current composer implementation.. This will be cleaned soon to optimize mass mailing through mail.thread and lessen usage of composer itself. Default values * subtype_id: will be False, forced by composer in mass mode; :param record/str source_ref: reference to a source for rendering. It can be one of * a MailTemplate record. It will be used to render the various message values (body, subject, recipients, ...). It should behave like using the mail composer with a template; * an IrUIView record. It will be used to render the content (body). Other fields are left to the caller and/or default values computation; * an XmlID of a MailTemplate or of an IrUiView: see above; :param dict render_values: additional rendering values for qweb context; :param str message_type: one of 'notification' or 'comment'; :param bool auto_commit: auto commit after each batch of emails sent (see ``MailComposer._action_send_mail()``); :param dict kwargs: additional values given to the 'mail.compose.message' creation; :return: created mail.mail records, as sudo
  • message_new(self, msg_dict, custom_values=None)
    @api.model
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :rtype: int :return: the id of the newly created thread object
  • message_notify(self, *, body='', subject=False, author_id=None, email_from=None, model=False, res_id=False, subtype_xmlid=None, subtype_id=False, partner_ids=False, attachments=None, attachment_ids=None, **kwargs)
    @api.returns('mail.message', <expr>)
    Shortcut allowing to notify partners of messages that should not be displayed on a document. It pushes notifications on inbox or by email depending on the user configuration, like other notifications. Default values * subtype_id: if not given, fallback on ``note`` to be consistent with what message_post does; :param str body: body of the message, usually raw HTML that will be sanitized :param str subject: subject of the message :param int author_id: optional ID of partner record being the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param str email_from: from address of the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param str model: when invoked on MailThread directly, this method allows to push a notification on a given record (allows to notify on not thread-enabled records); :param int res_id: defines the record in combination with model; :param str subtype_xmlid: optional xml id of a mail.message.subtype to fetch, will force value of subtype_id; :param int subtype_id: subtype_id of the message, used mainly for followers notification mechanism; :param list(int) partner_ids: partner_ids to notify in addition to partners computed based on subtype / followers matching; :param list(tuple(str,str), tuple(str,str, dict)) attachments : list of attachment tuples in the form ``(name,content)`` or ``(name,content, info)`` where content is NOT base64 encoded; :param list attachment_ids: list of existing attachments to link to this message Should not be a list of commands. Attachment records attached to mail composer will be attached to the related document. Extra keyword arguments will be used either * as default column values for the new mail.message record if they match mail.message fields; * propagated to notification methods if not; :return: posted mail.message records
  • message_parse(self, message, save_original=False)
    @api.model
    Parses an email.message.Message representing an RFC-2822 email and returns a generic dict holding the message details. :param message: email to parse :type message: email.message.Message :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'email_from': from, 'to': to + delivered-to, 'cc': cc, 'recipients': delivered-to + to + cc + resent-to + resent-cc, 'partner_ids': partners found based on recipients emails, 'body': unified_body, 'references': references, 'in_reply_to': in-reply-to, 'is_bounce': True if it has been detected as a bounce email 'parent_id': parent mail.message based on in_reply_to or references, 'is_internal': answer to an internal message (note), 'date': date, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_post(self, *, body='', subject=None, message_type='notification', email_from=None, author_id=None, parent_id=False, subtype_xmlid=None, subtype_id=False, partner_ids=None, attachments=None, attachment_ids=None, body_is_html=False, **kwargs)
    @api.returns('mail.message', <expr>)
    Post a new message in an existing thread, returning the new mail.message. :param str|Markup body: body of the message, str content will be escaped, Markup for html body :param str subject: subject of the message :param str message_type: see mail_message.message_type field. Can be anything but user_notification, reserved for message_notify :param str email_from: from address of the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param int author_id: optional ID of partner record being the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param int parent_id: handle thread formation :param str subtype_xmlid: optional xml id of a mail.message.subtype to fetch, will force value of subtype_id; :param int subtype_id: subtype_id of the message, used mainly for followers notification mechanism; :param list(int) partner_ids: partner_ids to notify in addition to partners computed based on subtype / followers matching; :param list(tuple(str,str), tuple(str,str, dict)) attachments : list of attachment tuples in the form ``(name,content)`` or ``(name,content, info)`` where content is NOT base64 encoded; :param list attachment_ids: list of existing attachments to link to this message Should not be a list of commands. Attachment records attached to mail composer will be attached to the related document. :param bool body_is_html: indicates body should be threated as HTML even if str to be used only for RPC calls Extra keyword arguments will be used either * as default column values for the new mail.message record if they match mail.message fields; * propagated to notification methods if not; :return record: newly create mail.message
  • message_post_with_source(self, source_ref, render_values=None, message_type='notification', subtype_xmlid=False, subtype_id=False, **kwargs)
    Post a message on each record of self, using a view to render the body using QWeb. Default values * subtype_id: if not given, fallback on ``note`` to be consistent with what message_post does; :param record/str source_ref: reference to a source for rendering. It can be one of * a MailTemplate record. It will be used to render the various message values (body, subject, recipients, ...). It should behave like using the mail composer with a template; * an IrUIView record. It will be used to render the content (body). Other fields are left to the caller and/or default values computation; * an XmlID of a MailTemplate or of an IrUiView: see above :param dict render_values: additional rendering values for qweb context; :param str message_type: one of 'notification' or 'comment'; :param str subtype_xmlid: optional xml id of a mail.message.subtype to fetch, will force value of subtype_id; :param int subtype_id: subtype_id of the message, used mainly for followers notification mechanism; :param dict kwargs: additional values given to the 'mail.compose.message' creation; :return: posted mail.message records
  • message_process(self, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None)
    @api.model
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: string or xmlrpclib.Binary :type dict custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None)
    @api.model
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: * if the message replies to an existing thread by having a Message-Id that matches an existing mail_message.message_id, we take the original message model/thread_id pair and ignore custom_value as no creation will take place; * look for a mail.alias entry matching the message recipients and use the corresponding model, thread_id, custom_values and user_id. This could lead to a thread update or creation depending on the alias; * fallback on provided ``model``, ``thread_id`` and ``custom_values``; * raise an exception as no route has been found :param string message: an email.message instance :param dict message_dict: dictionary holding parsed message variables :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :type dict custom_values: optional dictionary of default field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of routes [(model, thread_id, custom_values, user_id, alias)] :raises: ValueError, TypeError
  • message_subscribe(self, partner_ids=None, subtype_ids=None)
    Main public API to add followers to a record set. Its main purpose is to perform access rights checks before calling ``_message_subscribe``.
  • message_unsubscribe(self, partner_ids=None)
    Remove partners from the records followers.
  • message_update(self, msg_dict, update_vals=None)
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • notify_cancel_by_type(self, notification_type)
    @api.model
    Subclasses must call this method and then * either call the standard implementation _notify_cancel_by_type_generic * or implements their own logic
  • unlink(self)
    Override unlink to delete messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • write(self, values)

New fields (3)
  • email_normalized Char
    compute='_compute_email_normalized' compute_sudo=True help='This field is used to search on email address as the primary email field can contain more than strictly an email address.' store=True string='Normalized Email'
  • is_blacklisted Boolean
    compute='_compute_is_blacklisted' compute_sudo=True groups='base.group_user' help="If the email address is on the blacklist, the contact won't receive mass mailing anymore, from any list" search='_search_is_blacklisted' store=False string='Blacklist'
  • message_bounce Integer
    default=0 help='Counter of the number of bounced emails for this contact' args: 'Bounce'
Public methods (1)
  • mail_action_blacklist_remove(self)

New fields (1)
  • email_cc Char
    args: 'Email cc'
Public methods (2)
  • message_new(self, msg_dict, custom_values=None)
    @api.model
  • message_update(self, msg_dict, update_vals=None)
    Adds cc email to self.email_cc while trying to keep email as raw as possible but unique

New fields (1)
  • message_main_attachment_id Many2one → ir.attachment
    comodel_name='ir.attachment' copy=False index='btree_not_null' string='Main Attachment'
Public methods (0)

No public methods.

New fields (1)
  • duration_tracking Json
    compute='_compute_duration_tracking' help='JSON that maps ids from a many2one field to seconds spent' string='Status time'
Public methods (0)

No public methods.

New fields (15)
  • currency_id Many2one → res.currency
    help='Used to display the currency when tracking monetary values' ondelete='set null' readonly=True args: 'res.currency', 'Currency'
  • field_groups Char
    compute='_compute_field_groups'
  • field_id Many2one → ir.model.fields
    index=True ondelete='set null' readonly=True required=False args: 'ir.model.fields'
  • field_info Json
    args: 'Removed field information'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message ID'
  • new_value_char Char
    readonly=True args: 'New Value Char'
  • new_value_datetime Datetime
    readonly=True args: 'New Value Datetime'
  • new_value_float Float
    readonly=True args: 'New Value Float'
  • new_value_integer Integer
    readonly=True args: 'New Value Integer'
  • new_value_text Text
    readonly=True args: 'New Value Text'
  • old_value_char Char
    readonly=True args: 'Old Value Char'
  • old_value_datetime Datetime
    readonly=True args: 'Old Value DateTime'
  • old_value_float Float
    readonly=True args: 'Old Value Float'
  • old_value_integer Integer
    readonly=True args: 'Old Value Integer'
  • old_value_text Text
    readonly=True args: 'Old Value Text'
Public methods (0)

No public methods.

New fields (5)
  • message Html
    args: 'Message'
  • notify Boolean
    default=True args: 'Send Notification'
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' required=True args: 'Related Document Model'
Public methods (2)
  • add_followers(self)
  • default_get(self, fields)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cron_mode=True)
    Send a message to Odoo's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (10)
  • alias_domain_id Many2one → mail.alias.domain
    default=<expr> string='Email Domain' args: 'mail.alias.domain'
  • alias_domain_name Char
    readonly=True related='alias_domain_id.name' store=True args: 'Alias Domain Name'
  • bounce_email Char
    compute='_compute_bounce' string='Bounce Email'
  • bounce_formatted Char
    compute='_compute_bounce' string='Bounce'
  • catchall_email Char
    compute='_compute_catchall' string='Catchall Email'
  • catchall_formatted Char
    compute='_compute_catchall' string='Catchall'
  • default_from_email Char
    readonly=True related='alias_domain_id.default_from_email' string='Default From'
  • email_formatted Char
    compute='_compute_email_formatted' compute_sudo=True string='Formatted Email'
  • email_primary_color Char
    compute='_compute_email_primary_color' readonly=False store=True args: 'Email Header Color'
  • email_secondary_color Char
    compute='_compute_email_secondary_color' readonly=False store=True args: 'Email Button Color'
Public methods (0)

No public methods.

New fields (17)
  • alias_domain_id Many2one → mail.alias.domain
    help='If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.' readonly=False related='company_id.alias_domain_id' args: 'mail.alias.domain', 'Alias Domain'
  • email_primary_color Char
    readonly=False related='company_id.email_primary_color'
  • email_secondary_color Char
    readonly=False related='company_id.email_secondary_color'
  • external_email_server_default Boolean
    config_parameter='base_setup.default_external_email_server' args: 'Use Custom Email Servers'
  • fail_counter Integer
    compute='_compute_fail_counter' args: 'Fail Mail'
  • google_translate_api_key Char
    config_parameter='mail.google_translate_api_key' help='A valid Google API key is required to enable message translation. https://cloud.google.com/translate/docs/setup' args: 'Message Translation API Key'
  • module_google_gmail Boolean
    args: 'Support Gmail Authentication'
  • module_microsoft_outlook Boolean
    args: 'Support Outlook Authentication'
  • restrict_template_rendering Boolean
    config_parameter='mail.restrict.template.rendering' help='Users will still be able to render templates.\nHowever only Mail Template Editors will be able to create new dynamic templates or modify existing ones.' args: 'Restrict Template Rendering'
  • sfu_server_key Char
    config_parameter='mail.sfu_server_key' help='Base64 encoded key' args: 'SFU Server key'
  • sfu_server_url Char
    config_parameter='mail.sfu_server_url' args: 'SFU Server URL'
  • tenor_api_key Char
    config_parameter='discuss.klipy_api_key' help='Add a Klipy GIF API key to enable GIFs support. https://docs.klipy.com/getting-started\nIf you were using a Tenor GIF API key (service shutdown on June 30, 2026), please replace it here with a Klipy GIF API key' args: 'Klipy API key'
  • tenor_content_filter Selection
    config_parameter='discuss.tenor_content_filter' default='low' help='https://docs.klipy.com/migrate-from-tenor/content-filtering' string='Klipy content filter' args: [('high', 'High'), ('medium', 'Medium'), ('low', 'Low'), ('off', 'Off')]
  • tenor_gif_limit Integer
    config_parameter='discuss.tenor_gif_limit' default=8 help='Fetch up to the specified number of GIF.' string='Klipy GIF limits'
  • twilio_account_sid Char
    config_parameter='mail.twilio_account_sid' args: 'Twilio Account SID'
  • twilio_account_token Char
    config_parameter='mail.twilio_account_token' args: 'Twilio Account Auth Token'
  • use_twilio_rtc_servers Boolean
    config_parameter='mail.use_twilio_rtc_servers' help='If you want to use twilio as TURN/STUN server provider' args: 'Use Twilio ICE servers'
Public methods (2)
  • open_email_layout(self)
  • open_mail_templates(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals)

New fields (8)
  • contact_address_inline Char
    compute='_compute_contact_address_inline' string='Inlined Complete Address' tracking=True
  • email Char
    tracking=1
  • name Char
    tracking=1
  • parent_id Many2one
    tracking=3
  • phone Char
    tracking=2
  • starred_message_ids Many2many → mail.message
    args: 'mail.message', 'mail_message_res_partner_starred_rel'
  • user_id Many2one
    tracking=4
  • vat Char
    tracking=5
Public methods (4)
  • find_or_create(self, email, assert_valid_email=False)
    @api.model@api.returns('self', <expr>)
    Override to use the email_normalized field.
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first partners' such that the name or email matches a 'search' string. Prioritize partners that are also (internal) users, and then extend the research to all partners. The return format is a list of partner data (as per returned by `mail_partner_format()`).
  • im_search(self, name, limit=20, excluded_ids=None)
    @api.model
    Search partner with a name and return its id, name and im_status. Note : the user must be logged :param name : the partner name to search :param limit : the limit of result to return :param excluded_ids : the ids of excluded partners
  • mail_partner_format(self, fields=None)

New fields (1)
  • channel_ids Many2many → discuss.channel
    copy=False string='Channels' args: 'discuss.channel', 'discuss_channel_member', 'partner_id', 'channel_id'
Public methods (2)
  • get_mention_suggestions_from_channel(self, channel_id, search, limit=8)
    @api.model
    Return 'limit'-first partners' such that the name or email matches a 'search' string. Prioritize partners that are also (internal) users, and then extend the research to all partners. Only members of the given channel are returned. The return format is a list of partner data (as per returned by `mail_partner_format()`).
  • search_for_channel_invite(self, search_term, channel_id=None, limit=30)
    @api.model
    Returns partners matching search_term that can be invited to a channel. If the channel_id is specified, only partners that can actually be invited to the channel are returned (not already members, and in accordance to the channel configuration).

New fields (1)
  • notification_type Selection
    compute='_compute_notification_type' default='email' help='Policy on how to handle Chatter notifications:\n- Handle by Emails: notifications are sent to your email address\n- Handle in Odoo: notifications appear in your Odoo Inbox' inverse='_inverse_notification_type' required=True store=True args: [('email', 'Handle by Emails'), ('inbox', 'Handle in Odoo')], 'Notification'
Public methods (6)
  • SELF_READABLE_FIELDS(self)
    @property
  • SELF_WRITEABLE_FIELDS(self)
    @property
  • action_archive(self)
  • create(self, vals_list)
    @api.model_create_multi
  • systray_get_activities(self)
    @api.model
  • write(self, vals)

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (6)
  • is_discuss_sidebar_category_channel_open Boolean
    default=True string='Is discuss sidebar category channel open?'
  • is_discuss_sidebar_category_chat_open Boolean
    default=True string='Is discuss sidebar category chat open?'
  • push_to_talk_key Char
    help='String formatted to represent a key with modifiers following this pattern: shift.ctrl.alt.key, e.g: truthy.1.true.b' string='Push-To-Talk shortcut'
  • use_push_to_talk Boolean
    default=False string='Use the push to talk feature'
  • voice_active_duration Integer
    default=200 help='How long the audio broadcast will remain active after passing the volume threshold' string='Duration of voice activity in ms'
  • volume_settings_ids One2many → res.users.settings.volumes
    string='Volumes of other partners' args: 'res.users.settings.volumes', 'user_setting_id'
Public methods (2)
  • set_res_users_settings(self, new_settings)
  • set_volume_setting(self, partner_id, volume, guest_id=None)
    Saves the volume of a guest or a partner. Either partner_id or guest_id must be specified. :param float volume: the selected volume between 0 and 1 :param int partner_id: :param int guest_id:

New fields (4)
  • guest_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner'
  • user_setting_id Many2one → res.users.settings
    index=True ondelete='cascade' required=True args: 'res.users.settings'
  • volume Float
    default=0.5 help='Ranges between 0.0 and 1.0, scale depends on the browser implementation'
Public methods (1)
  • init(self)

New fields (1)
  • template_fs Char
    copy=False help='File from where the template originates. Used to reset broken template.' string='Template Filename'
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • reset_template(self)
    Resets the Template with values given in source file. We ignore the case of template being overridden in another modules because it is extremely less likely to happen. This method also tries to reset the translation terms for the current user lang (all langs are not supported due to costly file operation).
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/16.0/mail
VERSION
VERSION 1.10
CATEGORY
CATEGORYProductivity/Discuss
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Martin Trigaux, Fabien Pinckaers, Olivier Dony, Thibault Delavallée, Denis Ledoux, Fabien Meghazi, Xavier ALT, David Monjoie, Xavier Morel, Goffin Simon, Mohammed Shekha, Nicolas Lempereur, Thibault Francois, Géry Debongnie, Aaron Bohy, Jeremy Kersten, GitHub, Lucas Perais (lpe), Damien Bouvy, Barad Mahendra, Yannick Tivisse, qsm-odoo, Dharmraj Jhala, Adrien Dieudonne, Christophe Monniez, Jorge Pinna Puissant, Denis Vermylen, Lucas Perais, Alexandre Kühn, Julien Castiaux, Aurélien Warnon, Xavier-Do, David Tran, Romeo Fragomeli, Victor Feyens, Adrien Dieudonné, Paul Morelle, Sébastien Theys, Florent de Labarre, Julien Mougenot, Vincent Schippefilt, Anh Thao Pham (pta), svs-odoo, Nikunj Ladava, Samuel Degueldre, Alvaro Fuentes, std-odoo, Achraf (abz), David Beguin, Ivan Yelizariev, Nasreddin Boulif (bon), Rémy Voet (ryv), Thanh Dodeur, Gorash, Mathieu Duckerts-Antoine, Pierre Paridans, Yenthe666, Hiral Bhavsar, abd-msyukyu-odoo, Jérôme Vanhaudenard, William Braeckman, bit-odoo, Romain Estievenart, Kevin Baptiste, Pierre Verkest, odoo, Xavier BOL (xbo), roen-odoo, Stanislas Sobieski, Hubert Van de Walle (huvw), Hardik Prajapati, Miquel Raïch, Laurent Desausoi (lade), sofiagvaladze, Julien Van Roy, Florian Damhaut, Merlin (megu), MerlinGuillaume, yhu-odoo, thcl-odoo, mafo-odoo, Didier (did), Krzysztof Magusiak, Audric Onockx (auon), Antoine Guenet, Florian Charlier, Patrick Hoste, anhe-odoo, Walid HANNICHE (waha), Yolann Sabaux, Abdelouahab (abla), Nicolas Bayet, Antoine Vandevenne (anv), Aurelien van Delft (avd), Mathieu Walravens, Achraf, Fabio Barbero, Julien Giannone, Renaud Thiry, Julien Banken, Ipsita Borisagar, Stanislas Gueniffey, niyasraphy, Iván Todorovich, bve-odoo, jorv, Habib (ayh), damr, Francois (fge), Thomas Lefebvre (thle), Archana Vaghasiya, Andro Gvivradze, Louis Wicket (wil), tsm-odoo, Victor Piryns (pivi), Shawcker, Julien (jula), Thomas Becquevort (thbe), miad-odoo, amdi-odoo, Tom De Caluwé, Simon Genin (ges), Pierre-Yves Dufays, Malay Khamar, Michele, Om Rabara, duongnguyen, Levi Siuzdak (sile), Maruan Aguerdouh (magm), Jinane Maksoud, Sébastien Geelen (sge), Bruno Boi, Antoine (ande), flvr-odoo, FrancoisGe, Michael (mcm), Rahul Prajapati, Chong Wang (cwg), Carlos Valverde, Odoo, Leloup Loïc (lole), bram1000, Brieuc-brd, jlzhou, Nguyễn Đại Dương, Leonardo Pavan Rocha, Mahdi Cheikh Rouhou (macr), Andrzej(pian), Zelong Lin, Walid (wasa), maad-odoo, stefanorigano (SRI), MAHAMADASIF ANSARI, Astik Singh, dane@odoo.com, Adam Heinz, Dang Van Loc, Mattis Megevand, Maryam Kia, jorv-odoo, Matthieu Stockbauer, yosa-odoo, Adrien Minne (adrm), Sergey Shebanin, Julien Carion (juca), Tanguy Quéguineur, TSO, Alex Kühn, Krunal Trivedi, Martin Trigaux (mat), duongnguyen-viindoo, aath-odoo, xlu-odoo, Mathieu (mano), thle-odoo, Mathieu Coutant, Antoine (anso), sabr, umgu-odoo, Viktors Lipskis (vili), Nemael, fdardenne, joda-odoo, Syed Nasir, Shyam Gohil, Sahil Patel, zel-odoo, John Kirkwood (kij)
WEBSITE
WEBSITEhttps://www.odoo.com/app/discuss
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:40:52
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web
    - bus
    - web_tour
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Chat, mail gateway and private channel.
=======================================

Communicate with your colleagues/customers/guest within Odoo.

Discuss/Chat
------------
User-friendly "Discuss" features that allows one 2 one or group communication
(text chat/voice call/video call), invite guests and share documents with
them, all real-time.

Mail gateway
------------
Sending information and documents made simplified. You can send emails
from Odoo itself, and that too with great possibilities. For example,
design a beautiful email template for the invoices, and use the same
for all your customers, no need to do the same exercise every time.

Chatter
-------
Do all the contextual conversation on a document. For example on an
applicant, directly post an update to send email to the applicant,
schedule the next interview call, attach the contract, add HR officer
to the follower list to notify them for important events(with help of
subtypes),...


Retrieve incoming email on POP/IMAP servers.
============================================
Enter the parameters of your POP/IMAP account(s), and any incoming emails on
these accounts will be automatically downloaded into your Odoo system. All
POP3/IMAP-compatible servers are supported, included those that require an
encrypted SSL/TLS connection.
This can be used to easily create email-based workflows for many email-enabled Odoo documents, such as:
----------------------------------------------------------------------------------------------------------
    * CRM Leads/Opportunities
    * CRM Claims
    * Project Issues
    * Project Tasks
    * Human Resource Recruitment (Applicants)
Just install the relevant application, and you can assign any of these document
types (Leads, Project Issues) to your incoming email accounts. New emails will
automatically spawn new documents of the chosen type, so it's a snap to create a
mailbox-to-Odoo integration. Even better: these documents directly act as mini
conversations synchronized by email. You can reply from within Odoo, and the
answers will automatically be collected when they come back, and attached to the
same *conversation* document.
For more specific needs, you may also assign custom-defined actions
(technically: Server Actions) to be triggered for each incoming mail.
    

Code Analysis

Views touched (89)
XML IDNameModelTypeStatus
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
email_template_form email.template.form mail.template form New
email_template_tree email.template.tree mail.template tree New
field_form_view ir.model.fields field Inherits base.view_model_fields_form
mail.discuss_public_channel_template Discuss Public Channel Template ir.ui.view qweb New
mail.discuss_public_layout mail.discuss_public_layout ir.ui.view qweb New
mail_activity_type_view_form mail.activity.type.view.form mail.activity.type form New
mail_activity_type_view_search mail.activity.type.search mail.activity.type search New
mail_activity_type_view_tree mail.activity.type.view.tree mail.activity.type tree New
mail_activity_view_calendar mail.activity.view.calendar mail.activity calendar New
mail_activity_view_form mail.activity.view.form mail.activity field Inherits mail.mail_activity_view_form_popup
mail_activity_view_form_popup mail.activity.view.form.popup mail.activity form New
mail_activity_view_search mail.activity.view.search mail.activity search New
mail_activity_view_tree mail.activity.view.tree mail.activity tree New
mail_blacklist_remove_view_form mail.blacklist.remove.form mail.blacklist.remove form New
mail_blacklist_view_form mail.blacklist.view.form mail.blacklist form New
mail_blacklist_view_search mail.blacklist.view.search mail.blacklist search New
mail_blacklist_view_tree mail.blacklist.view.tree mail.blacklist tree New
mail_bounce_alias_security mail_bounce_alias_security ir.ui.view qweb New
mail_bounce_catchall mail_bounce_catchall ir.ui.view qweb New
mail_channel_member_view_form mail.channel.member.form mail.channel.member form New
mail_channel_member_view_tree mail.channel.member.tree mail.channel.member tree New
mail_channel_rtc_session_view_form mail.channel.rtc.session.form mail.channel.rtc.session form New
mail_channel_rtc_session_view_search mail.channel.rtc.session.search mail.channel.rtc.session search New
mail_channel_rtc_session_view_tree mail.channel.rtc.session.tree mail.channel.rtc.session tree New
mail_channel_view_form mail.channel.form mail.channel form New
mail_channel_view_kanban mail.channel.kanban mail.channel kanban New
mail_channel_view_search mail.channel.search mail.channel search New
mail_channel_view_tree mail.channel.tree mail.channel tree New
mail_gateway_allowed_view_search mail.gateway.allowed.view.search mail.gateway.allowed search New
mail_gateway_allowed_view_tree mail.gateway.allowed.view.tree mail.gateway.allowed tree New
mail_guest_view_tree mail.guest.tree mail.guest tree New
mail_link_preview_view_tree mail.link.preview.tree mail.link.preview tree New
mail_message_reaction_view_tree mail.message.reaction.tree mail.message.reaction tree New
mail_message_schedule_view_form mail.message.schedule.view.form mail.message.schedule form New
mail_message_schedule_view_search mail.message.schedule.view.search mail.message.schedule search New
mail_message_schedule_view_tree mail.message.schedule.view.tree mail.message.schedule tree New
mail_message_view_form mail.message.view.form mail.message form New
mail_notification_layout Mail: mail notification layout template ir.ui.view qweb New
mail_notification_layout_with_responsible_signature Mail: mail notification layout with responsible signature (user_id of the record) ir.ui.view qweb Inherits mail.mail_notification_layout
mail_notification_light mail_notification_light ir.ui.view qweb New
mail_notification_view_form mail.notification.view.form mail.notification form New
mail_notification_view_tree mail.notification.view.tree mail.notification tree New
mail_resend_message_view_form mail.resend.message.view.form mail.resend.message form New
mail_shortcode_view_form mail.shortcode.form mail.shortcode form New
mail_shortcode_view_tree mail.shortcode.tree mail.shortcode tree New
mail_template_preview_view_form mail.template.preview.view.form mail.template.preview form New
mail_template_reset_view_form mail.template.reset.view.form mail.template.reset form New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
message_activity_assigned message_activity_assigned ir.ui.view qweb New
message_activity_done message_activity_done ir.ui.view qweb New
message_notification_limit_email message_notification_limit_email ir.ui.view qweb New
message_origin_link message_origin_link ir.ui.view qweb New
message_user_assigned message_user_assigned ir.ui.view qweb New
model_form_view ir.model field Inherits base.view_model_form
model_search_view ir.model field Inherits base.view_model_search
notification_preview notification_preview ir.ui.view qweb New
res_config_settings_view_form res.config.settings.view.form.inherit.mail res.config.settings div Inherits base_setup.res_config_settings_view_form
res_partner_view_activity res.partner.activity res.partner activity New
res_partner_view_form_inherit_mail res.partner.view.form.inherit.mail res.partner xpath Inherits base.view_partner_form
res_partner_view_kanban_inherit_mail res.partner.view.kanban.inherit.mail res.partner field Inherits base.res_partner_kanban_view
res_partner_view_search_inherit_mail res.partner.view.search.inherit.mail res.partner filter Inherits base.view_res_partner_filter
res_partner_view_tree_inherit_mail res.partner.view.tree.inherit.mail res.partner xpath Inherits base.view_partner_tree
res_users_settings_view_form res.users.settings.form res.users.settings form New
res_users_settings_view_tree res.users.settings.tree res.users.settings tree New
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_email_server_form fetchmail.server.form fetchmail.server form New
view_email_server_search fetchmail.server.search fetchmail.server search New
view_email_server_tree fetchmail.server.list fetchmail.server tree New
view_email_template_search email.template.search mail.template search New
view_followers_tree mail.followers.tree mail.followers tree New
view_ice_server_form mail.ice.server.form mail.ice.server form New
view_ice_server_tree mail.ice.server.tree mail.ice.server tree New
view_mail_alias_form mail.alias.form mail.alias form New
view_mail_alias_search mail.alias.search mail.alias search New
view_mail_alias_tree mail.alias.tree mail.alias tree New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tracking_value_form mail.tracking.value.form mail.tracking.value form New
view_mail_tracking_value_tree mail.tracking.value.tree mail.tracking.value tree New
view_mail_tree mail.mail.tree mail.mail tree New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.tree mail.message.subtype tree New
view_message_tree mail.message.tree mail.message tree New
view_server_action_form_template ir.actions.server.form ir.actions.server xpath Inherits base.view_server_action_form
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (60)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (1)
  • guest_id Many2one → mail.guest
    ondelete='cascade' args: 'mail.guest', 'Guest'
Public methods (1)
  • init(self)

New fields (18)
  • active Boolean
    default=True args: 'Active'
  • attach Boolean
    default=True help='Whether attachments should be downloaded. If not enabled, incoming emails will be stripped of any attachments before being processed' args: 'Keep Attachments'
  • configuration Text
    readonly=True args: 'Configuration'
  • date Datetime
    readonly=True string='Last Fetch Date'
  • is_ssl Boolean
    help='Connections are encrypted with SSL/TLS through a dedicated port (default: IMAPS=993, POP3S=995)' args: 'SSL/TLS'
  • message_ids One2many → mail.mail
    readonly=True string='Messages' args: 'mail.mail', 'fetchmail_server_id'
  • name Char
    required=True args: 'Name'
  • object_id Many2one → ir.model
    help='Process each incoming mail as part of a conversation corresponding to this document type. This will create new documents for new conversations, or attach follow-up emails to the existing conversations (documents).' string='Create a New Record' args: 'ir.model'
  • original Boolean
    help='Whether a full original copy of each email should be kept for reference and attached to each processed message. This will usually double the size of your message database.' args: 'Keep Original'
  • password Char
    readonly=True states={'draft': [('readonly', False)]}
  • port Integer
    readonly=True states={'draft': [('readonly', False)]}
  • priority Integer
    default=5 help='Defines the order of processing, lower values mean higher priority' readonly=True states={'draft': [('readonly', False)]} string='Server Priority'
  • script Char
    default='/mail/static/scripts/odoo-mailgate.py' readonly=True
  • server Char
    help='Hostname or IP of the mail server' readonly=True states={'draft': [('readonly', False)]} string='Server Name'
  • server_type Selection
    default='imap' index=True required=True string='Server Type' args: [('imap', 'IMAP Server'), ('pop', 'POP Server'), ('local', 'Local Server')]
  • server_type_info Text
    compute='_compute_server_type_info' args: 'Server Type Info'
  • state Selection
    copy=False default='draft' index=True readonly=True string='Status' args: [('draft', 'Not Confirmed'), ('done', 'Confirmed')]
  • user Char
    readonly=True states={'draft': [('readonly', False)]} string='Username'
Public methods (8)
  • button_confirm_login(self)
  • connect(self, allow_archived=False)
    :param bool allow_archived: by default (False), an exception is raised when calling this method on an archived record. It can be set to True for testing so that the exception is no longer raised.
  • create(self, vals_list)
    @api.model_create_multi
  • fetch_mail(self)
    WARNING: meant for cron usage only - will commit() after each email!
  • onchange_server_type(self)
    @api.onchange('server_type', 'is_ssl', 'object_id')
  • set_draft(self)
  • unlink(self)
  • write(self, values)

New fields (1)
  • view_mode Selection
    ondelete={'activity': 'cascade'} selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (13)
  • activity_date_deadline_range Integer
    compute='_compute_activity_info' readonly=False store=True string='Due Date In'
  • activity_date_deadline_range_type Selection
    compute='_compute_activity_info' default='days' readonly=False store=True string='Due type' args: [('days', 'Days'), ('weeks', 'Weeks'), ('months', 'Months')]
  • activity_note Html
    compute='_compute_activity_info' readonly=False store=True args: 'Note'
  • activity_summary Char
    compute='_compute_activity_info' readonly=False store=True args: 'Summary'
  • activity_type_id Many2one → mail.activity.type
    compute='_compute_activity_type_id' domain="['|', ('res_model', '=', False), ('res_model', '=', model_name)]" ondelete='restrict' readonly=False store=True string='Activity' args: 'mail.activity.type'
  • activity_user_field_name Char
    compute='_compute_activity_info' readonly=False store=True args: 'User field name'
  • activity_user_id Many2one → res.users
    compute='_compute_activity_info' readonly=False store=True string='Responsible' args: 'res.users'
  • activity_user_type Selection
    compute='_compute_activity_info' help="Use 'Specific User' to always assign the same user on the next activity. Use 'Generic User From Record' to specify the field name of the user to choose on the record." readonly=False store=True args: [('specific', 'Specific User'), ('generic', 'Generic User From Record')]
  • mail_post_autofollow Boolean
    compute='_compute_mail_post_autofollow' readonly=False store=True args: 'Subscribe Recipients'
  • mail_post_method Selection
    compute='_compute_mail_post_method' help='Choose method for email sending:\nEMail: send directly emails\nPost as Message: post on document and notify followers\nPost as Note: log a note on document' readonly=False selection=[('email', 'Email'), ('comment', 'Post as Message'), ('note', 'Post as Note')] store=True string='Send as'
  • partner_ids Many2many → res.partner
    compute='_compute_partner_ids' readonly=False store=True string='Add Followers' args: 'res.partner'
  • state Selection
    ondelete={'mail_post': 'cascade', 'followers': 'cascade', 'next_activity': 'cascade'} selection_add=[('mail_post', 'Send Email'), ('followers', 'Add Followers'), ('next_activity', 'Create Next Activity')]
  • template_id Many2one → mail.template
    compute='_compute_template_id' domain="[('model_id', '=', model_id)]" ondelete='set null' readonly=False store=True args: 'mail.template', 'Email Template'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • register_as_main_attachment(self, force=True)
    Registers this attachment as the main one of the model it is attached to.

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • set_param(self, key, value)
    @api.model
  • write(self, vals)

New fields (0)

No new fields.

Public methods (1)
  • session_info(self)

New fields (1)
  • mail_template_ids One2many → mail.template
    comodel_name='mail.template' inverse_name='mail_server_id' readonly=True string='Mail template using this mail server'
Public methods (0)

No public methods.

New fields (3)
  • is_mail_activity Boolean
    default=False string='Has Mail Activity'
  • is_mail_blacklist Boolean
    default=False string='Has Mail Blacklist'
  • is_mail_thread Boolean
    default=False string='Has Mail Thread'
Public methods (2)
  • unlink(self)
    Delete mail data (followers, messages, activities) associated with the models being deleted.
  • write(self, vals)

New fields (1)
  • tracking Integer
    help='If set every modification done to this field is tracked in the chatter. Value is used to order tracking values.' string='Enable Ordered Tracking'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (1)
  • type Selection
    selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (21)
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_decoration Selection
    readonly=True related='activity_type_id.decoration_type'
  • activity_type_id Many2one → mail.activity.type
    default=_default_activity_type domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" ondelete='restrict' string='Activity Type' args: 'mail.activity.type'
  • automated Boolean
    help='Indicates this activity has been created automatically and not by any user.' readonly=True args: 'Automated activity'
  • can_write Boolean
    compute='_compute_can_write'
  • chaining_type Selection
    readonly=True related='activity_type_id.chaining_type'
  • date_deadline Date
    default=fields.Date.context_today index=True required=True args: 'Due Date'
  • has_recommended_activities Boolean
    compute='_compute_has_recommended_activities' args: 'Next activities available'
  • icon Char
    readonly=True related='activity_type_id.icon' args: 'Icon'
  • mail_template_ids Many2many
    readonly=True related='activity_type_id.mail_template_ids'
  • note Html
    sanitize_style=True args: 'Note'
  • previous_activity_type_id Many2one → mail.activity.type
    readonly=True string='Previous Activity Type' args: 'mail.activity.type'
  • recommended_activity_type_id Many2one → mail.activity.type
    string='Recommended Activity Type' args: 'mail.activity.type'
  • request_partner_id Many2one → res.partner
    string='Requesting Partner' args: 'res.partner'
  • res_id Many2oneReference
    index=True model_field='res_model' string='Related Document ID'
  • res_model Char
    compute_sudo=True index=True readonly=True related='res_model_id.model' store=True args: 'Related Document Model'
  • res_model_id Many2one → ir.model
    index=True ondelete='cascade' required=True args: 'ir.model', 'Document Model'
  • res_name Char
    compute='_compute_res_name' compute_sudo=True readonly=True store=True args: 'Document Name'
  • state Selection
    compute='_compute_state' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')], 'State'
  • summary Char
    args: 'Summary'
  • user_id Many2one → res.users
    default=<expr> index=True required=True args: 'res.users', 'Assigned to'
Public methods (15)
  • action_close_dialog(self)
  • action_done(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_done_schedule_next(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_feedback(self, feedback=False, attachment_ids=None)
  • action_feedback_schedule_next(self, feedback=False, attachment_ids=None)
  • action_notify(self)
  • action_open_document(self)
    Opens the related record based on the model and ID
  • activity_format(self)
  • create(self, vals_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • get_activity_data(self, res_model, domain)
    @api.model
  • name_get(self)
  • read(self, fields=None, load='_classic_read')
    When reading specific fields, read calls _read that manually applies ir rules (_apply_ir_rules), instead of calling check_access_rule. Meaning that our custom rules enforcing from '_filter_access_rules' and '_filter_access_rules_python' are bypassed in that case. To make sure we apply our custom security rules, we force a call to 'check_access_rule'.
  • unlink(self)
  • write(self, values)

New fields (10)
  • activity_date_deadline Date
    compute='_compute_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_activity_date_deadline' store=False args: 'Next Activity Deadline'
  • activity_exception_decoration Selection
    compute='_compute_activity_exception_type' help='Type of the exception activity on record.' search='_search_activity_exception_decoration' args: [('warning', 'Alert'), ('danger', 'Error')]
  • activity_exception_icon Char
    compute='_compute_activity_exception_type' help='Icon to indicate an exception activity.' args: 'Icon'
  • activity_ids One2many → mail.activity
    auto_join=True groups='base.group_user' args: 'mail.activity', 'res_id', 'Activities'
  • activity_state Selection
    compute='_compute_activity_state' groups='base.group_user' help='Status based on activities\nOverdue: Due date is already passed\nToday: Activity date is today\nPlanned: Future activities.' search='_search_activity_state' string='Activity State' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')]
  • activity_summary Char
    groups='base.group_user' readonly=False related='activity_ids.summary' search='_search_activity_summary' args: 'Next Activity Summary'
  • activity_type_icon Char
    related='activity_ids.icon' args: 'Activity Type Icon'
  • activity_type_id Many2one → mail.activity.type
    groups='base.group_user' readonly=False related='activity_ids.activity_type_id' search='_search_activity_type_id' args: 'mail.activity.type', 'Next Activity Type'
  • activity_user_id Many2one → res.users
    groups='base.group_user' readonly=False related='activity_ids.user_id' search='_search_activity_user_id' args: 'res.users', 'Responsible User'
  • my_activity_date_deadline Date
    compute='_compute_my_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_my_activity_date_deadline' args: 'My Activity Deadline'
Public methods (9)
  • activity_feedback(self, act_type_xmlids, user_id=None, feedback=None, attachment_ids=None)
    Set activities as done, limiting to some activity types and optionally to a given user.
  • activity_reschedule(self, act_type_xmlids, user_id=None, date_deadline=None, new_user_id=None)
    Reschedule some automated activities. Activities to reschedule are selected based on type xml ids and optionally by user. Purpose is to be able to * update the deadline to date_deadline; * update the responsible to new_user_id;
  • activity_schedule(self, act_type_xmlid='', date_deadline=None, summary='', note='', **act_values)
    Schedule an activity on each record of the current record set. This method allow to provide as parameter act_type_xmlid. This is an xml_id of activity type instead of directly giving an activity_type_id. It is useful to avoid having various "env.ref" in the code and allow to let the mixin handle access rights. :param date_deadline: the day the activity must be scheduled on the timezone of the user must be considered to set the correct deadline
  • activity_search(self, act_type_xmlids='', user_id=None, additional_domain=None)
    Search automated activities on current record set, given a list of activity types xml IDs. It is useful when dealing with specific types involved in automatic activities management. :param act_type_xmlids: list of activity types xml IDs :param user_id: if set, restrict to activities of that user_id; :param additional_domain: if set, filter on that domain;
  • activity_send_mail(self, template_id)
    Automatically send an email based on the given mail.template, given its ID.
  • activity_unlink(self, act_type_xmlids, user_id=None)
    Unlink activities, limiting to some activity types and optionally to a given user.
  • toggle_active(self)
    Before archiving the record we should also remove its ongoing activities. Otherwise they stay in the systray and concerning archived records it makes no sense.
  • unlink(self)
    Override unlink to delete records activities through (res_model, res_id).
  • write(self, vals)

New fields (22)
  • active Boolean
    default=True
  • category Selection
    default='default' help='Actions may trigger specific behavior like opening calendar view or automatically mark as done when a document is uploaded' string='Action' args: [('default', 'None'), ('upload_file', 'Upload Document'), ('phonecall', 'Phonecall')]
  • chaining_type Selection
    default='suggest' required=True string='Chaining Type' args: [('suggest', 'Suggest Next Activity'), ('trigger', 'Trigger Next Activity')]
  • create_uid Many2one → res.users
    index=True args: 'res.users'
  • decoration_type Selection
    help='Change the background color of the related activities of this type.' string='Decoration Type' args: [('warning', 'Alert'), ('danger', 'Error')]
  • default_note Html
    string='Default Note' translate=True
  • default_user_id Many2one → res.users
    string='Default User' args: 'res.users'
  • delay_count Integer
    default=0 help='Number of days/week/month before executing the action. It allows to plan the action deadline.' args: 'Schedule'
  • delay_from Selection
    default='previous_activity' help='Type of delay' required=True string='Delay Type' args: [('current_date', 'after completion date'), ('previous_activity', 'after previous activity deadline')]
  • delay_label Char
    compute='_compute_delay_label'
  • delay_unit Selection
    default='days' help='Unit of delay' required=True string='Delay units' args: [('days', 'days'), ('weeks', 'weeks'), ('months', 'months')]
  • icon Char
    help='Font awesome icon e.g. fa-tasks' args: 'Icon'
  • initial_res_model Selection
    compute='_compute_initial_res_model' help='Technical field to keep track of the model at the start of editing to support UX related behaviour' selection=_get_model_selection store=False string='Initial model'
  • mail_template_ids Many2many → mail.template
    string='Email templates' args: 'mail.template'
  • name Char
    required=True translate=True args: 'Name'
  • previous_type_ids Many2many → mail.activity.type
    domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" string='Preceding Activities' args: 'mail.activity.type', 'mail_activity_rel', 'recommended_id', 'activity_id'
  • res_model Selection
    help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' selection=_get_model_selection string='Model'
  • res_model_change Boolean
    default=False store=False string='Model has change'
  • sequence Integer
    default=10 args: 'Sequence'
  • suggested_next_type_ids Many2many → mail.activity.type
    compute='_compute_suggested_next_type_ids' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" help='Suggest these activities once the current one is marked as done.' inverse='_inverse_suggested_next_type_ids' readonly=False store=True string='Suggest' args: 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id'
  • summary Char
    translate=True args: 'Default Summary'
  • triggered_next_type_id Many2one → mail.activity.type
    compute='_compute_triggered_next_type_id' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" help='Automatically schedule this activity once the current one is marked as done.' inverse='_inverse_triggered_next_type_id' ondelete='restrict' readonly=False store=True string='Trigger' args: 'mail.activity.type'
Public methods (0)

No public methods.

New fields (10)
  • alias_bounced_content Html
    help='If set, this content will automatically be sent out to unauthorized users instead of the default message.' translate=True args: 'Custom Bounced Message'
  • alias_contact Selection
    default='everyone' help='Policy to post a message on the document using the mailgateway.\n- everyone: everyone can post\n- partners: only authenticated partners\n- followers: only followers of the related document or members of following channels\n' required=True string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_defaults Text
    default='{}' help='A Python dictionary that will be evaluated to provide default values when creating new records for this alias.' required=True args: 'Default Values'
  • alias_domain Char
    compute='_compute_alias_domain' args: 'Alias domain'
  • alias_force_thread_id Integer
    help='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.' args: 'Record Thread ID'
  • alias_model_id Many2one → ir.model
    domain="[('field_id.name', '=', 'message_ids')]" help='The model (Odoo 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)' ondelete='cascade' required=True args: 'ir.model', 'Aliased Model'
  • alias_name Char
    copy=False help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>" args: 'Alias Name'
  • alias_parent_model_id Many2one → ir.model
    help='Parent model holding the alias. The model holding the alias reference is not necessarily the model given by alias_model_id (example: project (parent_model) and task (model))' args: 'ir.model', 'Parent Model'
  • alias_parent_thread_id Integer
    help='ID of the parent record holding the alias (example: project holding the task creation alias)' args: 'Parent Record Thread ID'
  • alias_user_id Many2one → res.users
    default=<expr> help='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.' args: 'res.users', 'Owner'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
    Creates email.alias records according to the values provided in ``vals`` with 1 alteration: * ``alias_name`` value may be cleaned by replacing certain unsafe characters; :raise UserError: if given alias_name is already assigned or there are duplicates in given vals_list;
  • name_get(self)
    Return the mail alias display alias_name, including the implicit mail catchall domain if exists from config otherwise "New Alias". e.g. `jobs@mail.odoo.com` or `jobs` or 'New Alias'
  • open_document(self)
  • open_parent_document(self)
  • write(self, vals)
    "Raises UserError if given alias name is already assigned

New fields (1)
  • alias_id Many2one → mail.alias
    ondelete='restrict' required=True string='Alias' args: 'mail.alias'
Public methods (4)
  • copy_data(self, default=None)
    @api.returns(None, <expr>)
  • create(self, vals_list)
    @api.model_create_multi
    Create a record with each ``vals`` or ``vals_list`` and create a corresponding alias.
  • unlink(self)
    Delete the given records, and cascade-delete their corresponding alias.
  • write(self, vals)
    Split writable fields of mail.alias and other fields alias fields will write with sudo and the other normally

New fields (2)
  • active Boolean
    default=True tracking=True
  • email Char
    help='This field is case insensitive.' index='trigram' required=True string='Email Address' tracking=True
Public methods (5)
  • action_add(self)
  • action_remove_with_reason(self, email, reason=None)
  • create(self, values)
    @api.model_create_multi
  • mail_action_blacklist_remove(self)
  • write(self, values)

New fields (2)
  • email Char
    name='Email' readonly=True required=True
  • reason Char
    name='Reason'
Public methods (1)
  • action_unblacklist_apply(self)

New fields (17)
  • active Boolean
    default=True help='Set active to false to hide the channel without removing it.'
  • avatar_128 Image
    compute='_compute_avatar_128' max_height=128 max_width=128 args: 'Avatar'
  • channel_member_ids One2many → mail.channel.member
    groups='base.group_user' string='Members' args: 'mail.channel.member', 'channel_id'
  • channel_partner_ids Many2many → res.partner
    compute='_compute_channel_partner_ids' compute_sudo=True groups='base.group_user' inverse='_inverse_channel_partner_ids' search='_search_channel_partner_ids' string='Partners' args: 'res.partner'
  • channel_type Selection
    default='channel' help='Chat is private and unique between 2 persons. Group is private among invited persons. Channel can be freely joined (depending on its configuration).' readonly=True required=True string='Channel Type' args: [('chat', 'Chat'), ('channel', 'Channel'), ('group', 'Group')]
  • default_display_mode Selection
    help='Determines how the channel will be displayed by default when opening it from its invitation link. No value means display text (no voice/video).' selection=[('video_full_screen', 'Full screen video')] string='Default Display Mode'
  • description Text
    args: 'Description'
  • group_ids Many2many → res.groups
    help='Members of those groups will automatically added as followers. Note that they will be able to manage their subscription manually if necessary.' string='Auto Subscription' args: 'res.groups'
  • group_public_id Many2one → res.groups
    compute='_compute_group_public_id' readonly=False store=True string='Authorized Group' args: 'res.groups'
  • image_128 Image
    max_height=128 max_width=128 args: 'Image'
  • invitation_url Char
    compute='_compute_invitation_url' args: 'Invitation URL'
  • is_chat Boolean
    compute='_compute_is_chat' string='Is a chat'
  • is_member Boolean
    compute='_compute_is_member' search='_search_is_member' args: 'Is Member'
  • member_count Integer
    compute='_compute_member_count' compute_sudo=True string='Member Count'
  • name Char
    required=True args: 'Name'
  • rtc_session_ids One2many → mail.channel.rtc.session
    groups='base.group_system' args: 'mail.channel.rtc.session', 'channel_id'
  • uuid Char
    copy=False default=_generate_random_token size=50 args: 'UUID'
Public methods (23)
  • action_unfollow(self)
  • add_members(self, partner_ids=None, guest_ids=None, invite_to_rtc_call=False, open_chat_window=False, post_joined_message=True)
    Adds the given partner_ids and guest_ids as member of self channels.
  • channel_change_description(self, description)
  • channel_create(self, name, group_id)
    @api.model
    Create a channel and add the current partner, broadcast it (to make the user directly listen to it when polling) :param name : the name of the channel to create :param group_id : the group allowed to join the channel. :return dict : channel header
  • channel_fetch_preview(self)
    Return the last message of the given channels
  • channel_fetched(self)
    Broadcast the channel_fetched notification to channel members
  • channel_fold(self, state=None)
    Update the fold_state of the given session. In order to syncronize web browser tabs, the change will be broadcast to themselves (the current user channel). Note: the user need to be logged :param state : the new status of the session for the current user.
  • channel_get(self, partners_to, pin=True)
    @api.model
    Get the canonical private channel between some partners, create it if needed. To reuse an old channel (conversation), this one must be private, and contains only the given partners. :param partners_to : list of res.partner ids to add to the conversation :param pin : True if getting the channel should pin it for the current user :returns: channel_info of the created or existing channel :rtype: dict
  • channel_info(self)
    Get the informations header for the current channels :returns a list of channels values :rtype : list(dict)
  • channel_join(self)
    Shortcut to add the current user as member of self channels. Prefer calling add_members() directly when possible.
  • channel_pin(self, pinned=False)
  • channel_rename(self, name)
  • channel_set_custom_name(self, name)
  • create(self, vals_list)
    @api.model_create_multi
  • create_group(self, partners_to, default_display_mode=False, name='')
    @api.model
    Creates a group channel. :param partners_to : list of res.partner ids to add to the conversation :param str default_display_mode: how the channel will be displayed by default :param str name: group name. default name is computed client side from the list of members if no name is set :returns: channel_info of the created channel :rtype: dict
  • execute_command_help(self, **kwargs)
  • execute_command_leave(self, **kwargs)
  • execute_command_who(self, **kwargs)
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first channels' id, name, channel_type and authorizedGroupFullName fields such that the name matches a 'search' string. Exclude channels of type chat (DM) and group.
  • init(self)
  • load_more_members(self, known_member_ids)
  • message_post(self, *, message_type='notification', **kwargs)
    @api.returns('mail.message', <expr>)
  • write(self, vals)

New fields (15)
  • channel_id Many2one → mail.channel
    ondelete='cascade' readonly=True required=True string='Channel' args: 'mail.channel'
  • custom_channel_name Char
    args: 'Custom channel name'
  • fetched_message_id Many2one → mail.message
    index='btree_not_null' string='Last Fetched' args: 'mail.message'
  • fold_state Selection
    default='open' string='Conversation Fold State' args: [('open', 'Open'), ('folded', 'Folded'), ('closed', 'Closed')]
  • guest_id Many2one → mail.guest
    comodel_name='mail.guest' index=True ondelete='cascade' readonly=True string='Guest'
  • is_minimized Boolean
    args: 'Conversation is minimized'
  • is_pinned Boolean
    default=True args: 'Is pinned on the interface'
  • last_interest_dt Datetime
    default=fields.Datetime.now help='Contains the date and time of the last interesting event that happened in this channel for this partner. This includes: creating, joining, pinning, and new message posted.' args: 'Last Interest'
  • last_seen_dt Datetime
    args: 'Last seen date'
  • message_unread_counter Integer
    compute='_compute_message_unread' compute_sudo=True args: 'Unread Messages Counter'
  • partner_email Char
    related='partner_id.email' related_sudo=False args: 'Email'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' string='Recipient' args: 'res.partner'
  • rtc_inviting_session_id Many2one → mail.channel.rtc.session
    string='Ringing session' args: 'mail.channel.rtc.session'
  • rtc_session_ids One2many → mail.channel.rtc.session
    comodel_name='mail.channel.rtc.session' inverse_name='channel_member_id' string='RTC Sessions'
  • seen_message_id Many2one → mail.message
    index='btree_not_null' string='Last Seen' args: 'mail.message'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
    Similar access rule as the access rule of the mail channel. It can not be implemented in XML, because when the record will be created, the partner will be added in the channel and the security rule will always authorize the creation.
  • init(self)
  • name_get(self)
  • unlink(self)
  • write(self, vals)

New fields (9)
  • channel_id Many2one → mail.channel
    readonly=True related='channel_member_id.channel_id' store=True args: 'mail.channel'
  • channel_member_id Many2one → mail.channel.member
    ondelete='cascade' required=True args: 'mail.channel.member'
  • guest_id Many2one → mail.guest
    related='channel_member_id.guest_id' args: 'mail.guest'
  • is_camera_on Boolean
    string='Is sending user video'
  • is_deaf Boolean
    string='Has disabled incoming sound'
  • is_muted Boolean
    string='Is microphone muted'
  • is_screen_sharing_on Boolean
    string='Is sharing the screen'
  • partner_id Many2one → res.partner
    related='channel_member_id.partner_id' string='Partner' args: 'res.partner'
  • write_date Datetime
    index=True args: 'Last Updated On'
Public methods (3)
  • action_disconnect(self)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)

New fields (27)
  • active_domain Text
    readonly=True args: 'Active domain'
  • attachment_ids Many2many → ir.attachment
    args: 'ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', 'Attachments'
  • author_id Many2one → res.partner
    help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' args: 'res.partner', 'Author'
  • auto_delete Boolean
    help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Delete Emails'
  • auto_delete_message Boolean
    help='Do not keep a copy of the email in the document communication history (mass mailing only)' args: 'Delete Message Copy'
  • body Html
    compute=False default='' render_engine='qweb' sanitize_style=True args: 'Contents'
  • composition_mode Selection
    default='comment' selection=[('comment', 'Post on a document'), ('mass_mail', 'Email Mass Mailing'), ('mass_post', 'Post on Multiple Documents')] string='Composition mode'
  • email_add_signature Boolean
    default=True
  • email_from Char
    help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • email_layout_xmlid Char
    copy=False args: 'Email Notification Layout'
  • is_log Boolean
    args: 'Log as Internal Note'
  • mail_activity_type_id Many2one → mail.activity.type
    ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_type Selection
    default='comment' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' required=True args: [('auto_comment', 'Automated Targeted Notification'), ('comment', 'Comment'), ('notification', 'System notification')], 'Type'
  • model Char
    args: 'Related Document Model'
  • notify Boolean
    help='Notify followers of the document (mass post only)' args: 'Notify followers'
  • parent_id Many2one → mail.message
    ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    domain=_partner_ids_domain args: 'res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional Contacts'
  • record_name Char
    args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply To'
  • reply_to_force_new Boolean
    help='Manage answers as new incoming emails instead of replies going to the same thread.' string='Considers answers as new thread'
  • reply_to_mode Selection
    compute='_compute_reply_to_mode' help='Original Discussion: Answers go in the original document discussion thread. \n Another Email Address: Answers go to the email address mentioned in the tracking message-id instead of original document discussion thread. \n This has an impact on the generated message-id.' inverse='_inverse_reply_to_mode' string='Replies' args: [('update', 'Store email and replies in the chatter of each record'), ('new', 'Collect replies on a specific email address')]
  • res_id Integer
    args: 'Related Document ID'
  • subject Char
    compute=False args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    default=<expr> ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • template_id Many2one → mail.template
    domain="[('model', '=', model)]" args: 'mail.template', 'Use template'
  • use_active_domain Boolean
    args: 'Use active domain'
Public methods (7)
  • action_save_as_template(self)
    hit save as template button: current form value will be a new template attached to the current document.
  • action_send_mail(self)
    Used for action button that do not accept arguments.
  • default_get(self, fields)
    @api.model
    Handle composition mode. Some details about context keys: - comment: default mode, model and ID of a record the user comments - default_model or active_model - default_res_id or active_id - mass_mail: model and IDs of records the user mass-mails - active_ids: record IDs - default_model or active_model
  • generate_email_for_composer(self, template_id, res_ids, fields)
    @api.model
    Call email_template.generate_email(), get fields relevant for mail.compose.message, transform email_cc and email_to into partner_ids
  • get_mail_values(self, res_ids)
    Generate the values that will be used by send_mail to create mail_messages or mail_mails.
  • get_record_data(self, values)
    @api.model
    Returns a defaults-like dict with initial values for the composition wizard when sending an email related a previous email (parent_id) or a document (model, res_id). This is based on previously computed default values.
  • render_message(self, res_ids)
    Generate template-based values of wizard, for the document records given by res_ids. This method is meant to be inherited by email_template that will produce a more complete dictionary, using qweb templates. Each template is generated for all res_ids, allowing to parse the template once, and render it multiple times. This is useful for mass mailing where template rendering represent a significant part of the process. Default recipients are also computed, based on mail_thread method _message_get_default_recipients. This allows to ensure a mass mailing has always some recipients specified. :param browse wizard: current mail.compose.message browse record :param list res_ids: list of record ids :return dict results: for each res_id, the generated template values for subject, body, email_from and reply_to

New fields (5)
  • body Html
    compute='_compute_body' compute_sudo=False readonly=False render_engine='qweb' sanitize=False store=True args: 'Contents'
  • can_edit_body Boolean
    compute='_compute_can_edit_body' args: 'Can Edit Body'
  • is_mail_template_editor Boolean
    compute='_compute_is_mail_template_editor' args: 'Is Editor'
  • subject Char
    compute='_compute_subject' compute_sudo=False readonly=False store=True args: 'Subject'
  • template_id Many2one → mail.template
    domain="[('model', '=', render_model)]" args: 'mail.template', 'Mail Template'
Public methods (0)

No public methods.

New fields (7)
  • email Char
    related='partner_id.email' args: 'Email'
  • is_active Boolean
    related='partner_id.active' args: 'Is Active'
  • name Char
    related='partner_id.name' args: 'Name'
  • partner_id Many2one → res.partner
    domain=[('type', '!=', 'private')] index=True ondelete='cascade' required=True string='Related Partner' args: 'res.partner'
  • res_id Many2oneReference
    help='Id of the followed resource' index=True model_field='res_model' args: 'Related Document ID'
  • res_model Char
    index=True required=True args: 'Related Document Model Name'
  • subtype_ids Many2many → mail.message.subtype
    help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall." string='Subtype' args: 'mail.message.subtype'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (2)
  • email Char
    args: 'Email Address'
  • email_normalized Char
    compute='_compute_email_normalized' index=True store=True string='Normalized Email'
Public methods (1)
  • get_empty_list_help(self, help_message)
    @api.model

New fields (7)
  • access_token Char
    copy=False default=<expr> groups='base.group_system' readonly=True required=True string='Access Token'
  • channel_ids Many2many → mail.channel
    column1='guest_id' column2='channel_id' comodel_name='mail.channel' copy=False relation='mail_channel_member' string='Channels'
  • country_id Many2one → res.country
    comodel_name='res.country' string='Country'
  • im_status Char
    compute='_compute_im_status' args: 'IM Status'
  • lang Selection
    selection=_lang_get string='Language'
  • name Char
    required=True string='Name'
  • timezone Selection
    selection=_tz_get string='Timezone'
Public methods (0)

No public methods.

New fields (4)
  • credential Char
  • server_type Selection
    default='stun' required=True string='Type' args: [('stun', 'stun:'), ('turn', 'turn:')]
  • uri Char
    required=True args: 'URI'
  • username Char
Public methods (0)

No public methods.

New fields (9)
  • create_date Datetime
    index=True
  • image_mimetype Char
    args: 'Image MIME type'
  • message_id Many2one → mail.message
    index=True ondelete='cascade' required=True string='Message' args: 'mail.message'
  • og_description Text
    args: 'Description'
  • og_image Char
    args: 'Image'
  • og_mimetype Char
    args: 'MIME type'
  • og_title Char
    args: 'Title'
  • og_type Char
    args: 'Type'
  • source_url Char
    required=True args: 'URL'
Public methods (0)

No public methods.

New fields (19)
  • auto_delete Boolean
    help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_content Html
    compute='_compute_body_content' sanitize=True search='_search_body_content' args: 'Rich-text Contents'
  • body_html Text
    help='Rich-text/HTML message' args: 'Text Contents'
  • email_cc Char
    help='Carbon copy message recipients' args: 'Cc'
  • email_to Text
    help='Message recipients (emails)' args: 'To'
  • failure_reason Text
    copy=False help='Failure reason. This is usually the exception thrown by the email server, stored to ease the debugging of mailing issues.' readonly=1 args: 'Failure Reason'
  • failure_type Selection
    selection=[('unknown', 'Unknown error'), ('mail_email_invalid', 'Invalid email address'), ('mail_email_missing', 'Missing email'), ('mail_smtp', 'Connection failed (outgoing mail server problem)'), ('mail_bl', 'Blacklisted Address'), ('mail_optout', 'Opted Out'), ('mail_dup', 'Duplicated Email')] string='Failure type'
  • fetchmail_server_id Many2one → fetchmail.server
    readonly=True args: 'fetchmail.server', 'Inbound Mail Server'
  • headers Text
    copy=False args: 'Headers'
  • is_notification Boolean
    help='Mail has been created to notify people of an existing mail.message' args: 'Notification Email'
  • mail_message_id Many2one → mail.message
    auto_join=True index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • mail_message_id_int Integer
    compute='_compute_mail_message_id_int' compute_sudo=True
  • recipient_ids Many2many → res.partner
    context={'active_test': False} string='To (Partners)' args: 'res.partner'
  • references Text
    help='Message references, such as identifiers of previous messages' readonly=1 args: 'References'
  • restricted_attachment_count Integer
    compute='_compute_restricted_attachments' args: 'Restricted attachments'
  • scheduled_date Datetime
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. Unless a timezone is specified, it is considered as being in UTC timezone.' args: 'Scheduled Send Date'
  • state Selection
    copy=False default='outgoing' readonly=True args: [('outgoing', 'Outgoing'), ('sent', 'Sent'), ('received', 'Received'), ('exception', 'Delivery Failed'), ('cancel', 'Cancelled')], 'Status'
  • to_delete Boolean
    help='If set, the mail will be deleted during the next Email Queue CRON run.' args: 'To Delete'
  • unrestricted_attachment_ids Many2many → ir.attachment
    compute='_compute_restricted_attachments' inverse='_inverse_unrestricted_attachment_ids' string='Unrestricted Attachments' args: 'ir.attachment'
Public methods (11)
  • action_open_document(self)
    Opens the related record based on the model and ID
  • action_retry(self)
  • cancel(self)
  • create(self, values_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • fields_get(self, *args, **kwargs)
    @api.model
  • mark_outgoing(self)
  • process_email_queue(self, ids=None)
    @api.model
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! :param list ids: optional list of emails ids to send. If passed no search is performed, and these ids are used instead. :param dict context: if a 'filters' key is present in context, this value will be used as an additional filter to further restrict the outgoing messages to send (by default all 'outgoing' messages are sent).
  • send(self, auto_commit=False, raise_exception=False)
    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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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
  • unlink(self)
  • write(self, vals)

New fields (38)
  • attachment_ids Many2many → ir.attachment
    string='Attachments' args: 'ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id'
  • author_avatar Binary
    depends=['author_id'] readonly=False related='author_id.avatar_128' args: "Author's avatar"
  • author_guest_id Many2one → mail.guest
    comodel_name='mail.guest' string='Guest'
  • author_id Many2one → res.partner
    help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True ondelete='set null' args: 'res.partner', 'Author'
  • body Html
    default='' sanitize_style=True args: 'Contents'
  • canned_response_ids One2many → mail.shortcode
    store=False string='Canned Responses' args: 'mail.shortcode', 'message_ids'
  • child_ids One2many → mail.message
    args: 'mail.message', 'parent_id', 'Child Messages'
  • date Datetime
    default=fields.Datetime.now args: 'Date'
  • description Char
    compute='_compute_description' help='Message description: either the subject, or the beginning of the body' args: 'Short description'
  • email_add_signature Boolean
    default=True
  • email_from Char
    help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • email_layout_xmlid Char
    copy=False args: 'Layout'
  • has_error Boolean
    compute='_compute_has_error' search='_search_has_error' args: 'Has error'
  • is_current_user_or_guest_author Boolean
    compute='_compute_is_current_user_or_guest_author'
  • is_internal Boolean
    help='Hide to public / portal users, independently from subtype configuration.' args: 'Employee Only'
  • link_preview_ids One2many → mail.link.preview
    groups='base.group_erp_manager' string='Link Previews' args: 'mail.link.preview', 'message_id'
  • mail_activity_type_id Many2one → mail.activity.type
    index=True ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_ids One2many → mail.mail
    groups='base.group_system' string='Mails' args: 'mail.mail', 'mail_message_id'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_id Char
    copy=False help='Message unique identifier' index='btree' readonly=1 args: 'Message-Id'
  • message_type Selection
    default='email' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' required=True args: [('email', 'Email'), ('comment', 'Comment'), ('notification', 'System notification'), ('auto_comment', 'Automated Targeted Notification'), ('user_notification', 'User Specific Notification')], 'Type'
  • model Char
    args: 'Related Document Model'
  • needaction Boolean
    compute='_compute_needaction' search='_search_needaction' args: 'Need Action'
  • notification_ids One2many → mail.notification
    auto_join=True copy=False depends=['notified_partner_ids'] args: 'mail.notification', 'mail_message_id', 'Notifications'
  • notified_partner_ids Many2many → res.partner
    context={'active_test': False} copy=False depends=['notification_ids'] string='Partners with Need Action' args: 'res.partner', 'mail_notification'
  • parent_id Many2one → mail.message
    index='btree_not_null' ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    context={'active_test': False} string='Recipients' args: 'res.partner'
  • preview Char
    compute='_compute_preview' help='The text-only beginning of the body used as email preview.' args: 'Preview'
  • reaction_ids One2many → mail.message.reaction
    groups='base.group_system' string='Reactions' args: 'mail.message.reaction', 'message_id'
  • record_name Char
    args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • reply_to_force_new Boolean
    help='If true, answers do not go in the original document discussion thread. Instead, it will check for the reply_to in tracking message-id and redirected accordingly. This has an impact on the generated message-id.' args: 'No threading for answers'
  • res_id Many2oneReference
    model_field='model' args: 'Related Document ID'
  • starred Boolean
    compute='_compute_starred' compute_sudo=False help='Current user has a starred notification linked to this message' search='_search_starred' args: 'Starred'
  • starred_partner_ids Many2many → res.partner
    string='Favorited By' args: 'res.partner', 'mail_message_res_partner_starred_rel'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • tracking_value_ids One2many → mail.tracking.value
    groups='base.group_system' help='Tracked values are stored in a separate model. This field allow to reconstruct the tracking and to generate statistics on the model.' string='Tracking values' args: 'mail.tracking.value', 'mail_message_id'
Public methods (15)
  • action_open_document(self)
    Opens the related record based on the model and ID
  • check_access_rule(self, operation)
    Access rules of mail.message: - read: if - author_id == pid, uid is the author OR - uid is in the recipients (partner_ids) OR - uid has been notified (needaction) OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id (private message) OR - pid in message_follower_ids if model, res_id OR - uid can read the parent OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid is in the recipients (partner_ids) OR - uid has write or create access on the related document if model, res_id - otherwise: raise - unlink: if - uid has write or create access on the related document - otherwise: raise Specific case: non employee users see only messages with subtype (aka do not see internal logs).
  • create(self, values_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • export_data(self, fields_to_export)
  • init(self)
  • is_thread_message(self, vals=None)
  • mark_all_as_read(self, domain=None)
    @api.model
  • message_format(self, format_reply=True)
    Get the message values in the format for web client. Since message values can be broadcasted, computed fields MUST NOT BE READ and broadcasted. :returns list(dict). Example : { 'body': HTML content of the message 'model': u'res.partner', 'record_name': u'Agrolait', 'attachment_ids': [ { 'file_type_icon': u'webimage', 'id': 45, 'name': u'sample.png', 'filename': u'sample.png' } ], 'needaction_partner_ids': [], # list of partner ids 'res_id': 7, 'trackingValues': [ { 'changedField': "Customer", 'id': 2965, 'newValue': { 'currencyId': "", 'fieldType': 'char', 'value': "Axelor", ], 'oldValue': { 'currencyId': "", 'fieldType': 'char', 'value': "", ], } ], 'author_id': (3, u'Administrator'), 'email_from': 'sacha@pokemon.com' # email address or False 'subtype_id': (1, u'Discussions'), 'date': '2015-06-30 08:22:33', 'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner name_get 'message_type': u'comment', 'id': 59, 'subject': False 'is_note': True # only if the message is a note (subtype == note) 'is_discussion': False # only if the message is a discussion (subtype == discussion) 'is_notification': False # only if the message is a note but is a notification aka not linked to a document like assignation 'parentMessage': {...}, # formatted message that this message is a reply to. Only present if format_reply is True }
  • read(self, fields=None, load='_classic_read')
    Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_done(self)
    Remove the needaction from messages for the current partner.
  • toggle_message_starred(self)
    Toggle messages as (un)starred. Technically, the notifications related to uid are set to (un)starred.
  • unlink(self)
  • unstar_all(self)
    @api.model
    Unstar messages for the current partner.
  • write(self, vals)

New fields (4)
  • content Char
    readonly=True required=True string='Content'
  • guest_id Many2one → mail.guest
    comodel_name='mail.guest' ondelete='cascade' readonly=True string='Reacting Guest'
  • message_id Many2one → mail.message
    comodel_name='mail.message' ondelete='cascade' readonly=True required=True string='Message'
  • partner_id Many2one → res.partner
    comodel_name='res.partner' ondelete='cascade' readonly=True string='Reacting Partner'
Public methods (1)
  • init(self)

New fields (3)
  • mail_message_id Many2one → mail.message
    ondelete='cascade' required=True string='Message' args: 'mail.message'
  • notification_parameters Text
    args: 'Notification Parameter'
  • scheduled_datetime Datetime
    help='Datetime at which notification should be sent.' required=True args: 'Scheduled Send Date'
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • force_send(self)
    Launch notification process independently from the expected date.

New fields (10)
  • default Boolean
    default=True help='Activated by default when subscribing.' args: 'Default'
  • description Text
    help='Description that will be added in the message posted for this subtype. If void, the name will be added instead.' prefetch=True translate=True args: 'Description'
  • hidden Boolean
    help='Hide the subtype in the follower options' args: 'Hidden'
  • internal Boolean
    help='Messages with internal subtypes will be visible only by employees, aka members of base_user group' args: 'Internal Only'
  • name Char
    help='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.' required=True translate=True args: 'Message Type'
  • parent_id Many2one → mail.message.subtype
    help='Parent subtype, used for automatic subscription. This field is not correctly named. For example on a project, the parent_id of project subtypes refers to task-related subtypes.' ondelete='set null' string='Parent' args: 'mail.message.subtype'
  • relation_field Char
    help='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).' args: 'Relation field'
  • res_model Char
    help='Model the subtype applies to. If False, this subtype applies to all models.' args: 'Model'
  • sequence Integer
    default=1 help='Used to order subtypes.' args: 'Sequence'
  • track_recipients Boolean
    help='Whether to display all the recipients or only the important ones.' args: 'Track Recipients'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • default_subtypes(self, model_name)
    @api.model
    Retrieve the default subtypes (all, internal, external) for the given model.
  • unlink(self)
  • write(self, vals)

New fields (10)
  • author_id Many2one → res.partner
    ondelete='set null' args: 'res.partner', 'Author'
  • failure_reason Text
    copy=False args: 'Failure reason'
  • failure_type Selection
    selection=[('unknown', 'Unknown error'), ('mail_email_invalid', 'Invalid email address'), ('mail_email_missing', 'Missing email address'), ('mail_smtp', 'Connection failed (outgoing mail server problem)')] string='Failure type'
  • is_read Boolean
    index=True args: 'Is Read'
  • mail_mail_id Many2one → mail.mail
    help='Optional mail_mail ID. Used mainly to optimize searches.' index=True args: 'mail.mail', 'Mail'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification_status Selection
    default='ready' index=True string='Status' args: [('ready', 'Ready to Send'), ('sent', 'Sent'), ('bounce', 'Bounced'), ('exception', 'Exception'), ('canceled', 'Canceled')]
  • notification_type Selection
    default='inbox' index=True required=True string='Notification Type' args: [('inbox', 'Inbox'), ('email', 'Email')]
  • read_date Datetime
    copy=False args: 'Read Date'
  • res_partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner', 'Recipient'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • format_failure_reason(self)
  • init(self)
  • write(self, vals)

New fields (2)
  • lang Char
    help='Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. {{ object.partner_id.lang }}.' args: 'Language'
  • render_model Char
    compute='_compute_render_model' store=False args: 'Rendering Model'
Public methods (2)
  • create(self, values_list)
    @api.model_create_multi
  • write(self, vals)

New fields (6)
  • can_cancel Boolean
    compute='_compute_can_cancel'
  • can_resend Boolean
    compute='_compute_can_resend'
  • mail_message_id Many2one → mail.message
    readonly=True args: 'mail.message', 'Message'
  • notification_ids Many2many → mail.notification
    readonly=True string='Notifications' args: 'mail.notification'
  • partner_ids One2many → mail.resend.partner
    string='Recipients' args: 'mail.resend.partner', 'resend_wizard_id'
  • partner_readonly Boolean
    compute='_compute_partner_readonly'
Public methods (3)
  • cancel_mail_action(self)
  • default_get(self, fields)
    @api.model
  • resend_mail_action(self)
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (6)
  • email Char
    readonly=False related='partner_id.email' related_sudo=False string='Email Address'
  • message Char
    string='Error message'
  • name Char
    readonly=False related='partner_id.name' related_sudo=False string='Recipient Name'
  • partner_id Many2one → res.partner
    ondelete='cascade' required=True string='Partner' args: 'res.partner'
  • resend Boolean
    default=True string='Try Again'
  • resend_wizard_id Many2one → mail.resend.message
    string='Resend wizard' args: 'mail.resend.message'
Public methods (0)

No public methods.

New fields (4)
  • description Char
    args: 'Description'
  • message_ids Many2one → mail.message
    store=False string='Messages' args: 'mail.message'
  • source Char
    help="Shortcut that will automatically be substituted with longer content in your messages. Type ':' followed by the name of your shortcut (e.g. :hello) to use in your messages." index='trigram' required=True args: 'Shortcut'
  • substitution Text
    help='Content that will automatically replace the shortcut of your choosing. This content can still be adapted before sending your message.' required=True args: 'Substitution'
Public methods (0)

No public methods.

New fields (22)
  • active Boolean
    default=True
  • attachment_ids Many2many → ir.attachment
    help='You may attach files to this template, to be added to all emails created from this template' args: 'ir.attachment', 'email_template_attachment_rel', 'email_template_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    default=True help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_html Html
    prefetch=True render_engine='qweb' sanitize=False translate=True args: 'Body'
  • can_write Boolean
    compute='_compute_can_write' help='The current user can edit the template.'
  • description Text
    help="This field is used for internal description of the template's usage." translate=True args: 'Template description'
  • email_cc Char
    help='Carbon copy recipients (placeholders may be used here)' args: 'Cc'
  • email_from Char
    help="Sender address (placeholders may be used here). If not set, the default value will be the author's email alias if configured, or email address." args: 'From'
  • email_to Char
    help='Comma-separated recipient addresses (placeholders may be used here)' args: 'To (Emails)'
  • mail_server_id Many2one → ir.mail_server
    help='Optional preferred server for outgoing mails. If not set, the highest priority one will be used.' readonly=False args: 'ir.mail_server', 'Outgoing Mail Server'
  • model Char
    index=True readonly=True related='model_id.model' store=True args: 'Related Document Model'
  • model_id Many2one → ir.model
    args: 'ir.model', 'Applies to'
  • name Char
    translate=True args: 'Name'
  • partner_to Char
    help='Comma-separated ids of recipient partners (placeholders may be used here)' args: 'To (Partners)'
  • ref_ir_act_window Many2one → ir.actions.act_window
    copy=False help='Sidebar action to make this template available on records of the related document model' readonly=True args: 'ir.actions.act_window', 'Sidebar action'
  • reply_to Char
    help='Email address to which replies will be redirected when sending emails in mass; only used when the reply is not logged in the original discussion thread.' args: 'Reply To'
  • report_name Char
    help='Name to use for the generated report file (may contain placeholders)\nThe extension can be omitted and will then come from the report type.' prefetch=True translate=True args: 'Report Filename'
  • report_template Many2one → ir.actions.report
    args: 'ir.actions.report', 'Optional report to print and attach'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. You can use dynamic expression.' args: 'Scheduled Date'
  • subject Char
    help='Subject (placeholders may be used here)' prefetch=True translate=True args: 'Subject'
  • template_category Selection
    compute='_compute_template_category' search='_search_template_category' args: [('base_template', 'Base Template'), ('hidden_template', 'Hidden Template'), ('custom_template', 'Custom Template')]
  • use_default_to Boolean
    help='Default recipients of the record:\n- partner (using id on a partner or the partner_id field) OR\n- email (using email_from or email field)' args: 'Default recipients'
Public methods (10)
  • copy(self, default=None)
    @api.returns('self', <expr>)
  • create(self, vals_list)
    @api.model_create_multi
  • create_action(self)
  • default_get(self, fields)
    @api.model
  • generate_email(self, res_ids, fields)
    Generates an email from the template for given the given model based on records given by res_ids. :param res_id: id of the record to use for rendering the template (model is taken from template definition) :returns: a dict containing all relevant fields for creating a new mail.mail entry, with one extra key ``attachments``, in the format [(report_name, data)] where data is base64 encoded.
  • generate_recipients(self, results, res_ids)
    Generates the recipients of the template. Default values can ben generated instead of the template values if requested by template or context. Emails (email_to, email_cc) can be transformed into partners if requested in the context.
  • send_mail(self, res_id, force_send=False, raise_exception=False, email_values=None, email_layout_xmlid=False)
    Generates a new mail.mail. Template is rendered on record given by res_id and model coming from template. :param int res_id: id of the record to render the template :param bool force_send: send email immediately; otherwise use the mail queue (recommended); :param dict email_values: update generated mail with those values to further customize the mail; :param str email_layout_xmlid: optional notification layout to encapsulate the generated email; :returns: id of the mail.mail that was created
  • unlink(self)
  • unlink_action(self)
  • write(self, vals)

New fields (15)
  • attachment_ids Many2many → ir.attachment
    compute='_compute_mail_template_fields' args: 'ir.attachment', 'Attachments'
  • body_html Html
    compute='_compute_mail_template_fields' sanitize=False args: 'Body'
  • email_cc Char
    compute='_compute_mail_template_fields' help='Carbon copy recipients' args: 'Cc'
  • email_from Char
    compute='_compute_mail_template_fields' help='Sender address' args: 'From'
  • email_to Char
    compute='_compute_mail_template_fields' help='Comma-separated recipient addresses' args: 'To'
  • error_msg Char
    readonly=True args: 'Error Message'
  • lang Selection
    string='Template Preview Language' args: _selection_languages
  • mail_template_id Many2one → mail.template
    required=True string='Related Mail Template' args: 'mail.template'
  • model_id Many2one → ir.model
    related='mail_template_id.model_id' string='Targeted model' args: 'ir.model'
  • no_record Boolean
    compute='_compute_no_record' args: 'No Record'
  • partner_ids Many2many → res.partner
    compute='_compute_mail_template_fields' string='Recipients' args: 'res.partner'
  • reply_to Char
    compute='_compute_mail_template_fields' help='Preferred response address' args: 'Reply-To'
  • resource_ref Reference
    selection='_selection_target_model' string='Record'
  • scheduled_date Char
    compute='_compute_mail_template_fields' help='The queue manager will send the email after the date' args: 'Scheduled Date'
  • subject Char
    compute='_compute_mail_template_fields' args: 'Subject'
Public methods (1)
  • default_get(self, fields)
    @api.model

New fields (1)
  • template_ids Many2many → mail.template
    args: 'mail.template'
Public methods (1)
  • reset_template(self)

New fields (11)
  • has_message Boolean
    compute='_compute_has_message' search='_search_has_message' store=False
  • message_attachment_count Integer
    compute='_compute_message_attachment_count' groups='base.group_user' args: 'Attachment Count'
  • message_follower_ids One2many → mail.followers
    groups='base.group_user' string='Followers' args: 'mail.followers', 'res_id'
  • message_has_error Boolean
    compute='_compute_message_has_error' help='If checked, some messages have a delivery error.' search='_search_message_has_error' args: 'Message Delivery error'
  • message_has_error_counter Integer
    compute='_compute_message_has_error' help='Number of messages with delivery error' args: 'Number of errors'
  • message_ids One2many → mail.message
    auto_join=True domain=<expr> string='Messages' args: 'mail.message', 'res_id'
  • message_is_follower Boolean
    compute='_compute_message_is_follower' search='_search_message_is_follower' args: 'Is Follower'
  • message_main_attachment_id Many2one → ir.attachment
    comodel_name='ir.attachment' copy=False string='Main Attachment'
  • message_needaction Boolean
    compute='_compute_message_needaction' help='If checked, new messages require your attention.' search='_search_message_needaction' args: 'Action Needed'
  • message_needaction_counter Integer
    compute='_compute_message_needaction' help='Number of messages requiring action' args: 'Number of Actions'
  • message_partner_ids Many2many → res.partner
    comodel_name='res.partner' compute='_compute_message_partner_ids' groups='base.group_user' inverse='_inverse_message_partner_ids' search='_search_message_partner_ids' string='Followers (Partners)'
Public methods (18)
  • copy_data(self, default=None)
  • create(self, vals_list)
    @api.model_create_multi
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • get_empty_list_help(self, help)
    @api.model
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • message_change_thread(self, new_thread, new_parent_message=False)
    Transfer the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : my_lead.message_change_thread(my_project_task) will transfer the context of the thread of my_lead to my_project_task
  • message_new(self, msg_dict, custom_values=None)
    @api.model
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :rtype: int :return: the id of the newly created thread object
  • message_notify(self, *, partner_ids=False, parent_id=False, model=False, res_id=False, author_id=None, email_from=None, body='', subject=False, **kwargs)
    Shortcut allowing to notify partners of messages that shouldn't be displayed on a document. It pushes notifications on inbox or by email depending on the user configuration, like other notifications.
  • message_parse(self, message, save_original=False)
    @api.model
    Parses an email.message.Message representing an RFC-2822 email and returns a generic dict holding the message details. :param message: email to parse :type message: email.message.Message :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'email_from': from, 'to': to + delivered-to, 'cc': cc, 'recipients': delivered-to + to + cc + resent-to + resent-cc, 'partner_ids': partners found based on recipients emails, 'body': unified_body, 'references': references, 'in_reply_to': in-reply-to, 'parent_id': parent mail.message based on in_reply_to or references, 'is_internal': answer to an internal message (note), 'date': date, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_post(self, *, body='', subject=None, message_type='notification', email_from=None, author_id=None, parent_id=False, subtype_xmlid=None, subtype_id=False, partner_ids=None, attachments=None, attachment_ids=None, **kwargs)
    @api.returns('mail.message', <expr>)
    Post a new message in an existing thread, returning the new mail.message. :param str body: body of the message, usually raw HTML that will be sanitized :param str subject: subject of the message :param str message_type: see mail_message.message_type field. Can be anything but user_notification, reserved for message_notify :param str email_from: from address of the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param int author_id: optional ID of partner record being the author. See ``_message_compute_author`` that uses it to make email_from / author_id coherent; :param int parent_id: handle thread formation :param int subtype_id: subtype_id of the message, used mainly for followers notification mechanism; :param list(int) partner_ids: partner_ids to notify in addition to partners computed based on subtype / followers matching; :param list(tuple(str,str), tuple(str,str, dict)) attachments : list of attachment tuples in the form ``(name,content)`` or ``(name,content, info)`` where content is NOT base64 encoded; :param list attachment_ids: list of existing attachments to link to this message -Should only be set by chatter -Attachment object attached to mail.compose.message(0) will be attached to the related document. Extra keyword arguments will be used either * as default column values for the new mail.message record if they match mail.message fields; * propagated to notification methods; :return record: newly create mail.message
  • message_post_with_template(self, template_id, email_layout_xmlid=None, auto_commit=False, **kwargs)
    Helper method to send a mail with a template :param template_id : the id of the template to render to create the body of the message :param **kwargs : parameter to create a mail.compose.message woaerd (which inherit from mail.message)
  • message_post_with_view(self, views_or_xmlid, **kwargs)
    Helper method to send a mail / post a message using a view_id
  • message_process(self, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None)
    @api.model
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: string or xmlrpclib.Binary :type dict custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None)
    @api.model
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: * if the message replies to an existing thread by having a Message-Id that matches an existing mail_message.message_id, we take the original message model/thread_id pair and ignore custom_value as no creation will take place; * look for a mail.alias entry matching the message recipients and use the corresponding model, thread_id, custom_values and user_id. This could lead to a thread update or creation depending on the alias; * fallback on provided ``model``, ``thread_id`` and ``custom_values``; * raise an exception as no route has been found :param string message: an email.message instance :param dict message_dict: dictionary holding parsed message variables :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :type dict custom_values: optional dictionary of default field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of routes [(model, thread_id, custom_values, user_id, alias)] :raises: ValueError, TypeError
  • message_subscribe(self, partner_ids=None, subtype_ids=None)
    Main public API to add followers to a record set. Its main purpose is to perform access rights checks before calling ``_message_subscribe``.
  • message_unsubscribe(self, partner_ids=None)
    Remove partners from the records followers.
  • message_update(self, msg_dict, update_vals=None)
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • notify_cancel_by_type(self, notification_type)
    @api.model
    Subclasses must call this method and then * either call the standard implementation _notify_cancel_by_type_generic * or implements their own logic
  • unlink(self)
    Override unlink to delete messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • write(self, values)

New fields (3)
  • email_normalized Char
    compute='_compute_email_normalized' compute_sudo=True help='This field is used to search on email address as the primary email field can contain more than strictly an email address.' invisible=True store=True string='Normalized Email'
  • is_blacklisted Boolean
    compute='_compute_is_blacklisted' compute_sudo=True groups='base.group_user' help="If the email address is on the blacklist, the contact won't receive mass mailing anymore, from any list" search='_search_is_blacklisted' store=False string='Blacklist'
  • message_bounce Integer
    default=0 help='Counter of the number of bounced emails for this contact' args: 'Bounce'
Public methods (1)
  • mail_action_blacklist_remove(self)

New fields (1)
  • email_cc Char
    args: 'Email cc'
Public methods (2)
  • message_new(self, msg_dict, custom_values=None)
    @api.model
  • message_update(self, msg_dict, update_vals=None)
    Adds cc email to self.email_cc while trying to keep email as raw as possible but unique

New fields (19)
  • currency_id Many2one → res.currency
    help='Used to display the currency when tracking monetary values' ondelete='set null' readonly=True args: 'res.currency', 'Currency'
  • field Many2one → ir.model.fields
    index=True ondelete='cascade' readonly=1 required=True args: 'ir.model.fields'
  • field_desc Char
    readonly=1 required=True args: 'Field Description'
  • field_groups Char
    compute='_compute_field_groups'
  • field_type Char
    args: 'Field Type'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message ID'
  • new_value_char Char
    readonly=1 args: 'New Value Char'
  • new_value_datetime Datetime
    readonly=1 args: 'New Value Datetime'
  • new_value_float Float
    readonly=1 args: 'New Value Float'
  • new_value_integer Integer
    readonly=1 args: 'New Value Integer'
  • new_value_monetary Float
    readonly=1 args: 'New Value Monetary'
  • new_value_text Text
    readonly=1 args: 'New Value Text'
  • old_value_char Char
    readonly=1 args: 'Old Value Char'
  • old_value_datetime Datetime
    readonly=1 args: 'Old Value DateTime'
  • old_value_float Float
    readonly=1 args: 'Old Value Float'
  • old_value_integer Integer
    readonly=1 args: 'Old Value Integer'
  • old_value_monetary Float
    readonly=1 args: 'Old Value Monetary'
  • old_value_text Text
    readonly=1 args: 'Old Value Text'
  • tracking_sequence Integer
    default=100 readonly=1 args: 'Tracking field sequence'
Public methods (1)
  • create_tracking_values(self, initial_value, new_value, col_name, col_info, tracking_sequence, model_name)
    @api.model

New fields (5)
  • message Html
    args: 'Message'
  • partner_ids Many2many → res.partner
    domain=[('type', '!=', 'private')] help='List of partners that will be added as follower of the current document.' string='Recipients' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' required=True args: 'Related Document Model'
  • send_mail Boolean
    default=True help="If checked, the partners will receive an email warning they have been added in the document's followers." args: 'Send Email'
Public methods (2)
  • add_followers(self)
  • default_get(self, fields)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cron_mode=True)
    Send a message to Odoo's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (3)
  • catchall_email Char
    compute='_compute_catchall' string='Catchall Email'
  • catchall_formatted Char
    compute='_compute_catchall' string='Catchall'
  • email_formatted Char
    compute='_compute_email_formatted' compute_sudo=True string='Formatted Email'
Public methods (0)

No public methods.

New fields (10)
  • alias_domain Char
    config_parameter='mail.catchall.domain' help='If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.' args: 'Alias Domain'
  • fail_counter Integer
    compute='_compute_fail_counter' args: 'Fail Mail'
  • module_google_gmail Boolean
    args: 'Support Gmail Authentication'
  • module_microsoft_outlook Boolean
    args: 'Support Outlook Authentication'
  • primary_color Char
    readonly=False related='company_id.primary_color' string='Header Color'
  • restrict_template_rendering Boolean
    config_parameter='mail.restrict.template.rendering' help='Users will still be able to render templates.\nHowever only Mail Template Editors will be able to create new dynamic templates or modify existing ones.' args: 'Restrict Template Rendering'
  • secondary_color Char
    readonly=False related='company_id.secondary_color' string='Button Color'
  • twilio_account_sid Char
    config_parameter='mail.twilio_account_sid' args: 'Twilio Account SID'
  • twilio_account_token Char
    config_parameter='mail.twilio_account_token' args: 'Twilio Account Auth Token'
  • use_twilio_rtc_servers Boolean
    config_parameter='mail.use_twilio_rtc_servers' help='If you want to use twilio as TURN/STUN server provider' args: 'Use Twilio ICE servers'
Public methods (2)
  • open_email_layout(self)
  • open_mail_templates(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals)

New fields (6)
  • channel_ids Many2many → mail.channel
    copy=False string='Channels' args: 'mail.channel', 'mail_channel_member', 'partner_id', 'channel_id'
  • email Char
    tracking=1
  • parent_id Many2one
    tracking=3
  • phone Char
    tracking=2
  • user_id Many2one
    tracking=4
  • vat Char
    tracking=5
Public methods (5)
  • find_or_create(self, email, assert_valid_email=False)
    @api.model@api.returns('self', <expr>)
    Override to use the email_normalized field.
  • get_mention_suggestions(self, search, limit=8, channel_id=None)
    @api.model
    Return 'limit'-first partners' such that the name or email matches a 'search' string. Prioritize partners that are also (internal) users, and then extend the research to all partners. If channel_id is given, only members of this channel are returned. The return format is a list of partner data (as per returned by `mail_partner_format()`).
  • im_search(self, name, limit=20)
    @api.model
    Search partner with a name and return its id, name and im_status. Note : the user must be logged :param name : the partner name to search :param limit : the limit of result to return
  • mail_partner_format(self, fields=None)
  • search_for_channel_invite(self, search_term, channel_id=None, limit=30)
    @api.model
    Returns partners matching search_term that can be invited to a channel. If the channel_id is specified, only partners that can actually be invited to the channel are returned (not already members, and in accordance to the channel configuration).

New fields (3)
  • notification_type Selection
    compute='_compute_notification_type' default='email' help='Policy on how to handle Chatter notifications:\n- Handle by Emails: notifications are sent to your email address\n- Handle in Odoo: notifications appear in your Odoo Inbox' readonly=False required=True store=True args: [('email', 'Handle by Emails'), ('inbox', 'Handle in Odoo')], 'Notification'
  • res_users_settings_id Many2one → res.users.settings
    compute='_compute_res_users_settings_id' search='_search_res_users_settings_id' string='Settings' args: 'res.users.settings'
  • res_users_settings_ids One2many → res.users.settings
    args: 'res.users.settings', 'user_id'
Public methods (6)
  • SELF_READABLE_FIELDS(self)
    @property
  • SELF_WRITEABLE_FIELDS(self)
    @property
  • create(self, vals_list)
    @api.model_create_multi
  • systray_get_activities(self)
    @api.model
  • unlink(self)
  • write(self, vals)

New fields (7)
  • is_discuss_sidebar_category_channel_open Boolean
    default=True string='Is discuss sidebar category channel open?'
  • is_discuss_sidebar_category_chat_open Boolean
    default=True string='Is discuss sidebar category chat open?'
  • push_to_talk_key Char
    help='String formatted to represent a key with modifiers following this pattern: shift.ctrl.alt.key, e.g: truthy.1.true.b' string='Push-To-Talk shortcut'
  • use_push_to_talk Boolean
    default=False string='Use the push to talk feature'
  • user_id Many2one → res.users
    domain=[('res_users_settings_id', '=', False)] ondelete='cascade' required=True string='User' args: 'res.users'
  • voice_active_duration Integer
    help='How long the audio broadcast will remain active after passing the volume threshold' string='Duration of voice activity in ms'
  • volume_settings_ids One2many → res.users.settings.volumes
    string='Volumes of other partners' args: 'res.users.settings.volumes', 'user_setting_id'
Public methods (2)
  • set_res_users_settings(self, new_settings)
  • set_volume_setting(self, partner_id, volume, guest_id=None)
    Saves the volume of a guest or a partner. Either partner_id or guest_id must be specified. :param float volume: the selected volume between 0 and 1 :param int partner_id: :param int guest_id:

New fields (4)
  • guest_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner'
  • user_setting_id Many2one → res.users.settings
    index=True ondelete='cascade' required=True args: 'res.users.settings'
  • volume Float
    default=0.5 help='Ranges between 0.0 and 1.0, scale depends on the browser implementation'
Public methods (1)
  • init(self)

New fields (1)
  • template_fs Char
    copy=False help='File from where the template originates. Used to reset broken template.' string='Template Filename'
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • reset_template(self)
    Resets the Template with values given in source file. We ignore the case of template being overridden in another modules because it is extremely less likely to happen. This method also tries to reset the translation terms for the current user lang (all langs are not supported due to costly file operation).
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/15.0/mail
VERSION
VERSION 1.5
CATEGORY
CATEGORYProductivity/Discuss
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Martin Trigaux, Olivier Dony, Thibault Delavallée, Denis Ledoux, Xavier ALT, David Monjoie, Xavier Morel, Goffin Simon, Mohammed Shekha, Nicolas Lempereur, Thibault Francois, Aaron Bohy, Pedro M. Baeza, Jeremy Kersten, GitHub, Lucas Perais (lpe), Barad Mahendra, Yannick Tivisse, qsm-odoo, Nicolas Seinlet, Romain Derie, Jigar Patel, Christophe Monniez, Jorge Pinna Puissant, Alexandre Kühn, Julien Castiaux, Aurélien Warnon, Priyanka Kakadiya, Xavier-Do, David Tran, Romeo Fragomeli, Victor Feyens, Andrea Grazioso (agr-odoo), Paul Morelle, Xavier Dubuc, Sébastien Theys, david, Nasreddin (bon), Florent de Labarre, Julien Mougenot, Anh Thao Pham (pta), Luis González, Samuel Degueldre, Alvaro Fuentes, std-odoo, Achraf (abz), David Beguin, Lucas Lefèvre, Adrien Widart, Ivan Yelizariev, Jérémy Hennecart, Nasreddin Boulif (bon), Prakash Prajapati, Kamesh Patel, Nicolas Galler, nie, Tiffany Chang (tic), Rémy Voet (ryv), Thanh Dodeur, Gorash, Mathieu Duckerts-Antoine, Pierre Paridans, jbw, Hiral Bhavsar, yograj tandel, Arnaud Joset, Jérôme Vanhaudenard, William Braeckman, nounoubensebia, root, bit-odoo, Romain Estievenart, Kevin Baptiste, odoo, Xavier BOL (xbo), roen-odoo, Dhruv Patel, Stanislas Sobieski, Hubert Van de Walle (huvw), Miquel Raïch, Laurent Desausoi (lade), Julien Van Roy, Florian Damhaut, Merlin (megu), MerlinGuillaume, thcl-odoo, mafo-odoo, Didier (did), Audric Onockx (auon), Antoine Guenet, Florian Charlier, anhe-odoo, Walid HANNICHE (waha), Yolann Sabaux, Abdelouahab (abla), Swapnesh, Nicolas Bayet, Jinjiu Liu, Aurelien van Delft (avd), Michael Mattiello (mcm), dht-odoo, Fabio Barbero, Julien Giannone, Renaud Thiry, Julien Banken, Ipsita Borisagar, bve-odoo, jorv, Habib (ayh), damr, Francois (fge), Louis Wicket (wil), tsm-odoo, David, miad-odoo, Tom De Caluwé, Simon Genin (ges), Pierre-Yves Dufays, Qiuyu (QHO), Munaf Khan, duongnguyen, Maruan Aguerdouh (magm), Sébastien Geelen (sge), Bruno Boi, Antoine (ande), flvr-odoo, Rahul Prajapati, Leloup Loïc (lole), jlzhou, Leonardo Pavan Rocha, Andrzej(pian), Zelong Lin, Damien (abd), dane@odoo.com, Mattis Megevand, Maryam Kia, jorv-odoo, Thibault Delavalée, Matthieu Stockbauer, yosa-odoo, TSO, Shahnawaz Idariya, Alex Kühn, Krunal Trivedi
WEBSITE
WEBSITEhttps://www.odoo.com/app/discuss
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:25:28
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web
    - bus
    - web_tour
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (79)
XML IDNameModelTypeStatus
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
email_template_form email.template.form mail.template form New
email_template_tree email.template.tree mail.template tree New
field_form_view ir.model.fields field Inherits base.view_model_fields_form
mail.discuss_public_channel_template Discuss Public Channel Template ir.ui.view qweb New
mail.discuss_public_layout mail.discuss_public_layout ir.ui.view qweb New
mail_activity_type_view_form mail.activity.type.view.form mail.activity.type form New
mail_activity_type_view_search mail.activity.type.search mail.activity.type search New
mail_activity_type_view_tree mail.activity.type.view.tree mail.activity.type tree New
mail_activity_view_calendar mail.activity.view.calendar mail.activity calendar New
mail_activity_view_form mail.activity.view.form mail.activity field Inherits mail.mail_activity_view_form_popup
mail_activity_view_form_popup mail.activity.view.form.popup mail.activity form New
mail_activity_view_search mail.activity.view.search mail.activity search New
mail_activity_view_tree mail.activity.view.tree mail.activity tree New
mail_blacklist_remove_view_form mail.blacklist.remove.form mail.blacklist.remove form New
mail_blacklist_view_form mail.blacklist.view.form mail.blacklist form New
mail_blacklist_view_search mail.blacklist.view.search mail.blacklist search New
mail_blacklist_view_tree mail.blacklist.view.tree mail.blacklist tree New
mail_bounce_alias_security mail_bounce_alias_security ir.ui.view qweb New
mail_bounce_catchall mail_bounce_catchall ir.ui.view qweb New
mail_channel_partner_view_form mail.channel.partner.form mail.channel.partner form New
mail_channel_partner_view_tree mail.channel.partner.tree mail.channel.partner tree New
mail_channel_rtc_session_view_form mail.channel.rtc.session.form mail.channel.rtc.session form New
mail_channel_rtc_session_view_search mail.channel.rtc.session.search mail.channel.rtc.session search New
mail_channel_rtc_session_view_tree mail.channel.rtc.session.tree mail.channel.rtc.session tree New
mail_channel_view_form mail.channel.form mail.channel form New
mail_channel_view_kanban mail.channel.kanban mail.channel kanban New
mail_channel_view_search mail.channel.search mail.channel search New
mail_channel_view_tree mail.channel.tree mail.channel tree New
mail_guest_view_tree mail.guest.tree mail.guest tree New
mail_message_reaction_view_tree mail.message.reaction.tree mail.message.reaction tree New
mail_message_view_form mail.message.view.form mail.message form New
mail_notification_borders mail_notification_borders ir.ui.view qweb New
mail_notification_light mail_notification_light ir.ui.view qweb New
mail_notification_paynow Mail: Pay Now mail notification template ir.ui.view qweb New
mail_notification_view_form mail.notification.view.form mail.notification form New
mail_notification_view_tree mail.notification.view.tree mail.notification tree New
mail_resend_cancel_view_form mail.resend.cancel.view.form mail.resend.cancel form New
mail_resend_message_view_form mail.resend.message.view.form mail.resend.message form New
mail_shortcode_view_form mail.shortcode.form mail.shortcode form New
mail_shortcode_view_tree mail.shortcode.tree mail.shortcode tree New
mail_template_preview_view_form mail.template.preview.view.form mail.template.preview form New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
message_activity_assigned message_activity_assigned ir.ui.view qweb New
message_activity_done message_activity_done ir.ui.view qweb New
message_notification_email message_notification_email ir.ui.view qweb New
message_origin_link message_origin_link ir.ui.view qweb New
message_user_assigned message_user_assigned ir.ui.view qweb New
model_form_view ir.model field Inherits base.view_model_form
model_search_view ir.model field Inherits base.view_model_search
res_config_settings_view_form res.config.settings.view.form.inherit.mail res.config.settings div Inherits base_setup.res_config_settings_view_form
res_partner_view_activity res.partner.activity res.partner activity New
res_partner_view_form_inherit_mail res.partner.view.form.inherit.mail res.partner xpath Inherits base.view_partner_form
res_partner_view_kanban_inherit_mail res.partner.view.kanban.inherit.mail res.partner field Inherits base.res_partner_kanban_view
res_partner_view_search_inherit_mail res.partner.view.search.inherit.mail res.partner filter Inherits base.view_res_partner_filter
res_partner_view_tree_inherit_mail res.partner.view.tree.inherit.mail res.partner xpath Inherits base.view_partner_tree
res_users_settings_view_form res.users.settings.form res.users.settings form New
res_users_settings_view_tree res.users.settings.tree res.users.settings tree New
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_email_template_search email.template.search mail.template search New
view_followers_tree mail.followers.tree mail.followers tree New
view_ice_server_form mail.ice.server.form mail.ice.server form New
view_ice_server_tree mail.ice.server.tree mail.ice.server tree New
view_mail_alias_form mail.alias.form mail.alias form New
view_mail_alias_search mail.alias.search mail.alias search New
view_mail_alias_tree mail.alias.tree mail.alias tree New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tracking_value_form mail.tracking.value.form mail.tracking.value form New
view_mail_tracking_value_tree mail.tracking.value.tree mail.tracking.value tree New
view_mail_tree mail.mail.tree mail.mail tree New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.tree mail.message.subtype tree New
view_message_tree mail.message.tree mail.message tree New
view_server_action_form_template ir.actions.server.form ir.actions.server xpath Inherits base.view_server_action_form
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (53)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (1)
  • guest_id Many2one → mail.guest
    ondelete='cascade' args: 'mail.guest', 'Guest'
Public methods (1)
  • init(self)

New fields (1)
  • view_mode Selection
    ondelete={'activity': 'cascade'} selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (11)
  • activity_date_deadline_range Integer
    string='Due Date In'
  • activity_date_deadline_range_type Selection
    default='days' string='Due type' args: [('days', 'Days'), ('weeks', 'Weeks'), ('months', 'Months')]
  • activity_note Html
    args: 'Note'
  • activity_summary Char
    args: 'Summary'
  • activity_type_id Many2one → mail.activity.type
    domain="['|', ('res_model', '=', False), ('res_model', '=', model_name)]" ondelete='restrict' string='Activity' args: 'mail.activity.type'
  • activity_user_field_name Char
    default='user_id' help='Technical name of the user on the record' args: 'User field name'
  • activity_user_id Many2one → res.users
    string='Responsible' args: 'res.users'
  • activity_user_type Selection
    default='specific' help="Use 'Specific User' to always assign the same user on the next activity. Use 'Generic User From Record' to specify the field name of the user to choose on the record." args: [('specific', 'Specific User'), ('generic', 'Generic User From Record')]
  • partner_ids Many2many → res.partner
    string='Add Followers' args: 'res.partner'
  • state Selection
    ondelete={'email': 'cascade', 'followers': 'cascade', 'next_activity': 'cascade'} selection_add=[('email', 'Send Email'), ('followers', 'Add Followers'), ('next_activity', 'Create Next Activity')]
  • template_id Many2one → mail.template
    domain="[('model_id', '=', model_id)]" ondelete='set null' args: 'mail.template', 'Email Template'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • register_as_main_attachment(self, force=True)
    Registers this attachment as the main one of the model it is attached to.

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • set_param(self, key, value)
    @api.model
  • write(self, vals)

New fields (0)

No new fields.

Public methods (1)
  • session_info(self)

New fields (3)
  • is_mail_activity Boolean
    default=False help='Whether this model supports activities.' string='Mail Activity'
  • is_mail_blacklist Boolean
    default=False help='Whether this model supports blacklist.' string='Mail Blacklist'
  • is_mail_thread Boolean
    default=False help='Whether this model supports messages and notifications.' string='Mail Thread'
Public methods (2)
  • unlink(self)
    Delete mail data (followers, messages, activities) associated with the models being deleted.
  • write(self, vals)

New fields (1)
  • tracking Integer
    help='If set every modification done to this field is tracked in the chatter. Value is used to order tracking values.' string='Enable Ordered Tracking'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, vals)

New fields (1)
  • type Selection
    selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (21)
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_decoration Selection
    readonly=True related='activity_type_id.decoration_type'
  • activity_type_id Many2one → mail.activity.type
    default=_default_activity_type_id domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" ondelete='restrict' string='Activity Type' args: 'mail.activity.type'
  • automated Boolean
    help='Indicates this activity has been created automatically and not by any user.' readonly=True args: 'Automated activity'
  • can_write Boolean
    compute='_compute_can_write' help='Technical field to hide buttons if the current user has no access.'
  • chaining_type Selection
    readonly=True related='activity_type_id.chaining_type'
  • date_deadline Date
    default=fields.Date.context_today index=True required=True args: 'Due Date'
  • has_recommended_activities Boolean
    compute='_compute_has_recommended_activities' help='Technical field for UX purpose' args: 'Next activities available'
  • icon Char
    readonly=True related='activity_type_id.icon' args: 'Icon'
  • mail_template_ids Many2many
    readonly=True related='activity_type_id.mail_template_ids'
  • note Html
    sanitize_style=True args: 'Note'
  • previous_activity_type_id Many2one → mail.activity.type
    readonly=True string='Previous Activity Type' args: 'mail.activity.type'
  • recommended_activity_type_id Many2one → mail.activity.type
    string='Recommended Activity Type' args: 'mail.activity.type'
  • request_partner_id Many2one → res.partner
    string='Requesting Partner' args: 'res.partner'
  • res_id Many2oneReference
    index=True model_field='res_model' required=True string='Related Document ID'
  • res_model Char
    compute_sudo=True index=True readonly=True related='res_model_id.model' store=True args: 'Related Document Model'
  • res_model_id Many2one → ir.model
    index=True ondelete='cascade' required=True args: 'ir.model', 'Document Model'
  • res_name Char
    compute='_compute_res_name' compute_sudo=True help='Display name of the related document.' readonly=True store=True args: 'Document Name'
  • state Selection
    compute='_compute_state' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')], 'State'
  • summary Char
    args: 'Summary'
  • user_id Many2one → res.users
    default=<expr> index=True required=True args: 'res.users', 'Assigned to'
Public methods (14)
  • action_close_dialog(self)
  • action_done(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_done_schedule_next(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_feedback(self, feedback=False, attachment_ids=None)
  • action_feedback_schedule_next(self, feedback=False)
  • action_notify(self)
  • activity_format(self)
  • create(self, vals_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • get_activity_data(self, res_model, domain)
    @api.model
  • name_get(self)
  • read(self, fields=None, load='_classic_read')
    When reading specific fields, read calls _read that manually applies ir rules (_apply_ir_rules), instead of calling check_access_rule. Meaning that our custom rules enforcing from '_filter_access_rules' and '_filter_access_rules_python' are bypassed in that case. To make sure we apply our custom security rules, we force a call to 'check_access_rule'.
  • unlink(self)
  • write(self, values)

New fields (10)
  • activity_date_deadline Date
    compute='_compute_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_activity_date_deadline' store=False args: 'Next Activity Deadline'
  • activity_exception_decoration Selection
    compute='_compute_activity_exception_type' help='Type of the exception activity on record.' search='_search_activity_exception_decoration' args: [('warning', 'Alert'), ('danger', 'Error')]
  • activity_exception_icon Char
    compute='_compute_activity_exception_type' help='Icon to indicate an exception activity.' args: 'Icon'
  • activity_ids One2many → mail.activity
    auto_join=True groups='base.group_user' args: 'mail.activity', 'res_id', 'Activities'
  • activity_state Selection
    compute='_compute_activity_state' groups='base.group_user' help='Status based on activities\nOverdue: Due date is already passed\nToday: Activity date is today\nPlanned: Future activities.' search='_search_activity_state' string='Activity State' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')]
  • activity_summary Char
    groups='base.group_user' readonly=False related='activity_ids.summary' search='_search_activity_summary' args: 'Next Activity Summary'
  • activity_type_icon Char
    related='activity_ids.icon' args: 'Activity Type Icon'
  • activity_type_id Many2one → mail.activity.type
    groups='base.group_user' readonly=False related='activity_ids.activity_type_id' search='_search_activity_type_id' args: 'mail.activity.type', 'Next Activity Type'
  • activity_user_id Many2one → res.users
    groups='base.group_user' readonly=False related='activity_ids.user_id' search='_search_activity_user_id' args: 'res.users', 'Responsible User'
  • my_activity_date_deadline Date
    compute='_compute_my_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_my_activity_date_deadline' args: 'My Activity Deadline'
Public methods (9)
  • activity_feedback(self, act_type_xmlids, user_id=None, feedback=None)
    Set activities as done, limiting to some activity types and optionally to a given user.
  • activity_reschedule(self, act_type_xmlids, user_id=None, date_deadline=None, new_user_id=None)
    Reschedule some automated activities. Activities to reschedule are selected based on type xml ids and optionally by user. Purpose is to be able to * update the deadline to date_deadline; * update the responsible to new_user_id;
  • activity_schedule(self, act_type_xmlid='', date_deadline=None, summary='', note='', **act_values)
    Schedule an activity on each record of the current record set. This method allow to provide as parameter act_type_xmlid. This is an xml_id of activity type instead of directly giving an activity_type_id. It is useful to avoid having various "env.ref" in the code and allow to let the mixin handle access rights. :param date_deadline: the day the activity must be scheduled on the timezone of the user must be considered to set the correct deadline
  • activity_search(self, act_type_xmlids='', user_id=None, additional_domain=None)
    Search automated activities on current record set, given a list of activity types xml IDs. It is useful when dealing with specific types involved in automatic activities management. :param act_type_xmlids: list of activity types xml IDs :param user_id: if set, restrict to activities of that user_id; :param additional_domain: if set, filter on that domain;
  • activity_send_mail(self, template_id)
    Automatically send an email based on the given mail.template, given its ID.
  • activity_unlink(self, act_type_xmlids, user_id=None)
    Unlink activities, limiting to some activity types and optionally to a given user.
  • toggle_active(self)
    Before archiving the record we should also remove its ongoing activities. Otherwise they stay in the systray and concerning archived records it makes no sense.
  • unlink(self)
    Override unlink to delete records activities through (res_model, res_id).
  • write(self, vals)

New fields (22)
  • active Boolean
    default=True
  • category Selection
    default='default' help='Actions may trigger specific behavior like opening calendar view or automatically mark as done when a document is uploaded' string='Action' args: [('default', 'None'), ('upload_file', 'Upload Document'), ('phonecall', 'Phonecall')]
  • chaining_type Selection
    default='suggest' required=True string='Chaining Type' args: [('suggest', 'Suggest Next Activity'), ('trigger', 'Trigger Next Activity')]
  • create_uid Many2one → res.users
    index=True args: 'res.users'
  • decoration_type Selection
    help='Change the background color of the related activities of this type.' string='Decoration Type' args: [('warning', 'Alert'), ('danger', 'Error')]
  • default_note Html
    string='Default Note' translate=True
  • default_user_id Many2one → res.users
    string='Default User' args: 'res.users'
  • delay_count Integer
    default=0 help='Number of days/week/month before executing the action. It allows to plan the action deadline.' args: 'Schedule'
  • delay_from Selection
    default='previous_activity' help='Type of delay' required=True string='Delay Type' args: [('current_date', 'after completion date'), ('previous_activity', 'after previous activity deadline')]
  • delay_label Char
    compute='_compute_delay_label'
  • delay_unit Selection
    default='days' help='Unit of delay' required=True string='Delay units' args: [('days', 'days'), ('weeks', 'weeks'), ('months', 'months')]
  • icon Char
    help='Font awesome icon e.g. fa-tasks' args: 'Icon'
  • initial_res_model Selection
    compute='_compute_initial_res_model' help='Technical field to keep track of the model at the start of editing to support UX related behaviour' selection=_get_model_selection store=False string='Initial model'
  • mail_template_ids Many2many → mail.template
    string='Email templates' args: 'mail.template'
  • name Char
    required=True translate=True args: 'Name'
  • previous_type_ids Many2many → mail.activity.type
    domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" string='Preceding Activities' args: 'mail.activity.type', 'mail_activity_rel', 'recommended_id', 'activity_id'
  • res_model Selection
    help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' selection=_get_model_selection string='Model'
  • res_model_change Boolean
    default=False help='Technical field for UX related behaviour' store=False string='Model has change'
  • sequence Integer
    default=10 args: 'Sequence'
  • suggested_next_type_ids Many2many → mail.activity.type
    compute='_compute_suggested_next_type_ids' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" help='Suggest these activities once the current one is marked as done.' inverse='_inverse_suggested_next_type_ids' readonly=False store=True string='Suggest' args: 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id'
  • summary Char
    translate=True args: 'Default Summary'
  • triggered_next_type_id Many2one → mail.activity.type
    compute='_compute_triggered_next_type_id' domain="['|', ('res_model', '=', False), ('res_model', '=', res_model)]" help='Automatically schedule this activity once the current one is marked as done.' inverse='_inverse_triggered_next_type_id' ondelete='restrict' readonly=False store=True string='Trigger' args: 'mail.activity.type'
Public methods (0)

No public methods.

New fields (10)
  • alias_bounced_content Html
    help='If set, this content will automatically be sent out to unauthorized users instead of the default message.' translate=True args: 'Custom Bounced Message'
  • alias_contact Selection
    default='everyone' help='Policy to post a message on the document using the mailgateway.\n- everyone: everyone can post\n- partners: only authenticated partners\n- followers: only followers of the related document or members of following channels\n' required=True string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_defaults Text
    default='{}' help='A Python dictionary that will be evaluated to provide default values when creating new records for this alias.' required=True args: 'Default Values'
  • alias_domain Char
    compute='_compute_alias_domain' args: 'Alias domain'
  • alias_force_thread_id Integer
    help='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.' args: 'Record Thread ID'
  • alias_model_id Many2one → ir.model
    domain="[('field_id.name', '=', 'message_ids')]" help='The model (Odoo 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)' ondelete='cascade' required=True args: 'ir.model', 'Aliased Model'
  • alias_name Char
    copy=False help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>" args: 'Alias Name'
  • alias_parent_model_id Many2one → ir.model
    help='Parent model holding the alias. The model holding the alias reference is not necessarily the model given by alias_model_id (example: project (parent_model) and task (model))' args: 'ir.model', 'Parent Model'
  • alias_parent_thread_id Integer
    help='ID of the parent record holding the alias (example: project holding the task creation alias)' args: 'Parent Record Thread ID'
  • alias_user_id Many2one → res.users
    default=<expr> help='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.' args: 'res.users', 'Owner'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
    Creates email.alias records according to the values provided in ``vals`` with 1 alteration: * ``alias_name`` value may be cleaned by replacing certain unsafe characters; :raise UserError: if given alias_name is already assigned or there are duplicates in given vals_list;
  • name_get(self)
    Return the mail alias display alias_name, including the implicit mail catchall domain if exists from config otherwise "New Alias". e.g. `jobs@mail.odoo.com` or `jobs` or 'New Alias'
  • open_document(self)
  • open_parent_document(self)
  • write(self, vals)
    "Raises UserError if given alias name is already assigned

New fields (1)
  • alias_id Many2one → mail.alias
    ondelete='restrict' required=True string='Alias' args: 'mail.alias'
Public methods (4)
  • copy_data(self, default=None)
    @api.returns(None, <expr>)
  • create(self, vals_list)
    @api.model_create_multi
    Create a record with each ``vals`` or ``vals_list`` and create a corresponding alias.
  • unlink(self)
    Delete the given records, and cascade-delete their corresponding alias.
  • write(self, vals)
    Split writable fields of mail.alias and other fields alias fields will write with sudo and the other normally

New fields (2)
  • active Boolean
    default=True tracking=True
  • email Char
    help='This field is case insensitive.' index=True required=True string='Email Address' tracking=True
Public methods (5)
  • action_add(self)
  • action_remove_with_reason(self, email, reason=None)
  • create(self, values)
    @api.model_create_multi
  • mail_action_blacklist_remove(self)
  • write(self, values)

New fields (2)
  • email Char
    name='Email' readonly=True required=True
  • reason Char
    name='Reason'
Public methods (1)
  • action_unblacklist_apply(self)

New fields (17)
  • active Boolean
    default=True help='Set active to false to hide the channel without removing it.'
  • avatar_128 Image
    compute='_compute_avatar_128' max_height=128 max_width=128 args: 'Avatar'
  • channel_last_seen_partner_ids One2many → mail.channel.partner
    groups='base.group_user' string='Last Seen' args: 'mail.channel.partner', 'channel_id'
  • channel_partner_ids Many2many → res.partner
    compute='_compute_channel_partner_ids' compute_sudo=True groups='base.group_user' inverse='_inverse_channel_partner_ids' search='_search_channel_partner_ids' string='Members' args: 'res.partner'
  • channel_type Selection
    default='channel' help='Chat is private and unique between 2 persons. Group is private among invited persons. Channel can be freely joined (depending on its configuration).' string='Channel Type' args: [('chat', 'Chat'), ('channel', 'Channel'), ('group', 'Group')]
  • default_display_mode Selection
    help='Determines how the channel will be displayed by default when opening it from its invitation link. No value means display text (no voice/video).' selection=[('video_full_screen', 'Full screen video')] string='Default Display Mode'
  • description Text
    args: 'Description'
  • group_ids Many2many → res.groups
    help='Members of those groups will automatically added as followers. Note that they will be able to manage their subscription manually if necessary.' string='Auto Subscription' args: 'res.groups'
  • group_public_id Many2one → res.groups
    default=<expr> string='Authorized Group' args: 'res.groups'
  • image_128 Image
    max_height=128 max_width=128 args: 'Image'
  • is_chat Boolean
    compute='_compute_is_chat' string='Is a chat'
  • is_member Boolean
    compute='_compute_is_member' compute_sudo=True args: 'Is Member'
  • member_count Integer
    compute='_compute_member_count' compute_sudo=True help='Excluding guests from count.' string='Member Count'
  • name Char
    required=True translate=True args: 'Name'
  • public Selection
    default='groups' help='This group is visible by non members. Invisible groups can add members through the invite button.' required=True string='Privacy' args: [('public', 'Everyone'), ('private', 'Invited people only'), ('groups', 'Selected group of users')]
  • rtc_session_ids One2many → mail.channel.rtc.session
    groups='base.group_system' args: 'mail.channel.rtc.session', 'channel_id'
  • uuid Char
    copy=False default=_generate_random_token size=50 args: 'UUID'
Public methods (27)
  • action_unfollow(self)
  • add_members(self, partner_ids=None, guest_ids=None, invite_to_rtc_call=False)
    Adds the given partner_ids and guest_ids as member of self channels.
  • channel_change_description(self, description)
  • channel_create(self, name, privacy='groups')
    @api.model
    Create a channel and add the current partner, broadcast it (to make the user directly listen to it when polling) :param name : the name of the channel to create :param privacy : privacy of the channel. Should be 'public' or 'private'. :return dict : channel header
  • channel_fetch_listeners(self, uuid)
    @api.model
    Return the id, name and email of partners listening to the given channel
  • channel_fetch_preview(self)
    Return the last message of the given channels
  • channel_fetched(self)
    Broadcast the channel_fetched notification to channel members
  • channel_fold(self, uuid, state=None)
    @api.model
    Update the fold_state of the given session. In order to syncronize web browser tabs, the change will be broadcast to himself (the current user channel). Note: the user need to be logged :param state : the new status of the session for the current user.
  • channel_get(self, partners_to, pin=True)
    @api.model
    Get the canonical private channel between some partners, create it if needed. To reuse an old channel (conversation), this one must be private, and contains only the given partners. :param partners_to : list of res.partner ids to add to the conversation :param pin : True if getting the channel should pin it for the current user :returns: channel_info of the created or existing channel :rtype: dict
  • channel_info(self)
    Get the informations header for the current channels :returns a list of channels values :rtype : list(dict)
  • channel_join(self)
    Shortcut to add the current user as member of self channels. Prefer calling add_members() directly when possible.
  • channel_pin(self, uuid, pinned=False)
    @api.model
  • channel_rename(self, name)
  • channel_search_to_join(self, name=None, domain=None)
    @api.model
    Return the channel info of the channel the current partner can join :param name : the name of the researched channels :param domain : the base domain of the research :returns dict : channel dict
  • channel_set_custom_name(self, name)
  • create(self, vals_list)
    @api.model_create_multi
  • create_group(self, partners_to, default_display_mode=False)
    @api.model
    Create a group channel. :param partners_to : list of res.partner ids to add to the conversation :returns: channel_info of the created channel :rtype: dict
  • default_get(self, fields)
    @api.model
  • execute_command_help(self, **kwargs)
  • execute_command_leave(self, **kwargs)
  • execute_command_who(self, **kwargs)
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first channels' id, name and public fields such that the name matches a 'search' string. Exclude channels of type chat (DM), and private channels the current user isn't registered to.
  • init(self)
  • load_more_members(self, known_member_ids)
  • message_post(self, *, message_type='notification', **kwargs)
    @api.returns('mail.message', <expr>)
  • notify_typing(self, is_typing)
    Broadcast the typing notification to channel members :param is_typing: (boolean) tells whether the current user is typing or not
  • write(self, vals)

New fields (13)
  • channel_id Many2one → mail.channel
    ondelete='cascade' readonly=True required=True string='Channel' args: 'mail.channel'
  • custom_channel_name Char
    args: 'Custom channel name'
  • fetched_message_id Many2one → mail.message
    string='Last Fetched' args: 'mail.message'
  • fold_state Selection
    default='open' string='Conversation Fold State' args: [('open', 'Open'), ('folded', 'Folded'), ('closed', 'Closed')]
  • guest_id Many2one → mail.guest
    comodel_name='mail.guest' index=True ondelete='cascade' readonly=True string='Guest'
  • is_minimized Boolean
    args: 'Conversation is minimized'
  • is_pinned Boolean
    default=True args: 'Is pinned on the interface'
  • last_interest_dt Datetime
    default=fields.Datetime.now help='Contains the date and time of the last interesting event that happened in this channel for this partner. This includes: creating, joining, pinning, and new message posted.' args: 'Last Interest'
  • partner_email Char
    related='partner_id.email' related_sudo=False args: 'Email'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' string='Recipient' args: 'res.partner'
  • rtc_inviting_session_id Many2one → mail.channel.rtc.session
    string='Ringing session' args: 'mail.channel.rtc.session'
  • rtc_session_ids One2many → mail.channel.rtc.session
    comodel_name='mail.channel.rtc.session' inverse_name='channel_partner_id' string='RTC Sessions'
  • seen_message_id Many2one → mail.message
    string='Last Seen' args: 'mail.message'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
    Similar access rule as the access rule of the mail channel. It can not be implemented in XML, because when the record will be created, the partner will be added in the channel and the security rule will always authorize the creation.
  • init(self)
  • name_get(self)
  • unlink(self)
  • write(self, vals)

New fields (9)
  • channel_id Many2one → mail.channel
    readonly=True related='channel_partner_id.channel_id' store=True args: 'mail.channel'
  • channel_partner_id Many2one → mail.channel.partner
    index=True ondelete='cascade' required=True args: 'mail.channel.partner'
  • guest_id Many2one → mail.guest
    related='channel_partner_id.guest_id' args: 'mail.guest'
  • is_camera_on Boolean
    string='Is sending user video'
  • is_deaf Boolean
    string='Has disabled incoming sound'
  • is_muted Boolean
    string='Is microphone muted'
  • is_screen_sharing_on Boolean
    string='Is sharing the screen'
  • partner_id Many2one → res.partner
    related='channel_partner_id.partner_id' string='Partner' args: 'res.partner'
  • write_date Datetime
    index=True args: 'Last Updated On'
Public methods (3)
  • action_disconnect(self)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)

New fields (27)
  • active_domain Text
    readonly=True args: 'Active domain'
  • add_sign Boolean
    default=True
  • attachment_ids Many2many → ir.attachment
    args: 'ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', 'Attachments'
  • author_id Many2one → res.partner
    help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True args: 'res.partner', 'Author'
  • auto_delete Boolean
    help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Delete Emails'
  • auto_delete_message Boolean
    help='Do not keep a copy of the email in the document communication history (mass mailing only)' args: 'Delete Message Copy'
  • body Html
    compute=False default='' render_engine='qweb' sanitize_style=True args: 'Contents'
  • composition_mode Selection
    default='comment' selection=[('comment', 'Post on a document'), ('mass_mail', 'Email Mass Mailing'), ('mass_post', 'Post on Multiple Documents')] string='Composition mode'
  • email_from Char
    help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • is_log Boolean
    help='Whether the message is an internal note (comment mode only)' args: 'Log an Internal Note'
  • layout Char
    copy=False args: 'Layout'
  • mail_activity_type_id Many2one → mail.activity.type
    index=True ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_type Selection
    default='comment' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' required=True args: [('auto_comment', 'Automated Targeted Notification'), ('comment', 'Comment'), ('notification', 'System notification')], 'Type'
  • model Char
    index=True args: 'Related Document Model'
  • notify Boolean
    help='Notify followers of the document (mass post only)' args: 'Notify followers'
  • parent_id Many2one → mail.message
    help='Initial thread message.' index=True ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    domain=_partner_ids_domain args: 'res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional Contacts'
  • record_name Char
    help='Name get of the related document.' args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply To'
  • reply_to_force_new Boolean
    help='Manage answers as new incoming emails instead of replies going to the same thread.' string='Considers answers as new thread'
  • reply_to_mode Selection
    compute='_compute_reply_to_mode' help='Original Discussion: Answers go in the original document discussion thread. \n Another Email Address: Answers go to the email address mentioned in the tracking message-id instead of original document discussion thread. \n This has an impact on the generated message-id.' inverse='_inverse_reply_to_mode' string='Replies' args: [('update', 'Log in the original discussion thread'), ('new', 'Redirect to another email address')]
  • res_id Integer
    index=True args: 'Related Document ID'
  • subject Char
    compute=False args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    default=<expr> index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • template_id Many2one → mail.template
    domain="[('model', '=', model)]" index=True args: 'mail.template', 'Use template'
  • use_active_domain Boolean
    args: 'Use active domain'
Public methods (7)
  • action_save_as_template(self)
    hit save as template button: current form value will be a new template attached to the current document.
  • action_send_mail(self)
    Used for action button that do not accept arguments.
  • default_get(self, fields)
    @api.model
    Handle composition mode. Some details about context keys: - comment: default mode, model and ID of a record the user comments - default_model or active_model - default_res_id or active_id - mass_mail: model and IDs of records the user mass-mails - active_ids: record IDs - default_model or active_model
  • generate_email_for_composer(self, template_id, res_ids, fields)
    @api.model
    Call email_template.generate_email(), get fields relevant for mail.compose.message, transform email_cc and email_to into partner_ids
  • get_mail_values(self, res_ids)
    Generate the values that will be used by send_mail to create mail_messages or mail_mails.
  • get_record_data(self, values)
    @api.model
    Returns a defaults-like dict with initial values for the composition wizard when sending an email related a previous email (parent_id) or a document (model, res_id). This is based on previously computed default values.
  • render_message(self, res_ids)
    Generate template-based values of wizard, for the document records given by res_ids. This method is meant to be inherited by email_template that will produce a more complete dictionary, using qweb templates. Each template is generated for all res_ids, allowing to parse the template once, and render it multiple times. This is useful for mass mailing where template rendering represent a significant part of the process. Default recipients are also computed, based on mail_thread method _message_get_default_recipients. This allows to ensure a mass mailing has always some recipients specified. :param browse wizard: current mail.compose.message browse record :param list res_ids: list of record ids :return dict results: for each res_id, the generated template values for subject, body, email_from and reply_to

New fields (5)
  • body Html
    compute='_compute_body' readonly=False render_engine='qweb' sanitize=False store=True args: 'Contents'
  • can_edit_body Boolean
    compute='_compute_can_edit_body' args: 'Can Edit Body'
  • is_mail_template_editor Boolean
    compute='_compute_is_mail_template_editor' args: 'Is Editor'
  • subject Char
    compute='_compute_subject' readonly=False store=True args: 'Subject'
  • template_id Many2one → mail.template
    domain="[('model', '=', render_model)]" args: 'mail.template', 'Mail Template'
Public methods (0)

No public methods.

New fields (7)
  • email Char
    related='partner_id.email' args: 'Email'
  • is_active Boolean
    related='partner_id.active' args: 'Is Active'
  • name Char
    related='partner_id.name' args: 'Name'
  • partner_id Many2one → res.partner
    domain=[('type', '!=', 'private')] index=True ondelete='cascade' required=True string='Related Partner' args: 'res.partner'
  • res_id Many2oneReference
    help='Id of the followed resource' index=True model_field='res_model' args: 'Related Document ID'
  • res_model Char
    index=True required=True args: 'Related Document Model Name'
  • subtype_ids Many2many → mail.message.subtype
    help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall." string='Subtype' args: 'mail.message.subtype'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (6)
  • access_token Char
    copy=False default=<expr> groups='base.group_system' readonly=True required=True string='Access Token'
  • channel_ids Many2many → mail.channel
    column1='guest_id' column2='channel_id' comodel_name='mail.channel' copy=False relation='mail_channel_partner' string='Channels'
  • country_id Many2one → res.country
    comodel_name='res.country' string='Country'
  • lang Selection
    selection=_lang_get string='Language'
  • name Char
    required=True string='Name'
  • timezone Selection
    selection=_tz_get string='Timezone'
Public methods (0)

No public methods.

New fields (4)
  • credential Char
  • server_type Selection
    default='stun' required=True string='Type' args: [('stun', 'stun:'), ('turn', 'turn:')]
  • uri Char
    required=True args: 'URI'
  • username Char
Public methods (0)

No public methods.

New fields (13)
  • auto_delete Boolean
    help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_html Text
    help='Rich-text/HTML message' args: 'Rich-text Contents'
  • email_cc Char
    help='Carbon copy message recipients' args: 'Cc'
  • email_to Text
    help='Message recipients (emails)' args: 'To'
  • failure_reason Text
    copy=False help='Failure reason. This is usually the exception thrown by the email server, stored to ease the debugging of mailing issues.' readonly=1 args: 'Failure Reason'
  • failure_type Selection
    selection=[('unknown', 'Unknown error'), ('mail_email_invalid', 'Invalid email address'), ('mail_email_missing', 'Missing email'), ('mail_smtp', 'Connection failed (outgoing mail server problem)'), ('mail_bl', 'Blacklisted Address'), ('mail_optout', 'Opted Out'), ('mail_dup', 'Duplicated Email')] string='Failure type'
  • headers Text
    copy=False args: 'Headers'
  • is_notification Boolean
    help='Mail has been created to notify people of an existing mail.message' args: 'Notification Email'
  • mail_message_id Many2one → mail.message
    auto_join=True index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • recipient_ids Many2many → res.partner
    context={'active_test': False} string='To (Partners)' args: 'res.partner'
  • references Text
    help='Message references, such as identifiers of previous messages' readonly=1 args: 'References'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. Unless a timezone is specified, it is considered as being in UTC timezone.' args: 'Scheduled Send Date'
  • state Selection
    copy=False default='outgoing' readonly=True args: [('outgoing', 'Outgoing'), ('sent', 'Sent'), ('received', 'Received'), ('exception', 'Delivery Failed'), ('cancel', 'Cancelled')], 'Status'
Public methods (10)
  • action_retry(self)
  • cancel(self)
  • create(self, values_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • fields_get(self, *args, **kwargs)
    @api.model
  • mark_outgoing(self)
  • process_email_queue(self, ids=None)
    @api.model
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! :param list ids: optional list of emails ids to send. If passed no search is performed, and these ids are used instead. :param dict context: if a 'filters' key is present in context, this value will be used as an additional filter to further restrict the outgoing messages to send (by default all 'outgoing' messages are sent).
  • send(self, auto_commit=False, raise_exception=False)
    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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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
  • unlink(self)
  • write(self, vals)

New fields (36)
  • add_sign Boolean
    default=True
  • attachment_ids Many2many → ir.attachment
    help='Attachments are linked to a document through model / res_id and to the message through this field.' string='Attachments' args: 'ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id'
  • author_avatar Binary
    depends=['author_id'] readonly=False related='author_id.avatar_128' args: "Author's avatar"
  • author_guest_id Many2one → mail.guest
    comodel_name='mail.guest' string='Guest'
  • author_id Many2one → res.partner
    help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True ondelete='set null' args: 'res.partner', 'Author'
  • body Html
    default='' sanitize_style=True args: 'Contents'
  • canned_response_ids One2many → mail.shortcode
    store=False string='Canned Responses' args: 'mail.shortcode', 'message_ids'
  • child_ids One2many → mail.message
    args: 'mail.message', 'parent_id', 'Child Messages'
  • date Datetime
    default=fields.Datetime.now args: 'Date'
  • description Char
    compute='_compute_description' help='Message description: either the subject, or the beginning of the body' args: 'Short description'
  • email_from Char
    help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • email_layout_xmlid Char
    copy=False args: 'Layout'
  • has_error Boolean
    compute='_compute_has_error' help='Has error' search='_search_has_error' args: 'Has error'
  • is_current_user_or_guest_author Boolean
    compute='_compute_is_current_user_or_guest_author'
  • is_internal Boolean
    help='Hide to public / portal users, independently from subtype configuration.' args: 'Employee Only'
  • mail_activity_type_id Many2one → mail.activity.type
    index=True ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_ids One2many → mail.mail
    groups='base.group_system' string='Mails' args: 'mail.mail', 'mail_message_id'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_id Char
    copy=False help='Message unique identifier' index=True readonly=1 args: 'Message-Id'
  • message_type Selection
    default='email' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' required=True args: [('email', 'Email'), ('comment', 'Comment'), ('notification', 'System notification'), ('auto_comment', 'Automated Targeted Notification'), ('user_notification', 'User Specific Notification')], 'Type'
  • model Char
    index=True args: 'Related Document Model'
  • needaction Boolean
    compute='_compute_needaction' help='Need Action' search='_search_needaction' args: 'Need Action'
  • notification_ids One2many → mail.notification
    auto_join=True copy=False depends=['notified_partner_ids'] args: 'mail.notification', 'mail_message_id', 'Notifications'
  • notified_partner_ids Many2many → res.partner
    context={'active_test': False} copy=False depends=['notification_ids'] string='Partners with Need Action' args: 'res.partner', 'mail_notification'
  • parent_id Many2one → mail.message
    help='Initial thread message.' index=True ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    context={'active_test': False} string='Recipients' args: 'res.partner'
  • reaction_ids One2many → mail.message.reaction
    groups='base.group_system' string='Reactions' args: 'mail.message.reaction', 'message_id'
  • record_name Char
    help='Name get of the related document.' args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • reply_to_force_new Boolean
    help='If true, answers do not go in the original document discussion thread. Instead, it will check for the reply_to in tracking message-id and redirected accordingly. This has an impact on the generated message-id.' args: 'No threading for answers'
  • res_id Many2oneReference
    index=True model_field='model' args: 'Related Document ID'
  • starred Boolean
    compute='_compute_starred' compute_sudo=False help='Current user has a starred notification linked to this message' search='_search_starred' args: 'Starred'
  • starred_partner_ids Many2many → res.partner
    string='Favorited By' args: 'res.partner', 'mail_message_res_partner_starred_rel'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • tracking_value_ids One2many → mail.tracking.value
    groups='base.group_system' help='Tracked values are stored in a separate model. This field allow to reconstruct the tracking and to generate statistics on the model.' string='Tracking values' args: 'mail.tracking.value', 'mail_message_id'
Public methods (15)
  • action_open_document(self)
    Opens the related record based on the model and ID
  • check_access_rule(self, operation)
    Access rules of mail.message: - read: if - author_id == pid, uid is the author OR - uid is in the recipients (partner_ids) OR - uid has been notified (needaction) OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id (private message) OR - pid in message_follower_ids if model, res_id OR - uid can read the parent OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid is in the recipients (partner_ids) OR - uid has write or create access on the related document if model, res_id - otherwise: raise - unlink: if - uid has write or create access on the related document - otherwise: raise Specific case: non employee users see only messages with subtype (aka do not see internal logs).
  • create(self, values_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • export_data(self, fields_to_export)
  • init(self)
  • is_thread_message(self, vals=None)
  • mark_all_as_read(self, domain=None)
    @api.model
  • message_format(self, format_reply=True)
    Get the message values in the format for web client. Since message values can be broadcasted, computed fields MUST NOT BE READ and broadcasted. :returns list(dict). Example : { 'body': HTML content of the message 'model': u'res.partner', 'record_name': u'Agrolait', 'attachment_ids': [ { 'file_type_icon': u'webimage', 'id': 45, 'name': u'sample.png', 'filename': u'sample.png' } ], 'needaction_partner_ids': [], # list of partner ids 'res_id': 7, 'tracking_value_ids': [ { 'old_value': "", 'changed_field': "Customer", 'id': 2965, 'new_value': "Axelor" } ], 'author_id': (3, u'Administrator'), 'email_from': 'sacha@pokemon.com' # email address or False 'subtype_id': (1, u'Discussions'), 'date': '2015-06-30 08:22:33', 'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner name_get 'message_type': u'comment', 'id': 59, 'subject': False 'is_note': True # only if the message is a note (subtype == note) 'is_discussion': False # only if the message is a discussion (subtype == discussion) 'is_notification': False # only if the message is a note but is a notification aka not linked to a document like assignation 'parentMessage': {...}, # formatted message that this message is a reply to. Only present if format_reply is True }
  • read(self, fields=None, load='_classic_read')
    Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_done(self)
    Remove the needaction from messages for the current partner.
  • toggle_message_starred(self)
    Toggle messages as (un)starred. Technically, the notifications related to uid are set to (un)starred.
  • unlink(self)
  • unstar_all(self)
    @api.model
    Unstar messages for the current partner.
  • write(self, vals)

New fields (4)
  • content Char
    readonly=True required=True string='Content'
  • guest_id Many2one → mail.guest
    comodel_name='mail.guest' ondelete='cascade' readonly=True string='Reacting Guest'
  • message_id Many2one → mail.message
    comodel_name='mail.message' ondelete='cascade' readonly=True required=True string='Message'
  • partner_id Many2one → res.partner
    comodel_name='res.partner' ondelete='cascade' readonly=True string='Reacting Partner'
Public methods (1)
  • init(self)

New fields (9)
  • default Boolean
    default=True help='Activated by default when subscribing.' args: 'Default'
  • description Text
    help='Description that will be added in the message posted for this subtype. If void, the name will be added instead.' translate=True args: 'Description'
  • hidden Boolean
    help='Hide the subtype in the follower options' args: 'Hidden'
  • internal Boolean
    help='Messages with internal subtypes will be visible only by employees, aka members of base_user group' args: 'Internal Only'
  • name Char
    help='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.' required=True translate=True args: 'Message Type'
  • parent_id Many2one → mail.message.subtype
    help='Parent subtype, used for automatic subscription. This field is not correctly named. For example on a project, the parent_id of project subtypes refers to task-related subtypes.' ondelete='set null' string='Parent' args: 'mail.message.subtype'
  • relation_field Char
    help='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).' args: 'Relation field'
  • res_model Char
    help='Model the subtype applies to. If False, this subtype applies to all models.' args: 'Model'
  • sequence Integer
    default=1 help='Used to order subtypes.' args: 'Sequence'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • default_subtypes(self, model_name)
    @api.model
    Retrieve the default subtypes (all, internal, external) for the given model.
  • unlink(self)
  • write(self, vals)

New fields (9)
  • failure_reason Text
    copy=False args: 'Failure reason'
  • failure_type Selection
    selection=[('unknown', 'Unknown error'), ('mail_email_invalid', 'Invalid email address'), ('mail_email_missing', 'Missing email addresss'), ('mail_smtp', 'Connection failed (outgoing mail server problem)')] string='Failure type'
  • is_read Boolean
    index=True args: 'Is Read'
  • mail_mail_id Many2one → mail.mail
    help='Optional mail_mail ID. Used mainly to optimize searches.' index=True args: 'mail.mail', 'Mail'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification_status Selection
    default='ready' index=True string='Status' args: [('ready', 'Ready to Send'), ('sent', 'Sent'), ('bounce', 'Bounced'), ('exception', 'Exception'), ('canceled', 'Canceled')]
  • notification_type Selection
    default='inbox' index=True required=True string='Notification Type' args: [('inbox', 'Inbox'), ('email', 'Email')]
  • read_date Datetime
    copy=False args: 'Read Date'
  • res_partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner', 'Recipient'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • format_failure_reason(self)
  • init(self)
  • write(self, vals)

New fields (7)
  • copyvalue Char
    help='Final placeholder expression, to be copy-pasted in the desired template field.' store=False args: 'Placeholder Expression'
  • lang Char
    help='Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. {{ object.partner_id.lang }}.' args: 'Language'
  • model_object_field Many2one → ir.model.fields
    help='Select target field from the related document model.\nIf it is a relationship field you will be able to select a target field at the destination of the relationship.' store=False string='Field' args: 'ir.model.fields'
  • null_value Char
    help='Optional value to use if the target field is empty' store=False args: 'Default Value'
  • render_model Char
    compute='_compute_render_model' store=False args: 'Rendering Model'
  • sub_model_object_field Many2one → ir.model.fields
    help='When a relationship field is selected as first field, this field lets you select the target field within the destination document model (sub-model).' store=False args: 'ir.model.fields', 'Sub-field'
  • sub_object Many2one → ir.model
    help='When a relationship field is selected as first field, this field shows the document model the relationship goes to.' readonly=True store=False args: 'ir.model', 'Sub-model'
Public methods (2)
  • create(self, values_list)
    @api.model_create_multi
  • write(self, vals)

New fields (2)
  • help_message Char
    compute='_compute_help_message' string='Help message'
  • model Char
    string='Model'
Public methods (1)
  • cancel_resend_action(self)

New fields (5)
  • has_cancel Boolean
    compute='_compute_has_cancel'
  • mail_message_id Many2one → mail.message
    readonly=True args: 'mail.message', 'Message'
  • notification_ids Many2many → mail.notification
    readonly=True string='Notifications' args: 'mail.notification'
  • partner_ids One2many → mail.resend.partner
    string='Recipients' args: 'mail.resend.partner', 'resend_wizard_id'
  • partner_readonly Boolean
    compute='_compute_partner_readonly'
Public methods (3)
  • cancel_mail_action(self)
  • default_get(self, fields)
    @api.model
  • resend_mail_action(self)
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (6)
  • email Char
    readonly=False related='partner_id.email' related_sudo=False
  • message Char
    string='Help message'
  • name Char
    readonly=False related='partner_id.name' related_sudo=False
  • partner_id Many2one → res.partner
    ondelete='cascade' required=True string='Partner' args: 'res.partner'
  • resend Boolean
    default=True string='Send Again'
  • resend_wizard_id Many2one → mail.resend.message
    string='Resend wizard' args: 'mail.resend.message'
Public methods (0)

No public methods.

New fields (4)
  • description Char
    args: 'Description'
  • message_ids Many2one → mail.message
    store=False string='Messages' args: 'mail.message'
  • source Char
    help='The shortcut which must be replaced in the Chat Messages' index=True required=True args: 'Shortcut'
  • substitution Text
    help='The escaped html code replacing the shortcut' index=True required=True args: 'Substitution'
Public methods (0)

No public methods.

New fields (19)
  • attachment_ids Many2many → ir.attachment
    help='You may attach files to this template, to be added to all emails created from this template' args: 'ir.attachment', 'email_template_attachment_rel', 'email_template_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    default=True help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_html Html
    render_engine='qweb' sanitize=False translate=True args: 'Body'
  • can_write Boolean
    compute='_compute_can_write' help='The current user can edit the template.'
  • email_cc Char
    help='Carbon copy recipients (placeholders may be used here)' args: 'Cc'
  • email_from Char
    help="Sender address (placeholders may be used here). If not set, the default value will be the author's email alias if configured, or email address." args: 'From'
  • email_to Char
    help='Comma-separated recipient addresses (placeholders may be used here)' args: 'To (Emails)'
  • mail_server_id Many2one → ir.mail_server
    help='Optional preferred server for outgoing mails. If not set, the highest priority one will be used.' readonly=False args: 'ir.mail_server', 'Outgoing Mail Server'
  • model Char
    index=True readonly=True related='model_id.model' store=True args: 'Related Document Model'
  • model_id Many2one → ir.model
    help='The type of document this template can be used with' args: 'ir.model', 'Applies to'
  • name Char
    translate=True args: 'Name'
  • partner_to Char
    help='Comma-separated ids of recipient partners (placeholders may be used here)' args: 'To (Partners)'
  • ref_ir_act_window Many2one → ir.actions.act_window
    copy=False help='Sidebar action to make this template available on records of the related document model' readonly=True args: 'ir.actions.act_window', 'Sidebar action'
  • reply_to Char
    help='Email address to which replies will be redirected when sending emails in mass; only used when the reply is not logged in the original discussion thread.' args: 'Reply To'
  • report_name Char
    help='Name to use for the generated report file (may contain placeholders)\nThe extension can be omitted and will then come from the report type.' translate=True args: 'Report Filename'
  • report_template Many2one → ir.actions.report
    args: 'ir.actions.report', 'Optional report to print and attach'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. You can use dynamic expressions expression.' args: 'Scheduled Date'
  • subject Char
    help='Subject (placeholders may be used here)' translate=True args: 'Subject'
  • use_default_to Boolean
    help='Default recipients of the record:\n- partner (using id on a partner or the partner_id field) OR\n- email (using email_from or email field)' args: 'Default recipients'
Public methods (10)
  • copy(self, default=None)
    @api.returns('self', <expr>)
  • create(self, values_list)
    @api.model_create_multi
  • create_action(self)
  • default_get(self, fields)
    @api.model
  • generate_email(self, res_ids, fields)
    Generates an email from the template for given the given model based on records given by res_ids. :param res_id: id of the record to use for rendering the template (model is taken from template definition) :returns: a dict containing all relevant fields for creating a new mail.mail entry, with one extra key ``attachments``, in the format [(report_name, data)] where data is base64 encoded.
  • generate_recipients(self, results, res_ids)
    Generates the recipients of the template. Default values can ben generated instead of the template values if requested by template or context. Emails (email_to, email_cc) can be transformed into partners if requested in the context.
  • send_mail(self, res_id, force_send=False, raise_exception=False, email_values=None, notif_layout=False)
    Generates a new mail.mail. Template is rendered on record given by res_id and model coming from template. :param int res_id: id of the record to render the template :param bool force_send: send email immediately; otherwise use the mail queue (recommended); :param dict email_values: update generated mail with those values to further customize the mail; :param str notif_layout: optional notification layout to encapsulate the generated email; :returns: id of the mail.mail that was created
  • unlink(self)
  • unlink_action(self)
  • write(self, vals)

New fields (15)
  • attachment_ids Many2many → ir.attachment
    compute='_compute_mail_template_fields' args: 'ir.attachment', 'Attachments'
  • body_html Html
    compute='_compute_mail_template_fields' sanitize=False args: 'Body'
  • email_cc Char
    compute='_compute_mail_template_fields' help='Carbon copy recipients' args: 'Cc'
  • email_from Char
    compute='_compute_mail_template_fields' help='Sender address' args: 'From'
  • email_to Char
    compute='_compute_mail_template_fields' help='Comma-separated recipient addresses' args: 'To'
  • error_msg Char
    readonly=True args: 'Error Message'
  • lang Selection
    string='Template Preview Language' args: _selection_languages
  • mail_template_id Many2one → mail.template
    required=True string='Related Mail Template' args: 'mail.template'
  • model_id Many2one → ir.model
    related='mail_template_id.model_id' string='Targeted model' args: 'ir.model'
  • no_record Boolean
    compute='_compute_no_record' args: 'No Record'
  • partner_ids Many2many → res.partner
    compute='_compute_mail_template_fields' string='Recipients' args: 'res.partner'
  • reply_to Char
    compute='_compute_mail_template_fields' help='Preferred response address' args: 'Reply-To'
  • resource_ref Reference
    selection='_selection_target_model' string='Record'
  • scheduled_date Char
    compute='_compute_mail_template_fields' help='The queue manager will send the email after the date' args: 'Scheduled Date'
  • subject Char
    compute='_compute_mail_template_fields' args: 'Subject'
Public methods (1)
  • default_get(self, fields)
    @api.model

New fields (13)
  • has_message Boolean
    compute='_compute_has_message' search='_search_has_message' store=False
  • message_attachment_count Integer
    compute='_compute_message_attachment_count' groups='base.group_user' args: 'Attachment Count'
  • message_follower_ids One2many → mail.followers
    groups='base.group_user' string='Followers' args: 'mail.followers', 'res_id'
  • message_has_error Boolean
    compute='_compute_message_has_error' help='If checked, some messages have a delivery error.' search='_search_message_has_error' args: 'Message Delivery error'
  • message_has_error_counter Integer
    compute='_compute_message_has_error' help='Number of messages with delivery error' args: 'Number of errors'
  • message_ids One2many → mail.message
    auto_join=True domain=<expr> string='Messages' args: 'mail.message', 'res_id'
  • message_is_follower Boolean
    compute='_compute_message_is_follower' search='_search_message_is_follower' args: 'Is Follower'
  • message_main_attachment_id Many2one → ir.attachment
    comodel_name='ir.attachment' copy=False index=True string='Main Attachment'
  • message_needaction Boolean
    compute='_compute_message_needaction' help='If checked, new messages require your attention.' search='_search_message_needaction' args: 'Action Needed'
  • message_needaction_counter Integer
    compute='_compute_message_needaction' help='Number of messages which requires an action' args: 'Number of Actions'
  • message_partner_ids Many2many → res.partner
    comodel_name='res.partner' compute='_compute_message_partner_ids' groups='base.group_user' search='_search_message_partner_ids' string='Followers (Partners)'
  • message_unread Boolean
    compute='_compute_message_unread' help='If checked, new messages require your attention.' args: 'Unread Messages'
  • message_unread_counter Integer
    compute='_compute_message_unread' help='Number of unread messages' args: 'Unread Messages Counter'
Public methods (18)
  • copy_data(self, default=None)
  • create(self, vals_list)
    @api.model_create_multi
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • get_empty_list_help(self, help)
    @api.model
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • message_change_thread(self, new_thread, new_parent_message=False)
    Transfer the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : my_lead.message_change_thread(my_project_task) will transfer the context of the thread of my_lead to my_project_task
  • message_new(self, msg_dict, custom_values=None)
    @api.model
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :rtype: int :return: the id of the newly created thread object
  • message_notify(self, *, partner_ids=False, parent_id=False, model=False, res_id=False, author_id=None, email_from=None, body='', subject=False, **kwargs)
    Shortcut allowing to notify partners of messages that shouldn't be displayed on a document. It pushes notifications on inbox or by email depending on the user configuration, like other notifications.
  • message_parse(self, message, save_original=False)
    @api.model
    Parses an email.message.Message representing an RFC-2822 email and returns a generic dict holding the message details. :param message: email to parse :type message: email.message.Message :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'email_from': from, 'to': to + delivered-to, 'cc': cc, 'recipients': delivered-to + to + cc + resent-to + resent-cc, 'partner_ids': partners found based on recipients emails, 'body': unified_body, 'references': references, 'in_reply_to': in-reply-to, 'parent_id': parent mail.message based on in_reply_to or references, 'is_internal': answer to an internal message (note), 'date': date, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_post(self, *, body='', subject=None, message_type='notification', email_from=None, author_id=None, parent_id=False, subtype_xmlid=None, subtype_id=False, partner_ids=None, attachments=None, attachment_ids=None, add_sign=True, record_name=False, **kwargs)
    @api.returns('mail.message', <expr>)
    Post a new message in an existing thread, returning the new mail.message ID. :param str body: body of the message, usually raw HTML that will be sanitized :param str subject: subject of the message :param str message_type: see mail_message.message_type field. Can be anything but user_notification, reserved for message_notify :param int parent_id: handle thread formation :param int subtype_id: subtype_id of the message, used mainly use for followers notification mechanism; :param list(int) partner_ids: partner_ids to notify in addition to partners computed based on subtype / followers matching; :param list(tuple(str,str), tuple(str,str, dict) or int) attachments : list of attachment tuples in the form ``(name,content)`` or ``(name,content, info)``, where content is NOT base64 encoded :param list id attachment_ids: list of existing attachement to link to this message -Should only be setted by chatter -Attachement object attached to mail.compose.message(0) will be attached to the related document. Extra keyword arguments will be used as default column values for the new mail.message record. :return int: ID of newly created mail.message
  • message_post_with_template(self, template_id, email_layout_xmlid=None, auto_commit=False, **kwargs)
    Helper method to send a mail with a template :param template_id : the id of the template to render to create the body of the message :param **kwargs : parameter to create a mail.compose.message woaerd (which inherit from mail.message)
  • message_post_with_view(self, views_or_xmlid, **kwargs)
    Helper method to send a mail / post a message using a view_id
  • message_process(self, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None)
    @api.model
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: string or xmlrpclib.Binary :type dict custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None)
    @api.model
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: * if the message replies to an existing thread by having a Message-Id that matches an existing mail_message.message_id, we take the original message model/thread_id pair and ignore custom_value as no creation will take place; * look for a mail.alias entry matching the message recipients and use the corresponding model, thread_id, custom_values and user_id. This could lead to a thread update or creation depending on the alias; * fallback on provided ``model``, ``thread_id`` and ``custom_values``; * raise an exception as no route has been found :param string message: an email.message instance :param dict message_dict: dictionary holding parsed message variables :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :type dict custom_values: optional dictionary of default field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of routes [(model, thread_id, custom_values, user_id, alias)] :raises: ValueError, TypeError
  • message_subscribe(self, partner_ids=None, subtype_ids=None)
    Main public API to add followers to a record set. Its main purpose is to perform access rights checks before calling ``_message_subscribe``.
  • message_track(self, tracked_fields, initial_values)
    Track updated values. Comparing the initial and current values of the fields given in tracked_fields, it generates a message containing the updated values. This message can be linked to a mail.message.subtype given by the ``_track_subtype`` method. :param tracked_fields: iterable of field names to track :param initial_values: mapping {record_id: {field_name: value}} :return: mapping {record_id: (changed_field_names, tracking_value_ids)} containing existing records only
  • message_unsubscribe(self, partner_ids=None)
    Remove partners from the records followers.
  • message_update(self, msg_dict, update_vals=None)
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • unlink(self)
    Override unlink to delete messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • write(self, values)

New fields (3)
  • email_normalized Char
    compute='_compute_email_normalized' compute_sudo=True help='This field is used to search on email address as the primary email field can contain more than strictly an email address.' invisible=True store=True string='Normalized Email'
  • is_blacklisted Boolean
    compute='_compute_is_blacklisted' compute_sudo=True groups='base.group_user' help="If the email address is on the blacklist, the contact won't receive mass mailing anymore, from any list" search='_search_is_blacklisted' store=False string='Blacklist'
  • message_bounce Integer
    default=0 help='Counter of the number of bounced emails for this contact' args: 'Bounce'
Public methods (1)
  • mail_action_blacklist_remove(self)

New fields (1)
  • email_cc Char
    help='List of cc from incoming emails.' args: 'Email cc'
Public methods (2)
  • message_new(self, msg_dict, custom_values=None)
    @api.model
  • message_update(self, msg_dict, update_vals=None)
    Adds cc email to self.email_cc while trying to keep email as raw as possible but unique

New fields (19)
  • currency_id Many2one → res.currency
    help='Used to display the currency when tracking monetary values' ondelete='set null' readonly=True args: 'res.currency', 'Currency'
  • field Many2one → ir.model.fields
    ondelete='cascade' readonly=1 required=True args: 'ir.model.fields'
  • field_desc Char
    readonly=1 required=True args: 'Field Description'
  • field_groups Char
    compute='_compute_field_groups'
  • field_type Char
    args: 'Field Type'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message ID'
  • new_value_char Char
    readonly=1 args: 'New Value Char'
  • new_value_datetime Datetime
    readonly=1 args: 'New Value Datetime'
  • new_value_float Float
    readonly=1 args: 'New Value Float'
  • new_value_integer Integer
    readonly=1 args: 'New Value Integer'
  • new_value_monetary Float
    readonly=1 args: 'New Value Monetary'
  • new_value_text Text
    readonly=1 args: 'New Value Text'
  • old_value_char Char
    readonly=1 args: 'Old Value Char'
  • old_value_datetime Datetime
    readonly=1 args: 'Old Value DateTime'
  • old_value_float Float
    readonly=1 args: 'Old Value Float'
  • old_value_integer Integer
    readonly=1 args: 'Old Value Integer'
  • old_value_monetary Float
    readonly=1 args: 'Old Value Monetary'
  • old_value_text Text
    readonly=1 args: 'Old Value Text'
  • tracking_sequence Integer
    default=100 readonly=1 args: 'Tracking field sequence'
Public methods (4)
  • create_tracking_values(self, initial_value, new_value, col_name, col_info, tracking_sequence, model_name)
    @api.model
  • get_display_value(self, type)
  • get_new_display_value(self)
  • get_old_display_value(self)

New fields (5)
  • message Html
    args: 'Message'
  • partner_ids Many2many → res.partner
    domain=[('type', '!=', 'private')] help='List of partners that will be added as follower of the current document.' string='Recipients' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' index=True args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' index=True required=True args: 'Related Document Model'
  • send_mail Boolean
    default=True help="If checked, the partners will receive an email warning they have been added in the document's followers." args: 'Send Email'
Public methods (2)
  • add_followers(self)
  • default_get(self, fields)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cron_mode=True)
    Send a message to Odoo's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (3)
  • catchall_email Char
    compute='_compute_catchall' string='Catchall Email'
  • catchall_formatted Char
    compute='_compute_catchall' string='Catchall'
  • email_formatted Char
    compute='_compute_email_formatted' compute_sudo=True string='Formatted Email'
Public methods (0)

No public methods.

New fields (6)
  • alias_domain Char
    config_parameter='mail.catchall.domain' help='If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.' args: 'Alias Domain'
  • fail_counter Integer
    readonly=True args: 'Fail Mail'
  • restrict_template_rendering Boolean
    config_parameter='mail.restrict.template.rendering' help='Users will still be able to render templates.\nHowever only Mail Template Editors will be able to create new dynamic templates or modify existing ones.' args: 'Restrict Template Rendering'
  • twilio_account_sid Char
    config_parameter='mail.twilio_account_sid' args: 'Twilio Account SID'
  • twilio_account_token Char
    config_parameter='mail.twilio_account_token' args: 'Twilio Account Auth Token'
  • use_twilio_rtc_servers Boolean
    config_parameter='mail.use_twilio_rtc_servers' help='If you want to use twilio as TURN/STUN server provider' args: 'Use Twilio ICE servers'
Public methods (2)
  • get_values(self)
    @api.model
  • set_values(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals)

New fields (6)
  • channel_ids Many2many → mail.channel
    copy=False string='Channels' args: 'mail.channel', 'mail_channel_partner', 'partner_id', 'channel_id'
  • email Char
    tracking=1
  • parent_id Many2one
    tracking=3
  • phone Char
    tracking=2
  • user_id Many2one
    tracking=4
  • vat Char
    tracking=5
Public methods (5)
  • find_or_create(self, email, assert_valid_email=False)
    @api.model@api.returns('self', <expr>)
    Override to use the email_normalized field.
  • get_mention_suggestions(self, search, limit=8, channel_id=None)
    @api.model
    Return 'limit'-first partners' such that the name or email matches a 'search' string. Prioritize partners that are also (internal) users, and then extend the research to all partners. If channel_id is given, only members of this channel are returned. The return format is a list of partner data (as per returned by `mail_partner_format()`).
  • im_search(self, name, limit=20)
    @api.model
    Search partner with a name and return its id, name and im_status. Note : the user must be logged :param name : the partner name to search :param limit : the limit of result to return
  • mail_partner_format(self)
  • search_for_channel_invite(self, search_term, channel_id=None, limit=30)
    @api.model
    Returns partners matching search_term that can be invited to a channel. If the channel_id is specified, only partners that can actually be invited to the channel are returned (not already members, and in accordance to the channel configuration).

New fields (2)
  • notification_type Selection
    default='email' help='Policy on how to handle Chatter notifications:\n- Handle by Emails: notifications are sent to your email address\n- Handle in Odoo: notifications appear in your Odoo Inbox' required=True args: [('email', 'Handle by Emails'), ('inbox', 'Handle in Odoo')], 'Notification'
  • res_users_settings_ids One2many → res.users.settings
    args: 'res.users.settings', 'user_id'
Public methods (6)
  • SELF_READABLE_FIELDS(self)
    @property
  • SELF_WRITEABLE_FIELDS(self)
    @property
  • create(self, vals_list)
    @api.model_create_multi
  • systray_get_activities(self)
    @api.model
  • unlink(self)
  • write(self, vals)

New fields (7)
  • is_discuss_sidebar_category_channel_open Boolean
    default=True string='Is discuss sidebar category channel open?'
  • is_discuss_sidebar_category_chat_open Boolean
    default=True string='Is discuss sidebar category chat open?'
  • push_to_talk_key Char
    help='String formatted to represent a key with modifiers following this pattern: shift.ctrl.alt.key, e.g: truthy.1.true.b' string='Push-To-Talk shortcut'
  • use_push_to_talk Boolean
    default=False string='Use the push to talk feature'
  • user_id Many2one → res.users
    ondelete='cascade' readonly=True required=True string='User' args: 'res.users'
  • voice_active_duration Integer
    help='How long the audio broadcast will remain active after passing the volume threshold' string='Duration of voice activity in ms'
  • volume_settings_ids One2many → res.users.settings.volumes
    string='Volumes of other partners' args: 'res.users.settings.volumes', 'user_setting_id'
Public methods (2)
  • set_res_users_settings(self, new_settings)
  • set_volume_setting(self, partner_id, volume, guest_id=None)
    Saves the volume of a guest or a partner. Either partner_id or guest_id must be specified. :param float volume: the selected volume between 0 and 1 :param int partner_id: :param int guest_id:

New fields (4)
  • guest_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner'
  • user_setting_id Many2one → res.users.settings
    index=True ondelete='cascade' required=True args: 'res.users.settings'
  • volume Float
    default=0.5 help='Ranges between 0.0 and 1.0, scale depends on the browser implementation'
Public methods (1)
  • init(self)
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/14.0/mail
VERSION
VERSION 1.0
CATEGORY
CATEGORYProductivity/Discuss
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Martin Trigaux, Olivier Dony, Thibault Delavallée, Xavier ALT, Christophe Simonis, Xavier Morel, Goffin Simon, Mohammed Shekha, Nicolas Martinelli, Nicolas Lempereur, Thibault Francois, qdp-odoo, Aaron Bohy, Pedro M. Baeza, GitHub, Lucas Perais (lpe), Damien Bouvy, Barad Mahendra, Yannick Tivisse, Adrien Dieudonne, Jorge Pinna Puissant, Alexandre Kühn, Toufik Ben Jaa, Adrian Torres, Julien Castiaux, Aurélien Warnon, Priyanka Kakadiya, Xavier-Do, David Tran, Romeo Fragomeli, jvm-odoo, jerome hanke (jhk), Victor Feyens, Andrea Grazioso (agr-odoo), Paul Morelle, Xavier Dubuc, Sébastien Theys, david, Nasreddin (bon), alt-odoo, Florent de Labarre, Julien Mougenot, Jason Van Malder, Vincent Schippefilt, fw-bot, Anh Thao Pham (pta), Debauche Stéphane, Luis González, Alvaro Fuentes, std-odoo, Achraf (abz), David Beguin, Lucas Lefèvre, Adrien Widart, Ivan Yelizariev, Hubert (huvw), Nasreddin Boulif (bon), Prakash Prajapati, Kamesh Patel, Nicolas Galler, nie, Tiffany Chang (tic), Nathan Marotte (nama), Thanh Dodeur, Gorash, Mathieu Duckerts-Antoine, Pierre Paridans, Hoang Tran, Hiral Bhavsar, nounoubensebia, bit-odoo, Romain Estievenart, Kevin Baptiste, roen-odoo, Dhruv Patel, Hubert Van de Walle (huvw), Laurent Desausoi (lade), momegahed, mcm-odoo, Julien Van Roy, Florian Damhaut, Merlin (megu), MerlinGuillaume, tranngocson1996, thcl-odoo, Didier (did), jpr-odoo, anhe-odoo, Walid HANNICHE (waha), Abdelouahab (abla), Florian Gilbert, Hemali Bhimani, Aurelien van Delft (avd), Michael Mattiello (mcm), Julien Giannone, Renaud Thiry, Ipsita Borisagar, bve-odoo, Francois (fge), tsm-odoo, Simon Genin (ges), Pierre-Yves Dufays, Qiuyu (QHO), xO-Tx, Pierre Collinet (pic), Antoine (ande), Nguyen Viet Phuong, Nam Dao, imanie383, Rahul Prajapati, Hoang The Vuong, Odoo, Leloup Loïc (lole)
WEBSITE
WEBSITEhttps://www.odoo.com/page/discuss
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:14:30
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web
    - bus
    - web_tour
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (78)
XML IDNameModelTypeStatus
_assets_primary_variables _assets_primary_variables ir.ui.view qweb Inherits web._assets_primary_variables
assets_backend mail assets ir.ui.view qweb Inherits web.assets_backend
assets_backend_prod_only mail prod only assets ir.ui.view qweb Inherits web.assets_backend_prod_only
assets_tests Mail Assets Tests ir.ui.view qweb Inherits web.assets_tests
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
email_template_form email.template.form mail.template form New
email_template_tree email.template.tree mail.template tree New
field_form_view ir.model.fields field Inherits base.view_model_fields_form
mail_activity_type_view_form mail.activity.type.view.form mail.activity.type form New
mail_activity_type_view_search mail.activity.type.search mail.activity.type search New
mail_activity_type_view_tree mail.activity.type.view.tree mail.activity.type tree New
mail_activity_view_calendar mail.activity.view.calendar mail.activity calendar New
mail_activity_view_form_popup mail.activity.view.form.popup mail.activity form New
mail_activity_view_search mail.activity.view.search mail.activity search New
mail_activity_view_tree mail.activity.view.tree mail.activity tree New
mail_blacklist_remove_view_form mail.blacklist.remove.form mail.blacklist.remove form New
mail_blacklist_view_form mail.blacklist.view.form mail.blacklist form New
mail_blacklist_view_search mail.blacklist.view.search mail.blacklist search New
mail_blacklist_view_tree mail.blacklist.view.tree mail.blacklist tree New
mail_bounce_alias_security mail_bounce_alias_security ir.ui.view qweb New
mail_bounce_catchall mail_bounce_catchall ir.ui.view qweb New
mail_channel_notify_moderation mail_channel_notify_moderation ir.ui.view qweb New
mail_channel_partner_view_form mail.channel.partner.form mail.channel.partner form New
mail_channel_partner_view_tree mail.channel.partner.tree mail.channel.partner tree New
mail_channel_send_guidelines mail_channel_send_guidelines ir.ui.view qweb New
mail_channel_view_form mail.channel.form mail.channel form New
mail_channel_view_kanban mail.channel.kanban mail.channel kanban New
mail_channel_view_search mail.channel.search mail.channel search New
mail_channel_view_tree mail.channel.tree mail.channel tree New
mail_message_view_form mail.message.view.form mail.message form New
mail_moderation_view_search mail.moderation.view.search mail.moderation search New
mail_moderation_view_tree mail.moderation.view.tree mail.moderation tree New
mail_notification_borders mail_notification_borders ir.ui.view qweb New
mail_notification_light mail_notification_light ir.ui.view qweb New
mail_notification_paynow Mail: Pay Now mail notification template ir.ui.view qweb New
mail_notification_view_form mail.notification.view.form mail.notification form New
mail_notification_view_tree mail.notification.view.tree mail.notification tree New
mail_resend_cancel_view_form mail.resend.cancel.view.form mail.resend.cancel form New
mail_resend_message_view_form mail.resend.message.view.form mail.resend.message form New
mail_shortcode_view_form mail.shortcode.form mail.shortcode form New
mail_shortcode_view_tree mail.shortcode.tree mail.shortcode tree New
mail_template_preview_view_form mail.template.preview.view.form mail.template.preview form New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
message_activity_assigned message_activity_assigned ir.ui.view qweb New
message_activity_done message_activity_done ir.ui.view qweb New
message_notification_email message_notification_email ir.ui.view qweb New
message_origin_link message_origin_link ir.ui.view qweb New
message_user_assigned message_user_assigned ir.ui.view qweb New
model_form_view ir.model field Inherits base.view_model_form
model_search_view ir.model field Inherits base.view_model_search
qunit_mobile_suite mail_qunit_mobile_suite ir.ui.view qweb Inherits web.qunit_mobile_suite_tests
qunit_suite mail_tests ir.ui.view qweb Inherits web.qunit_suite_tests
res_config_settings_view_form res.config.settings.view.form.inherit.mail res.config.settings div Inherits base_setup.res_config_settings_view_form
res_partner_view_activity res.partner.activity res.partner activity New
res_partner_view_form_inherit_mail res.partner.view.form.inherit.mail res.partner xpath Inherits base.view_partner_form
res_partner_view_kanban_inherit_mail res.partner.view.kanban.inherit.mail res.partner field Inherits base.res_partner_kanban_view
res_partner_view_search_inherit_mail res.partner.view.search.inherit.mail res.partner filter Inherits base.view_res_partner_filter
res_partner_view_tree_inherit_mail res.partner.view.tree.inherit.mail res.partner xpath Inherits base.view_partner_tree
tests_assets mail_tests_assets ir.ui.view qweb Inherits web.tests_assets
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_email_template_search email.template.search mail.template search New
view_followers_tree mail.followers.tree mail.followers tree New
view_mail_alias_form mail.alias.form mail.alias form New
view_mail_alias_search mail.alias.search mail.alias search New
view_mail_alias_tree mail.alias.tree mail.alias tree New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tracking_value_form mail.tracking.value.form mail.tracking.value form New
view_mail_tracking_value_tree mail.tracking.value.tree mail.tracking.value tree New
view_mail_tree mail.mail.tree mail.mail tree New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.tree mail.message.subtype tree New
view_message_tree mail.message.tree mail.message tree New
view_server_action_form_template ir.actions.server.form ir.actions.server xpath Inherits base.view_server_action_form
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (46)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (1)
  • view_mode Selection
    ondelete={'activity': 'cascade'} selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (12)
  • activity_date_deadline_range Integer
    string='Due Date In'
  • activity_date_deadline_range_type Selection
    default='days' string='Due type' args: [('days', 'Days'), ('weeks', 'Weeks'), ('months', 'Months')]
  • activity_note Html
    args: 'Note'
  • activity_summary Char
    args: 'Summary'
  • activity_type_id Many2one → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', model_id)]" ondelete='restrict' string='Activity' args: 'mail.activity.type'
  • activity_user_field_name Char
    default='user_id' help='Technical name of the user on the record' args: 'User field name'
  • activity_user_id Many2one → res.users
    string='Responsible' args: 'res.users'
  • activity_user_type Selection
    default='specific' help="Use 'Specific User' to always assign the same user on the next activity. Use 'Generic User From Record' to specify the field name of the user to choose on the record." required=True args: [('specific', 'Specific User'), ('generic', 'Generic User From Record')]
  • channel_ids Many2many → mail.channel
    string='Add Channels' args: 'mail.channel'
  • partner_ids Many2many → res.partner
    string='Add Followers' args: 'res.partner'
  • state Selection
    ondelete={'email': 'cascade', 'followers': 'cascade', 'next_activity': 'cascade'} selection_add=[('email', 'Send Email'), ('followers', 'Add Followers'), ('next_activity', 'Create Next Activity')]
  • template_id Many2one → mail.template
    domain="[('model_id', '=', model_id)]" ondelete='set null' args: 'mail.template', 'Email Template'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • register_as_main_attachment(self, force=True)
    Registers this attachment as the main one of the model it is attached to.

New fields (0)

No new fields.

Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, vals)

New fields (0)

No new fields.

Public methods (1)
  • session_info(self)

New fields (3)
  • is_mail_activity Boolean
    default=False help='Whether this model supports activities.' string='Mail Activity'
  • is_mail_blacklist Boolean
    default=False help='Whether this model supports blacklist.' string='Mail Blacklist'
  • is_mail_thread Boolean
    default=False help='Whether this model supports messages and notifications.' string='Mail Thread'
Public methods (2)
  • unlink(self)
  • write(self, vals)

New fields (1)
  • tracking Integer
    help='If set every modification done to this field is tracked in the chatter. Value is used to order tracking values.' string='Enable Ordered Tracking'
Public methods (0)

No public methods.

New fields (1)
  • type Selection
    selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (21)
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_decoration Selection
    readonly=True related='activity_type_id.decoration_type'
  • activity_type_id Many2one → mail.activity.type
    default=_default_activity_type_id domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" ondelete='restrict' string='Activity Type' args: 'mail.activity.type'
  • automated Boolean
    help='Indicates this activity has been created automatically and not by any user.' readonly=True args: 'Automated activity'
  • can_write Boolean
    compute='_compute_can_write' help='Technical field to hide buttons if the current user has no access.'
  • date_deadline Date
    default=fields.Date.context_today index=True required=True args: 'Due Date'
  • force_next Boolean
    readonly=True related='activity_type_id.force_next'
  • has_recommended_activities Boolean
    compute='_compute_has_recommended_activities' help='Technical field for UX purpose' args: 'Next activities available'
  • icon Char
    readonly=True related='activity_type_id.icon' args: 'Icon'
  • mail_template_ids Many2many
    readonly=True related='activity_type_id.mail_template_ids'
  • note Html
    sanitize_style=True args: 'Note'
  • previous_activity_type_id Many2one → mail.activity.type
    readonly=True string='Previous Activity Type' args: 'mail.activity.type'
  • recommended_activity_type_id Many2one → mail.activity.type
    string='Recommended Activity Type' args: 'mail.activity.type'
  • request_partner_id Many2one → res.partner
    string='Requesting Partner' args: 'res.partner'
  • res_id Many2oneReference
    index=True model_field='res_model' required=True string='Related Document ID'
  • res_model Char
    compute_sudo=True index=True readonly=True related='res_model_id.model' store=True args: 'Related Document Model'
  • res_model_id Many2one → ir.model
    index=True ondelete='cascade' required=True args: 'ir.model', 'Document Model'
  • res_name Char
    compute='_compute_res_name' compute_sudo=True help='Display name of the related document.' readonly=True store=True args: 'Document Name'
  • state Selection
    compute='_compute_state' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')], 'State'
  • summary Char
    args: 'Summary'
  • user_id Many2one → res.users
    default=<expr> index=True required=True args: 'res.users', 'Assigned to'
Public methods (13)
  • action_close_dialog(self)
  • action_done(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_done_schedule_next(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_feedback(self, feedback=False, attachment_ids=None)
  • action_feedback_schedule_next(self, feedback=False)
  • action_notify(self)
  • activity_format(self)
  • create(self, values)
    @api.model
  • default_get(self, fields)
    @api.model
  • get_activity_data(self, res_model, domain)
    @api.model
  • name_get(self)
  • unlink(self)
  • write(self, values)

New fields (10)
  • activity_date_deadline Date
    compute='_compute_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_activity_date_deadline' store=False args: 'Next Activity Deadline'
  • activity_exception_decoration Selection
    compute='_compute_activity_exception_type' help='Type of the exception activity on record.' search='_search_activity_exception_decoration' args: [('warning', 'Alert'), ('danger', 'Error')]
  • activity_exception_icon Char
    compute='_compute_activity_exception_type' help='Icon to indicate an exception activity.' args: 'Icon'
  • activity_ids One2many → mail.activity
    auto_join=True groups='base.group_user' args: 'mail.activity', 'res_id', 'Activities'
  • activity_state Selection
    compute='_compute_activity_state' groups='base.group_user' help='Status based on activities\nOverdue: Due date is already passed\nToday: Activity date is today\nPlanned: Future activities.' string='Activity State' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')]
  • activity_summary Char
    groups='base.group_user' readonly=False related='activity_ids.summary' search='_search_activity_summary' args: 'Next Activity Summary'
  • activity_type_icon Char
    related='activity_ids.icon' args: 'Activity Type Icon'
  • activity_type_id Many2one → mail.activity.type
    groups='base.group_user' readonly=False related='activity_ids.activity_type_id' search='_search_activity_type_id' args: 'mail.activity.type', 'Next Activity Type'
  • activity_user_id Many2one → res.users
    groups='base.group_user' readonly=False related='activity_ids.user_id' search='_search_activity_user_id' args: 'res.users', 'Responsible User'
  • my_activity_date_deadline Date
    compute='_compute_my_activity_date_deadline' compute_sudo=False groups='base.group_user' readonly=True search='_search_my_activity_date_deadline' args: 'My Activity Deadline'
Public methods (9)
  • activity_feedback(self, act_type_xmlids, user_id=None, feedback=None)
    Set activities as done, limiting to some activity types and optionally to a given user.
  • activity_reschedule(self, act_type_xmlids, user_id=None, date_deadline=None, new_user_id=None)
    Reschedule some automated activities. Activities to reschedule are selected based on type xml ids and optionally by user. Purpose is to be able to * update the deadline to date_deadline; * update the responsible to new_user_id;
  • activity_schedule(self, act_type_xmlid='', date_deadline=None, summary='', note='', **act_values)
    Schedule an activity on each record of the current record set. This method allow to provide as parameter act_type_xmlid. This is an xml_id of activity type instead of directly giving an activity_type_id. It is useful to avoid having various "env.ref" in the code and allow to let the mixin handle access rights. :param date_deadline: the day the activity must be scheduled on the timezone of the user must be considered to set the correct deadline
  • activity_search(self, act_type_xmlids='', user_id=None, additional_domain=None)
    Search automated activities on current record set, given a list of activity types xml IDs. It is useful when dealing with specific types involved in automatic activities management. :param act_type_xmlids: list of activity types xml IDs :param user_id: if set, restrict to activities of that user_id; :param additional_domain: if set, filter on that domain;
  • activity_send_mail(self, template_id)
    Automatically send an email based on the given mail.template, given its ID.
  • activity_unlink(self, act_type_xmlids, user_id=None)
    Unlink activities, limiting to some activity types and optionally to a given user.
  • toggle_active(self)
    Before archiving the record we should also remove its ongoing activities. Otherwise they stay in the systray and concerning archived records it makes no sense.
  • unlink(self)
    Override unlink to delete records activities through (res_model, res_id).
  • write(self, vals)

New fields (22)
  • active Boolean
    default=True
  • category Selection
    default='default' help='Actions may trigger specific behavior like opening calendar view or automatically mark as done when a document is uploaded' string='Action to Perform' args: [('default', 'None'), ('upload_file', 'Upload Document')]
  • create_uid Many2one → res.users
    index=True args: 'res.users'
  • decoration_type Selection
    help='Change the background color of the related activities of this type.' string='Decoration Type' args: [('warning', 'Alert'), ('danger', 'Error')]
  • default_description Html
    string='Default Description' translate=True
  • default_next_type_id Many2one → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" ondelete='restrict' args: 'mail.activity.type', 'Default Next Activity'
  • default_user_id Many2one → res.users
    string='Default User' args: 'res.users'
  • delay_count Integer
    default=0 help='Number of days/week/month before executing the action. It allows to plan the action deadline.' args: 'Scheduled Date'
  • delay_from Selection
    default='previous_activity' help='Type of delay' required=True string='Delay Type' args: [('current_date', 'after validation date'), ('previous_activity', 'after previous activity deadline')]
  • delay_label Char
    compute='_compute_delay_label'
  • delay_unit Selection
    default='days' help='Unit of delay' required=True string='Delay units' args: [('days', 'days'), ('weeks', 'weeks'), ('months', 'months')]
  • force_next Boolean
    default=False args: 'Trigger Next Activity'
  • icon Char
    help='Font awesome icon e.g. fa-tasks' args: 'Icon'
  • initial_res_model_id Many2one → ir.model
    compute='_compute_initial_res_model_id' help='Technical field to keep track of the model at the start of editing to support UX related behaviour' store=False args: 'ir.model', 'Initial model'
  • mail_template_ids Many2many → mail.template
    string='Email templates' args: 'mail.template'
  • name Char
    required=True translate=True args: 'Name'
  • next_type_ids Many2many → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" string='Recommended Next Activities' args: 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id'
  • previous_type_ids Many2many → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" string='Preceding Activities' args: 'mail.activity.type', 'mail_activity_rel', 'recommended_id', 'activity_id'
  • res_model_change Boolean
    default=False help='Technical field for UX related behaviour' store=False string='Model has change'
  • res_model_id Many2one → ir.model
    domain=['&', ('is_mail_thread', '=', True), ('transient', '=', False)] help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' index=True args: 'ir.model', 'Model'
  • sequence Integer
    default=10 args: 'Sequence'
  • summary Char
    translate=True args: 'Default Summary'
Public methods (1)
  • default_get(self, fields)
    @api.model

New fields (10)
  • alias_bounced_content Html
    help='If set, this content will automatically be sent out to unauthorized users instead of the default message.' translate=True args: 'Custom Bounced Message'
  • alias_contact Selection
    default='everyone' help='Policy to post a message on the document using the mailgateway.\n- everyone: everyone can post\n- partners: only authenticated partners\n- followers: only followers of the related document or members of following channels\n' required=True string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_defaults Text
    default='{}' help='A Python dictionary that will be evaluated to provide default values when creating new records for this alias.' required=True args: 'Default Values'
  • alias_domain Char
    compute='_compute_alias_domain' default=_default_alias_domain args: 'Alias domain'
  • alias_force_thread_id Integer
    help='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.' args: 'Record Thread ID'
  • alias_model_id Many2one → ir.model
    domain="[('field_id.name', '=', 'message_ids')]" help='The model (Odoo 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)' ondelete='cascade' required=True args: 'ir.model', 'Aliased Model'
  • alias_name Char
    copy=False help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>" args: 'Alias Name'
  • alias_parent_model_id Many2one → ir.model
    help='Parent model holding the alias. The model holding the alias reference is not necessarily the model given by alias_model_id (example: project (parent_model) and task (model))' args: 'ir.model', 'Parent Model'
  • alias_parent_thread_id Integer
    help='ID of the parent record holding the alias (example: project holding the task creation alias)' args: 'Parent Record Thread ID'
  • alias_user_id Many2one → res.users
    default=<expr> help='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.' args: 'res.users', 'Owner'
Public methods (5)
  • create(self, vals)
    @api.model
    Creates an email.alias record according to the values provided in ``vals``, with 2 alterations: the ``alias_name`` value may be cleaned by replacing certain unsafe characters, and the ``alias_model_id`` value will set to the model ID of the ``model_name`` context value, if provided. Also, it raises UserError if given alias name is already assigned.
  • name_get(self)
    Return the mail alias display alias_name, including the implicit mail catchall domain if exists from config otherwise "New Alias". e.g. `jobs@mail.odoo.com` or `jobs` or 'New Alias'
  • open_document(self)
  • open_parent_document(self)
  • write(self, vals)
    "Raises UserError if given alias name is already assigned

New fields (1)
  • alias_id Many2one → mail.alias
    ondelete='restrict' required=True string='Alias' args: 'mail.alias'
Public methods (4)
  • copy_data(self, default=None)
    @api.returns(None, <expr>)
  • create(self, vals_list)
    @api.model_create_multi
    Create a record with each ``vals`` or ``vals_list`` and create a corresponding alias.
  • unlink(self)
    Delete the given records, and cascade-delete their corresponding alias.
  • write(self, vals)
    Split writable fields of mail.alias and other fields alias fields will write with sudo and the other normally

New fields (2)
  • active Boolean
    default=True tracking=True
  • email Char
    help='This field is case insensitive.' index=True required=True string='Email Address' tracking=True
Public methods (5)
  • action_add(self)
  • action_remove_with_reason(self, email, reason=None)
  • create(self, values)
    @api.model_create_multi
  • mail_action_blacklist_remove(self)
  • write(self, values)

New fields (2)
  • email Char
    name='Email' readonly=True required=True
  • reason Char
    name='Reason'
Public methods (1)
  • action_unblacklist_apply(self)

New fields (25)
  • active Boolean
    default=True help='Set active to false to hide the channel without removing it.'
  • channel_last_seen_partner_ids One2many → mail.channel.partner
    depends=['channel_partner_ids'] string='Last Seen' args: 'mail.channel.partner', 'channel_id'
  • channel_message_ids Many2many → mail.message
    copy=False args: 'mail.message', 'mail_message_mail_channel_rel'
  • channel_partner_ids Many2many → res.partner
    depends=['channel_last_seen_partner_ids'] string='Listeners' args: 'res.partner', 'mail_channel_partner', 'channel_id', 'partner_id'
  • channel_type Selection
    default='channel' args: [('chat', 'Chat Discussion'), ('channel', 'Channel')], 'Channel Type'
  • description Text
    args: 'Description'
  • email_send Boolean
    default=False args: 'Send messages by email'
  • group_ids Many2many → res.groups
    help='Members of those groups will automatically added as followers. Note that they will be able to manage their subscription manually if necessary.' string='Auto Subscription' args: 'res.groups'
  • group_public_id Many2one → res.groups
    default=<expr> string='Authorized Group' args: 'res.groups'
  • image_128 Image
    default=_get_default_image max_height=128 max_width=128 args: 'Image'
  • is_chat Boolean
    compute='_compute_is_chat' default=False string='Is a chat'
  • is_member Boolean
    compute='_compute_is_member' args: 'Is a member'
  • is_moderator Boolean
    compute='_compute_is_moderator' help='Current user is a moderator of the channel' string='Moderator'
  • is_subscribed Boolean
    compute='_compute_is_subscribed' args: 'Is Subscribed'
  • moderation Boolean
    string='Moderate this channel'
  • moderation_count Integer
    compute='_compute_moderation_count' groups='base.group_user' string='Moderated emails count'
  • moderation_guidelines Boolean
    help='Newcomers on this moderated channel will automatically receive the guidelines.' string='Send guidelines to new subscribers'
  • moderation_guidelines_msg Text
    string='Guidelines'
  • moderation_ids One2many → mail.moderation
    groups='base.group_user' string='Moderated Emails' args: 'mail.moderation', 'channel_id'
  • moderation_notify Boolean
    help='People receive an automatic notification about their message being waiting for moderation.' string='Automatic notification'
  • moderation_notify_msg Text
    string='Notification message'
  • moderator_ids Many2many → res.users
    string='Moderators' args: 'res.users', 'mail_channel_moderator_rel'
  • name Char
    required=True translate=True args: 'Name'
  • public Selection
    default='groups' help='This group is visible by non members. Invisible groups can add members through the invite button.' required=True args: [('public', 'Everyone'), ('private', 'Invited people only'), ('groups', 'Selected group of users')], 'Privacy'
  • uuid Char
    copy=False default=<expr> index=True size=50 args: 'UUID'
Public methods (31)
  • action_follow(self)
  • action_unfollow(self)
  • channel_create(self, name, privacy='groups')
    @api.model
    Create a channel and add the current partner, broadcast it (to make the user directly listen to it when polling) :param name : the name of the channel to create :param privacy : privacy of the channel. Should be 'public' or 'private'. :return dict : channel header
  • channel_fetch_listeners(self, uuid)
    @api.model
    Return the id, name and email of partners listening to the given channel
  • channel_fetch_message(self, last_id=False, limit=20)
    Return message values of the current channel. :param last_id : last message id to start the research :param limit : maximum number of messages to fetch :returns list of messages values :rtype : list(dict)
  • channel_fetch_preview(self)
    Return the last message of the given channels
  • channel_fetch_slot(self)
    @api.model
    Return the channels of the user grouped by 'slot' (channel, direct_message or private_group), and the mapping between partner_id/channel_id for direct_message channels. :returns dict : the grouped channels and the mapping
  • channel_fetched(self)
    Broadcast the channel_fetched notification to channel members :param channel_ids : list of channel id that has been fetched by current user
  • channel_fold(self, uuid, state=None)
    @api.model
    Update the fold_state of the given session. In order to syncronize web browser tabs, the change will be broadcast to himself (the current user channel). Note: the user need to be logged :param state : the new status of the session for the current user.
  • channel_get(self, partners_to, pin=True)
    @api.model
    Get the canonical private channel between some partners, create it if needed. To reuse an old channel (conversation), this one must be private, and contains only the given partners. :param partners_to : list of res.partner ids to add to the conversation :param pin : True if getting the channel should pin it for the current user :returns: channel_info of the created or existing channel :rtype: dict
  • channel_get_and_minimize(self, partners_to)
    @api.model
  • channel_info(self, extra_info=False)
    Get the informations header for the current channels :returns a list of channels values :rtype : list(dict)
  • channel_invite(self, partner_ids)
    Add the given partner_ids to the current channels and broadcast the channel header to them. :param partner_ids : list of partner id to add
  • channel_join_and_get_info(self)
  • channel_minimize(self, uuid, minimized=True)
    @api.model
  • channel_pin(self, uuid, pinned=False)
    @api.model
  • channel_search_to_join(self, name=None, domain=None)
    @api.model
    Return the channel info of the channel the current partner can join :param name : the name of the researched channels :param domain : the base domain of the research :returns dict : channel dict
  • channel_seen(self, last_message_id=None)
    Mark channel as seen by updating seen message id of the current logged partner :param last_message_id: the id of the message to be marked as seen, last message of the thread by default. This param SHOULD be required, the default behaviour is DEPRECATED and kept only for compatibility reasons.
  • channel_set_custom_name(self, channel_id, name=False)
    @api.model
  • create(self, vals)
    @api.model
  • default_get(self, fields)
    @api.model
  • execute_command(self, command='', **kwargs)
    Executes a given command
  • get_mention_commands(self)
    @api.model@ormcache()
    Returns the allowed commands in channels
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first channels' id, name and public fields such that the name matches a 'search' string. Exclude channels of type chat (DM), and private channels the current user isn't registered to.
  • init(self)
  • message_post(self, *, message_type='notification', **kwargs)
    @api.returns('mail.message', <expr>)
  • notify_typing(self, is_typing)
    Broadcast the typing notification to channel members :param is_typing: (boolean) tells whether the current user is typing or not
  • partner_info(self, all_partners, direct_partners)
    @api.model
    Return the information needed by channel to display channel members :param all_partners: list of res.parner(): :param direct_partners: list of res.parner(): :returns: a list of {'id', 'name', 'email'} for each partner and adds {im_status} for direct_partners. :rtype : list(dict)
  • send_guidelines(self)
    Send guidelines to all channel members.
  • unlink(self)
  • write(self, vals)

New fields (9)
  • channel_id Many2one → mail.channel
    ondelete='cascade' string='Channel' args: 'mail.channel'
  • custom_channel_name Char
    args: 'Custom channel name'
  • fetched_message_id Many2one → mail.message
    string='Last Fetched' args: 'mail.message'
  • fold_state Selection
    default='open' string='Conversation Fold State' args: [('open', 'Open'), ('folded', 'Folded'), ('closed', 'Closed')]
  • is_minimized Boolean
    args: 'Conversation is minimized'
  • is_pinned Boolean
    default=True args: 'Is pinned on the interface'
  • partner_email Char
    depends=['partner_id'] related='partner_id.email' related_sudo=False args: 'Email'
  • partner_id Many2one → res.partner
    ondelete='cascade' string='Recipient' args: 'res.partner'
  • seen_message_id Many2one → mail.message
    string='Last Seen' args: 'mail.message'
Public methods (2)
  • create(self, vals)
    @api.model
    Similar access rule as the access rule of the mail channel. It can not be implemented in XML, because when the record will be created, the partner will be added in the channel and the security rule will always authorize the creation.
  • write(self, vals)

New fields (26)
  • active_domain Text
    readonly=True args: 'Active domain'
  • add_sign Boolean
    default=True
  • attachment_ids Many2many → ir.attachment
    args: 'ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', 'Attachments'
  • author_id Many2one → res.partner
    help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True args: 'res.partner', 'Author'
  • auto_delete Boolean
    help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Delete Emails'
  • auto_delete_message Boolean
    help='Do not keep a copy of the email in the document communication history (mass mailing only)' args: 'Delete Message Copy'
  • body Html
    default='' sanitize_style=True args: 'Contents'
  • composition_mode Selection
    default='comment' selection=[('comment', 'Post on a document'), ('mass_mail', 'Email Mass Mailing'), ('mass_post', 'Post on Multiple Documents')] string='Composition mode'
  • email_from Char
    help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • is_log Boolean
    help='Whether the message is an internal note (comment mode only)' args: 'Log an Internal Note'
  • layout Char
    copy=False args: 'Layout'
  • mail_activity_type_id Many2one → mail.activity.type
    index=True ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_type Selection
    default='comment' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' required=True args: [('comment', 'Comment'), ('notification', 'System notification')], 'Type'
  • model Char
    index=True args: 'Related Document Model'
  • no_auto_thread Boolean
    help='Answers do not go in the original document discussion thread. This has an impact on the generated message-id.' args: 'No threading for answers'
  • notify Boolean
    help='Notify followers of the document (mass post only)' args: 'Notify followers'
  • parent_id Many2one → mail.message
    help='Initial thread message.' index=True ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    domain=[('type', '!=', 'private')] args: 'res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional Contacts'
  • record_name Char
    help='Name get of the related document.' args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • res_id Integer
    index=True args: 'Related Document ID'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    default=<expr> index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • template_id Many2one → mail.template
    domain="[('model', '=', model)]" index=True args: 'mail.template', 'Use template'
  • use_active_domain Boolean
    args: 'Use active domain'
Public methods (10)
  • action_send_mail(self)
  • default_get(self, fields)
    @api.model
    Handle composition mode. Some details about context keys: - comment: default mode, model and ID of a record the user comments - default_model or active_model - default_res_id or active_id - mass_mail: model and IDs of records the user mass-mails - active_ids: record IDs - default_model or active_model
  • generate_email_for_composer(self, template_id, res_ids, fields)
    @api.model
    Call email_template.generate_email(), get fields relevant for mail.compose.message, transform email_cc and email_to into partner_ids
  • get_mail_values(self, res_ids)
    Generate the values that will be used by send_mail to create mail_messages or mail_mails.
  • get_record_data(self, values)
    @api.model
    Returns a defaults-like dict with initial values for the composition wizard when sending an email related a previous email (parent_id) or a document (model, res_id). This is based on previously computed default values.
  • onchange_template_id(self, template_id, composition_mode, model, res_id)
    - mass_mailing: we cannot render, so return the template values - normal mode: return rendered values /!\ for x2many field, this onchange return command instead of ids
  • onchange_template_id_wrapper(self)
    @api.onchange('template_id')
  • render_message(self, res_ids)
    Generate template-based values of wizard, for the document records given by res_ids. This method is meant to be inherited by email_template that will produce a more complete dictionary, using Jinja2 templates. Each template is generated for all res_ids, allowing to parse the template once, and render it multiple times. This is useful for mass mailing where template rendering represent a significant part of the process. Default recipients are also computed, based on mail_thread method _message_get_default_recipients. This allows to ensure a mass mailing has always some recipients specified. :param browse wizard: current mail.compose.message browse record :param list res_ids: list of record ids :return dict results: for each res_id, the generated template values for subject, body, email_from and reply_to
  • save_as_template(self)
    hit save as template button: current form value will be a new template attached to the current document.
  • send_mail(self, auto_commit=False)
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (8)
  • channel_id Many2one → mail.channel
    index=True ondelete='cascade' string='Listener' args: 'mail.channel'
  • email Char
    compute='_compute_related_fields' help='Email of the related partner (if exist) or False' args: 'Email'
  • is_active Boolean
    compute='_compute_related_fields' help='If the related partner is active (if exist) or if related channel exist' args: 'Is Active'
  • name Char
    compute='_compute_related_fields' help='Name of the related partner (if exist) or the related channel' args: 'Name'
  • partner_id Many2one → res.partner
    domain=[('type', '!=', 'private')] index=True ondelete='cascade' string='Related Partner' args: 'res.partner'
  • res_id Many2oneReference
    help='Id of the followed resource' index=True model_field='res_model' args: 'Related Document ID'
  • res_model Char
    index=True required=True args: 'Related Document Model Name'
  • subtype_ids Many2many → mail.message.subtype
    help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall." string='Subtype' args: 'mail.message.subtype'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (12)
  • auto_delete Boolean
    help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_html Text
    help='Rich-text/HTML message' args: 'Rich-text Contents'
  • email_cc Char
    help='Carbon copy message recipients' args: 'Cc'
  • email_to Text
    help='Message recipients (emails)' args: 'To'
  • failure_reason Text
    help='Failure reason. This is usually the exception thrown by the email server, stored to ease the debugging of mailing issues.' readonly=1 args: 'Failure Reason'
  • headers Text
    copy=False args: 'Headers'
  • mail_message_id Many2one → mail.message
    auto_join=True index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification Boolean
    help='Mail has been created to notify people of an existing mail.message' args: 'Is Notification'
  • recipient_ids Many2many → res.partner
    context={'active_test': False} string='To (Partners)' args: 'res.partner'
  • references Text
    help='Message references, such as identifiers of previous messages' readonly=1 args: 'References'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible.' args: 'Scheduled Send Date'
  • state Selection
    copy=False default='outgoing' readonly=True args: [('outgoing', 'Outgoing'), ('sent', 'Sent'), ('received', 'Received'), ('exception', 'Delivery Failed'), ('cancel', 'Cancelled')], 'Status'
Public methods (8)
  • cancel(self)
  • create(self, values_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • mark_outgoing(self)
  • process_email_queue(self, ids=None)
    @api.model
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! :param list ids: optional list of emails ids to send. If passed no search is performed, and these ids are used instead. :param dict context: if a 'filters' key is present in context, this value will be used as an additional filter to further restrict the outgoing messages to send (by default all 'outgoing' messages are sent).
  • send(self, auto_commit=False, raise_exception=False)
    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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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
  • unlink(self)
  • write(self, vals)

New fields (37)
  • add_sign Boolean
    default=True
  • attachment_ids Many2many → ir.attachment
    help='Attachments are linked to a document through model / res_id and to the message through this field.' string='Attachments' args: 'ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id'
  • author_avatar Binary
    depends=['author_id'] readonly=False related='author_id.image_128' args: "Author's avatar"
  • author_id Many2one → res.partner
    help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True ondelete='set null' args: 'res.partner', 'Author'
  • body Html
    default='' sanitize_style=True args: 'Contents'
  • canned_response_ids One2many → mail.shortcode
    store=False string='Canned Responses' args: 'mail.shortcode', 'message_ids'
  • channel_ids Many2many → mail.channel
    string='Channels' args: 'mail.channel', 'mail_message_mail_channel_rel'
  • child_ids One2many → mail.message
    args: 'mail.message', 'parent_id', 'Child Messages'
  • date Datetime
    default=fields.Datetime.now args: 'Date'
  • description Char
    compute='_compute_description' help='Message description: either the subject, or the beginning of the body' args: 'Short description'
  • email_from Char
    help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • email_layout_xmlid Char
    copy=False args: 'Layout'
  • has_error Boolean
    compute='_compute_has_error' help='Has error' search='_search_has_error' args: 'Has error'
  • is_internal Boolean
    help='Hide to public / portal users, independently from subtype configuration.' args: 'Employee Only'
  • mail_activity_type_id Many2one → mail.activity.type
    index=True ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_ids One2many → mail.mail
    groups='base.group_system' string='Mails' args: 'mail.mail', 'mail_message_id'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_id Char
    copy=False help='Message unique identifier' index=True readonly=1 args: 'Message-Id'
  • message_type Selection
    default='email' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' required=True args: [('email', 'Email'), ('comment', 'Comment'), ('notification', 'System notification'), ('user_notification', 'User Specific Notification')], 'Type'
  • model Char
    index=True args: 'Related Document Model'
  • moderation_status Selection
    index=True string='Moderation Status' args: [('pending_moderation', 'Pending Moderation'), ('accepted', 'Accepted'), ('rejected', 'Rejected')]
  • moderator_id Many2one → res.users
    index=True string='Moderated By' args: 'res.users'
  • need_moderation Boolean
    compute='_compute_need_moderation' search='_search_need_moderation' args: 'Need moderation'
  • needaction Boolean
    compute='_get_needaction' help='Need Action' search='_search_needaction' args: 'Need Action'
  • no_auto_thread Boolean
    help='Answers do not go in the original document discussion thread. This has an impact on the generated message-id.' args: 'No threading for answers'
  • notification_ids One2many → mail.notification
    auto_join=True copy=False depends=['notified_partner_ids'] args: 'mail.notification', 'mail_message_id', 'Notifications'
  • notified_partner_ids Many2many → res.partner
    context={'active_test': False} copy=False depends=['notification_ids'] string='Partners with Need Action' args: 'res.partner', 'mail_message_res_partner_needaction_rel'
  • parent_id Many2one → mail.message
    help='Initial thread message.' index=True ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    context={'active_test': False} string='Recipients' args: 'res.partner'
  • record_name Char
    help='Name get of the related document.' args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • res_id Many2oneReference
    index=True model_field='model' args: 'Related Document ID'
  • starred Boolean
    compute='_get_starred' compute_sudo=False help='Current user has a starred notification linked to this message' search='_search_starred' args: 'Starred'
  • starred_partner_ids Many2many → res.partner
    string='Favorited By' args: 'res.partner', 'mail_message_res_partner_starred_rel'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • tracking_value_ids One2many → mail.tracking.value
    groups='base.group_system' help='Tracked values are stored in a separate model. This field allow to reconstruct the tracking and to generate statistics on the model.' string='Tracking values' args: 'mail.tracking.value', 'mail_message_id'
Public methods (17)
  • check_access_rule(self, operation)
    Access rules of mail.message: - read: if - author_id == pid, uid is the author OR - uid is in the recipients (partner_ids) OR - uid has been notified (needaction) OR - uid is member of a listern channel (channel_ids.partner_ids) OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id (private message) OR - pid in message_follower_ids if model, res_id OR - uid can read the parent OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid is in the recipients (partner_ids) OR - uid is moderator of the channel and moderation_status is pending_moderation OR - uid has write or create access on the related document if model, res_id and moderation_status is not pending_moderation - otherwise: raise - unlink: if - uid is moderator of the channel and moderation_status is pending_moderation OR - uid has write or create access on the related document if model, res_id and moderation_status is not pending_moderation - otherwise: raise Specific case: non employee users see only messages with subtype (aka do not see internal logs).
  • create(self, values_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • export_data(self, fields_to_export)
  • init(self)
  • is_thread_message(self, vals=None)
  • mark_all_as_read(self, domain=None)
    @api.model
  • message_fetch(self, domain, limit=20, moderated_channel_ids=None)
    @api.model
    Get a limited amount of formatted messages with provided domain. :param domain: the domain to filter messages; :param limit: the maximum amount of messages to get; :param list(int) moderated_channel_ids: if set, it contains the ID of a moderated channel. Fetched messages should include pending moderation messages for moderators. If the current user is not moderator, it should still get self-authored messages that are pending moderation; :returns list(dict).
  • message_fetch_failed(self)
    Returns first 100 messages, sent by the current user, that have errors, in the format expected by the web client.
  • message_format(self)
    Get the message values in the format for web client. Since message values can be broadcasted, computed fields MUST NOT BE READ and broadcasted. :returns list(dict). Example : { 'body': HTML content of the message 'model': u'res.partner', 'record_name': u'Agrolait', 'attachment_ids': [ { 'file_type_icon': u'webimage', 'id': 45, 'name': u'sample.png', 'filename': u'sample.png' } ], 'needaction_partner_ids': [], # list of partner ids 'res_id': 7, 'tracking_value_ids': [ { 'old_value': "", 'changed_field': "Customer", 'id': 2965, 'new_value': "Axelor" } ], 'author_id': (3, u'Administrator'), 'email_from': 'sacha@pokemon.com' # email address or False 'subtype_id': (1, u'Discussions'), 'channel_ids': [], # list of channel ids 'date': '2015-06-30 08:22:33', 'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner name_get 'message_type': u'comment', 'id': 59, 'subject': False 'is_note': True # only if the message is a note (subtype == note) 'is_discussion': False # only if the message is a discussion (subtype == discussion) 'is_notification': False # only if the message is a note but is a notification aka not linked to a document like assignation 'moderation_status': 'pending_moderation' }
  • moderate(self, decision, **kwargs)
    Moderate messages. A check is done on moderation status of the current user to ensure we only moderate valid messages.
  • read(self, fields=None, load='_classic_read')
    Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_done(self)
    Remove the needaction from messages for the current partner.
  • toggle_message_starred(self)
    Toggle messages as (un)starred. Technically, the notifications related to uid are set to (un)starred.
  • unlink(self)
  • unstar_all(self)
    @api.model
    Unstar messages for the current partner.
  • write(self, vals)

New fields (9)
  • default Boolean
    default=True help='Activated by default when subscribing.' args: 'Default'
  • description Text
    help='Description that will be added in the message posted for this subtype. If void, the name will be added instead.' translate=True args: 'Description'
  • hidden Boolean
    help='Hide the subtype in the follower options' args: 'Hidden'
  • internal Boolean
    help='Messages with internal subtypes will be visible only by employees, aka members of base_user group' args: 'Internal Only'
  • name Char
    help='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.' required=True translate=True args: 'Message Type'
  • parent_id Many2one → mail.message.subtype
    help='Parent subtype, used for automatic subscription. This field is not correctly named. For example on a project, the parent_id of project subtypes refers to task-related subtypes.' ondelete='set null' string='Parent' args: 'mail.message.subtype'
  • relation_field Char
    help='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).' args: 'Relation field'
  • res_model Char
    help='Model the subtype applies to. If False, this subtype applies to all models.' args: 'Model'
  • sequence Integer
    default=1 help='Used to order subtypes.' args: 'Sequence'
Public methods (4)
  • create(self, vals)
    @api.model
  • default_subtypes(self, model_name)
    @api.model
    Retrieve the default subtypes (all, internal, external) for the given model.
  • unlink(self)
  • write(self, vals)

New fields (3)
  • channel_id Many2one → mail.channel
    index=True required=True string='Channel' args: 'mail.channel'
  • email Char
    index=True required=True string='Email'
  • status Selection
    required=True string='Status' args: [('allow', 'Always Allow'), ('ban', 'Permanent Ban')]
Public methods (0)

No public methods.

New fields (9)
  • failure_reason Text
    copy=False args: 'Failure reason'
  • failure_type Selection
    selection=[('SMTP', 'Connection failed (outgoing mail server problem)'), ('RECIPIENT', 'Invalid email address'), ('BOUNCE', 'Email address rejected by destination'), ('UNKNOWN', 'Unknown error')] string='Failure type'
  • is_read Boolean
    index=True args: 'Is Read'
  • mail_id Many2one → mail.mail
    help='Optional mail_mail ID. Used mainly to optimize searches.' index=True args: 'mail.mail', 'Mail'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification_status Selection
    default='ready' index=True string='Status' args: [('ready', 'Ready to Send'), ('sent', 'Sent'), ('bounce', 'Bounced'), ('exception', 'Exception'), ('canceled', 'Canceled')]
  • notification_type Selection
    default='inbox' index=True required=True string='Notification Type' args: [('inbox', 'Inbox'), ('email', 'Email')]
  • read_date Datetime
    copy=False args: 'Read Date'
  • res_partner_id Many2one → res.partner
    index=True ondelete='cascade' args: 'res.partner', 'Recipient'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • format_failure_reason(self)
  • init(self)
  • write(self, vals)

New fields (6)
  • copyvalue Char
    help='Final placeholder expression, to be copy-pasted in the desired template field.' store=False args: 'Placeholder Expression'
  • lang Char
    help='Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. ${object.partner_id.lang}.' args: 'Language'
  • model_object_field Many2one → ir.model.fields
    help='Select target field from the related document model.\nIf it is a relationship field you will be able to select a target field at the destination of the relationship.' store=False string='Field' args: 'ir.model.fields'
  • null_value Char
    help='Optional value to use if the target field is empty' store=False args: 'Default Value'
  • sub_model_object_field Many2one → ir.model.fields
    help='When a relationship field is selected as first field, this field lets you select the target field within the destination document model (sub-model).' store=False args: 'ir.model.fields', 'Sub-field'
  • sub_object Many2one → ir.model
    help='When a relationship field is selected as first field, this field shows the document model the relationship goes to.' readonly=True store=False args: 'ir.model', 'Sub-model'
Public methods (0)

No public methods.

New fields (2)
  • help_message Char
    compute='_compute_help_message' string='Help message'
  • model Char
    string='Model'
Public methods (1)
  • cancel_resend_action(self)

New fields (5)
  • has_cancel Boolean
    compute='_compute_has_cancel'
  • mail_message_id Many2one → mail.message
    readonly=True args: 'mail.message', 'Message'
  • notification_ids Many2many → mail.notification
    readonly=True string='Notifications' args: 'mail.notification'
  • partner_ids One2many → mail.resend.partner
    string='Recipients' args: 'mail.resend.partner', 'resend_wizard_id'
  • partner_readonly Boolean
    compute='_compute_partner_readonly'
Public methods (3)
  • cancel_mail_action(self)
  • default_get(self, fields)
    @api.model
  • resend_mail_action(self)
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (6)
  • email Char
    readonly=False related='partner_id.email' related_sudo=False
  • message Char
    string='Help message'
  • name Char
    readonly=False related='partner_id.name' related_sudo=False
  • partner_id Many2one → res.partner
    ondelete='cascade' required=True string='Partner' args: 'res.partner'
  • resend Boolean
    default=True string='Send Again'
  • resend_wizard_id Many2one → mail.resend.message
    string='Resend wizard' args: 'mail.resend.message'
Public methods (0)

No public methods.

New fields (4)
  • description Char
    args: 'Description'
  • message_ids Many2one → mail.message
    store=False string='Messages' args: 'mail.message'
  • source Char
    help='The shortcut which must be replaced in the Chat Messages' index=True required=True args: 'Shortcut'
  • substitution Text
    help='The escaped html code replacing the shortcut' index=True required=True args: 'Substitution'
Public methods (0)

No public methods.

New fields (18)
  • attachment_ids Many2many → ir.attachment
    help='You may attach files to this template, to be added to all emails created from this template' args: 'ir.attachment', 'email_template_attachment_rel', 'email_template_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    default=True help="This option permanently removes any track of email after it's been sent, including from the Technical menu in the Settings, in order to preserve storage space of your Odoo database." args: 'Auto Delete'
  • body_html Html
    sanitize=False translate=True args: 'Body'
  • email_cc Char
    help='Carbon copy recipients (placeholders may be used here)' args: 'Cc'
  • email_from Char
    help="Sender address (placeholders may be used here). If not set, the default value will be the author's email alias if configured, or email address." args: 'From'
  • email_to Char
    help='Comma-separated recipient addresses (placeholders may be used here)' args: 'To (Emails)'
  • mail_server_id Many2one → ir.mail_server
    help='Optional preferred server for outgoing mails. If not set, the highest priority one will be used.' readonly=False args: 'ir.mail_server', 'Outgoing Mail Server'
  • model Char
    index=True readonly=True related='model_id.model' store=True args: 'Related Document Model'
  • model_id Many2one → ir.model
    help='The type of document this template can be used with' args: 'ir.model', 'Applies to'
  • name Char
    args: 'Name'
  • partner_to Char
    help='Comma-separated ids of recipient partners (placeholders may be used here)' args: 'To (Partners)'
  • ref_ir_act_window Many2one → ir.actions.act_window
    copy=False help='Sidebar action to make this template available on records of the related document model' readonly=True args: 'ir.actions.act_window', 'Sidebar action'
  • reply_to Char
    help='Preferred response address (placeholders may be used here)' args: 'Reply-To'
  • report_name Char
    help='Name to use for the generated report file (may contain placeholders)\nThe extension can be omitted and will then come from the report type.' translate=True args: 'Report Filename'
  • report_template Many2one → ir.actions.report
    args: 'ir.actions.report', 'Optional report to print and attach'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. Jinja2 placeholders may be used.' args: 'Scheduled Date'
  • subject Char
    help='Subject (placeholders may be used here)' translate=True args: 'Subject'
  • use_default_to Boolean
    help='Default recipients of the record:\n- partner (using id on a partner or the partner_id field) OR\n- email (using email_from or email field)' args: 'Default recipients'
Public methods (10)
  • copy(self, default=None)
    @api.returns('self', <expr>)
  • create(self, values_list)
    @api.model_create_multi
  • create_action(self)
  • default_get(self, fields)
    @api.model
  • generate_email(self, res_ids, fields)
    Generates an email from the template for given the given model based on records given by res_ids. :param res_id: id of the record to use for rendering the template (model is taken from template definition) :returns: a dict containing all relevant fields for creating a new mail.mail entry, with one extra key ``attachments``, in the format [(report_name, data)] where data is base64 encoded.
  • generate_recipients(self, results, res_ids)
    Generates the recipients of the template. Default values can ben generated instead of the template values if requested by template or context. Emails (email_to, email_cc) can be transformed into partners if requested in the context.
  • send_mail(self, res_id, force_send=False, raise_exception=False, email_values=None, notif_layout=False)
    Generates a new mail.mail. Template is rendered on record given by res_id and model coming from template. :param int res_id: id of the record to render the template :param bool force_send: send email immediately; otherwise use the mail queue (recommended); :param dict email_values: update generated mail with those values to further customize the mail; :param str notif_layout: optional notification layout to encapsulate the generated email; :returns: id of the mail.mail that was created
  • unlink(self)
  • unlink_action(self)
  • write(self, vals)

New fields (15)
  • attachment_ids Many2many → ir.attachment
    compute='_compute_mail_template_fields' args: 'ir.attachment', 'Attachments'
  • body_html Html
    compute='_compute_mail_template_fields' sanitize=False args: 'Body'
  • email_cc Char
    compute='_compute_mail_template_fields' help='Carbon copy recipients' args: 'Cc'
  • email_from Char
    compute='_compute_mail_template_fields' help='Sender address' args: 'From'
  • email_to Char
    compute='_compute_mail_template_fields' help='Comma-separated recipient addresses' args: 'To'
  • error_msg Char
    readonly=True args: 'Error Message'
  • lang Selection
    string='Template Preview Language' args: _selection_languages
  • mail_template_id Many2one → mail.template
    required=True string='Related Mail Template' args: 'mail.template'
  • model_id Many2one → ir.model
    related='mail_template_id.model_id' string='Targeted model' args: 'ir.model'
  • no_record Boolean
    compute='_compute_no_record' args: 'No Record'
  • partner_ids Many2many → res.partner
    compute='_compute_mail_template_fields' string='Recipients' args: 'res.partner'
  • reply_to Char
    compute='_compute_mail_template_fields' help='Preferred response address' args: 'Reply-To'
  • resource_ref Reference
    selection='_selection_target_model' string='Record'
  • scheduled_date Char
    compute='_compute_mail_template_fields' help='The queue manager will send the email after the date' args: 'Scheduled Date'
  • subject Char
    compute='_compute_mail_template_fields' args: 'Subject'
Public methods (1)
  • default_get(self, fields)
    @api.model

New fields (13)
  • message_attachment_count Integer
    compute='_compute_message_attachment_count' groups='base.group_user' args: 'Attachment Count'
  • message_channel_ids Many2many → mail.channel
    comodel_name='mail.channel' compute='_get_followers' groups='base.group_user' search='_search_follower_channels' string='Followers (Channels)'
  • message_follower_ids One2many → mail.followers
    groups='base.group_user' string='Followers' args: 'mail.followers', 'res_id'
  • message_has_error Boolean
    compute='_compute_message_has_error' help='If checked, some messages have a delivery error.' search='_search_message_has_error' args: 'Message Delivery error'
  • message_has_error_counter Integer
    compute='_compute_message_has_error' help='Number of messages with delivery error' args: 'Number of errors'
  • message_ids One2many → mail.message
    auto_join=True domain=<expr> string='Messages' args: 'mail.message', 'res_id'
  • message_is_follower Boolean
    compute='_compute_is_follower' search='_search_is_follower' args: 'Is Follower'
  • message_main_attachment_id Many2one → ir.attachment
    comodel_name='ir.attachment' copy=False index=True string='Main Attachment'
  • message_needaction Boolean
    compute='_get_message_needaction' help='If checked, new messages require your attention.' search='_search_message_needaction' args: 'Action Needed'
  • message_needaction_counter Integer
    compute='_get_message_needaction' help='Number of messages which requires an action' args: 'Number of Actions'
  • message_partner_ids Many2many → res.partner
    comodel_name='res.partner' compute='_get_followers' groups='base.group_user' search='_search_follower_partners' string='Followers (Partners)'
  • message_unread Boolean
    compute='_get_message_unread' help='If checked, new messages require your attention.' args: 'Unread Messages'
  • message_unread_counter Integer
    compute='_get_message_unread' help='Number of unread messages' args: 'Unread Messages Counter'
Public methods (21)
  • copy_data(self, default=None)
  • create(self, vals_list)
    @api.model_create_multi
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • get_empty_list_help(self, help)
    @api.model
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • get_mail_message_access(self, res_ids, operation, model_name=None)
    @api.model
    Deprecated, remove with v14+
  • message_change_thread(self, new_thread)
    Transfer the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : my_lead.message_change_thread(my_project_task) will transfer the context of the thread of my_lead to my_project_task
  • message_new(self, msg_dict, custom_values=None)
    @api.model
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :rtype: int :return: the id of the newly created thread object
  • message_notify(self, *, partner_ids=False, parent_id=False, model=False, res_id=False, author_id=None, email_from=None, body='', subject=False, **kwargs)
    Shortcut allowing to notify partners of messages that shouldn't be displayed on a document. It pushes notifications on inbox or by email depending on the user configuration, like other notifications.
  • message_parse(self, message, save_original=False)
    @api.model
    Parses an email.message.Message representing an RFC-2822 email and returns a generic dict holding the message details. :param message: email to parse :type message: email.message.Message :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'email_from': from, 'to': to + delivered-to, 'cc': cc, 'recipients': delivered-to + to + cc + resent-to + resent-cc, 'partner_ids': partners found based on recipients emails, 'body': unified_body, 'references': references, 'in_reply_to': in-reply-to, 'parent_id': parent mail.message based on in_reply_to or references, 'is_internal': answer to an internal message (note), 'date': date, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_post(self, *, body='', subject=None, message_type='notification', email_from=None, author_id=None, parent_id=False, subtype_xmlid=None, subtype_id=False, partner_ids=None, channel_ids=None, attachments=None, attachment_ids=None, add_sign=True, record_name=False, **kwargs)
    @api.returns('mail.message', <expr>)
    Post a new message in an existing thread, returning the new mail.message ID. :param str body: body of the message, usually raw HTML that will be sanitized :param str subject: subject of the message :param str message_type: see mail_message.message_type field. Can be anything but user_notification, reserved for message_notify :param int parent_id: handle thread formation :param int subtype_id: subtype_id of the message, mainly use fore followers mechanism :param list(int) partner_ids: partner_ids to notify :param list(int) channel_ids: channel_ids to notify :param list(tuple(str,str), tuple(str,str, dict) or int) attachments : list of attachment tuples in the form ``(name,content)`` or ``(name,content, info)``, where content is NOT base64 encoded :param list id attachment_ids: list of existing attachement to link to this message -Should only be setted by chatter -Attachement object attached to mail.compose.message(0) will be attached to the related document. Extra keyword arguments will be used as default column values for the new mail.message record. :return int: ID of newly created mail.message
  • message_post_with_template(self, template_id, email_layout_xmlid=None, auto_commit=False, **kwargs)
    Helper method to send a mail with a template :param template_id : the id of the template to render to create the body of the message :param **kwargs : parameter to create a mail.compose.message woaerd (which inherit from mail.message)
  • message_post_with_view(self, views_or_xmlid, **kwargs)
    Helper method to send a mail / post a message using a view_id to render using the ir.qweb engine. This method is stand alone, because there is nothing in template and composer that allows to handle views in batch. This method should probably disappear when templates handle ir ui views.
  • message_process(self, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None)
    @api.model
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: string or xmlrpclib.Binary :type dict custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None)
    @api.model
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: * if the message replies to an existing thread by having a Message-Id that matches an existing mail_message.message_id, we take the original message model/thread_id pair and ignore custom_value as no creation will take place; * look for a mail.alias entry matching the message recipients and use the corresponding model, thread_id, custom_values and user_id. This could lead to a thread update or creation depending on the alias; * fallback on provided ``model``, ``thread_id`` and ``custom_values``; * raise an exception as no route has been found :param string message: an email.message instance :param dict message_dict: dictionary holding parsed message variables :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :type dict custom_values: optional dictionary of default field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of routes [(model, thread_id, custom_values, user_id, alias)] :raises: ValueError, TypeError
  • message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None)
    Main public API to add followers to a record set. Its main purpose is to perform access rights checks before calling ``_message_subscribe``.
  • message_track(self, tracked_fields, initial_values)
    Track updated values. Comparing the initial and current values of the fields given in tracked_fields, it generates a message containing the updated values. This message can be linked to a mail.message.subtype given by the ``_track_subtype`` method. :param tracked_fields: iterable of field names to track :param initial_values: mapping {record_id: {field_name: value}} :return: mapping {record_id: (changed_field_names, tracking_value_ids)} containing existing records only
  • message_unsubscribe(self, partner_ids=None, channel_ids=None)
    Remove partners from the records followers.
  • message_update(self, msg_dict, update_vals=None)
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • static_message_track(self, record, tracked_fields, initial)
    Deprecated, remove in v14+
  • unlink(self)
    Override unlink to delete messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • with_lang(self)
    Deprecated, remove in 14+
  • write(self, values)

New fields (3)
  • email_normalized Char
    compute='_compute_email_normalized' compute_sudo=True help='This field is used to search on email address as the primary email field can contain more than strictly an email address.' invisible=True store=True string='Normalized Email'
  • is_blacklisted Boolean
    compute='_compute_is_blacklisted' compute_sudo=True groups='base.group_user' help="If the email address is on the blacklist, the contact won't receive mass mailing anymore, from any list" search='_search_is_blacklisted' store=False string='Blacklist'
  • message_bounce Integer
    default=0 help='Counter of the number of bounced emails for this contact' args: 'Bounce'
Public methods (1)
  • mail_action_blacklist_remove(self)

New fields (1)
  • email_cc Char
    help='List of cc from incoming emails.' args: 'Email cc'
Public methods (2)
  • message_new(self, msg_dict, custom_values=None)
    @api.model
  • message_update(self, msg_dict, update_vals=None)
    Adds cc email to self.email_cc while trying to keep email as raw as possible but unique

New fields (18)
  • field Many2one → ir.model.fields
    ondelete='cascade' readonly=1 required=True args: 'ir.model.fields'
  • field_desc Char
    readonly=1 required=True args: 'Field Description'
  • field_groups Char
    compute='_compute_field_groups'
  • field_type Char
    args: 'Field Type'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message ID'
  • new_value_char Char
    readonly=1 args: 'New Value Char'
  • new_value_datetime Datetime
    readonly=1 args: 'New Value Datetime'
  • new_value_float Float
    readonly=1 args: 'New Value Float'
  • new_value_integer Integer
    readonly=1 args: 'New Value Integer'
  • new_value_monetary Float
    readonly=1 args: 'New Value Monetary'
  • new_value_text Text
    readonly=1 args: 'New Value Text'
  • old_value_char Char
    readonly=1 args: 'Old Value Char'
  • old_value_datetime Datetime
    readonly=1 args: 'Old Value DateTime'
  • old_value_float Float
    readonly=1 args: 'Old Value Float'
  • old_value_integer Integer
    readonly=1 args: 'Old Value Integer'
  • old_value_monetary Float
    readonly=1 args: 'Old Value Monetary'
  • old_value_text Text
    readonly=1 args: 'Old Value Text'
  • tracking_sequence Integer
    default=100 readonly=1 args: 'Tracking field sequence'
Public methods (4)
  • create_tracking_values(self, initial_value, new_value, col_name, col_info, tracking_sequence, model_name)
    @api.model
  • get_display_value(self, type)
  • get_new_display_value(self)
  • get_old_display_value(self)

New fields (6)
  • channel_ids Many2many → mail.channel
    domain=[('channel_type', '=', 'channel')] help='List of channels that will be added as listeners of the current document.' string='Channels' args: 'mail.channel'
  • message Html
    args: 'Message'
  • partner_ids Many2many → res.partner
    domain=[('type', '!=', 'private')] help='List of partners that will be added as follower of the current document.' string='Recipients' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' index=True args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' index=True required=True args: 'Related Document Model'
  • send_mail Boolean
    default=True help="If checked, the partners will receive an email warning they have been added in the document's followers." args: 'Send Email'
Public methods (2)
  • add_followers(self)
  • default_get(self, fields)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cron_mode=True)
    Send a message to Odoo's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (3)
  • catchall_email Char
    compute='_compute_catchall' string='Catchall Email'
  • catchall_formatted Char
    compute='_compute_catchall' string='Catchall'
  • email_formatted Char
    compute='_compute_email_formatted' compute_sudo=True string='Formatted Email'
Public methods (0)

No public methods.

New fields (2)
  • alias_domain Char
    config_parameter='mail.catchall.domain' help='If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.' args: 'Alias Domain'
  • fail_counter Integer
    readonly=True args: 'Fail Mail'
Public methods (2)
  • get_values(self)
    @api.model
  • set_values(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals, context=None)

New fields (4)
  • channel_ids Many2many → mail.channel
    copy=False string='Channels' args: 'mail.channel', 'mail_channel_partner', 'partner_id', 'channel_id'
  • email Char
    tracking=1
  • phone Char
    tracking=2
  • user_id Many2one
    tracking=True
Public methods (7)
  • find_or_create(self, email, assert_valid_email=False)
    @api.model@api.returns('self', <expr>)
    Override to use the email_normalized field.
  • get_mention_suggestions(self, search, limit=8, channel_id=None)
    @api.model
    Return 'limit'-first partners' id, name and email such that the name or email matches a 'search' string. Prioritize users, and then extend the research to all partners. If channel_id is given, only members of this channel are returned.
  • get_needaction_count(self)
    @api.model
    compute the number of needaction of the current user
  • get_starred_count(self)
    @api.model
    compute the number of starred of the current user
  • get_static_mention_suggestions(self)
    @api.model
    Returns static mention suggestions of partners, loaded once at webclient initialization and stored client side. By default all the internal users are returned. The return format is a list of lists. The first level of list is an arbitrary split that allows overrides to return their own list. The second level of list is a list of partner data (as per returned by `mail_partner_format()`).
  • im_search(self, name, limit=20)
    @api.model
    Search partner with a name and return its id, name and im_status. Note : the user must be logged :param name : the partner name to search :param limit : the limit of result to return
  • mail_partner_format(self)

New fields (4)
  • is_moderator Boolean
    compute='_compute_is_moderator' string='Is moderator'
  • moderation_channel_ids Many2many → mail.channel
    string='Moderated channels' args: 'mail.channel', 'mail_channel_moderator_rel'
  • moderation_counter Integer
    compute='_compute_moderation_counter' string='Moderation count'
  • notification_type Selection
    default='email' help='Policy on how to handle Chatter notifications:\n- Handle by Emails: notifications are sent to your email address\n- Handle in Odoo: notifications appear in your Odoo Inbox' required=True args: [('email', 'Handle by Emails'), ('inbox', 'Handle in Odoo')], 'Notification'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • systray_get_activities(self)
    @api.model
  • unlink(self)
  • write(self, vals)
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/13.0/mail
VERSION
VERSION 1.0
CATEGORY
CATEGORYDiscuss
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Christophe Matthieu, Martin Trigaux, Olivier Dony, Thibault Delavallée, Denis Ledoux, Christophe Simonis, Xavier Morel, Goffin Simon, Nicolas Martinelli, Nicolas Lempereur, Thibault Francois, Géry Debongnie, Aaron Bohy, Pedro M. Baeza, Jeremy Kersten, GitHub, Lucas Perais (lpe), Damien Bouvy, Yannick Tivisse, Martin Geubelle, Odoo Online, Pierre Masereel, Romain Derie, Laurent Smet, Jigar Patel, jem-odoo, Adrien Dieudonne, RomainLibert, Jorge Pinna Puissant, Jairo Llopis, Alexandre Kühn, Toufik Ben Jaa, Adrian Torres, wan, mreficent, XavierDo, Julien Castiaux, Rémi Rahir, Aurélien Warnon, Priyanka Kakadiya, Xavier-Do, David Tran, Romeo Fragomeli, jvm-odoo, mgh-odoo, jerome hanke (jhk), Andrea Grazioso (agr-odoo), Paul Morelle, Loan (lse), Xavier Dubuc, Sébastien Theys, Shreya Modi, david, Nasreddin (bon), alt-odoo, Florent de Labarre, Julien Mougenot, Jason Van Malder, fw-bot, Anh Thao Pham (pta), Debauche Stéphane, Samuel Degueldre, std-odoo, Achraf (abz), David Beguin, Lucas Lefèvre, Adrien Widart, Ivan Yelizariev, Naglis Jonaitis, Nasreddin Boulif (bon), Kamesh Patel, Nicolas Galler, Swapnesh Shah, nie, Nathan Marotte (nama), Antoine Prieels (ANP), Thanh Dodeur, fja-odoo, ThanhDodeurOdoo, Pierre Paridans, Varun Raval, Parth Choksi, Yenthe666, Hiral Bhavsar, jbm-odoo, Jinal Patel, nounoubensebia, root, bit-odoo, Romain Estievenart, Kevin Baptiste, Dhruv Patel, Hubert Van de Walle (huvw), asa-odoo, Geoffroy Larue, momegahed, mcm-odoo, Mitali Patel, Florian Damhaut, Merlin (megu), Kaushalya Mandaliya, thcl-odoo, diagnoza, jpr-odoo, Nimesh Jethva, João Marques, Alexandre D. Díaz, Julien Giannone, Renaud Thiry
WEBSITE
WEBSITEhttps://www.odoo.com/page/discuss
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:06:43
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web
    - bus
    - web_tour
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (70)
XML IDNameModelTypeStatus
_assets_primary_variables _assets_primary_variables ir.ui.view qweb Inherits web._assets_primary_variables
assets_backend mail assets ir.ui.view qweb Inherits web.assets_backend
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
email_template_form email.template.form mail.template form New
email_template_preview_form email_template.preview.form email_template.preview form New
email_template_tree email.template.tree mail.template tree New
field_form_view ir.model.fields field Inherits base.view_model_fields_form
js_test_assets mail_js_test_assets ir.ui.view qweb Inherits web.js_tests_assets
mail_activity_type_view_form mail.activity.type.view.form mail.activity.type form New
mail_activity_type_view_search mail.activity.type.search mail.activity.type search New
mail_activity_type_view_tree mail.activity.type.view.tree mail.activity.type tree New
mail_activity_view_calendar mail.activity.view.calendar mail.activity calendar New
mail_activity_view_form_popup mail.activity.view.form.popup mail.activity form New
mail_activity_view_search mail.activity.view.search mail.activity search New
mail_activity_view_tree mail.activity.view.tree mail.activity tree New
mail_blacklist_view_form mail.blacklist.view.form mail.blacklist form New
mail_blacklist_view_search mail.blacklist.view.search mail.blacklist search New
mail_blacklist_view_tree mail.blacklist.view.tree mail.blacklist tree New
mail_bounce_catchall mail_bounce_catchall ir.ui.view qweb New
mail_channel_notify_moderation mail_channel_notify_moderation ir.ui.view qweb New
mail_channel_partner_view_form mail.channel.partner.form mail.channel.partner form New
mail_channel_partner_view_tree mail.channel.partner.tree mail.channel.partner tree New
mail_channel_send_guidelines mail_channel_send_guidelines ir.ui.view qweb New
mail_channel_view_form mail.channel.form mail.channel form New
mail_channel_view_kanban mail.channel.kanban mail.channel kanban New
mail_channel_view_search mail.channel.search mail.channel search New
mail_channel_view_tree mail.channel.tree mail.channel tree New
mail_moderation_view_search mail.moderation.view.search mail.moderation search New
mail_moderation_view_tree mail.moderation.view.tree mail.moderation tree New
mail_notification_borders mail_notification_borders ir.ui.view qweb New
mail_notification_light mail_notification_light ir.ui.view qweb New
mail_notification_paynow Mail: Pay Now mail notification template ir.ui.view qweb New
mail_resend_cancel_view_form mail.resend.cancel.view.form mail.resend.cancel form New
mail_resend_message_view_form mail.resend.message.view.form mail.resend.message form New
mail_shortcode_view_form mail.shortcode.form mail.shortcode form New
mail_shortcode_view_tree mail.shortcode.tree mail.shortcode tree New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
message_activity_assigned message_activity_assigned ir.ui.view qweb New
message_activity_done message_activity_done ir.ui.view qweb New
message_notification_email message_notification_email ir.ui.view qweb New
message_origin_link message_origin_link ir.ui.view qweb New
message_user_assigned message_user_assigned ir.ui.view qweb New
model_form_view ir.model field Inherits base.view_model_form
model_search_view ir.model field Inherits base.view_model_search
qunit_suite mail_tests ir.ui.view qweb Inherits web.qunit_suite
res_config_settings_view_form res.config.settings.view.form.inherit.mail res.config.settings div Inherits base_setup.res_config_settings_view_form
res_partner_view_activity res.partner.activity res.partner activity New
res_partner_view_form_inherit_mail res.partner.view.form.inherit.mail res.partner xpath Inherits base.view_partner_form
res_partner_view_form_short res.partner.view.form.short.inherit.mail res.partner xpath Inherits base.view_partner_short_form
res_partner_view_search_inherit_mail res.partner.view.search.inherit.mail res.partner filter Inherits base.view_res_partner_filter
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_email_template_search email.template.search mail.template search New
view_followers_tree mail.followers.tree mail.followers tree New
view_mail_alias_form mail.alias.form mail.alias form New
view_mail_alias_search mail.alias.search mail.alias search New
view_mail_alias_tree mail.alias.tree mail.alias tree New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tracking_value_form mail.tracking.value.form mail.tracking.value form New
view_mail_tracking_value_tree mail.tracking.value.tree mail.tracking.value tree New
view_mail_tree mail.mail.tree mail.mail tree New
view_message_form mail.message.form mail.message form New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.tree mail.message.subtype tree New
view_message_tree mail.message.tree mail.message tree New
view_server_action_form_template ir.actions.server.form ir.actions.server xpath Inherits base.view_server_action_form
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (44)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (4)
  • attachment_ids Many2many
    store=False string='Attachments'
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • preview_lang Selection
    string='Template Preview Language' args: _get_languages
  • res_id Selection
    args: _get_records, 'Sample Document'
Public methods (2)
  • default_get(self, fields)
    @api.model
  • on_change_res_id(self)
    @api.onchange('res_id', 'preview_lang')

New fields (1)
  • view_mode Selection
    selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (12)
  • activity_date_deadline_range Integer
    string='Due Date In'
  • activity_date_deadline_range_type Selection
    default='days' string='Due type' args: [('days', 'Days'), ('weeks', 'Weeks'), ('months', 'Months')]
  • activity_note Html
    args: 'Note'
  • activity_summary Char
    args: 'Summary'
  • activity_type_id Many2one → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', model_id)]" string='Activity' args: 'mail.activity.type'
  • activity_user_field_name Char
    default='user_id' help='Technical name of the user on the record' args: 'User field name'
  • activity_user_id Many2one → res.users
    string='Responsible' args: 'res.users'
  • activity_user_type Selection
    default='specific' help="Use 'Specific User' to always assign the same user on the next activity. Use 'Generic User From Record' to specify the field name of the user to choose on the record." required=True args: [('specific', 'Specific User'), ('generic', 'Generic User From Record')]
  • channel_ids Many2many → mail.channel
    string='Add Channels' args: 'mail.channel'
  • partner_ids Many2many → res.partner
    string='Add Followers' args: 'res.partner'
  • state Selection
    selection_add=[('email', 'Send Email'), ('followers', 'Add Followers'), ('next_activity', 'Create Next Activity')]
  • template_id Many2one → mail.template
    domain="[('model_id', '=', model_id)]" ondelete='set null' args: 'mail.template', 'Email Template'
Public methods (4)
  • on_change_template_id(self)
    @api.onchange('template_id')
  • run_action_email(self, action, eval_context=None)
    @api.model
  • run_action_followers_multi(self, action, eval_context=None)
    @api.model
  • run_action_next_activity(self, action, eval_context=None)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • register_as_main_attachment(self, force=True)
    Registers this attachment as the main one of the model it is attached to.

New fields (0)

No new fields.

Public methods (1)
  • power_on(self, *args, **kwargs)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • session_info(self)

New fields (3)
  • is_mail_activity Boolean
    default=False help='Whether this model supports activities.' string='Mail Activity'
  • is_mail_blacklist Boolean
    default=False help='Whether this model supports blacklist.' string='Mail Blacklist'
  • is_mail_thread Boolean
    default=False help='Whether this model supports messages and notifications.' string='Mail Thread'
Public methods (2)
  • unlink(self)
  • write(self, vals)

New fields (1)
  • tracking Integer
    help='If set every modification done to this field is tracked in the chatter. Value is used to order tracking values.' string='Enable Ordered Tracking'
Public methods (1)
  • unlink(self)
    Delete 'mail.tracking.value's when a module is uninstalled

New fields (1)
  • type Selection
    selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (20)
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_decoration Selection
    readonly=True related='activity_type_id.decoration_type'
  • activity_type_id Many2one → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" ondelete='restrict' string='Activity Type' args: 'mail.activity.type'
  • automated Boolean
    help='Indicates this activity has been created automatically and not by any user.' readonly=True args: 'Automated activity'
  • can_write Boolean
    compute='_compute_can_write' help='Technical field to hide buttons if the current user has no access.'
  • date_deadline Date
    default=fields.Date.context_today index=True required=True args: 'Due Date'
  • force_next Boolean
    readonly=True related='activity_type_id.force_next'
  • has_recommended_activities Boolean
    compute='_compute_has_recommended_activities' help='Technical field for UX purpose' args: 'Next activities available'
  • icon Char
    readonly=True related='activity_type_id.icon' args: 'Icon'
  • mail_template_ids Many2many
    readonly=True related='activity_type_id.mail_template_ids'
  • note Html
    sanitize_style=True args: 'Note'
  • previous_activity_type_id Many2one → mail.activity.type
    readonly=True string='Previous Activity Type' args: 'mail.activity.type'
  • recommended_activity_type_id Many2one → mail.activity.type
    string='Recommended Activity Type' args: 'mail.activity.type'
  • res_id Many2oneReference
    index=True model_field='res_model' required=True string='Related Document ID'
  • res_model Char
    compute_sudo=True index=True readonly=True related='res_model_id.model' store=True args: 'Related Document Model'
  • res_model_id Many2one → ir.model
    index=True ondelete='cascade' required=True args: 'ir.model', 'Document Model'
  • res_name Char
    compute='_compute_res_name' compute_sudo=True help='Display name of the related document.' readonly=True store=True args: 'Document Name'
  • state Selection
    compute='_compute_state' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')], 'State'
  • summary Char
    args: 'Summary'
  • user_id Many2one → res.users
    default=<expr> index=True required=True args: 'res.users', 'Assigned to'
Public methods (13)
  • action_close_dialog(self)
  • action_done(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_done_schedule_next(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_feedback(self, feedback=False, attachment_ids=None)
  • action_feedback_schedule_next(self, feedback=False)
  • action_notify(self)
  • activity_format(self)
  • create(self, values)
    @api.model
  • default_get(self, fields)
    @api.model
  • get_activity_data(self, res_model, domain)
    @api.model
  • name_get(self)
  • unlink(self)
  • write(self, values)

New fields (8)
  • activity_date_deadline Date
    compute='_compute_activity_date_deadline' groups='base.group_user' readonly=True search='_search_activity_date_deadline' store=False args: 'Next Activity Deadline'
  • activity_exception_decoration Selection
    compute='_compute_activity_exception_type' help='Type of the exception activity on record.' search='_search_activity_exception_decoration' args: [('warning', 'Alert'), ('danger', 'Error')]
  • activity_exception_icon Char
    compute='_compute_activity_exception_type' help='Icon to indicate an exception activity.' args: 'Icon'
  • activity_ids One2many → mail.activity
    auto_join=True groups='base.group_user' args: 'mail.activity', 'res_id', 'Activities'
  • activity_state Selection
    compute='_compute_activity_state' groups='base.group_user' help='Status based on activities\nOverdue: Due date is already passed\nToday: Activity date is today\nPlanned: Future activities.' string='Activity State' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')]
  • activity_summary Char
    groups='base.group_user' readonly=False related='activity_ids.summary' search='_search_activity_summary' args: 'Next Activity Summary'
  • activity_type_id Many2one → mail.activity.type
    groups='base.group_user' readonly=False related='activity_ids.activity_type_id' search='_search_activity_type_id' args: 'mail.activity.type', 'Next Activity Type'
  • activity_user_id Many2one → res.users
    groups='base.group_user' readonly=False related='activity_ids.user_id' search='_search_activity_user_id' args: 'res.users', 'Responsible User'
Public methods (9)
  • activity_feedback(self, act_type_xmlids, user_id=None, feedback=None)
    Set activities as done, limiting to some activity types and optionally to a given user.
  • activity_reschedule(self, act_type_xmlids, user_id=None, date_deadline=None, new_user_id=None)
    Reschedule some automated activities. Activities to reschedule are selected based on type xml ids and optionally by user. Purpose is to be able to * update the deadline to date_deadline; * update the responsible to new_user_id;
  • activity_schedule(self, act_type_xmlid='', date_deadline=None, summary='', note='', **act_values)
    Schedule an activity on each record of the current record set. This method allow to provide as parameter act_type_xmlid. This is an xml_id of activity type instead of directly giving an activity_type_id. It is useful to avoid having various "env.ref" in the code and allow to let the mixin handle access rights. :param date_deadline: the day the activity must be scheduled on the timezone of the user must be considered to set the correct deadline
  • activity_schedule_with_view(self, act_type_xmlid='', date_deadline=None, summary='', views_or_xmlid='', render_context=None, **act_values)
    Helper method: Schedule an activity on each record of the current record set. This method allow to the same mecanism as `activity_schedule`, but provide 2 additionnal parameters: :param views_or_xmlid: record of ir.ui.view or string representing the xmlid of the qweb template to render :type views_or_xmlid: string or recordset :param render_context: the values required to render the given qweb template :type render_context: dict
  • activity_send_mail(self, template_id)
    Automatically send an email based on the given mail.template, given its ID.
  • activity_unlink(self, act_type_xmlids, user_id=None)
    Unlink activities, limiting to some activity types and optionally to a given user.
  • toggle_active(self)
    Before archiving the record we should also remove its ongoing activities. Otherwise they stay in the systray and concerning archived records it makes no sense.
  • unlink(self)
    Override unlink to delete records activities through (res_model, res_id).
  • write(self, vals)

New fields (21)
  • active Boolean
    default=True
  • category Selection
    default='default' help='Actions may trigger specific behavior like opening calendar view or automatically mark as done when a document is uploaded' string='Action to Perform' args: [('default', 'None'), ('upload_file', 'Upload Document')]
  • create_uid Many2one → res.users
    index=True args: 'res.users'
  • decoration_type Selection
    help='Change the background color of the related activities of this type.' string='Decoration Type' args: [('warning', 'Alert'), ('danger', 'Error')]
  • default_description Html
    string='Default Description' translate=True
  • default_next_type_id Many2one → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" args: 'mail.activity.type', 'Default Next Activity'
  • default_user_id Many2one → res.users
    string='Default User' args: 'res.users'
  • delay_count Integer
    default=0 help='Number of days/week/month before executing the action. It allows to plan the action deadline.' args: 'Scheduled Date'
  • delay_from Selection
    default='previous_activity' help='Type of delay' required=True string='Delay Type' args: [('current_date', 'after validation date'), ('previous_activity', 'after previous activity deadline')]
  • delay_unit Selection
    default='days' help='Unit of delay' required=True string='Delay units' args: [('days', 'days'), ('weeks', 'weeks'), ('months', 'months')]
  • force_next Boolean
    default=False args: 'Trigger Next Activity'
  • icon Char
    help='Font awesome icon e.g. fa-tasks' args: 'Icon'
  • initial_res_model_id Many2one → ir.model
    compute='_compute_initial_res_model_id' help='Technical field to keep trace of the model at the beginning of the edition for UX related behaviour' store=False args: 'ir.model', 'Initial model'
  • mail_template_ids Many2many → mail.template
    string='Email templates' args: 'mail.template'
  • name Char
    required=True translate=True args: 'Name'
  • next_type_ids Many2many → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" string='Recommended Next Activities' args: 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id'
  • previous_type_ids Many2many → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" string='Preceding Activities' args: 'mail.activity.type', 'mail_activity_rel', 'recommended_id', 'activity_id'
  • res_model_change Boolean
    default=False help='Technical field for UX related behaviour' store=False string='Model has change'
  • res_model_id Many2one → ir.model
    domain=['&', ('is_mail_thread', '=', True), ('transient', '=', False)] help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' index=True args: 'ir.model', 'Model'
  • sequence Integer
    default=10 args: 'Sequence'
  • summary Char
    translate=True args: 'Default Summary'
Public methods (2)
  • default_get(self, fields)
    @api.model
  • unlink(self)

New fields (1)
  • email_normalized Char
    compute='_compute_email_normalized' compute_sudo=True help='This field is used to search on email address as the primary email field can contain more than strictly an email address.' invisible=True store=True string='Normalized Email'
Public methods (0)

No public methods.

New fields (9)
  • alias_contact Selection
    default='everyone' help='Policy to post a message on the document using the mailgateway.\n- everyone: everyone can post\n- partners: only authenticated partners\n- followers: only followers of the related document or members of following channels\n' required=True string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_defaults Text
    default='{}' help='A Python dictionary that will be evaluated to provide default values when creating new records for this alias.' required=True args: 'Default Values'
  • alias_domain Char
    compute='_get_alias_domain' default=<expr> args: 'Alias domain'
  • alias_force_thread_id Integer
    help='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.' args: 'Record Thread ID'
  • alias_model_id Many2one → ir.model
    domain="[('field_id.name', '=', 'message_ids')]" help='The model (Odoo 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)' ondelete='cascade' required=True args: 'ir.model', 'Aliased Model'
  • alias_name Char
    help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>" args: 'Alias Name'
  • alias_parent_model_id Many2one → ir.model
    help='Parent model holding the alias. The model holding the alias reference is not necessarily the model given by alias_model_id (example: project (parent_model) and task (model))' args: 'ir.model', 'Parent Model'
  • alias_parent_thread_id Integer
    help='ID of the parent record holding the alias (example: project holding the task creation alias)' args: 'Parent Record Thread ID'
  • alias_user_id Many2one → res.users
    default=<expr> help='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.' args: 'res.users', 'Owner'
Public methods (5)
  • create(self, vals)
    @api.model
    Creates an email.alias record according to the values provided in ``vals``, with 2 alterations: the ``alias_name`` value may be suffixed in order to make it unique (and certain unsafe characters replaced), and he ``alias_model_id`` value will set to the model ID of the ``model_name`` context value, if provided.
  • name_get(self)
    Return the mail alias display alias_name, including the implicit mail catchall domain if exists from config otherwise "New Alias". e.g. `jobs@mail.odoo.com` or `jobs` or 'New Alias'
  • open_document(self)
  • open_parent_document(self)
  • write(self, vals)
    "give a unique alias name if given alias name is already assigned

New fields (1)
  • alias_id Many2one → mail.alias
    ondelete='restrict' required=True string='Alias' args: 'mail.alias'
Public methods (4)
  • create(self, vals)
    @api.model
    Create a record with ``vals``, and create a corresponding alias.
  • get_alias_model_name(self, vals)
    Return the model name for the alias. Incoming emails that are not replies to existing records will cause the creation of a new record of this alias model. The value may depend on ``vals``, the dict of values passed to ``create`` when a record of this model is created.
  • get_alias_values(self)
    Return values to create an alias, or to write on the alias after its creation.
  • unlink(self)
    Delete the given records, and cascade-delete their corresponding alias.

New fields (2)
  • active Boolean
    default=True tracking=True
  • email Char
    help='This field is case insensitive.' index=True required=True string='Email Address' tracking=True
Public methods (2)
  • create(self, values)
    @api.model_create_multi
  • write(self, values)

New fields (24)
  • channel_last_seen_partner_ids One2many → mail.channel.partner
    depends=['channel_partner_ids'] string='Last Seen' args: 'mail.channel.partner', 'channel_id'
  • channel_message_ids Many2many → mail.message
    copy=False args: 'mail.message', 'mail_message_mail_channel_rel'
  • channel_partner_ids Many2many → res.partner
    depends=['channel_last_seen_partner_ids'] string='Listeners' args: 'res.partner', 'mail_channel_partner', 'channel_id', 'partner_id'
  • channel_type Selection
    default='channel' args: [('chat', 'Chat Discussion'), ('channel', 'Channel')], 'Channel Type'
  • description Text
    args: 'Description'
  • email_send Boolean
    default=False args: 'Send messages by email'
  • group_ids Many2many → res.groups
    help='Members of those groups will automatically added as followers. Note that they will be able to manage their subscription manually if necessary.' string='Auto Subscription' args: 'res.groups'
  • group_public_id Many2one → res.groups
    default=<expr> string='Authorized Group' args: 'res.groups'
  • image_128 Image
    default=_get_default_image max_height=128 max_width=128 args: 'Image'
  • is_chat Boolean
    compute='_compute_is_chat' default=False string='Is a chat'
  • is_member Boolean
    compute='_compute_is_member' args: 'Is a member'
  • is_moderator Boolean
    compute='_compute_is_moderator' help='Current user is a moderator of the channel' string='Moderator'
  • is_subscribed Boolean
    compute='_compute_is_subscribed' args: 'Is Subscribed'
  • moderation Boolean
    string='Moderate this channel'
  • moderation_count Integer
    compute='_compute_moderation_count' groups='base.group_user' string='Moderated emails count'
  • moderation_guidelines Boolean
    help='Newcomers on this moderated channel will automatically receive the guidelines.' string='Send guidelines to new subscribers'
  • moderation_guidelines_msg Text
    string='Guidelines'
  • moderation_ids One2many → mail.moderation
    groups='base.group_user' string='Moderated Emails' args: 'mail.moderation', 'channel_id'
  • moderation_notify Boolean
    help='People receive an automatic notification about their message being waiting for moderation.' string='Automatic notification'
  • moderation_notify_msg Text
    string='Notification message'
  • moderator_ids Many2many → res.users
    string='Moderators' args: 'res.users', 'mail_channel_moderator_rel'
  • name Char
    required=True translate=True args: 'Name'
  • public Selection
    default='groups' help='This group is visible by non members. Invisible groups can add members through the invite button.' required=True args: [('public', 'Everyone'), ('private', 'Invited people only'), ('groups', 'Selected group of users')], 'Privacy'
  • uuid Char
    copy=False default=<expr> index=True size=50 args: 'UUID'
Public methods (32)
  • action_follow(self)
  • action_unfollow(self)
  • channel_create(self, name, privacy='groups')
    @api.model
    Create a channel and add the current partner, broadcast it (to make the user directly listen to it when polling) :param name : the name of the channel to create :param privacy : privacy of the channel. Should be 'public' or 'private'. :return dict : channel header
  • channel_fetch_listeners(self, uuid)
    @api.model
    Return the id, name and email of partners listening to the given channel
  • channel_fetch_message(self, last_id=False, limit=20)
    Return message values of the current channel. :param last_id : last message id to start the research :param limit : maximum number of messages to fetch :returns list of messages values :rtype : list(dict)
  • channel_fetch_preview(self)
    Return the last message of the given channels
  • channel_fetch_slot(self)
    @api.model
    Return the channels of the user grouped by 'slot' (channel, direct_message or private_group), and the mapping between partner_id/channel_id for direct_message channels. :returns dict : the grouped channels and the mapping
  • channel_fetched(self)
    Broadcast the channel_fetched notification to channel members :param channel_ids : list of channel id that has been fetched by current user
  • channel_fold(self, uuid, state=None)
    @api.model
    Update the fold_state of the given session. In order to syncronize web browser tabs, the change will be broadcast to himself (the current user channel). Note: the user need to be logged :param state : the new status of the session for the current user.
  • channel_get(self, partners_to, pin=True)
    @api.model
    Get the canonical private channel between some partners, create it if needed. To reuse an old channel (conversation), this one must be private, and contains only the given partners. :param partners_to : list of res.partner ids to add to the conversation :param pin : True if getting the channel should pin it for the current user :returns a channel header, or False if the users_to was False :rtype : dict
  • channel_get_and_minimize(self, partners_to)
    @api.model
  • channel_info(self, extra_info=False)
    Get the informations header for the current channels :returns a list of channels values :rtype : list(dict)
  • channel_invite(self, partner_ids)
    Add the given partner_ids to the current channels and broadcast the channel header to them. :param partner_ids : list of partner id to add
  • channel_join_and_get_info(self)
  • channel_minimize(self, uuid, minimized=True)
    @api.model
  • channel_pin(self, uuid, pinned=False)
    @api.model
  • channel_search_to_join(self, name=None, domain=None)
    @api.model
    Return the channel info of the channel the current partner can join :param name : the name of the researched channels :param domain : the base domain of the research :returns dict : channel dict
  • channel_seen(self)
  • channel_set_custom_name(self, channel_id, name=False)
    @api.model
  • create(self, vals)
    @api.model
  • default_get(self, fields)
    @api.model
  • execute_command(self, command='', **kwargs)
    Executes a given command
  • get_alias_model_name(self, vals)
  • get_mention_commands(self)
    @api.model@ormcache()
    Returns the allowed commands in channels
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first channels' id, name and public fields such that the name matches a 'search' string. Exclude channels of type chat (DM), and private channels the current user isn't registered to.
  • init(self)
  • message_post(self, *, message_type='notification', **kwargs)
    @api.returns('mail.message', <expr>)
  • notify_typing(self, is_typing, is_website_user=False)
    Broadcast the typing notification to channel members :param is_typing: (boolean) tells whether the current user is typing or not :param is_website_user: (boolean) tells whether the user that notifies comes from the website-side. This is useful in order to distinguish operator and unlogged users for livechat, because unlogged users have the same partner_id as the admin (default: False).
  • partner_info(self, all_partners, direct_partners)
    @api.model
    Return the information needed by channel to display channel members :param all_partners: list of res.parner(): :param direct_partners: list of res.parner(): :returns: a list of {'id', 'name', 'email'} for each partner and adds {im_status, out_of_office_message} for direct_partners. :rtype : list(dict)
  • send_guidelines(self)
    Send guidelines to all channel members.
  • unlink(self)
  • write(self, vals)

New fields (9)
  • channel_id Many2one → mail.channel
    ondelete='cascade' string='Channel' args: 'mail.channel'
  • custom_channel_name Char
    args: 'Custom channel name'
  • fetched_message_id Many2one → mail.message
    string='Last Fetched' args: 'mail.message'
  • fold_state Selection
    default='open' string='Conversation Fold State' args: [('open', 'Open'), ('folded', 'Folded'), ('closed', 'Closed')]
  • is_minimized Boolean
    args: 'Conversation is minimized'
  • is_pinned Boolean
    default=True args: 'Is pinned on the interface'
  • partner_email Char
    depends=['partner_id'] readonly=False related='partner_id.email' args: 'Email'
  • partner_id Many2one → res.partner
    ondelete='cascade' string='Recipient' args: 'res.partner'
  • seen_message_id Many2one → mail.message
    string='Last Seen' args: 'mail.message'
Public methods (3)
  • create(self, vals)
    @api.model
  • unlink(self)
  • write(self, vals)

New fields (26)
  • active_domain Text
    readonly=True args: 'Active domain'
  • add_sign Boolean
    default=True
  • attachment_ids Many2many → ir.attachment
    args: 'ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', 'Attachments'
  • author_id Many2one → res.partner
    help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True args: 'res.partner', 'Author'
  • auto_delete Boolean
    help='Delete sent emails (mass mailing only)' args: 'Delete Emails'
  • auto_delete_message Boolean
    help='Do not keep a copy of the email in the document communication history (mass mailing only)' args: 'Delete Message Copy'
  • body Html
    default='' sanitize_style=True args: 'Contents'
  • composition_mode Selection
    default='comment' selection=_get_composition_mode_selection string='Composition mode'
  • email_from Char
    help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • is_log Boolean
    help='Whether the message is an internal note (comment mode only)' args: 'Log an Internal Note'
  • layout Char
    copy=False args: 'Layout'
  • mail_activity_type_id Many2one → mail.activity.type
    index=True ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_type Selection
    default='comment' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' required=True args: [('comment', 'Comment'), ('notification', 'System notification')], 'Type'
  • model Char
    index=True args: 'Related Document Model'
  • no_auto_thread Boolean
    help='Answers do not go in the original document discussion thread. This has an impact on the generated message-id.' args: 'No threading for answers'
  • notify Boolean
    help='Notify followers of the document (mass post only)' args: 'Notify followers'
  • parent_id Many2one → mail.message
    help='Initial thread message.' index=True ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    args: 'res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional Contacts'
  • record_name Char
    help='Name get of the related document.' args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • res_id Integer
    index=True args: 'Related Document ID'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    default=<expr> index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • template_id Many2one → mail.template
    domain="[('model', '=', model)]" index=True args: 'mail.template', 'Use template'
  • use_active_domain Boolean
    args: 'Use active domain'
Public methods (10)
  • action_send_mail(self)
  • default_get(self, fields)
    @api.model
    Handle composition mode. Some details about context keys: - comment: default mode, model and ID of a record the user comments - default_model or active_model - default_res_id or active_id - reply: active_id of a message the user replies to - default_parent_id or message_id or active_id: ID of the mail.message we reply to - message.res_model or default_model - message.res_id or default_res_id - mass_mail: model and IDs of records the user mass-mails - active_ids: record IDs - default_model or active_model
  • generate_email_for_composer(self, template_id, res_ids, fields=None)
    @api.model
    Call email_template.generate_email(), get fields relevant for mail.compose.message, transform email_cc and email_to into partner_ids
  • get_mail_values(self, res_ids)
    Generate the values that will be used by send_mail to create mail_messages or mail_mails.
  • get_record_data(self, values)
    @api.model
    Returns a defaults-like dict with initial values for the composition wizard when sending an email related a previous email (parent_id) or a document (model, res_id). This is based on previously computed default values.
  • onchange_template_id(self, template_id, composition_mode, model, res_id)
    - mass_mailing: we cannot render, so return the template values - normal mode: return rendered values /!\ for x2many field, this onchange return command instead of ids
  • onchange_template_id_wrapper(self)
    @api.onchange('template_id')
  • render_message(self, res_ids)
    Generate template-based values of wizard, for the document records given by res_ids. This method is meant to be inherited by email_template that will produce a more complete dictionary, using Jinja2 templates. Each template is generated for all res_ids, allowing to parse the template once, and render it multiple times. This is useful for mass mailing where template rendering represent a significant part of the process. Default recipients are also computed, based on mail_thread method _message_get_default_recipients. This allows to ensure a mass mailing has always some recipients specified. :param browse wizard: current mail.compose.message browse record :param list res_ids: list of record ids :return dict results: for each res_id, the generated template values for subject, body, email_from and reply_to
  • save_as_template(self)
    hit save as template button: current form value will be a new template attached to the current document.
  • send_mail(self, auto_commit=False)
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (5)
  • channel_id Many2one → mail.channel
    index=True ondelete='cascade' string='Listener' args: 'mail.channel'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' string='Related Partner' args: 'res.partner'
  • res_id Many2oneReference
    help='Id of the followed resource' index=True model_field='res_model' args: 'Related Document ID'
  • res_model Char
    index=True required=True args: 'Related Document Model Name'
  • subtype_ids Many2many → mail.message.subtype
    help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall." string='Subtype' args: 'mail.message.subtype'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)

New fields (12)
  • auto_delete Boolean
    help='Permanently delete this email after sending it, to save space' args: 'Auto Delete'
  • body_html Text
    help='Rich-text/HTML message' args: 'Rich-text Contents'
  • email_cc Char
    help='Carbon copy message recipients' args: 'Cc'
  • email_to Text
    help='Message recipients (emails)' args: 'To'
  • failure_reason Text
    help='Failure reason. This is usually the exception thrown by the email server, stored to ease the debugging of mailing issues.' readonly=1 args: 'Failure Reason'
  • headers Text
    copy=False args: 'Headers'
  • mail_message_id Many2one → mail.message
    auto_join=True index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification Boolean
    help='Mail has been created to notify people of an existing mail.message' args: 'Is Notification'
  • recipient_ids Many2many → res.partner
    context={'active_test': False} string='To (Partners)' args: 'res.partner'
  • references Text
    help='Message references, such as identifiers of previous messages' readonly=1 args: 'References'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible.' args: 'Scheduled Send Date'
  • state Selection
    copy=False default='outgoing' readonly=True args: [('outgoing', 'Outgoing'), ('sent', 'Sent'), ('received', 'Received'), ('exception', 'Delivery Failed'), ('cancel', 'Cancelled')], 'Status'
Public methods (8)
  • cancel(self)
  • create(self, values)
    @api.model
  • default_get(self, fields)
    @api.model
  • mark_outgoing(self)
  • process_email_queue(self, ids=None)
    @api.model
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! :param list ids: optional list of emails ids to send. If passed no search is performed, and these ids are used instead. :param dict context: if a 'filters' key is present in context, this value will be used as an additional filter to further restrict the outgoing messages to send (by default all 'outgoing' messages are sent).
  • send(self, auto_commit=False, raise_exception=False)
    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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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
  • unlink(self)
  • write(self, vals)

New fields (35)
  • add_sign Boolean
    default=True
  • attachment_ids Many2many → ir.attachment
    help='Attachments are linked to a document through model / res_id and to the message through this field.' string='Attachments' args: 'ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id'
  • author_avatar Binary
    depends=['author_id'] readonly=False related='author_id.image_128' args: "Author's avatar"
  • author_id Many2one → res.partner
    default=_get_default_author help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True ondelete='set null' args: 'res.partner', 'Author'
  • body Html
    default='' sanitize_style=True args: 'Contents'
  • canned_response_ids One2many → mail.shortcode
    store=False string='Canned Responses' args: 'mail.shortcode', 'message_ids'
  • channel_ids Many2many → mail.channel
    string='Channels' args: 'mail.channel', 'mail_message_mail_channel_rel'
  • child_ids One2many → mail.message
    args: 'mail.message', 'parent_id', 'Child Messages'
  • date Datetime
    default=fields.Datetime.now args: 'Date'
  • email_from Char
    default=_get_default_from help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • email_layout_xmlid Char
    copy=False args: 'Layout'
  • has_error Boolean
    compute='_compute_has_error' help='Has error' search='_search_has_error' args: 'Has error'
  • mail_activity_type_id Many2one → mail.activity.type
    index=True ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_ids One2many → mail.mail
    string='Mails' args: 'mail.mail', 'mail_message_id'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_id Char
    copy=False help='Message unique identifier' index=True readonly=1 args: 'Message-Id'
  • message_type Selection
    default='email' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' required=True args: [('email', 'Email'), ('comment', 'Comment'), ('notification', 'System notification'), ('user_notification', 'User Specific Notification')], 'Type'
  • model Char
    index=True args: 'Related Document Model'
  • moderation_status Selection
    index=True string='Moderation Status' args: [('pending_moderation', 'Pending Moderation'), ('accepted', 'Accepted'), ('rejected', 'Rejected')]
  • moderator_id Many2one → res.users
    index=True string='Moderated By' args: 'res.users'
  • need_moderation Boolean
    compute='_compute_need_moderation' search='_search_need_moderation' args: 'Need moderation'
  • needaction Boolean
    compute='_get_needaction' help='Need Action' search='_search_needaction' args: 'Need Action'
  • no_auto_thread Boolean
    help='Answers do not go in the original document discussion thread. This has an impact on the generated message-id.' args: 'No threading for answers'
  • notification_ids One2many → mail.notification
    auto_join=True copy=False depends=['notified_partner_ids'] args: 'mail.notification', 'mail_message_id', 'Notifications'
  • notified_partner_ids Many2many → res.partner
    context={'active_test': False} depends=['notification_ids'] string='Partners with Need Action' args: 'res.partner', 'mail_message_res_partner_needaction_rel'
  • parent_id Many2one → mail.message
    help='Initial thread message.' index=True ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    context={'active_test': False} string='Recipients' args: 'res.partner'
  • record_name Char
    help='Name get of the related document.' args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • res_id Many2oneReference
    index=True model_field='model' args: 'Related Document ID'
  • starred Boolean
    compute='_get_starred' compute_sudo=False help='Current user has a starred notification linked to this message' search='_search_starred' args: 'Starred'
  • starred_partner_ids Many2many → res.partner
    string='Favorited By' args: 'res.partner', 'mail_message_res_partner_starred_rel'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • tracking_value_ids One2many → mail.tracking.value
    groups='base.group_system' help='Tracked values are stored in a separate model. This field allow to reconstruct the tracking and to generate statistics on the model.' string='Tracking values' args: 'mail.tracking.value', 'mail_message_id'
Public methods (16)
  • check_access_rule(self, operation)
    Access rules of mail.message: - read: if - author_id == pid, uid is the author OR - uid is in the recipients (partner_ids) OR - uid has been notified (needaction) OR - uid is member of a listern channel (channel_ids.partner_ids) OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id (private message) OR - pid in message_follower_ids if model, res_id OR - uid can read the parent OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid is in the recipients (partner_ids) OR - uid is moderator of the channel and moderation_status is pending_moderation OR - uid has write or create access on the related document if model, res_id and moderation_status is not pending_moderation - otherwise: raise - unlink: if - uid is moderator of the channel and moderation_status is pending_moderation OR - uid has write or create access on the related document if model, res_id and moderation_status is not pending_moderation - otherwise: raise Specific case: non employee users see only messages with subtype (aka do not see internal logs).
  • create(self, values_list)
    @api.model_create_multi
  • export_data(self, fields_to_export)
  • init(self)
  • is_thread_message(self, vals=None)
  • mark_all_as_read(self, domain=None)
    @api.model
  • message_fetch(self, domain, limit=20, moderated_channel_ids=None)
    @api.model
    Get a limited amount of formatted messages with provided domain. :param domain: the domain to filter messages; :param limit: the maximum amount of messages to get; :param list(int) moderated_channel_ids: if set, it contains the ID of a moderated channel. Fetched messages should include pending moderation messages for moderators. If the current user is not moderator, it should still get self-authored messages that are pending moderation; :returns list(dict).
  • message_fetch_failed(self)
  • message_format(self)
    Get the message values in the format for web client. Since message values can be broadcasted, computed fields MUST NOT BE READ and broadcasted. :returns list(dict). Example : { 'body': HTML content of the message 'model': u'res.partner', 'record_name': u'Agrolait', 'attachment_ids': [ { 'file_type_icon': u'webimage', 'id': 45, 'name': u'sample.png', 'filename': u'sample.png' } ], 'needaction_partner_ids': [], # list of partner ids 'res_id': 7, 'tracking_value_ids': [ { 'old_value': "", 'changed_field': "Customer", 'id': 2965, 'new_value': "Axelor" } ], 'author_id': (3, u'Administrator'), 'email_from': 'sacha@pokemon.com' # email address or False 'subtype_id': (1, u'Discussions'), 'channel_ids': [], # list of channel ids 'date': '2015-06-30 08:22:33', 'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner name_get 'message_type': u'comment', 'id': 59, 'subject': False 'is_note': True # only if the message is a note (subtype == note) 'is_discussion': False # only if the message is a discussion (subtype == discussion) 'is_notification': False # only if the message is a note but is a notification aka not linked to a document like assignation 'moderation_status': 'pending_moderation' }
  • moderate(self, decision, **kwargs)
    Moderate messages. A check is done on moderation status of the current user to ensure we only moderate valid messages.
  • read(self, fields=None, load='_classic_read')
    Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_done(self)
    Remove the needaction from messages for the current partner.
  • toggle_message_starred(self)
    Toggle messages as (un)starred. Technically, the notifications related to uid are set to (un)starred.
  • unlink(self)
  • unstar_all(self)
    @api.model
    Unstar messages for the current partner.
  • write(self, vals)

New fields (9)
  • default Boolean
    default=True help='Activated by default when subscribing.' args: 'Default'
  • description Text
    help='Description that will be added in the message posted for this subtype. If void, the name will be added instead.' translate=True args: 'Description'
  • hidden Boolean
    help='Hide the subtype in the follower options' args: 'Hidden'
  • internal Boolean
    help='Messages with internal subtypes will be visible only by employees, aka members of base_user group' args: 'Internal Only'
  • name Char
    help='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.' required=True translate=True args: 'Message Type'
  • parent_id Many2one → mail.message.subtype
    help='Parent subtype, used for automatic subscription. This field is not correctly named. For example on a project, the parent_id of project subtypes refers to task-related subtypes.' ondelete='set null' string='Parent' args: 'mail.message.subtype'
  • relation_field Char
    help='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).' args: 'Relation field'
  • res_model Char
    help='Model the subtype applies to. If False, this subtype applies to all models.' args: 'Model'
  • sequence Integer
    default=1 help='Used to order subtypes.' args: 'Sequence'
Public methods (4)
  • create(self, vals)
    @api.model
  • default_subtypes(self, model_name)
    @api.model
    Retrieve the default subtypes (all, internal, external) for the given model.
  • unlink(self)
  • write(self, vals)

New fields (3)
  • channel_id Many2one → mail.channel
    index=True required=True string='Channel' args: 'mail.channel'
  • email Char
    index=True required=True string='Email'
  • status Selection
    required=True string='Status' args: [('allow', 'Always Allow'), ('ban', 'Permanent Ban')]
Public methods (0)

No public methods.

New fields (9)
  • failure_reason Text
    copy=False args: 'Failure reason'
  • failure_type Selection
    selection=[('SMTP', 'Connection failed (outgoing mail server problem)'), ('RECIPIENT', 'Invalid email address'), ('BOUNCE', 'Email address rejected by destination'), ('UNKNOWN', 'Unknown error')] string='Failure type'
  • is_read Boolean
    index=True args: 'Is Read'
  • mail_id Many2one → mail.mail
    index=True args: 'mail.mail', 'Mail'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification_status Selection
    default='ready' index=True args: [('ready', 'Ready to Send'), ('sent', 'Sent'), ('bounce', 'Bounced'), ('exception', 'Exception'), ('canceled', 'Canceled')], 'Email Status'
  • notification_type Selection
    default='inbox' index=True required=True string='Notification Type' args: [('inbox', 'Inbox'), ('email', 'Email')]
  • read_date Datetime
    copy=False args: 'Read Date'
  • res_partner_id Many2one → res.partner
    index=True ondelete='cascade' required=False args: 'res.partner', 'Needaction Recipient'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • format_failure_reason(self)
  • init(self)
  • write(self, vals)

New fields (2)
  • help_message Char
    compute='_compute_help_message' string='Help message'
  • model Char
    string='Model'
Public methods (1)
  • cancel_resend_action(self)

New fields (5)
  • has_cancel Boolean
    compute='_compute_has_cancel'
  • mail_message_id Many2one → mail.message
    readonly=True args: 'mail.message', 'Message'
  • notification_ids Many2many → mail.notification
    readonly=True string='Notifications' args: 'mail.notification'
  • partner_ids One2many → mail.resend.partner
    string='Recipients' args: 'mail.resend.partner', 'resend_wizard_id'
  • partner_readonly Boolean
    compute='_compute_partner_readonly'
Public methods (3)
  • cancel_mail_action(self)
  • default_get(self, fields)
    @api.model
  • resend_mail_action(self)
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (6)
  • email Char
    readonly=False related='partner_id.email' related_sudo=False
  • message Char
    string='Help message'
  • name Char
    readonly=False related='partner_id.name' related_sudo=False
  • partner_id Many2one → res.partner
    ondelete='cascade' required=True string='Partner' args: 'res.partner'
  • resend Boolean
    default=True string='Send Again'
  • resend_wizard_id Many2one → mail.resend.message
    string='Resend wizard' args: 'mail.resend.message'
Public methods (0)

No public methods.

New fields (4)
  • description Char
    args: 'Description'
  • message_ids Many2one → mail.message
    store=False string='Messages' args: 'mail.message'
  • source Char
    help='The shortcut which must be replaced in the Chat Messages' index=True required=True args: 'Shortcut'
  • substitution Text
    help='The escaped html code replacing the shortcut' index=True required=True args: 'Substitution'
Public methods (0)

No public methods.

New fields (25)
  • attachment_ids Many2many → ir.attachment
    help='You may attach files to this template, to be added to all emails created from this template' args: 'ir.attachment', 'email_template_attachment_rel', 'email_template_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    default=True help='Permanently delete this email after sending it, to save space' args: 'Auto Delete'
  • body_html Html
    sanitize=False translate=True args: 'Body'
  • copyvalue Char
    help='Final placeholder expression, to be copy-pasted in the desired template field.' args: 'Placeholder Expression'
  • email_cc Char
    help='Carbon copy recipients (placeholders may be used here)' args: 'Cc'
  • email_from Char
    help="Sender address (placeholders may be used here). If not set, the default value will be the author's email alias if configured, or email address." args: 'From'
  • email_to Char
    help='Comma-separated recipient addresses (placeholders may be used here)' args: 'To (Emails)'
  • lang Char
    help='Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. ${object.partner_id.lang}.' placeholder='${object.partner_id.lang}' args: 'Language'
  • mail_server_id Many2one → ir.mail_server
    help='Optional preferred server for outgoing mails. If not set, the highest priority one will be used.' readonly=False args: 'ir.mail_server', 'Outgoing Mail Server'
  • model Char
    index=True readonly=True related='model_id.model' store=True args: 'Related Document Model'
  • model_id Many2one → ir.model
    help='The type of document this template can be used with' args: 'ir.model', 'Applies to'
  • model_object_field Many2one → ir.model.fields
    help='Select target field from the related document model.\nIf it is a relationship field you will be able to select a target field at the destination of the relationship.' string='Field' args: 'ir.model.fields'
  • name Char
    args: 'Name'
  • null_value Char
    help='Optional value to use if the target field is empty' args: 'Default Value'
  • partner_to Char
    help='Comma-separated ids of recipient partners (placeholders may be used here)' args: 'To (Partners)'
  • ref_ir_act_window Many2one → ir.actions.act_window
    copy=False help='Sidebar action to make this template available on records of the related document model' readonly=True args: 'ir.actions.act_window', 'Sidebar action'
  • reply_to Char
    help='Preferred response address (placeholders may be used here)' args: 'Reply-To'
  • report_name Char
    help='Name to use for the generated report file (may contain placeholders)\nThe extension can be omitted and will then come from the report type.' translate=True args: 'Report Filename'
  • report_template Many2one → ir.actions.report
    args: 'ir.actions.report', 'Optional report to print and attach'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. Jinja2 placeholders may be used.' args: 'Scheduled Date'
  • sub_model_object_field Many2one → ir.model.fields
    help='When a relationship field is selected as first field, this field lets you select the target field within the destination document model (sub-model).' args: 'ir.model.fields', 'Sub-field'
  • sub_object Many2one → ir.model
    help='When a relationship field is selected as first field, this field shows the document model the relationship goes to.' readonly=True args: 'ir.model', 'Sub-model'
  • subject Char
    help='Subject (placeholders may be used here)' translate=True args: 'Subject'
  • use_default_to Boolean
    help='Default recipients of the record:\n- partner (using id on a partner or the partner_id field) OR\n- email (using email_from or email field)' args: 'Default recipients'
  • user_signature Boolean
    help="If checked, the user's signature will be appended to the text version of the message" args: 'Add Signature'
Public methods (15)
  • build_expression(self, field_name, sub_field_name, null_value)
    Returns a placeholder expression for use in a template field, based on the values provided in the placeholder assistant. :param field_name: main field name :param sub_field_name: sub field name (M2O) :param null_value: default value if the target value is empty :return: final placeholder expression
  • copy(self, default=None)
    @api.returns('self', <expr>)
  • create(self, values_list)
    @api.model_create_multi
  • create_action(self)
  • default_get(self, fields)
    @api.model
  • generate_email(self, res_ids, fields=None)
    Generates an email from the template for given the given model based on records given by res_ids. :param res_id: id of the record to use for rendering the template (model is taken from template definition) :returns: a dict containing all relevant fields for creating a new mail.mail entry, with one extra key ``attachments``, in the format [(report_name, data)] where data is base64 encoded.
  • generate_recipients(self, results, res_ids)
    Generates the recipients of the template. Default values can ben generated instead of the template values if requested by template or context. Emails (email_to, email_cc) can be transformed into partners if requested in the context.
  • get_email_template(self, res_ids)
  • onchange_model_id(self)
    @api.onchange('model_id')
  • onchange_sub_model_object_value_field(self)
    @api.onchange('model_object_field', 'sub_model_object_field', 'null_value')
  • render_post_process(self, html)
    @api.model
  • send_mail(self, res_id, force_send=False, raise_exception=False, email_values=None, notif_layout=False)
    Generates a new mail.mail. Template is rendered on record given by res_id and model coming from template. :param int res_id: id of the record to render the template :param bool force_send: send email immediately; otherwise use the mail queue (recommended); :param dict email_values: update generated mail with those values to further customize the mail; :param str notif_layout: optional notification layout to encapsulate the generated email; :returns: id of the mail.mail that was created
  • unlink(self)
  • unlink_action(self)
  • write(self, vals)

New fields (13)
  • message_attachment_count Integer
    compute='_compute_message_attachment_count' groups='base.group_user' args: 'Attachment Count'
  • message_channel_ids Many2many → mail.channel
    comodel_name='mail.channel' compute='_get_followers' search='_search_follower_channels' string='Followers (Channels)'
  • message_follower_ids One2many → mail.followers
    string='Followers' args: 'mail.followers', 'res_id'
  • message_has_error Boolean
    compute='_compute_message_has_error' help='If checked, some messages have a delivery error.' search='_search_message_has_error' args: 'Message Delivery error'
  • message_has_error_counter Integer
    compute='_compute_message_has_error' help='Number of messages with delivery error' args: 'Number of errors'
  • message_ids One2many → mail.message
    auto_join=True domain=<expr> string='Messages' args: 'mail.message', 'res_id'
  • message_is_follower Boolean
    compute='_compute_is_follower' search='_search_is_follower' args: 'Is Follower'
  • message_main_attachment_id Many2one → ir.attachment
    comodel_name='ir.attachment' copy=False index=True string='Main Attachment'
  • message_needaction Boolean
    compute='_get_message_needaction' help='If checked, new messages require your attention.' search='_search_message_needaction' args: 'Action Needed'
  • message_needaction_counter Integer
    compute='_get_message_needaction' help='Number of messages which requires an action' args: 'Number of Actions'
  • message_partner_ids Many2many → res.partner
    comodel_name='res.partner' compute='_get_followers' search='_search_follower_partners' string='Followers (Partners)'
  • message_unread Boolean
    compute='_get_message_unread' help='If checked, new messages require your attention.' args: 'Unread Messages'
  • message_unread_counter Integer
    compute='_get_message_unread' help='Number of unread messages' args: 'Unread Messages Counter'
Public methods (21)
  • copy_data(self, default=None)
  • create(self, vals_list)
    @api.model_create_multi
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False)
    @api.model
  • get_empty_list_help(self, help)
    @api.model
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • get_mail_message_access(self, res_ids, operation, model_name=None)
    @api.model
    mail.message check permission rules for related document. This method is meant to be inherited in order to implement addons-specific behavior. A common behavior would be to allow creating messages when having read access rule on the document, for portal document such as issues.
  • message_change_thread(self, new_thread)
    Transfer the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : my_lead.message_change_thread(my_project_task) will transfer the context of the thread of my_lead to my_project_task
  • message_new(self, msg_dict, custom_values=None)
    @api.model
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :rtype: int :return: the id of the newly created thread object
  • message_notify(self, *, partner_ids=False, parent_id=False, model=False, res_id=False, author_id=None, email_from=None, body='', subject=False, **kwargs)
    Shortcut allowing to notify partners of messages that shouldn't be displayed on a document. It pushes notifications on inbox or by email depending on the user configuration, like other notifications.
  • message_parse(self, message, save_original=False)
    @api.model
    Parses an email.message.Message representing an RFC-2822 email and returns a generic dict holding the message details. :param message: email to parse :type message: email.message.Message :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'email_from': from, 'to': to + delivered-to, 'cc': cc, 'recipients': delivered-to + to + cc + resent-to + resent-cc, 'partner_ids': partners found based on recipients emails, 'body': unified_body, 'references': references, 'in_reply_to': in-reply-to, 'parent_id': parent mail.message based on in_reply_to or references, 'internal': answer to an internal message (note), 'date': date, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_post(self, *, body='', subject=None, message_type='notification', email_from=None, author_id=None, parent_id=False, subtype_id=False, subtype=None, partner_ids=None, channel_ids=None, attachments=None, attachment_ids=None, add_sign=True, record_name=False, **kwargs)
    @api.returns('mail.message', <expr>)
    Post a new message in an existing thread, returning the new mail.message ID. :param str body: body of the message, usually raw HTML that will be sanitized :param str subject: subject of the message :param str message_type: see mail_message.message_type field. Can be anything but user_notification, reserved for message_notify :param int parent_id: handle thread formation :param int subtype_id: subtype_id of the message, mainly use fore followers mechanism :param int subtype: xmlid that will be used to compute subtype_id if subtype_id is not given. :param list(int) partner_ids: partner_ids to notify :param list(int) channel_ids: channel_ids to notify :param list(tuple(str,str), tuple(str,str, dict) or int) attachments : list of attachment tuples in the form ``(name,content)`` or ``(name,content, info)``, where content is NOT base64 encoded :param list id attachment_ids: list of existing attachement to link to this message -Should only be setted by chatter -Attachement object attached to mail.compose.message(0) will be attached to the related document. Extra keyword arguments will be used as default column values for the new mail.message record. :return int: ID of newly created mail.message
  • message_post_with_template(self, template_id, email_layout_xmlid=None, auto_commit=False, **kwargs)
    Helper method to send a mail with a template :param template_id : the id of the template to render to create the body of the message :param **kwargs : parameter to create a mail.compose.message woaerd (which inherit from mail.message)
  • message_post_with_view(self, views_or_xmlid, **kwargs)
    Helper method to send a mail / post a message using a view_id to render using the ir.qweb engine. This method is stand alone, because there is nothing in template and composer that allows to handle views in batch. This method should probably disappear when templates handle ir ui views.
  • message_process(self, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None)
    @api.model
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: string or xmlrpclib.Binary :type dict custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None)
    @api.model
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: * if the message replies to an existing thread by having a Message-Id that matches an existing mail_message.message_id, we take the original message model/thread_id pair and ignore custom_value as no creation will take place; * look for a mail.alias entry matching the message recipients and use the corresponding model, thread_id, custom_values and user_id. This could lead to a thread update or creation depending on the alias; * fallback on provided ``model``, ``thread_id`` and ``custom_values``; * raise an exception as no route has been found :param string message: an email.message instance :param dict message_dict: dictionary holding parsed message variables :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :type dict custom_values: optional dictionary of default field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of routes [(model, thread_id, custom_values, user_id, alias)] :raises: ValueError, TypeError
  • message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None)
    Main public API to add followers to a record set. Its main purpose is to perform access rights checks before calling ``_message_subscribe``.
  • message_track(self, tracked_fields, initial_values)
    Track updated values. Comparing the initial and current values of the fields given in tracked_fields, it generates a message containing the updated values. This message can be linked to a mail.message.subtype given by the ``_track_subtype`` method.
  • message_unsubscribe(self, partner_ids=None, channel_ids=None)
    Remove partners from the records followers.
  • message_update(self, msg_dict, update_vals=None)
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • unlink(self)
    Override unlink to delete messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • with_lang(self)
  • write(self, values)

New fields (2)
  • is_blacklisted Boolean
    compute='_compute_is_blacklisted' compute_sudo=True groups='base.group_user' help="If the email address is on the blacklist, the contact won't receive mass mailing anymore, from any list" search='_search_is_blacklisted' store=False string='Blacklist'
  • message_bounce Integer
    default=0 help='Counter of the number of bounced emails for this contact' args: 'Bounce'
Public methods (0)

No public methods.

New fields (1)
  • email_cc Char
    help='List of cc from incoming emails.' args: 'Email cc'
Public methods (2)
  • message_new(self, msg_dict, custom_values=None)
    @api.model
  • message_update(self, msg_dict, update_vals=None)
    Adds cc email to self.email_cc while trying to keep email as raw as possible but unique

New fields (18)
  • field Char
    readonly=1 required=True args: 'Changed Field'
  • field_desc Char
    readonly=1 required=True args: 'Field Description'
  • field_groups Char
    compute='_compute_field_groups'
  • field_type Char
    args: 'Field Type'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message ID'
  • new_value_char Char
    readonly=1 args: 'New Value Char'
  • new_value_datetime Datetime
    readonly=1 args: 'New Value Datetime'
  • new_value_float Float
    readonly=1 args: 'New Value Float'
  • new_value_integer Integer
    readonly=1 args: 'New Value Integer'
  • new_value_monetary Float
    readonly=1 args: 'New Value Monetary'
  • new_value_text Text
    readonly=1 args: 'New Value Text'
  • old_value_char Char
    readonly=1 args: 'Old Value Char'
  • old_value_datetime Datetime
    readonly=1 args: 'Old Value DateTime'
  • old_value_float Float
    readonly=1 args: 'Old Value Float'
  • old_value_integer Integer
    readonly=1 args: 'Old Value Integer'
  • old_value_monetary Float
    readonly=1 args: 'Old Value Monetary'
  • old_value_text Text
    readonly=1 args: 'Old Value Text'
  • tracking_sequence Integer
    default=100 readonly=1 args: 'Tracking field sequence'
Public methods (4)
  • create_tracking_values(self, initial_value, new_value, col_name, col_info, tracking_sequence)
    @api.model
  • get_display_value(self, type)
  • get_new_display_value(self)
  • get_old_display_value(self)

New fields (6)
  • channel_ids Many2many → mail.channel
    domain=[('channel_type', '=', 'channel')] help='List of channels that will be added as listeners of the current document.' string='Channels' args: 'mail.channel'
  • message Html
    args: 'Message'
  • partner_ids Many2many → res.partner
    help='List of partners that will be added as follower of the current document.' string='Recipients' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' index=True args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' index=True required=True args: 'Related Document Model'
  • send_mail Boolean
    default=True help="If checked, the partners will receive an email warning they have been added in the document's followers." args: 'Send Email'
Public methods (2)
  • add_followers(self)
  • default_get(self, fields)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cron_mode=True)
    Send a message to Odoo's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (1)
  • catchall Char
    compute='_compute_catchall' string='Catchall Email'
Public methods (0)

No public methods.

New fields (2)
  • alias_domain Char
    config_parameter='mail.catchall.domain' help='If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.' args: 'Alias Domain'
  • fail_counter Integer
    readonly=True args: 'Fail Mail'
Public methods (2)
  • get_values(self)
    @api.model
  • set_values(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals, context=None)

New fields (2)
  • channel_ids Many2many → mail.channel
    copy=False string='Channels' args: 'mail.channel', 'mail_channel_partner', 'partner_id', 'channel_id'
  • user_id Many2one
    tracking=True
Public methods (5)
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first partners' id, name and email such that the name or email matches a 'search' string. Prioritize users, and then extend the research to all partners.
  • get_needaction_count(self)
    @api.model
    compute the number of needaction of the current user
  • get_starred_count(self)
    @api.model
    compute the number of starred of the current user
  • get_static_mention_suggestions(self)
    @api.model
    To be overwritten to return the id, name and email of partners used as static mention suggestions loaded once at webclient initialization and stored client side.
  • im_search(self, name, limit=20)
    @api.model
    Search partner with a name and return its id, name and im_status. Note : the user must be logged :param name : the partner name to search :param limit : the limit of result to return

New fields (7)
  • alias_contact Selection
    readonly=False related='alias_id.alias_contact' string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_id Many2one → mail.alias
    auto_join=True copy=False help="Email address internally associated with this user. Incoming emails will appear in the user's notifications." ondelete='set null' required=False args: 'mail.alias', 'Alias'
  • is_moderator Boolean
    compute='_compute_is_moderator' string='Is moderator'
  • moderation_channel_ids Many2many → mail.channel
    string='Moderated channels' args: 'mail.channel', 'mail_channel_moderator_rel'
  • moderation_counter Integer
    compute='_compute_moderation_counter' string='Moderation count'
  • notification_type Selection
    default='email' help='Policy on how to handle Chatter notifications:\n- Handle by Emails: notifications are sent to your email address\n- Handle in Odoo: notifications appear in your Odoo Inbox' required=True args: [('email', 'Handle by Emails'), ('inbox', 'Handle in Odoo')], 'Notification'
  • out_of_office_message Char
    string='Chat Status'
Public methods (4)
  • create(self, values)
    @api.model
  • systray_get_activities(self)
    @api.model
  • unlink(self)
  • write(self, vals)
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/12.0/mail
VERSION
VERSION 1.0
CATEGORY
CATEGORYDiscuss
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Christophe Matthieu, Martin Trigaux, Fabien Pinckaers, Antony Lesuisse, Olivier Dony, Thibault Delavallée, Denis Ledoux, Christophe Simonis, Xavier Morel, Goffin Simon, Simon Lejeune, Nicolas Martinelli, Nicolas Lempereur, Richard Mathot, qdp-odoo, Géry Debongnie, Aaron Bohy, Pedro M. Baeza, ged-odoo, GitHub, Lucas Perais (lpe), Olivier Colson, Yannick Tivisse, Alexandre Kühn, qsm-odoo, Martin Geubelle, Dharmraj Jhala, Nicolas Seinlet, Romain Derie, Toufik Benjaa, jem-odoo, Adrien Dieudonne, RomainLibert, Christophe Monniez, len-odoo, Julien (juc) Castiaux, Jorge Pinna Puissant, Jairo Llopis, Nans Lefebvre, Alexandre Kühn, Toufik Ben Jaa, Adrian Torres, mreficent, Moens Alexandre, XavierDo, Julien Castiaux, Rémi Rahir, Aurélien Warnon, Xavier-Do, jvm-odoo, jerome hanke (jhk), Florimond Husquinet (fhu), Andrea Grazioso (agr-odoo), Loan (lse), Fanny He, Xavier Dubuc, Sébastien Theys, david, Nasreddin (bon), alt-odoo, fw-bot, Anh Thao Pham (pta), Debauche Stéphane, Luis González, Kinjal Mehta, Quentin Smetz (qsm), David Beguin, Lucas Lefèvre, Adrien Widart, Kamesh Patel, Nicolas Galler, Thanh Dodeur, ThanhDodeurOdoo, Pierre Paridans, Hiral Bhavsar, jbm-odoo, nounoubensebia, root, bit-odoo, Romain Estievenart
WEBSITE
WEBSITEhttps://www.odoo.com/page/discuss
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-05 23:57:01
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web
    - bus
    - web_tour
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (70)
XML IDNameModelTypeStatus
_assets_primary_variables _assets_primary_variables ir.ui.view qweb Inherits web._assets_primary_variables
assets_backend mail assets ir.ui.view qweb Inherits web.assets_backend
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
email_template_form email.template.form mail.template form New
email_template_preview_form email_template.preview.form email_template.preview form New
email_template_tree email.template.tree mail.template tree New
field_form_view ir.model.fields field Inherits base.view_model_fields_form
js_test_assets mail_js_test_assets ir.ui.view qweb Inherits web.js_tests_assets
mail_activity_type_view_form mail.activity.type.view.form mail.activity.type form New
mail_activity_type_view_search mail.activity.type.search mail.activity.type search New
mail_activity_type_view_tree mail.activity.type.view.tree mail.activity.type tree New
mail_activity_view_calendar mail.activity.view.calendar mail.activity calendar New
mail_activity_view_form_popup mail.activity.view.form.popup mail.activity form New
mail_activity_view_search mail.activity.view.search mail.activity search New
mail_activity_view_tree mail.activity.view.tree mail.activity tree New
mail_blacklist_view_form mail.blacklist.view.form mail.blacklist form New
mail_blacklist_view_search mail.blacklist.view.search mail.blacklist search New
mail_blacklist_view_tree mail.blacklist.view.tree mail.blacklist tree New
mail_bounce_catchall mail_bounce_catchall ir.ui.view qweb New
mail_channel_notify_moderation mail_channel_notify_moderation ir.ui.view qweb New
mail_channel_partner_view_form mail.channel.partner.form mail.channel.partner form New
mail_channel_partner_view_tree mail.channel.partner.tree mail.channel.partner tree New
mail_channel_send_guidelines mail_channel_send_guidelines ir.ui.view qweb New
mail_channel_view_form mail.channel.form mail.channel form New
mail_channel_view_kanban mail.channel.kanban mail.channel kanban New
mail_channel_view_search mail.channel.search mail.channel search New
mail_channel_view_tree mail.channel.tree mail.channel tree New
mail_moderation_view_search mail.moderation.view.search mail.moderation search New
mail_moderation_view_tree mail.moderation.view.tree mail.moderation tree New
mail_notification_borders mail_notification_borders ir.ui.view qweb New
mail_notification_light mail_notification_light ir.ui.view qweb New
mail_notification_paynow Mail: Pay Now mail notification template ir.ui.view qweb New
mail_resend_cancel_view_form mail.resend.cancel.form mail.resend.cancel form New
mail_resend_message_view_form mail.resend.message.form mail.resend.message form New
mail_shortcode_view_form mail.shortcode.form mail.shortcode form New
mail_shortcode_view_tree mail.shortcode.tree mail.shortcode tree New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
message_activity_assigned message_activity_assigned ir.ui.view qweb New
message_activity_done message_activity_done ir.ui.view qweb New
message_notification_email message_notification_email ir.ui.view qweb New
message_origin_link message_origin_link ir.ui.view qweb New
message_user_assigned message_user_assigned ir.ui.view qweb New
model_form_view ir.model field Inherits base.view_model_form
model_search_view ir.model field Inherits base.view_model_search
qunit_mobile_suite mail_mobile_tests ir.ui.view qweb Inherits web.qunit_mobile_suite
qunit_suite mail_tests ir.ui.view qweb Inherits web.qunit_suite
res_config_settings_view_form res.config.settings.view.form.inherit.mail res.config.settings div Inherits base_setup.res_config_settings_view_form
res_partner_view_form_inherit_mail res.partner.view.form.inherit.mail res.partner xpath Inherits base.view_partner_form
res_partner_view_form_short res.partner.view.form.short.inherit.mail res.partner xpath Inherits base.view_partner_short_form
res_partner_view_search_inherit_mail res.partner.view.search.inherit.mail res.partner filter Inherits base.view_res_partner_filter
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_email_template_search email.template.search mail.template search New
view_followers_tree mail.followers.tree mail.followers tree New
view_mail_alias_form mail.alias.form mail.alias form New
view_mail_alias_search mail.alias.search mail.alias search New
view_mail_alias_tree mail.alias.tree mail.alias tree New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tracking_value_form mail.tracking.value.form mail.tracking.value form New
view_mail_tracking_value_tree mail.tracking.value.tree mail.tracking.value tree New
view_mail_tree mail.mail.tree mail.mail tree New
view_message_form mail.message.form mail.message form New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.tree mail.message.subtype tree New
view_message_tree mail.message.tree mail.message tree New
view_server_action_form_template ir.actions.server.form ir.actions.server notebook Inherits base.view_server_action_form
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (40)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (3)
  • attachment_ids Many2many
    store=False string='Attachments'
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • res_id Selection
    args: _get_records, 'Sample Document'
Public methods (2)
  • default_get(self, fields)
    @api.model
  • on_change_res_id(self)
    @api.onchange('res_id')@api.multi

New fields (1)
  • view_mode Selection
    selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (12)
  • activity_date_deadline_range Integer
    string='Due Date In'
  • activity_date_deadline_range_type Selection
    default='days' string='Due type' args: [('days', 'Days'), ('weeks', 'Weeks'), ('months', 'Months')]
  • activity_note Html
    args: 'Note'
  • activity_summary Char
    args: 'Summary'
  • activity_type_id Many2one → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', model_id)]" string='Activity' args: 'mail.activity.type'
  • activity_user_field_name Char
    default='user_id' help='Technical name of the user on the record' args: 'User field name'
  • activity_user_id Many2one → res.users
    string='Responsible' args: 'res.users'
  • activity_user_type Selection
    default='specific' help="Use 'Specific User' to always assign the same user on the next activity. Use 'Generic User From Record' to specify the field name of the user to choose on the record." required=True args: [('specific', 'Specific User'), ('generic', 'Generic User From Record')]
  • channel_ids Many2many → mail.channel
    string='Add Channels' args: 'mail.channel'
  • partner_ids Many2many → res.partner
    string='Add Followers' args: 'res.partner'
  • state Selection
    selection_add=[('email', 'Send Email'), ('followers', 'Add Followers'), ('next_activity', 'Create Next Activity')]
  • template_id Many2one → mail.template
    domain="[('model_id', '=', model_id)]" ondelete='set null' args: 'mail.template', 'Email Template'
Public methods (4)
  • on_change_template_id(self)
    @api.onchange('template_id')
  • run_action_email(self, action, eval_context=None)
    @api.model
  • run_action_followers_multi(self, action, eval_context=None)
    @api.model
  • run_action_next_activity(self, action, eval_context=None)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • register_as_main_attachment(self, force=True)
    Registers this attachment as the main one of the model it is attached to.

New fields (0)

No new fields.

Public methods (1)
  • power_on(self, *args, **kwargs)
    @api.model

New fields (1)
  • is_mail_thread Boolean
    default=False help='Whether this model supports messages and notifications.' oldname='mail_thread' string='Mail Thread'
Public methods (2)
  • unlink(self)
  • write(self, vals)
    @api.multi

New fields (1)
  • track_visibility Selection
    help='When set, every modification to this field will be tracked in the chatter.' string='Tracking' args: [('onchange', 'On Change'), ('always', 'Always')]
Public methods (0)

No public methods.

New fields (1)
  • type Selection
    selection_add=[('activity', 'Activity')]
Public methods (0)

No public methods.

New fields (21)
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_decoration Selection
    readonly=True related='activity_type_id.decoration_type'
  • activity_type_id Many2one → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" ondelete='restrict' args: 'mail.activity.type', 'Activity'
  • automated Boolean
    help='Indicates this activity has been created automatically and not by any user.' readonly=True args: 'Automated activity'
  • create_user_id Many2one → res.users
    default=<expr> index=True args: 'res.users', 'Creator'
  • date_deadline Date
    default=fields.Date.context_today index=True required=True args: 'Due Date'
  • feedback Html
    args: 'Feedback'
  • force_next Boolean
    readonly=False related='activity_type_id.force_next'
  • has_recommended_activities Boolean
    compute='_compute_has_recommended_activities' help='Technical field for UX purpose' args: 'Next activities available'
  • icon Char
    readonly=True related='activity_type_id.icon' args: 'Icon'
  • mail_template_ids Many2many
    readonly=False related='activity_type_id.mail_template_ids'
  • note Html
    sanitize_style=True args: 'Note'
  • previous_activity_type_id Many2one → mail.activity.type
    readonly=True string='Previous Activity Type' args: 'mail.activity.type'
  • recommended_activity_type_id Many2one → mail.activity.type
    string='Recommended Activity Type' args: 'mail.activity.type'
  • res_id Integer
    index=True required=True args: 'Related Document ID'
  • res_model Char
    index=True readonly=True related='res_model_id.model' store=True args: 'Related Document Model'
  • res_model_id Many2one → ir.model
    index=True ondelete='cascade' required=True args: 'ir.model', 'Document Model'
  • res_name Char
    compute='_compute_res_name' help='Display name of the related document.' readonly=True store=True args: 'Document Name'
  • state Selection
    compute='_compute_state' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')], 'State'
  • summary Char
    args: 'Summary'
  • user_id Many2one → res.users
    default=<expr> index=True required=True args: 'res.users', 'Assigned to'
Public methods (13)
  • action_close_dialog(self)
    @api.multi
  • action_done(self)
    @api.multi
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_done_schedule_next(self)
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_feedback(self, feedback=False)
  • action_feedback_schedule_next(self, feedback=False)
    @api.multi
  • action_notify(self)
    @api.multi
  • activity_format(self)
    @api.multi
  • create(self, values)
    @api.model
  • default_get(self, fields)
    @api.model
  • get_activity_data(self, res_model, domain)
    @api.model
  • name_get(self)
    @api.multi
  • unlink(self)
    @api.multi
  • write(self, values)
    @api.multi

New fields (6)
  • activity_date_deadline Date
    compute='_compute_activity_date_deadline' groups='base.group_user' readonly=True search='_search_activity_date_deadline' store=False args: 'Next Activity Deadline'
  • activity_ids One2many → mail.activity
    auto_join=True domain=<expr> groups='base.group_user' args: 'mail.activity', 'res_id', 'Activities'
  • activity_state Selection
    compute='_compute_activity_state' groups='base.group_user' help='Status based on activities\nOverdue: Due date is already passed\nToday: Activity date is today\nPlanned: Future activities.' string='Activity State' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')]
  • activity_summary Char
    groups='base.group_user' readonly=False related='activity_ids.summary' search='_search_activity_summary' args: 'Next Activity Summary'
  • activity_type_id Many2one → mail.activity.type
    groups='base.group_user' readonly=False related='activity_ids.activity_type_id' search='_search_activity_type_id' args: 'mail.activity.type', 'Next Activity Type'
  • activity_user_id Many2one → res.users
    groups='base.group_user' readonly=False related='activity_ids.user_id' search='_search_activity_user_id' args: 'res.users', 'Responsible User'
Public methods (9)
  • activity_feedback(self, act_type_xmlids, user_id=None, feedback=None)
    Set activities as done, limiting to some activity types and optionally to a given user.
  • activity_reschedule(self, act_type_xmlids, user_id=None, date_deadline=None, new_user_id=None)
    Reschedule some automated activities. Activities to reschedule are selected based on type xml ids and optionally by user. Purpose is to be able to * update the deadline to date_deadline; * update the responsible to new_user_id;
  • activity_schedule(self, act_type_xmlid='', date_deadline=None, summary='', note='', **act_values)
    Schedule an activity on each record of the current record set. This method allow to provide as parameter act_type_xmlid. This is an xml_id of activity type instead of directly giving an activity_type_id. It is useful to avoid having various "env.ref" in the code and allow to let the mixin handle access rights. :param date_deadline: the day the activity must be scheduled on the timezone of the user must be considered to set the correct deadline
  • activity_schedule_with_view(self, act_type_xmlid='', date_deadline=None, summary='', views_or_xmlid='', render_context=None, **act_values)
    Helper method: Schedule an activity on each record of the current record set. This method allow to the same mecanism as `activity_schedule`, but provide 2 additionnal parameters: :param views_or_xmlid: record of ir.ui.view or string representing the xmlid of the qweb template to render :type views_or_xmlid: string or recordset :param render_context: the values required to render the given qweb template :type render_context: dict
  • activity_send_mail(self, template_id)
    Automatically send an email based on the given mail.template, given its ID.
  • activity_unlink(self, act_type_xmlids, user_id=None)
    Unlink activities, limiting to some activity types and optionally to a given user.
  • toggle_active(self)
    @api.multi
    Before archiving the record we should also remove its ongoing activities. Otherwise they stay in the systray and concerning archived records it makes no sense.
  • unlink(self)
    @api.multi
    Override unlink to delete records activities through (res_model, res_id).
  • write(self, vals)
    @api.multi

New fields (18)
  • active Boolean
    default=True
  • category Selection
    default='default' help='Categories may trigger specific behavior like opening calendar view' string='Category' args: [('default', 'Other')]
  • decoration_type Selection
    help='Change the background color of the related activities of this type.' string='Decoration Type' args: [('warning', 'Alert'), ('danger', 'Error')]
  • default_next_type_id Many2one → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" args: 'mail.activity.type', 'Default Next Activity'
  • delay_count Integer
    default=0 help='Number of days/week/month before executing the action. It allows to plan the action deadline.' oldname='days' args: 'After'
  • delay_from Selection
    default='previous_activity' help='Type of delay' required=True string='Delay Type' args: [('current_date', 'after validation date'), ('previous_activity', 'after previous activity deadline')]
  • delay_unit Selection
    default='days' help='Unit of delay' required=True string='Delay units' args: [('days', 'days'), ('weeks', 'weeks'), ('months', 'months')]
  • force_next Boolean
    default=False args: 'Auto Schedule Next Activity'
  • icon Char
    help='Font awesome icon e.g. fa-tasks' args: 'Icon'
  • initial_res_model_id Many2one → ir.model
    compute='_compute_initial_res_model_id' help='Technical field to keep trace of the model at the beginning of the edition for UX related behaviour' store=False args: 'ir.model', 'Initial model'
  • mail_template_ids Many2many → mail.template
    string='Mails templates' args: 'mail.template'
  • name Char
    required=True translate=True args: 'Name'
  • next_type_ids Many2many → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" string='Recommended Next Activities' args: 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id'
  • previous_type_ids Many2many → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" string='Preceding Activities' args: 'mail.activity.type', 'mail_activity_rel', 'recommended_id', 'activity_id'
  • res_model_change Boolean
    default=False help='Technical field for UX related behaviour' store=False string='Model has change'
  • res_model_id Many2one → ir.model
    domain=['&', ('is_mail_thread', '=', True), ('transient', '=', False)] help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' index=True args: 'ir.model', 'Model'
  • sequence Integer
    default=10 args: 'Sequence'
  • summary Char
    translate=True args: 'Summary'
Public methods (1)
  • default_get(self, fields)
    @api.model

New fields (9)
  • alias_contact Selection
    default='everyone' help='Policy to post a message on the document using the mailgateway.\n- everyone: everyone can post\n- partners: only authenticated partners\n- followers: only followers of the related document or members of following channels\n' required=True string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_defaults Text
    default='{}' help='A Python dictionary that will be evaluated to provide default values when creating new records for this alias.' required=True args: 'Default Values'
  • alias_domain Char
    compute='_get_alias_domain' default=<expr> args: 'Alias domain'
  • alias_force_thread_id Integer
    help='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.' args: 'Record Thread ID'
  • alias_model_id Many2one → ir.model
    domain="[('field_id.name', '=', 'message_ids')]" help='The model (Odoo 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)' ondelete='cascade' required=True args: 'ir.model', 'Aliased Model'
  • alias_name Char
    help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>" args: 'Alias Name'
  • alias_parent_model_id Many2one → ir.model
    help='Parent model holding the alias. The model holding the alias reference is not necessarily the model given by alias_model_id (example: project (parent_model) and task (model))' args: 'ir.model', 'Parent Model'
  • alias_parent_thread_id Integer
    help='ID of the parent record holding the alias (example: project holding the task creation alias)' args: 'Parent Record Thread ID'
  • alias_user_id Many2one → res.users
    defaults=<expr> help='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.' args: 'res.users', 'Owner'
Public methods (5)
  • create(self, vals)
    @api.model
    Creates an email.alias record according to the values provided in ``vals``, with 2 alterations: the ``alias_name`` value may be suffixed in order to make it unique (and certain unsafe characters replaced), and he ``alias_model_id`` value will set to the model ID of the ``model_name`` context value, if provided.
  • name_get(self)
    @api.multi
    Return the mail alias display alias_name, including the implicit mail catchall domain if exists from config otherwise "New Alias". e.g. `jobs@mail.odoo.com` or `jobs` or 'New Alias'
  • open_document(self)
    @api.multi
  • open_parent_document(self)
    @api.multi
  • write(self, vals)
    @api.multi
    "give a unique alias name if given alias name is already assigned

New fields (1)
  • alias_id Many2one → mail.alias
    ondelete='restrict' required=True string='Alias' args: 'mail.alias'
Public methods (4)
  • create(self, vals)
    @api.model
    Create a record with ``vals``, and create a corresponding alias.
  • get_alias_model_name(self, vals)
    Return the model name for the alias. Incoming emails that are not replies to existing records will cause the creation of a new record of this alias model. The value may depend on ``vals``, the dict of values passed to ``create`` when a record of this model is created.
  • get_alias_values(self)
    Return values to create an alias, or to write on the alias after its creation.
  • unlink(self)
    @api.multi
    Delete the given records, and cascade-delete their corresponding alias.

New fields (2)
  • active Boolean
    default=True track_visibility=True
  • email Char
    help='This field is case insensitive.' index=True required=True string='Email Address' track_visibility=True
Public methods (2)
  • create(self, values)
    @api.model_create_multi
  • write(self, values)
    @api.multi

New fields (1)
  • is_blacklisted Boolean
    compute='_compute_is_blacklisted' compute_sudo=True groups='base.group_user' help="If the email address is on the blacklist, the contact won't receive mass mailing anymore, from any list" search='_search_is_blacklisted' store=False string='Blacklist'
Public methods (0)

No public methods.

New fields (26)
  • channel_last_seen_partner_ids One2many → mail.channel.partner
    string='Last Seen' args: 'mail.channel.partner', 'channel_id'
  • channel_message_ids Many2many → mail.message
    args: 'mail.message', 'mail_message_mail_channel_rel'
  • channel_partner_ids Many2many → res.partner
    string='Listeners' args: 'res.partner', 'mail_channel_partner', 'channel_id', 'partner_id'
  • channel_type Selection
    default='channel' args: [('chat', 'Chat Discussion'), ('channel', 'Channel')], 'Channel Type'
  • description Text
    args: 'Description'
  • email_send Boolean
    default=False args: 'Send messages by email'
  • group_ids Many2many → res.groups
    help='Members of those groups will automatically added as followers. Note that they will be able to manage their subscription manually if necessary.' string='Auto Subscription' args: 'res.groups'
  • group_public_id Many2one → res.groups
    default=<expr> string='Authorized Group' args: 'res.groups'
  • image Binary
    attachment=True default=_get_default_image help='This field holds the image used as photo for the group, limited to 1024x1024px.' args: 'Photo'
  • image_medium Binary
    attachment=True help='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.' args: 'Medium-sized photo'
  • image_small Binary
    attachment=True help='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.' args: 'Small-sized photo'
  • is_chat Boolean
    compute='_compute_is_chat' default=False string='Is a chat'
  • is_member Boolean
    compute='_compute_is_member' args: 'Is a member'
  • is_moderator Boolean
    compute='_compute_is_moderator' help='Current user is a moderator of the channel' string='Moderator'
  • is_subscribed Boolean
    compute='_compute_is_subscribed' args: 'Is Subscribed'
  • moderation Boolean
    string='Moderate this channel'
  • moderation_count Integer
    compute='_compute_moderation_count' groups='base.group_user' string='Moderated emails count'
  • moderation_guidelines Boolean
    help='Newcomers on this moderated channel will automatically receive the guidelines.' string='Send guidelines to new subscribers'
  • moderation_guidelines_msg Text
    string='Guidelines'
  • moderation_ids One2many → mail.moderation
    groups='base.group_user' string='Moderated Emails' args: 'mail.moderation', 'channel_id'
  • moderation_notify Boolean
    help='People receive an automatic notification about their message being waiting for moderation.' string='Automatic notification'
  • moderation_notify_msg Text
    string='Notification message'
  • moderator_ids Many2many → res.users
    string='Moderators' args: 'res.users', 'mail_channel_moderator_rel'
  • name Char
    required=True translate=True args: 'Name'
  • public Selection
    default='groups' help='This group is visible by non members. Invisible groups can add members through the invite button.' required=True args: [('public', 'Everyone'), ('private', 'Invited people only'), ('groups', 'Selected group of users')], 'Privacy'
  • uuid Char
    copy=False default=<expr> index=True size=50 args: 'UUID'
Public methods (30)
  • action_follow(self)
    @api.multi
  • action_unfollow(self)
    @api.multi
  • channel_create(self, name, privacy='public')
    @api.model
    Create a channel and add the current partner, broadcast it (to make the user directly listen to it when polling) :param name : the name of the channel to create :param privacy : privacy of the channel. Should be 'public' or 'private'. :return dict : channel header
  • channel_fetch_listeners(self, uuid)
    @api.model
    Return the id, name and email of partners listening to the given channel
  • channel_fetch_message(self, last_id=False, limit=20)
    @api.multi
    Return message values of the current channel. :param last_id : last message id to start the research :param limit : maximum number of messages to fetch :returns list of messages values :rtype : list(dict)
  • channel_fetch_preview(self)
    @api.multi
    Return the last message of the given channels
  • channel_fetch_slot(self)
    @api.model
    Return the channels of the user grouped by 'slot' (channel, direct_message or private_group), and the mapping between partner_id/channel_id for direct_message channels. :returns dict : the grouped channels and the mapping
  • channel_fold(self, uuid, state=None)
    @api.model
    Update the fold_state of the given session. In order to syncronize web browser tabs, the change will be broadcast to himself (the current user channel). Note: the user need to be logged :param state : the new status of the session for the current user.
  • channel_get(self, partners_to, pin=True)
    @api.model
    Get the canonical private channel between some partners, create it if needed. To reuse an old channel (conversation), this one must be private, and contains only the given partners. :param partners_to : list of res.partner ids to add to the conversation :param pin : True if getting the channel should pin it for the current user :returns a channel header, or False if the users_to was False :rtype : dict
  • channel_get_and_minimize(self, partners_to)
    @api.model
  • channel_info(self, extra_info=False)
    @api.multi
    Get the informations header for the current channels :returns a list of channels values :rtype : list(dict)
  • channel_invite(self, partner_ids)
    @api.multi
    Add the given partner_ids to the current channels and broadcast the channel header to them. :param partner_ids : list of partner id to add
  • channel_join_and_get_info(self)
    @api.multi
  • channel_minimize(self, uuid, minimized=True)
    @api.model
  • channel_pin(self, uuid, pinned=False)
    @api.model
  • channel_search_to_join(self, name=None, domain=None)
    @api.model
    Return the channel info of the channel the current partner can join :param name : the name of the researched channels :param domain : the base domain of the research :returns dict : channel dict
  • channel_seen(self)
    @api.multi
  • create(self, vals)
    @api.model
  • default_get(self, fields)
    @api.model
  • execute_command(self, command='', **kwargs)
    @api.multi
    Executes a given command
  • get_alias_model_name(self, vals)
  • get_mention_commands(self)
    @api.model@ormcache()
    Returns the allowed commands in channels
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first channels' id, name and public fields such that the name matches a 'search' string. Exclude channels of type chat (DM), and private channels the current user isn't registered to.
  • init(self)
    @api.model_cr
  • message_post(self, message_type='notification', **kwargs)
    @api.multi@api.returns('mail.message', <expr>)
  • message_receive_bounce(self, email, partner, mail_id=None)
    @api.multi
    Override bounce management to unsubscribe bouncing addresses
  • notify_typing(self, is_typing, is_website_user=False)
    @api.multi
    Broadcast the typing notification to channel members :param is_typing: (boolean) tells whether the current user is typing or not :param is_website_user: (boolean) tells whether the user that notifies comes from the website-side. This is useful in order to distinguish operator and unlogged users for livechat, because unlogged users have the same partner_id as the admin (default: False).
  • send_guidelines(self)
    @api.multi
    Send guidelines to all channel members.
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (7)
  • channel_id Many2one → mail.channel
    ondelete='cascade' string='Channel' args: 'mail.channel'
  • fold_state Selection
    default='open' string='Conversation Fold State' args: [('open', 'Open'), ('folded', 'Folded'), ('closed', 'Closed')]
  • is_minimized Boolean
    args: 'Conversation is minimized'
  • is_pinned Boolean
    default=True args: 'Is pinned on the interface'
  • partner_email Char
    readonly=False related='partner_id.email' args: 'Email'
  • partner_id Many2one → res.partner
    ondelete='cascade' string='Recipient' args: 'res.partner'
  • seen_message_id Many2one → mail.message
    string='Last Seen' args: 'mail.message'
Public methods (3)
  • create(self, vals)
    @api.model
  • unlink(self)
  • write(self, vals)

New fields (13)
  • active_domain Text
    readonly=True args: 'Active domain'
  • attachment_ids Many2many → ir.attachment
    args: 'ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    help='Delete sent emails (mass mailing only)' args: 'Delete Emails'
  • auto_delete_message Boolean
    help='Do not keep a copy of the email in the document communication history (mass mailing only)' args: 'Delete Message Copy'
  • composition_mode Selection
    default='comment' selection=_get_composition_mode_selection string='Composition mode'
  • is_log Boolean
    help='Whether the message is an internal note (comment mode only)' args: 'Log an Internal Note'
  • message_type Selection
    default='comment'
  • notify Boolean
    help='Notify followers of the document (mass post only)' args: 'Notify followers'
  • partner_ids Many2many → res.partner
    args: 'res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional Contacts'
  • subject Char
    default=False
  • subtype_id Many2one
    default=<expr>
  • template_id Many2one → mail.template
    domain="[('model', '=', model)]" index=True args: 'mail.template', 'Use template'
  • use_active_domain Boolean
    args: 'Use active domain'
Public methods (11)
  • action_send_mail(self)
    @api.multi
  • check_access_rule(self, operation)
    @api.multi
    Access rules of mail.compose.message: - create: if - model, no res_id, I create a message in mass mail mode - then: fall back on mail.message acces rules
  • default_get(self, fields)
    @api.model
    Handle composition mode. Some details about context keys: - comment: default mode, model and ID of a record the user comments - default_model or active_model - default_res_id or active_id - reply: active_id of a message the user replies to - default_parent_id or message_id or active_id: ID of the mail.message we reply to - message.res_model or default_model - message.res_id or default_res_id - mass_mail: model and IDs of records the user mass-mails - active_ids: record IDs - default_model or active_model
  • generate_email_for_composer(self, template_id, res_ids, fields=None)
    @api.model
    Call email_template.generate_email(), get fields relevant for mail.compose.message, transform email_cc and email_to into partner_ids
  • get_mail_values(self, res_ids)
    @api.multi
    Generate the values that will be used by send_mail to create mail_messages or mail_mails.
  • get_record_data(self, values)
    @api.model
    Returns a defaults-like dict with initial values for the composition wizard when sending an email related a previous email (parent_id) or a document (model, res_id). This is based on previously computed default values.
  • onchange_template_id(self, template_id, composition_mode, model, res_id)
    @api.multi
    - mass_mailing: we cannot render, so return the template values - normal mode: return rendered values /!\ for x2many field, this onchange return command instead of ids
  • onchange_template_id_wrapper(self)
    @api.multi@api.onchange('template_id')
  • render_message(self, res_ids)
    @api.multi
    Generate template-based values of wizard, for the document records given by res_ids. This method is meant to be inherited by email_template that will produce a more complete dictionary, using Jinja2 templates. Each template is generated for all res_ids, allowing to parse the template once, and render it multiple times. This is useful for mass mailing where template rendering represent a significant part of the process. Default recipients are also computed, based on mail_thread method message_get_default_recipients. This allows to ensure a mass mailing has always some recipients specified. :param browse wizard: current mail.compose.message browse record :param list res_ids: list of record ids :return dict results: for each res_id, the generated template values for subject, body, email_from and reply_to
  • save_as_template(self)
    @api.multi
    hit save as template button: current form value will be a new template attached to the current document.
  • send_mail(self, auto_commit=False)
    @api.multi
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (5)
  • channel_id Many2one → mail.channel
    index=True ondelete='cascade' string='Listener' args: 'mail.channel'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' string='Related Partner' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' index=True args: 'Related Document ID'
  • res_model Char
    index=True required=True args: 'Related Document Model Name'
  • subtype_ids Many2many → mail.message.subtype
    help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall." string='Subtype' args: 'mail.message.subtype'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (12)
  • auto_delete Boolean
    help='Permanently delete this email after sending it, to save space' args: 'Auto Delete'
  • body_html Text
    help='Rich-text/HTML message' args: 'Rich-text Contents'
  • email_cc Char
    help='Carbon copy message recipients' args: 'Cc'
  • email_to Text
    help='Message recipients (emails)' args: 'To'
  • failure_reason Text
    help='Failure reason. This is usually the exception thrown by the email server, stored to ease the debugging of mailing issues.' readonly=1 args: 'Failure Reason'
  • headers Text
    copy=False args: 'Headers'
  • mail_message_id Many2one → mail.message
    auto_join=True index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification Boolean
    help='Mail has been created to notify people of an existing mail.message' args: 'Is Notification'
  • recipient_ids Many2many → res.partner
    context={'active_test': False} string='To (Partners)' args: 'res.partner'
  • references Text
    help='Message references, such as identifiers of previous messages' readonly=1 args: 'References'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible.' args: 'Scheduled Send Date'
  • state Selection
    copy=False default='outgoing' readonly=True args: [('outgoing', 'Outgoing'), ('sent', 'Sent'), ('received', 'Received'), ('exception', 'Delivery Failed'), ('cancel', 'Cancelled')], 'Status'
Public methods (8)
  • cancel(self)
    @api.multi
  • create(self, values)
    @api.model
  • default_get(self, fields)
    @api.model
  • mark_outgoing(self)
    @api.multi
  • process_email_queue(self, ids=None)
    @api.model
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! :param list ids: optional list of emails ids to send. If passed no search is performed, and these ids are used instead. :param dict context: if a 'filters' key is present in context, this value will be used as an additional filter to further restrict the outgoing messages to send (by default all 'outgoing' messages are sent).
  • send(self, auto_commit=False, raise_exception=False)
    @api.multi
    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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (33)
  • add_sign Boolean
    default=True
  • attachment_ids Many2many → ir.attachment
    help='Attachments are linked to a document through model / res_id and to the message through this field.' string='Attachments' args: 'ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id'
  • author_avatar Binary
    readonly=False related='author_id.image_small' args: "Author's avatar"
  • author_id Many2one → res.partner
    default=_get_default_author help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True ondelete='set null' args: 'res.partner', 'Author'
  • body Html
    default='' sanitize_style=True args: 'Contents'
  • channel_ids Many2many → mail.channel
    string='Channels' args: 'mail.channel', 'mail_message_mail_channel_rel'
  • child_ids One2many → mail.message
    args: 'mail.message', 'parent_id', 'Child Messages'
  • date Datetime
    default=fields.Datetime.now args: 'Date'
  • email_from Char
    default=_get_default_from help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • has_error Boolean
    compute='_compute_has_error' help='Has error' search='_search_has_error' args: 'Has error'
  • layout Char
    copy=False args: 'Layout'
  • mail_activity_type_id Many2one → mail.activity.type
    index=True ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_id Char
    copy=False help='Message unique identifier' index=True readonly=1 args: 'Message-Id'
  • message_type Selection
    default='email' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' oldname='type' required=True args: [('email', 'Email'), ('comment', 'Comment'), ('notification', 'System notification')], 'Type'
  • model Char
    index=True args: 'Related Document Model'
  • moderation_status Selection
    index=True string='Moderation Status' args: [('pending_moderation', 'Pending Moderation'), ('accepted', 'Accepted'), ('rejected', 'Rejected')]
  • moderator_id Many2one → res.users
    index=True string='Moderated By' args: 'res.users'
  • need_moderation Boolean
    compute='_compute_need_moderation' search='_search_need_moderation' args: 'Need moderation'
  • needaction Boolean
    compute='_get_needaction' help='Need Action' search='_search_needaction' args: 'Need Action'
  • needaction_partner_ids Many2many → res.partner
    context={'active_test': False} string='Partners with Need Action' args: 'res.partner', 'mail_message_res_partner_needaction_rel'
  • no_auto_thread Boolean
    help='Answers do not go in the original document discussion thread. This has an impact on the generated message-id.' args: 'No threading for answers'
  • notification_ids One2many → mail.notification
    auto_join=True copy=False args: 'mail.notification', 'mail_message_id', 'Notifications'
  • parent_id Many2one → mail.message
    help='Initial thread message.' index=True ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    context={'active_test': False} string='Recipients' args: 'res.partner'
  • record_name Char
    help='Name get of the related document.' args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • res_id Integer
    index=True args: 'Related Document ID'
  • starred Boolean
    compute='_get_starred' help='Current user has a starred notification linked to this message' search='_search_starred' args: 'Starred'
  • starred_partner_ids Many2many → res.partner
    string='Favorited By' args: 'res.partner', 'mail_message_res_partner_starred_rel'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • tracking_value_ids One2many → mail.tracking.value
    groups='base.group_system' help='Tracked values are stored in a separate model. This field allow to reconstruct the tracking and to generate statistics on the model.' string='Tracking values' args: 'mail.tracking.value', 'mail_message_id'
Public methods (15)
  • check_access_rule(self, operation)
    @api.multi
    Access rules of mail.message: - read: if - author_id == pid, uid is the author OR - uid is in the recipients (partner_ids) OR - uid has been notified (needaction) OR - uid is member of a listern channel (channel_ids.partner_ids) OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id (private message) OR - pid in message_follower_ids if model, res_id OR - uid can read the parent OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid is in the recipients (partner_ids) OR - uid is moderator of the channel and moderation_status is pending_moderation OR - uid has write or create access on the related document if model, res_id and moderation_status is not pending_moderation - otherwise: raise - unlink: if - uid is moderator of the channel and moderation_status is pending_moderation OR - uid has write or create access on the related document if model, res_id and moderation_status is not pending_moderation - otherwise: raise Specific case: non employee users see only messages with subtype (aka do not see internal logs).
  • create(self, values)
    @api.model
  • export_data(self, fields_to_export, raw_data=False)
  • init(self)
    @api.model_cr
  • mark_all_as_read(self, channel_ids=None, domain=None)
    @api.model
    Remove all needactions of the current partner. If channel_ids is given, restrict to messages written in one of those channels.
  • message_fetch(self, domain, limit=20, moderated_channel_ids=None)
    @api.model
    Get a limited amount of formatted messages with provided domain. :param domain: the domain to filter messages; :param limit: the maximum amount of messages to get; :param list(int) moderated_channel_ids: if set, it contains the ID of a moderated channel. Fetched messages should include pending moderation messages for moderators. If the current user is not moderator, it should still get self-authored messages that are pending moderation; :returns list(dict).
  • message_fetch_failed(self)
    @api.multi
  • message_format(self)
    @api.multi
    Get the message values in the format for web client. Since message values can be broadcasted, computed fields MUST NOT BE READ and broadcasted. :returns list(dict). Example : { 'body': HTML content of the message 'model': u'res.partner', 'record_name': u'Agrolait', 'attachment_ids': [ { 'file_type_icon': u'webimage', 'id': 45, 'name': u'sample.png', 'filename': u'sample.png' } ], 'needaction_partner_ids': [], # list of partner ids 'res_id': 7, 'tracking_value_ids': [ { 'old_value': "", 'changed_field': "Customer", 'id': 2965, 'new_value': "Axelor" } ], 'author_id': (3, u'Administrator'), 'email_from': 'sacha@pokemon.com' # email address or False 'subtype_id': (1, u'Discussions'), 'channel_ids': [], # list of channel ids 'date': '2015-06-30 08:22:33', 'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner name_get 'message_type': u'comment', 'id': 59, 'subject': False 'is_note': True # only if the message is a note (subtype == note) 'is_discussion': False # only if the message is a discussion (subtype == discussion) 'is_notification': False # only if the message is a note but is a notification aka not linked to a document like assignation 'moderation_status': 'pending_moderation' }
  • moderate(self, decision, **kwargs)
    @api.multi
    Moderate messages. A check is done on moderation status of the current user to ensure we only moderate valid messages.
  • read(self, fields=None, load='_classic_read')
    @api.multi
    Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_done(self)
    @api.multi
    Remove the needaction from messages for the current partner.
  • toggle_message_starred(self)
    @api.multi
    Toggle messages as (un)starred. Technically, the notifications related to uid are set to (un)starred.
  • unlink(self)
    @api.multi
  • unstar_all(self)
    @api.model
    Unstar messages for the current partner.
  • write(self, vals)
    @api.multi

New fields (9)
  • default Boolean
    default=True help='Activated by default when subscribing.' args: 'Default'
  • description Text
    help='Description that will be added in the message posted for this subtype. If void, the name will be added instead.' translate=True args: 'Description'
  • hidden Boolean
    help='Hide the subtype in the follower options' args: 'Hidden'
  • internal Boolean
    help='Messages with internal subtypes will be visible only by employees, aka members of base_user group' args: 'Internal Only'
  • name Char
    help='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.' required=True translate=True args: 'Message Type'
  • parent_id Many2one → mail.message.subtype
    help='Parent subtype, used for automatic subscription. This field is not correctly named. For example on a project, the parent_id of project subtypes refers to task-related subtypes.' ondelete='set null' string='Parent' args: 'mail.message.subtype'
  • relation_field Char
    help='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).' args: 'Relation field'
  • res_model Char
    help='Model the subtype applies to. If False, this subtype applies to all models.' args: 'Model'
  • sequence Integer
    default=1 help='Used to order subtypes.' args: 'Sequence'
Public methods (4)
  • create(self, vals)
    @api.model
  • default_subtypes(self, model_name)
    @api.model
    Retrieve the default subtypes (all, internal, external) for the given model.
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (3)
  • channel_id Many2one → mail.channel
    index=True required=True string='Channel' args: 'mail.channel'
  • email Char
    index=True required=True string='Email'
  • status Selection
    required=True string='Status' args: [('allow', 'Always Allow'), ('ban', 'Permanent Ban')]
Public methods (0)

No public methods.

New fields (8)
  • email_status Selection
    default='ready' index=True args: [('ready', 'Ready to Send'), ('sent', 'Sent'), ('bounce', 'Bounced'), ('exception', 'Exception'), ('canceled', 'Canceled')], 'Email Status'
  • failure_reason Text
    copy=False args: 'Failure reason'
  • failure_type Selection
    selection=[('SMTP', 'Connection failed (outgoing mail server problem)'), ('RECIPIENT', 'Invalid email address'), ('BOUNCE', 'Email address rejected by destination'), ('UNKNOWN', 'Unknown error')] string='Failure type'
  • is_email Boolean
    index=True args: 'Sent by Email'
  • is_read Boolean
    index=True args: 'Is Read'
  • mail_id Many2one → mail.mail
    index=True args: 'mail.mail', 'Mail'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • res_partner_id Many2one → res.partner
    index=True ondelete='cascade' required=True args: 'res.partner', 'Needaction Recipient'
Public methods (4)
  • create(self, vals)
    @api.model
  • format_failure_reason(self)
    @api.multi
  • init(self)
    @api.model_cr
  • write(self, vals)
    @api.multi

New fields (2)
  • help_message Char
    compute='_compute_help_message' string='Help message'
  • model Char
    string='Model'
Public methods (1)
  • cancel_resend_action(self)
    @api.multi

New fields (5)
  • has_cancel Boolean
    compute='_compute_has_cancel'
  • mail_message_id Many2one → mail.message
    readonly=True args: 'mail.message', 'Message'
  • notification_ids Many2many → mail.notification
    readonly=True string='Notifications' args: 'mail.notification'
  • partner_ids One2many → mail.resend.partner
    string='Recipients' args: 'mail.resend.partner', 'resend_wizard_id'
  • partner_readonly Boolean
    compute='_compute_partner_readonly'
Public methods (3)
  • cancel_mail_action(self)
    @api.multi
  • default_get(self, fields)
    @api.model
  • resend_mail_action(self)
    @api.multi
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (6)
  • email Char
    readonly=False related='partner_id.email' related_sudo=False
  • message Char
    string='Help message'
  • name Char
    readonly=False related='partner_id.name' related_sudo=False
  • partner_id Many2one → res.partner
    ondelete='cascade' required=True string='Partner' args: 'res.partner'
  • resend Boolean
    default=True string='Send Again'
  • resend_wizard_id Many2one → mail.resend.message
    string='Resend wizard' args: 'mail.resend.message'
Public methods (0)

No public methods.

New fields (3)
  • description Char
    args: 'Description'
  • source Char
    help='The shortcut which must be replaced in the Chat Messages' index=True required=True args: 'Shortcut'
  • substitution Text
    help='The escaped html code replacing the shortcut' index=True required=True args: 'Substitution'
Public methods (0)

No public methods.

New fields (25)
  • attachment_ids Many2many → ir.attachment
    help='You may attach files to this template, to be added to all emails created from this template' args: 'ir.attachment', 'email_template_attachment_rel', 'email_template_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    default=True help='Permanently delete this email after sending it, to save space' args: 'Auto Delete'
  • body_html Html
    sanitize=False translate=True args: 'Body'
  • copyvalue Char
    help='Final placeholder expression, to be copy-pasted in the desired template field.' args: 'Placeholder Expression'
  • email_cc Char
    help='Carbon copy recipients (placeholders may be used here)' args: 'Cc'
  • email_from Char
    help="Sender address (placeholders may be used here). If not set, the default value will be the author's email alias if configured, or email address." args: 'From'
  • email_to Char
    help='Comma-separated recipient addresses (placeholders may be used here)' args: 'To (Emails)'
  • lang Char
    help='Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. ${object.partner_id.lang}.' placeholder='${object.partner_id.lang}' args: 'Language'
  • mail_server_id Many2one → ir.mail_server
    help='Optional preferred server for outgoing mails. If not set, the highest priority one will be used.' readonly=False args: 'ir.mail_server', 'Outgoing Mail Server'
  • model Char
    index=True readonly=True related='model_id.model' store=True args: 'Related Document Model'
  • model_id Many2one → ir.model
    help='The type of document this template can be used with' args: 'ir.model', 'Applies to'
  • model_object_field Many2one → ir.model.fields
    help='Select target field from the related document model.\nIf it is a relationship field you will be able to select a target field at the destination of the relationship.' string='Field' args: 'ir.model.fields'
  • name Char
    args: 'Name'
  • null_value Char
    help='Optional value to use if the target field is empty' args: 'Default Value'
  • partner_to Char
    help='Comma-separated ids of recipient partners (placeholders may be used here)' oldname='email_recipients' args: 'To (Partners)'
  • ref_ir_act_window Many2one → ir.actions.act_window
    copy=False help='Sidebar action to make this template available on records of the related document model' readonly=True args: 'ir.actions.act_window', 'Sidebar action'
  • reply_to Char
    help='Preferred response address (placeholders may be used here)' args: 'Reply-To'
  • report_name Char
    help='Name to use for the generated report file (may contain placeholders)\nThe extension can be omitted and will then come from the report type.' translate=True args: 'Report Filename'
  • report_template Many2one → ir.actions.report
    args: 'ir.actions.report', 'Optional report to print and attach'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. Jinja2 placeholders may be used.' args: 'Scheduled Date'
  • sub_model_object_field Many2one → ir.model.fields
    help='When a relationship field is selected as first field, this field lets you select the target field within the destination document model (sub-model).' args: 'ir.model.fields', 'Sub-field'
  • sub_object Many2one → ir.model
    help='When a relationship field is selected as first field, this field shows the document model the relationship goes to.' readonly=True args: 'ir.model', 'Sub-model'
  • subject Char
    help='Subject (placeholders may be used here)' translate=True args: 'Subject'
  • use_default_to Boolean
    help='Default recipients of the record:\n- partner (using id on a partner or the partner_id field) OR\n- email (using email_from or email field)' args: 'Default recipients'
  • user_signature Boolean
    help="If checked, the user's signature will be appended to the text version of the message" args: 'Add Signature'
Public methods (13)
  • build_expression(self, field_name, sub_field_name, null_value)
    Returns a placeholder expression for use in a template field, based on the values provided in the placeholder assistant. :param field_name: main field name :param sub_field_name: sub field name (M2O) :param null_value: default value if the target value is empty :return: final placeholder expression
  • copy(self, default=None)
    @api.multi@api.returns('self', <expr>)
  • create_action(self)
    @api.multi
  • default_get(self, fields)
    @api.model
  • generate_email(self, res_ids, fields=None)
    @api.multi
    Generates an email from the template for given the given model based on records given by res_ids. :param res_id: id of the record to use for rendering the template (model is taken from template definition) :returns: a dict containing all relevant fields for creating a new mail.mail entry, with one extra key ``attachments``, in the format [(report_name, data)] where data is base64 encoded.
  • generate_recipients(self, results, res_ids)
    @api.multi
    Generates the recipients of the template. Default values can ben generated instead of the template values if requested by template or context. Emails (email_to, email_cc) can be transformed into partners if requested in the context.
  • get_email_template(self, res_ids)
    @api.multi
  • onchange_model_id(self)
    @api.onchange('model_id')
  • onchange_sub_model_object_value_field(self)
    @api.onchange('model_object_field', 'sub_model_object_field', 'null_value')
  • render_post_process(self, html)
    @api.model
  • send_mail(self, res_id, force_send=False, raise_exception=False, email_values=None, notif_layout=False)
    @api.multi
    Generates a new mail.mail. Template is rendered on record given by res_id and model coming from template. :param int res_id: id of the record to render the template :param bool force_send: send email immediately; otherwise use the mail queue (recommended); :param dict email_values: update generated mail with those values to further customize the mail; :param str notif_layout: optional notification layout to encapsulate the generated email; :returns: id of the mail.mail that was created
  • unlink(self)
    @api.multi
  • unlink_action(self)
    @api.multi

New fields (13)
  • message_attachment_count Integer
    compute='_compute_message_attachment_count' args: 'Attachment Count'
  • message_channel_ids Many2many → mail.channel
    comodel_name='mail.channel' compute='_get_followers' search='_search_follower_channels' string='Followers (Channels)'
  • message_follower_ids One2many → mail.followers
    domain=<expr> string='Followers' args: 'mail.followers', 'res_id'
  • message_has_error Boolean
    compute='_compute_message_has_error' help='If checked, some messages have a delivery error.' search='_search_message_has_error' args: 'Message Delivery error'
  • message_has_error_counter Integer
    compute='_compute_message_has_error' help='Number of messages with delivery error' args: 'Number of error'
  • message_ids One2many → mail.message
    auto_join=True domain=<expr> string='Messages' args: 'mail.message', 'res_id'
  • message_is_follower Boolean
    compute='_compute_is_follower' search='_search_is_follower' args: 'Is Follower'
  • message_main_attachment_id Many2one → ir.attachment
    comodel_name='ir.attachment' copy=False index=True string='Main Attachment'
  • message_needaction Boolean
    compute='_get_message_needaction' help='If checked, new messages require your attention.' search='_search_message_needaction' args: 'Action Needed'
  • message_needaction_counter Integer
    compute='_get_message_needaction' help='Number of messages which requires an action' args: 'Number of Actions'
  • message_partner_ids Many2many → res.partner
    comodel_name='res.partner' compute='_get_followers' search='_search_follower_partners' string='Followers (Partners)'
  • message_unread Boolean
    compute='_get_message_unread' help='If checked new messages require your attention.' args: 'Unread Messages'
  • message_unread_counter Integer
    compute='_get_message_unread' help='Number of unread messages' args: 'Unread Messages Counter'
Public methods (26)
  • check_mail_message_access(self, res_ids, operation, model_name=None)
    @api.model
    mail.message check permission rules for related document. This method is meant to be inherited in order to implement addons-specific behavior. A common behavior would be to allow creating messages when having read access rule on the document, for portal document such as issues.
  • copy_data(self, default=None)
    @api.multi
  • create(self, vals_list)
    @api.model_create_multi
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False)
    @api.model
  • get_empty_list_help(self, help)
    @api.model
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • message_change_thread(self, new_thread)
    @api.multi
    Transfer the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : my_lead.message_change_thread(my_project_task) will transfer the context of the thread of my_lead to my_project_task
  • message_get_default_recipients(self, res_model=None, res_ids=None)
    @api.multi
  • message_get_suggested_recipients(self)
    @api.multi
    Returns suggested recipients for ids. Those are a list of tuple (partner_id, partner_name, reason), to be managed by Chatter.
  • message_new(self, msg_dict, custom_values=None)
    @api.model
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :rtype: int :return: the id of the newly created thread object
  • message_notify(self, partner_ids, body='', subject=False, **kwargs)
    Shortcut allowing to notify partners of messages not linked to any document. It pushes notifications on inbox or by email depending on the user configuration, like other notifications.
  • message_parse(self, message, save_original=False)
    @api.model
    Parses a string or email.message.Message representing an RFC-2822 email, and returns a generic dict holding the message details. :param message: the message to parse :type message: email.message.Message | string | unicode :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'from': from, 'to': to, 'cc': cc, 'body': unified_body, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_partner_info_from_emails(self, emails, link_mail=False)
    @api.multi
    Convert a list of emails into a list partner_ids and a list new_partner_ids. The return value is non conventional because it is meant to be used by the mail widget. :return dict: partner_ids and new_partner_ids
  • message_post(self, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, notif_layout=False, add_sign=True, model_description=False, mail_auto_delete=True, **kwargs)
    @api.multi@api.returns('mail.message', <expr>)
    Post a new message in an existing thread, returning the new mail.message ID. :param int thread_id: thread ID to post into, or list with one ID; if False/0, mail.message model will also be set as False :param str body: body of the message, usually raw HTML that will be sanitized :param str type: see mail_message.message_type field :param int parent_id: handle reply to a previous message by adding the parent partners to the message in case of private discussion :param tuple(str,str) attachments or list id: list of attachment tuples in the form ``(name,content)``, where content is NOT base64 encoded Extra keyword arguments will be used as default column values for the new mail.message record. Special cases: - attachment_ids: supposed not attached to any document; attach them to the related document. Should only be set by Chatter. :return int: ID of newly created mail.message
  • message_post_with_template(self, template_id, **kwargs)
    @api.multi
    Helper method to send a mail with a template :param template_id : the id of the template to render to create the body of the message :param **kwargs : parameter to create a mail.compose.message woaerd (which inherit from mail.message)
  • message_post_with_view(self, views_or_xmlid, **kwargs)
    @api.multi
    Helper method to send a mail / post a message using a view_id to render using the ir.qweb engine. This method is stand alone, because there is nothing in template and composer that allows to handle views in batch. This method should probably disappear when templates handle ir ui views.
  • message_process(self, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None)
    @api.model
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). There is a special case where the target model is False: a reply to a private message. In this case, we skip the message_new / message_update step, to just post a new message using mail_thread message_post. :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: string or xmlrpclib.Binary :type dict custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • message_receive_bounce(self, email, partner, mail_id=None)
    @api.multi
    Called by ``message_process`` when a bounce email (such as Undelivered Mail Returned to Sender) is received for an existing thread. The default behavior is to check is an integer ``message_bounce`` column exists. If it is the case, its content is incremented. :param mail_id: ID of the sent email that bounced. It may not exist anymore but it could be usefull if the information was kept. This is used notably in mass mailing. :param RecordSet partner: partner matching the bounced email address, if any :param string email: email that caused the bounce
  • message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None)
    @api.model
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: * if the message replies to an existing thread by having a Message-Id that matches an existing mail_message.message_id, we take the original message model/thread_id pair and ignore custom_value as no creation will take place * if the message replies to an existing thread by having In-Reply-To or References matching odoo model/thread_id Message-Id and if this thread has messages without message_id, take this model/thread_id pair and ignore custom_value as no creation will take place (6.1 compatibility) * look for a mail.alias entry matching the message recipients and use the corresponding model, thread_id, custom_values and user_id. This could lead to a thread update or creation depending on the alias * fallback on provided ``model``, ``thread_id`` and ``custom_values`` * raise an exception as no route has been found :param string message: an email.message instance :param dict message_dict: dictionary holding parsed message variables :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :type dict custom_values: optional dictionary of default field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of routes [(model, thread_id, custom_values, user_id, alias)] :raises: ValueError, TypeError
  • message_route_process(self, message, message_dict, routes)
    @api.model
  • message_route_verify(self, message, message_dict, route, update_author=True, assert_model=True, create_fallback=True, allow_private=False, drop_alias=False)
    @api.model
    Verify route validity. Check and rules: 1 - if thread_id -> check that document effectively exists; otherwise fallback on a message_new by resetting thread_id 2 - check that message_update exists if thread_id is set; or at least that message_new exist [ - find author_id if udpate_author is set] 3 - if there is an alias, check alias_contact: 'followers' and thread_id: check on target document that the author is in the followers 'followers' and alias_parent_thread_id: check on alias parent document that the author is in the followers 'partners': check that author_id id set :param message: an email.message instance :param message_dict: dictionary of values that will be given to mail_message.create() :param route: route to check which is a tuple (model, thread_id, custom_values, uid, alias) :param update_author: update message_dict['author_id']. TDE TODO: move me :param assert_model: if an error occurs, tell whether to raise an error or just log a warning and try other processing or invalidate route :param create_fallback: if the route aims at updating a record and that record does not exists or does not support update either fallback on creating a new record in the same model or raise / warn :param allow_private: allow void model / thread_id routes, aka private discussions
  • message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None)
    @api.multi
    Main public API to add followers to a record set. Its main purpose is to perform access rights checks before calling ``_message_subscribe``.
  • message_track(self, tracked_fields, initial_values)
    @api.multi
    Track updated values. Comparing the initial and current values of the fields given in tracked_fields, it generates a message containing the updated values. This message can be linked to a mail.message.subtype given by the ``_track_subtype`` method.
  • message_unsubscribe(self, partner_ids=None, channel_ids=None)
    @api.multi
    Remove partners from the records followers.
  • message_update(self, msg_dict, update_vals=None)
    @api.multi
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • unlink(self)
    @api.multi
    Override unlink to delete messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • write(self, values)
    @api.multi

New fields (17)
  • field Char
    readonly=1 required=True args: 'Changed Field'
  • field_desc Char
    readonly=1 required=True args: 'Field Description'
  • field_type Char
    args: 'Field Type'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message ID'
  • new_value_char Char
    readonly=1 args: 'New Value Char'
  • new_value_datetime Datetime
    readonly=1 args: 'New Value Datetime'
  • new_value_float Float
    readonly=1 args: 'New Value Float'
  • new_value_integer Integer
    readonly=1 args: 'New Value Integer'
  • new_value_monetary Float
    readonly=1 args: 'New Value Monetary'
  • new_value_text Text
    readonly=1 args: 'New Value Text'
  • old_value_char Char
    readonly=1 args: 'Old Value Char'
  • old_value_datetime Datetime
    readonly=1 args: 'Old Value DateTime'
  • old_value_float Float
    readonly=1 args: 'Old Value Float'
  • old_value_integer Integer
    readonly=1 args: 'Old Value Integer'
  • old_value_monetary Float
    readonly=1 args: 'Old Value Monetary'
  • old_value_text Text
    readonly=1 args: 'Old Value Text'
  • track_sequence Integer
    default=100 readonly=1 args: 'Tracking field sequence'
Public methods (4)
  • create_tracking_values(self, initial_value, new_value, col_name, col_info, track_sequence)
    @api.model
  • get_display_value(self, type)
    @api.multi
  • get_new_display_value(self)
    @api.multi
  • get_old_display_value(self)
    @api.multi

New fields (6)
  • channel_ids Many2many → mail.channel
    domain=[('channel_type', '=', 'channel')] help='List of channels that will be added as listeners of the current document.' string='Channels' args: 'mail.channel'
  • message Html
    args: 'Message'
  • partner_ids Many2many → res.partner
    help='List of partners that will be added as follower of the current document.' string='Recipients' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' index=True args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' index=True required=True args: 'Related Document Model'
  • send_mail Boolean
    default=True help="If checked, the partners will receive an email warning they have been added in the document's followers." args: 'Send Email'
Public methods (2)
  • add_followers(self)
    @api.multi
  • default_get(self, fields)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cron_mode=True)
    @api.multi
    Send a message to Odoo's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (1)
  • catchall Char
    compute='_compute_catchall' string='Catchall Email'
Public methods (0)

No public methods.

New fields (2)
  • alias_domain Char
    config_parameter='mail.catchall.domain' help='If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.' args: 'Alias Domain'
  • fail_counter Integer
    readonly=True args: 'Fail Mail'
Public methods (2)
  • get_values(self)
    @api.model
  • set_values(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals, context=None)
    @api.multi

New fields (2)
  • channel_ids Many2many → mail.channel
    copy=False string='Channels' args: 'mail.channel', 'mail_channel_partner', 'partner_id', 'channel_id'
  • message_bounce Integer
    default=0 help='Counter of the number of bounced emails for this contact' args: 'Bounce'
Public methods (6)
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first partners' id, name and email such that the name or email matches a 'search' string. Prioritize users, and then extend the research to all partners.
  • get_needaction_count(self)
    @api.model
    compute the number of needaction of the current user
  • get_starred_count(self)
    @api.model
    compute the number of starred of the current user
  • get_static_mention_suggestions(self)
    @api.model
    To be overwritten to return the id, name and email of partners used as static mention suggestions loaded once at webclient initialization and stored client side.
  • message_get_default_recipients(self)
    @api.multi
  • message_get_suggested_recipients(self)
    @api.multi

New fields (6)
  • alias_contact Selection
    readonly=False related='alias_id.alias_contact' string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_id Many2one → mail.alias
    auto_join=True copy=False help="Email address internally associated with this user. Incoming emails will appear in the user's notifications." ondelete='set null' required=False args: 'mail.alias', 'Alias'
  • is_moderator Boolean
    compute='_compute_is_moderator' string='Is moderator'
  • moderation_channel_ids Many2many → mail.channel
    string='Moderated channels' args: 'mail.channel', 'mail_channel_moderator_rel'
  • moderation_counter Integer
    compute='_compute_moderation_counter' string='Moderation count'
  • notification_type Selection
    default='email' help='Policy on how to handle Chatter notifications:\n- Handle by Emails: notifications are sent to your email address\n- Handle in Odoo: notifications appear in your Odoo Inbox' required=True args: [('email', 'Handle by Emails'), ('inbox', 'Handle in Odoo')], 'Notification Management'
Public methods (3)
  • create(self, values)
    @api.model
  • systray_get_activities(self)
    @api.model
  • write(self, vals)
    @api.multi
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/11.0/mail
VERSION
VERSION 1.0
CATEGORY
CATEGORYDiscuss
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Christophe Matthieu, Martin Trigaux, Fabien Pinckaers, Olivier Dony, Thibault Delavallée, Denis Ledoux, Christophe Simonis, David Monjoie, Xavier Morel, Goffin Simon, Nicolas Martinelli, Nicolas Lempereur, Jérome Maes, xmo-odoo, qdp-odoo, Géry Debongnie, Aaron Bohy, ged-odoo, Jeremy Kersten, GitHub, Lucas Perais (lpe), Yannick Tivisse, Alexandre Kühn, qsm-odoo, Martin Geubelle, Odoo Online, Laurent Smet, DVE, fwi-odoo, tbe-odoo, Adrien Dieudonne, RomainLibert, len-odoo, Julien (juc) Castiaux, Jorge Pinna Puissant, Nans Lefebvre, Lucas Perais, amoyaux, Alexandre Kühn, jev-odoo, Moens Alexandre, XavierDo, Julien Castiaux, jvm-odoo, Victor Feyens, Loan (lse), Pere Albujer, Katherine Zaoral, VincentSchippefilt, Debauche Stéphane
WEBSITE
WEBSITEhttps://www.odoo.com/page/enterprise-social-network
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-05 23:53:43
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web
    - bus
    - web_tour
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (51)
XML IDNameModelTypeStatus
assets_backend mail assets ir.ui.view qweb Inherits web.assets_backend
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
email_template_form email.template.form mail.template form New
email_template_preview_form email_template.preview.form email_template.preview form New
email_template_tree email.template.tree mail.template tree New
field_form_view ir.model.fields field Inherits base.view_model_fields_form
mail_activity_type_view_form mail.activity.type.view.form mail.activity.type form New
mail_activity_type_view_tree mail.activity.type.view.tree mail.activity.type tree New
mail_activity_view_calendar mail.activity.view.calendar mail.activity calendar New
mail_activity_view_form_popup mail.activity.view.form.popup mail.activity form New
mail_activity_view_search mail.activity.view.search mail.activity search New
mail_activity_view_tree mail.activity.view.tree mail.activity tree New
mail_channel_partner_view_form mail.channel.partner.form mail.channel.partner form New
mail_channel_partner_view_tree mail.channel.partner.tree mail.channel.partner tree New
mail_channel_view_form mail.channel.form mail.channel form New
mail_channel_view_kanban mail.channel.kanban mail.channel kanban New
mail_channel_view_search mail.channel.search mail.channel search New
mail_channel_view_tree mail.channel.tree mail.channel tree New
mail_shortcode_view_form mail.shortcode.form mail.shortcode form New
mail_shortcode_view_tree mail.shortcode.tree mail.shortcode tree New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
message_activity_done message_activity_done ir.ui.view qweb New
message_origin_link message_origin_link ir.ui.view qweb New
message_user_assigned message_user_assigned ir.ui.view qweb New
model_form_view ir.model field Inherits base.view_model_form
model_search_view ir.model field Inherits base.view_model_search
qunit_mobile_suite mail_mobile_tests ir.ui.view qweb Inherits web.qunit_mobile_suite
qunit_suite mail_tests ir.ui.view qweb Inherits web.qunit_suite
res_config_settings_view_form res.config.settings.view.form.inherit.mail res.config.settings div Inherits base_setup.res_config_settings_view_form
res_partner_view_form_inherit_mail res.partner.view.form.inherit.mail res.partner xpath Inherits base.view_partner_form
res_partner_view_search_inherit_mail res.partner.view.search.inherit.mail res.partner filter Inherits base.view_res_partner_filter
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_email_template_search email.template.search mail.template search New
view_followers_tree mail.followers.tree mail.followers tree New
view_mail_alias_form mail.alias.form mail.alias form New
view_mail_alias_search mail.alias.search mail.alias search New
view_mail_alias_tree mail.alias.tree mail.alias tree New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tracking_value_form mail.tracking.value.form mail.tracking.value form New
view_mail_tracking_value_tree mail.tracking.value.tree mail.tracking.value tree New
view_mail_tree mail.mail.tree mail.mail tree New
view_message_form mail.message.form mail.message form New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.tree mail.message.subtype tree New
view_message_tree mail.message.tree mail.message tree New
view_server_action_form_template ir.actions.server.form ir.actions.server field Inherits base.view_server_action_form
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (29)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (3)
  • attachment_ids Many2many
    store=False string='Attachments'
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • res_id Selection
    args: _get_records, 'Sample Document'
Public methods (2)
  • default_get(self, fields)
    @api.model
  • on_change_res_id(self)
    @api.onchange('res_id')@api.multi

New fields (4)
  • channel_ids Many2many → mail.channel
    string='Add Channels' args: 'mail.channel'
  • partner_ids Many2many → res.partner
    string='Add Followers' args: 'res.partner'
  • state Selection
    selection_add=[('email', 'Send Email'), ('followers', 'Add Followers')]
  • template_id Many2one → mail.template
    domain="[('model_id', '=', model_id)]" ondelete='set null' args: 'mail.template', 'Email Template'
Public methods (3)
  • on_change_template_id(self)
    @api.onchange('template_id')
    Render the raw template in the server action fields.
  • run_action_email(self, action, eval_context=None)
    @api.model
  • run_action_followers_multi(self, action, eval_context=None)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • power_on(self, *args, **kwargs)
    @api.model

New fields (1)
  • is_mail_thread Boolean
    default=False help='Whether this model supports messages and notifications.' oldname='mail_thread' string='Mail Thread'
Public methods (2)
  • unlink(self)
  • write(self, vals)
    @api.multi

New fields (1)
  • track_visibility Selection
    help='When set, every modification to this field will be tracked in the chatter.' string='Tracking' args: [('onchange', 'On Change'), ('always', 'Always')]
Public methods (0)

No public methods.

New fields (16)
  • activity_category Selection
    readonly=True related='activity_type_id.category'
  • activity_type_id Many2one → mail.activity.type
    domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]" args: 'mail.activity.type', 'Activity'
  • date_deadline Date
    default=fields.Date.context_today index=True required=True args: 'Due Date'
  • feedback Html
    args: 'Feedback'
  • has_recommended_activities Boolean
    compute='_compute_has_recommended_activities' help='Technical field for UX purpose' args: 'Next activities available'
  • icon Char
    readonly=True related='activity_type_id.icon' args: 'Icon'
  • note Html
    sanitize_style=True args: 'Note'
  • previous_activity_type_id Many2one → mail.activity.type
    readonly=True string='Previous Activity Type' args: 'mail.activity.type'
  • recommended_activity_type_id Many2one → mail.activity.type
    string='Recommended Activity Type' args: 'mail.activity.type'
  • res_id Integer
    index=True required=True args: 'Related Document ID'
  • res_model Char
    index=True readonly=True related='res_model_id.model' store=True args: 'Related Document Model'
  • res_model_id Many2one → ir.model
    index=True ondelete='cascade' required=True args: 'ir.model', 'Related Document Model'
  • res_name Char
    compute='_compute_res_name' help='Display name of the related document.' readonly=True store=True args: 'Document Name'
  • state Selection
    compute='_compute_state' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')], 'State'
  • summary Char
    args: 'Summary'
  • user_id Many2one → res.users
    default=<expr> index=True required=True args: 'res.users', 'Assigned to'
Public methods (7)
  • action_close_dialog(self)
    @api.multi
  • action_done(self)
    @api.multi
    Wrapper without feedback because web button add context as parameter, therefore setting context to feedback
  • action_feedback(self, feedback=False)
  • create(self, values)
    @api.model
  • default_get(self, fields)
    @api.model
  • unlink(self)
    @api.multi
  • write(self, values)
    @api.multi

New fields (6)
  • activity_date_deadline Date
    groups='base.group_user' readonly=True related='activity_ids.date_deadline' store=True args: 'Next Activity Deadline'
  • activity_ids One2many → mail.activity
    auto_join=True domain=<expr> groups='base.group_user' args: 'mail.activity', 'res_id', 'Activities'
  • activity_state Selection
    compute='_compute_activity_state' groups='base.group_user' help='Status based on activities\nOverdue: Due date is already passed\nToday: Activity date is today\nPlanned: Future activities.' string='State' args: [('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')]
  • activity_summary Char
    groups='base.group_user' related='activity_ids.summary' search='_search_activity_summary' args: 'Next Activity Summary'
  • activity_type_id Many2one → mail.activity.type
    groups='base.group_user' related='activity_ids.activity_type_id' search='_search_activity_type_id' args: 'mail.activity.type', 'Next Activity Type'
  • activity_user_id Many2one → res.users
    groups='base.group_user' related='activity_ids.user_id' search='_search_activity_user_id' args: 'res.users', 'Responsible'
Public methods (2)
  • unlink(self)
    @api.multi
    Override unlink to delete records activities through (res_model, res_id).
  • write(self, vals)
    @api.multi

New fields (9)
  • category Selection
    default='default' help='Categories may trigger specific behavior like opening calendar view' string='Category' args: [('default', 'Other')]
  • days Integer
    default=0 help='Number of days before executing the action. It allows to plan the action deadline.' args: '# Days'
  • icon Char
    help='Font awesome icon e.g. fa-tasks' args: 'Icon'
  • name Char
    required=True translate=True args: 'Name'
  • next_type_ids Many2many → mail.activity.type
    string='Recommended Next Activities' args: 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id'
  • previous_type_ids Many2many → mail.activity.type
    string='Preceding Activities' args: 'mail.activity.type', 'mail_activity_rel', 'recommended_id', 'activity_id'
  • res_model_id Many2one → ir.model
    help='Specify a model if the activity should be specific to a model and not available when managing activities for other models.' index=True args: 'ir.model', 'Model'
  • sequence Integer
    default=10 args: 'Sequence'
  • summary Char
    translate=True args: 'Summary'
Public methods (0)

No public methods.

New fields (9)
  • alias_contact Selection
    default='everyone' help='Policy to post a message on the document using the mailgateway.\n- everyone: everyone can post\n- partners: only authenticated partners\n- followers: only followers of the related document or members of following channels\n' required=True string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_defaults Text
    default='{}' help='A Python dictionary that will be evaluated to provide default values when creating new records for this alias.' required=True args: 'Default Values'
  • alias_domain Char
    compute='_get_alias_domain' default=<expr> args: 'Alias domain'
  • alias_force_thread_id Integer
    help='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.' args: 'Record Thread ID'
  • alias_model_id Many2one → ir.model
    domain="[('field_id.name', '=', 'message_ids')]" help='The model (Odoo 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)' ondelete='cascade' required=True args: 'ir.model', 'Aliased Model'
  • alias_name Char
    help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>" args: 'Alias Name'
  • alias_parent_model_id Many2one → ir.model
    help='Parent model holding the alias. The model holding the alias reference is not necessarily the model given by alias_model_id (example: project (parent_model) and task (model))' args: 'ir.model', 'Parent Model'
  • alias_parent_thread_id Integer
    help='ID of the parent record holding the alias (example: project holding the task creation alias)' args: 'Parent Record Thread ID'
  • alias_user_id Many2one → res.users
    defaults=<expr> help='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.' args: 'res.users', 'Owner'
Public methods (5)
  • create(self, vals)
    @api.model
    Creates an email.alias record according to the values provided in ``vals``, with 2 alterations: the ``alias_name`` value may be suffixed in order to make it unique (and certain unsafe characters replaced), and he ``alias_model_id`` value will set to the model ID of the ``model_name`` context value, if provided.
  • name_get(self)
    @api.multi
    Return the mail alias display alias_name, including the implicit mail catchall domain if exists from config otherwise "New Alias". e.g. `jobs@mail.odoo.com` or `jobs` or 'New Alias'
  • open_document(self)
    @api.multi
  • open_parent_document(self)
    @api.multi
  • write(self, vals)
    @api.multi
    "give a unique alias name if given alias name is already assigned

New fields (1)
  • alias_id Many2one → mail.alias
    ondelete='restrict' required=True string='Alias' args: 'mail.alias'
Public methods (4)
  • create(self, vals)
    @api.model
    Create a record with ``vals``, and create a corresponding alias.
  • get_alias_model_name(self, vals)
    Return the model name for the alias. Incoming emails that are not replies to existing records will cause the creation of a new record of this alias model. The value may depend on ``vals``, the dict of values passed to ``create`` when a record of this model is created.
  • get_alias_values(self)
    Return values to create an alias, or to write on the alias after its creation.
  • unlink(self)
    @api.multi
    Delete the given records, and cascade-delete their corresponding alias.

New fields (16)
  • channel_last_seen_partner_ids One2many → mail.channel.partner
    string='Last Seen' args: 'mail.channel.partner', 'channel_id'
  • channel_message_ids Many2many → mail.message
    args: 'mail.message', 'mail_message_mail_channel_rel'
  • channel_partner_ids Many2many → res.partner
    string='Listeners' args: 'res.partner', 'mail_channel_partner', 'channel_id', 'partner_id'
  • channel_type Selection
    default='channel' args: [('chat', 'Chat Discussion'), ('channel', 'Channel')], 'Channel Type'
  • description Text
    args: 'Description'
  • email_send Boolean
    default=False args: 'Send messages by email'
  • group_ids Many2many → res.groups
    help='Members of those groups will automatically added as followers. Note that they will be able to manage their subscription manually if necessary.' string='Auto Subscription' args: 'res.groups'
  • group_public_id Many2one → res.groups
    default=<expr> string='Authorized Group' args: 'res.groups'
  • image Binary
    attachment=True default=_get_default_image help='This field holds the image used as photo for the group, limited to 1024x1024px.' args: 'Photo'
  • image_medium Binary
    attachment=True help='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.' args: 'Medium-sized photo'
  • image_small Binary
    attachment=True help='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.' args: 'Small-sized photo'
  • is_member Boolean
    compute='_compute_is_member' args: 'Is a member'
  • is_subscribed Boolean
    compute='_compute_is_subscribed' args: 'Is Subscribed'
  • name Char
    required=True translate=True args: 'Name'
  • public Selection
    default='groups' help='This group is visible by non members. Invisible groups can add members through the invite button.' required=True args: [('public', 'Everyone'), ('private', 'Invited people only'), ('groups', 'Selected group of users')], 'Privacy'
  • uuid Char
    copy=False default=<expr> index=True size=50 args: 'UUID'
Public methods (30)
  • action_follow(self)
    @api.multi
  • action_unfollow(self)
    @api.multi
  • channel_create(self, name, privacy='public')
    @api.model
    Create a channel and add the current partner, broadcast it (to make the user directly listen to it when polling) :param name : the name of the channel to create :param privacy : privacy of the channel. Should be 'public' or 'private'. :return dict : channel header
  • channel_fetch_listeners(self, uuid)
    @api.model
    Return the id, name and email of partners listening to the given channel
  • channel_fetch_message(self, last_id=False, limit=20)
    @api.multi
    Return message values of the current channel. :param last_id : last message id to start the research :param limit : maximum number of messages to fetch :returns list of messages values :rtype : list(dict)
  • channel_fetch_preview(self)
    @api.multi
    Return the last message of the given channels
  • channel_fetch_slot(self)
    @api.model
    Return the channels of the user grouped by 'slot' (channel, direct_message or private_group), and the mapping between partner_id/channel_id for direct_message channels. :returns dict : the grouped channels and the mapping
  • channel_fold(self, uuid, state=None)
    @api.model
    Update the fold_state of the given session. In order to syncronize web browser tabs, the change will be broadcast to himself (the current user channel). Note: the user need to be logged :param state : the new status of the session for the current user.
  • channel_get(self, partners_to, pin=True)
    @api.model
    Get the canonical private channel between some partners, create it if needed. To reuse an old channel (conversation), this one must be private, and contains only the given partners. :param partners_to : list of res.partner ids to add to the conversation :param pin : True if getting the channel should pin it for the current user :returns a channel header, or False if the users_to was False :rtype : dict
  • channel_get_and_minimize(self, partners_to)
    @api.model
  • channel_info(self, extra_info=False)
    @api.multi
    Get the informations header for the current channels :returns a list of channels values :rtype : list(dict)
  • channel_invite(self, partner_ids)
    @api.multi
    Add the given partner_ids to the current channels and broadcast the channel header to them. :param partner_ids : list of partner id to add
  • channel_join_and_get_info(self)
    @api.multi
  • channel_minimize(self, uuid, minimized=True)
    @api.model
  • channel_pin(self, uuid, pinned=False)
    @api.model
  • channel_search_to_join(self, name=None, domain=None)
    @api.model
    Return the channel info of the channel the current partner can join :param name : the name of the researched channels :param domain : the base domain of the research :returns dict : channel dict
  • channel_seen(self)
    @api.multi
  • create(self, vals)
    @api.model
  • default_get(self, fields)
    @api.model
  • execute_command(self, command='', **kwargs)
    @api.multi
    Executes a given command
  • get_alias_model_name(self, vals)
  • get_mention_commands(self)
    @api.model@ormcache()
    Returns the allowed commands in channels
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first channels' id, name and public fields such that the name matches a 'search' string. Exclude channels of type chat (DM), and private channels the current user isn't registered to.
  • init(self)
    @api.model_cr
  • message_get_email_values(self, notif_mail=None)
    @api.multi
  • message_get_recipient_values(self, notif_message=None, recipient_ids=None)
    @api.multi
  • message_post(self, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, content_subtype='html', **kwargs)
    @api.multi@api.returns('self', <expr>)
  • message_receive_bounce(self, email, partner, mail_id=None)
    @api.multi
    Override bounce management to unsubscribe bouncing addresses
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (7)
  • channel_id Many2one → mail.channel
    ondelete='cascade' string='Channel' args: 'mail.channel'
  • fold_state Selection
    default='open' string='Conversation Fold State' args: [('open', 'Open'), ('folded', 'Folded'), ('closed', 'Closed')]
  • is_minimized Boolean
    args: 'Conversation is minimized'
  • is_pinned Boolean
    default=True args: 'Is pinned on the interface'
  • partner_email Char
    related='partner_id.email' args: 'Email'
  • partner_id Many2one → res.partner
    ondelete='cascade' string='Recipient' args: 'res.partner'
  • seen_message_id Many2one → mail.message
    string='Last Seen' args: 'mail.message'
Public methods (3)
  • create(self, vals)
    @api.model
  • unlink(self)
  • write(self, vals)

New fields (13)
  • active_domain Text
    readonly=True args: 'Active domain'
  • attachment_ids Many2many → ir.attachment
    args: 'ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    help='Delete sent emails (mass mailing only)' args: 'Delete Emails'
  • auto_delete_message Boolean
    help='Do not keep a copy of the email in the document communication history (mass mailing only)' args: 'Delete Message Copy'
  • composition_mode Selection
    default='comment' selection=_get_composition_mode_selection string='Composition mode'
  • is_log Boolean
    help='Whether the message is an internal note (comment mode only)' args: 'Log an Internal Note'
  • message_type Selection
    default='comment'
  • notify Boolean
    help='Notify followers of the document (mass post only)' args: 'Notify followers'
  • partner_ids Many2many → res.partner
    args: 'res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional Contacts'
  • subject Char
    default=False
  • subtype_id Many2one
    default=<expr>
  • template_id Many2one → mail.template
    domain="[('model', '=', model)]" index=True args: 'mail.template', 'Use template'
  • use_active_domain Boolean
    args: 'Use active domain'
Public methods (12)
  • check_access_rule(self, operation)
    @api.multi
    Access rules of mail.compose.message: - create: if - model, no res_id, I create a message in mass mail mode - then: fall back on mail.message acces rules
  • default_get(self, fields)
    @api.model
    Handle composition mode. Some details about context keys: - comment: default mode, model and ID of a record the user comments - default_model or active_model - default_res_id or active_id - reply: active_id of a message the user replies to - default_parent_id or message_id or active_id: ID of the mail.message we reply to - message.res_model or default_model - message.res_id or default_res_id - mass_mail: model and IDs of records the user mass-mails - active_ids: record IDs - default_model or active_model
  • generate_email_for_composer(self, template_id, res_ids, fields=None)
    @api.model
    Call email_template.generate_email(), get fields relevant for mail.compose.message, transform email_cc and email_to into partner_ids
  • get_mail_values(self, res_ids)
    @api.multi
    Generate the values that will be used by send_mail to create mail_messages or mail_mails.
  • get_record_data(self, values)
    @api.model
    Returns a defaults-like dict with initial values for the composition wizard when sending an email related a previous email (parent_id) or a document (model, res_id). This is based on previously computed default values.
  • onchange_template_id(self, template_id, composition_mode, model, res_id)
    @api.multi
    - mass_mailing: we cannot render, so return the template values - normal mode: return rendered values /!\ for x2many field, this onchange return command instead of ids
  • onchange_template_id_wrapper(self)
    @api.multi@api.onchange('template_id')
  • render_message(self, res_ids)
    @api.multi
    Generate template-based values of wizard, for the document records given by res_ids. This method is meant to be inherited by email_template that will produce a more complete dictionary, using Jinja2 templates. Each template is generated for all res_ids, allowing to parse the template once, and render it multiple times. This is useful for mass mailing where template rendering represent a significant part of the process. Default recipients are also computed, based on mail_thread method message_get_default_recipients. This allows to ensure a mass mailing has always some recipients specified. :param browse wizard: current mail.compose.message browse record :param list res_ids: list of record ids :return dict results: for each res_id, the generated template values for subject, body, email_from and reply_to
  • render_template(self, template, model, res_ids, post_process=False)
    @api.model
  • save_as_template(self)
    @api.multi
    hit save as template button: current form value will be a new template attached to the current document.
  • send_mail(self, auto_commit=False)
    @api.multi
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.
  • send_mail_action(self)
    @api.multi

New fields (5)
  • channel_id Many2one → mail.channel
    index=True ondelete='cascade' string='Listener' args: 'mail.channel'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' string='Related Partner' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' index=True args: 'Related Document ID'
  • res_model Char
    index=True required=True args: 'Related Document Model Name'
  • subtype_ids Many2many → mail.message.subtype
    help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall." string='Subtype' args: 'mail.message.subtype'
Public methods (3)
  • create(self, vals)
    @api.model
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (12)
  • auto_delete Boolean
    help='Permanently delete this email after sending it, to save space' args: 'Auto Delete'
  • body_html Text
    help='Rich-text/HTML message' args: 'Rich-text Contents'
  • email_cc Char
    help='Carbon copy message recipients' args: 'Cc'
  • email_to Text
    help='Message recipients (emails)' args: 'To'
  • failure_reason Text
    help='Failure reason. This is usually the exception thrown by the email server, stored to ease the debugging of mailing issues.' readonly=1 args: 'Failure Reason'
  • headers Text
    copy=False args: 'Headers'
  • mail_message_id Many2one → mail.message
    auto_join=True index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification Boolean
    help='Mail has been created to notify people of an existing mail.message' args: 'Is Notification'
  • recipient_ids Many2many → res.partner
    string='To (Partners)' args: 'res.partner'
  • references Text
    help='Message references, such as identifiers of previous messages' readonly=1 args: 'References'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible.' args: 'Scheduled Send Date'
  • state Selection
    copy=False default='outgoing' readonly=True args: [('outgoing', 'Outgoing'), ('sent', 'Sent'), ('received', 'Received'), ('exception', 'Delivery Failed'), ('cancel', 'Cancelled')], 'Status'
Public methods (11)
  • cancel(self)
    @api.multi
  • create(self, values)
    @api.model
  • default_get(self, fields)
    @api.model
  • mark_outgoing(self)
    @api.multi
  • process_email_queue(self, ids=None)
    @api.model
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! :param list ids: optional list of emails ids to send. If passed no search is performed, and these ids are used instead. :param dict context: if a 'filters' key is present in context, this value will be used as an additional filter to further restrict the outgoing messages to send (by default all 'outgoing' messages are sent).
  • send(self, auto_commit=False, raise_exception=False)
    @api.multi
    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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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
  • send_get_email_dict(self, partner=None)
    @api.multi
    Return a dictionary for specific email values, depending on a partner, or generic to the whole recipients given by mail.email_to. :param Model partner: specific recipient partner
  • send_get_mail_body(self, partner=None)
    @api.multi
    Return a specific ir_email body. The main purpose of this method is to be inherited to add custom content depending on some module.
  • send_get_mail_to(self, partner=None)
    @api.multi
    Forge the email_to with the following heuristic: - if 'partner', recipient specific (Partner Name <email>) - else fallback on mail.email_to splitting
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (27)
  • attachment_ids Many2many → ir.attachment
    help='Attachments are linked to a document through model / res_id and to the message through this field.' string='Attachments' args: 'ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id'
  • author_avatar Binary
    related='author_id.image_small' args: "Author's avatar"
  • author_id Many2one → res.partner
    default=_get_default_author help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True ondelete='set null' args: 'res.partner', 'Author'
  • body Html
    default='' sanitize_style=True strip_classes=True args: 'Contents'
  • channel_ids Many2many → mail.channel
    string='Channels' args: 'mail.channel', 'mail_message_mail_channel_rel'
  • child_ids One2many → mail.message
    args: 'mail.message', 'parent_id', 'Child Messages'
  • date Datetime
    default=fields.Datetime.now args: 'Date'
  • email_from Char
    default=_get_default_from help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • mail_activity_type_id Many2one → mail.activity.type
    index=True ondelete='set null' args: 'mail.activity.type', 'Mail Activity Type'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_id Char
    copy=False help='Message unique identifier' index=True readonly=1 args: 'Message-Id'
  • message_type Selection
    default='email' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' oldname='type' required=True args: [('email', 'Email'), ('comment', 'Comment'), ('notification', 'System notification')], 'Type'
  • model Char
    index=True args: 'Related Document Model'
  • needaction Boolean
    compute='_get_needaction' help='Need Action' search='_search_needaction' args: 'Need Action'
  • needaction_partner_ids Many2many → res.partner
    string='Partners with Need Action' args: 'res.partner', 'mail_message_res_partner_needaction_rel'
  • no_auto_thread Boolean
    help='Answers do not go in the original document discussion thread. This has an impact on the generated message-id.' args: 'No threading for answers'
  • notification_ids One2many → mail.notification
    auto_join=True copy=False args: 'mail.notification', 'mail_message_id', 'Notifications'
  • parent_id Many2one → mail.message
    help='Initial thread message.' index=True ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • record_name Char
    help='Name get of the related document.' args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • res_id Integer
    index=True args: 'Related Document ID'
  • starred Boolean
    compute='_get_starred' help='Current user has a starred notification linked to this message' search='_search_starred' args: 'Starred'
  • starred_partner_ids Many2many → res.partner
    string='Favorited By' args: 'res.partner', 'mail_message_res_partner_starred_rel'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • tracking_value_ids One2many → mail.tracking.value
    groups='base.group_no_one' help='Tracked values are stored in a separate model. This field allow to reconstruct the tracking and to generate statistics on the model.' string='Tracking values' args: 'mail.tracking.value', 'mail_message_id'
Public methods (13)
  • check_access_rule(self, operation)
    @api.multi
    Access rules of mail.message: - read: if - author_id == pid, uid is the author OR - uid is in the recipients (partner_ids) OR - uid has been notified (needaction) OR - uid is member of a listern channel (channel_ids.partner_ids) OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id (private message) OR - pid in message_follower_ids if model, res_id OR - uid can read the parent OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid is in the recipients (partner_ids) OR - uid has write or create access on the related document if model, res_id - otherwise: raise - unlink: if - uid has write or create access on the related document if model, res_id - otherwise: raise Specific case: non employee users see only messages with subtype (aka do not see internal logs).
  • create(self, values)
    @api.model
  • init(self)
    @api.model_cr
  • mark_all_as_read(self, channel_ids=None, domain=None)
    @api.model
    Remove all needactions of the current partner. If channel_ids is given, restrict to messages written in one of those channels.
  • mark_as_unread(self, channel_ids=None)
    @api.multi
    Add needactions to messages for the current partner.
  • message_fetch(self, domain, limit=20)
    @api.model
  • message_format(self)
    @api.multi
    Get the message values in the format for web client. Since message values can be broadcasted, computed fields MUST NOT BE READ and broadcasted. :returns list(dict). Example : { 'body': HTML content of the message 'model': u'res.partner', 'record_name': u'Agrolait', 'attachment_ids': [ { 'file_type_icon': u'webimage', 'id': 45, 'name': u'sample.png', 'filename': u'sample.png' } ], 'needaction_partner_ids': [], # list of partner ids 'res_id': 7, 'tracking_value_ids': [ { 'old_value': "", 'changed_field': "Customer", 'id': 2965, 'new_value': "Axelor" } ], 'author_id': (3, u'Administrator'), 'email_from': 'sacha@pokemon.com' # email address or False 'subtype_id': (1, u'Discussions'), 'channel_ids': [], # list of channel ids 'date': '2015-06-30 08:22:33', 'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner name_get 'message_type': u'comment', 'id': 59, 'subject': False 'is_note': True # only if the subtype is internal }
  • read(self, fields=None, load='_classic_read')
    @api.multi
    Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_done(self)
    @api.multi
    Remove the needaction from messages for the current partner.
  • toggle_message_starred(self)
    @api.multi
    Toggle messages as (un)starred. Technically, the notifications related to uid are set to (un)starred.
  • unlink(self)
    @api.multi
  • unstar_all(self)
    @api.model
    Unstar messages for the current partner.
  • write(self, vals)
    @api.multi

New fields (9)
  • default Boolean
    default=True help='Activated by default when subscribing.' args: 'Default'
  • description Text
    help='Description that will be added in the message posted for this subtype. If void, the name will be added instead.' translate=True args: 'Description'
  • hidden Boolean
    help='Hide the subtype in the follower options' args: 'Hidden'
  • internal Boolean
    help='Messages with internal subtypes will be visible only by employees, aka members of base_user group' args: 'Internal Only'
  • name Char
    help='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.' required=True translate=True args: 'Message Type'
  • parent_id Many2one → mail.message.subtype
    help='Parent subtype, used for automatic subscription. This field is not correctly named. For example on a project, the parent_id of project subtypes refers to task-related subtypes.' ondelete='set null' string='Parent' args: 'mail.message.subtype'
  • relation_field Char
    help='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).' args: 'Relation field'
  • res_model Char
    help='Model the subtype applies to. If False, this subtype applies to all models.' args: 'Model'
  • sequence Integer
    default=1 help='Used to order subtypes.' args: 'Sequence'
Public methods (5)
  • auto_subscribe_subtypes(self, model_name)
    Retrieve the header subtypes and relations for the given model.
  • create(self, vals)
    @api.model
  • default_subtypes(self, model_name)
    Retrieve the default subtypes (all, internal, external) for the given model.
  • unlink(self)
  • write(self, vals)

New fields (5)
  • email_status Selection
    default='ready' index=True args: [('ready', 'Ready to Send'), ('sent', 'Sent'), ('bounce', 'Bounced'), ('exception', 'Exception')], 'Email Status'
  • is_email Boolean
    index=True args: 'Sent by Email'
  • is_read Boolean
    index=True args: 'Is Read'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • res_partner_id Many2one → res.partner
    index=True ondelete='cascade' required=True args: 'res.partner', 'Needaction Recipient'
Public methods (3)
  • create(self, vals)
    @api.model
  • init(self)
    @api.model_cr
  • write(self, vals)
    @api.multi

New fields (5)
  • description Char
    args: 'Description'
  • shortcode_type Selection
    default='text' help='* Smiley are only used for HTML code to display an image * Text (default value) is used to substitute text with another text' required=True args: [('image', 'Smiley'), ('text', 'Canned Response')]
  • source Char
    help='The shortcut which must be replaced in the Chat Messages' index=True required=True args: 'Shortcut'
  • substitution Text
    help='The escaped html code replacing the shortcut' index=True required=True args: 'Substitution'
  • unicode_source Char
    help='The source is replaced by this unicode character in the Chat Messages' string='Unicode Character'
Public methods (0)

No public methods.

New fields (25)
  • attachment_ids Many2many → ir.attachment
    help='You may attach files to this template, to be added to all emails created from this template' args: 'ir.attachment', 'email_template_attachment_rel', 'email_template_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    default=True help='Permanently delete this email after sending it, to save space' args: 'Auto Delete'
  • body_html Html
    sanitize=False translate=True args: 'Body'
  • copyvalue Char
    help='Final placeholder expression, to be copy-pasted in the desired template field.' args: 'Placeholder Expression'
  • email_cc Char
    help='Carbon copy recipients (placeholders may be used here)' args: 'Cc'
  • email_from Char
    help="Sender address (placeholders may be used here). If not set, the default value will be the author's email alias if configured, or email address." args: 'From'
  • email_to Char
    help='Comma-separated recipient addresses (placeholders may be used here)' args: 'To (Emails)'
  • lang Char
    help='Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. ${object.partner_id.lang}.' placeholder='${object.partner_id.lang}' args: 'Language'
  • mail_server_id Many2one → ir.mail_server
    help='Optional preferred server for outgoing mails. If not set, the highest priority one will be used.' readonly=False args: 'ir.mail_server', 'Outgoing Mail Server'
  • model Char
    index=True readonly=True related='model_id.model' store=True args: 'Related Document Model'
  • model_id Many2one → ir.model
    help='The type of document this template can be used with' args: 'ir.model', 'Applies to'
  • model_object_field Many2one → ir.model.fields
    help='Select target field from the related document model.\nIf it is a relationship field you will be able to select a target field at the destination of the relationship.' string='Field' args: 'ir.model.fields'
  • name Char
    args: 'Name'
  • null_value Char
    help='Optional value to use if the target field is empty' args: 'Default Value'
  • partner_to Char
    help='Comma-separated ids of recipient partners (placeholders may be used here)' oldname='email_recipients' args: 'To (Partners)'
  • ref_ir_act_window Many2one → ir.actions.act_window
    copy=False help='Sidebar action to make this template available on records of the related document model' readonly=True args: 'ir.actions.act_window', 'Sidebar action'
  • reply_to Char
    help='Preferred response address (placeholders may be used here)' args: 'Reply-To'
  • report_name Char
    help='Name to use for the generated report file (may contain placeholders)\nThe extension can be omitted and will then come from the report type.' translate=True args: 'Report Filename'
  • report_template Many2one → ir.actions.report
    args: 'ir.actions.report', 'Optional report to print and attach'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. Jinja2 placeholders may be used.' args: 'Scheduled Date'
  • sub_model_object_field Many2one → ir.model.fields
    help='When a relationship field is selected as first field, this field lets you select the target field within the destination document model (sub-model).' args: 'ir.model.fields', 'Sub-field'
  • sub_object Many2one → ir.model
    help='When a relationship field is selected as first field, this field shows the document model the relationship goes to.' readonly=True args: 'ir.model', 'Sub-model'
  • subject Char
    help='Subject (placeholders may be used here)' translate=True args: 'Subject'
  • use_default_to Boolean
    help='Default recipients of the record:\n- partner (using id on a partner or the partner_id field) OR\n- email (using email_from or email field)' args: 'Default recipients'
  • user_signature Boolean
    help="If checked, the user's signature will be appended to the text version of the message" args: 'Add Signature'
Public methods (14)
  • build_expression(self, field_name, sub_field_name, null_value)
    Returns a placeholder expression for use in a template field, based on the values provided in the placeholder assistant. :param field_name: main field name :param sub_field_name: sub field name (M2O) :param null_value: default value if the target value is empty :return: final placeholder expression
  • copy(self, default=None)
    @api.multi
  • create_action(self)
    @api.multi
  • default_get(self, fields)
    @api.model
  • generate_email(self, res_ids, fields=None)
    @api.multi
    Generates an email from the template for given the given model based on records given by res_ids. :param template_id: id of the template to render. :param res_id: id of the record to use for rendering the template (model is taken from template definition) :returns: a dict containing all relevant fields for creating a new mail.mail entry, with one extra key ``attachments``, in the format [(report_name, data)] where data is base64 encoded.
  • generate_recipients(self, results, res_ids)
    @api.multi
    Generates the recipients of the template. Default values can ben generated instead of the template values if requested by template or context. Emails (email_to, email_cc) can be transformed into partners if requested in the context.
  • get_email_template(self, res_ids)
    @api.multi
  • onchange_model_id(self)
    @api.onchange('model_id')
  • onchange_sub_model_object_value_field(self)
    @api.onchange('model_object_field', 'sub_model_object_field', 'null_value')
  • render_post_process(self, html)
    @api.model
  • render_template(self, template_txt, model, res_ids, post_process=False)
    @api.model
    Render the given template text, replace mako expressions ``${expr}`` with the result of evaluating these expressions with an evaluation context containing: - ``user``: Model of the current user - ``object``: record of the document record this mail is related to - ``context``: the context passed to the mail composition wizard :param str template_txt: the template text to render :param str model: model name of the document record this mail is related to. :param int res_ids: list of ids of document records those mails are related to.
  • send_mail(self, res_id, force_send=False, raise_exception=False, email_values=None)
    @api.multi
    Generates a new mail message for the given template and record, and schedules it for delivery through the ``mail`` module's scheduler. :param int res_id: id of the record to render the template with (model is taken from the template) :param bool force_send: if True, the generated mail.message is immediately sent after being created, as if the scheduler was executed for this message only. :param dict email_values: if set, the generated mail.message is updated with given values dict :returns: id of the mail.message that was created
  • unlink(self)
    @api.multi
  • unlink_action(self)
    @api.multi

New fields (10)
  • message_channel_ids Many2many → mail.channel
    comodel_name='mail.channel' compute='_get_followers' search='_search_follower_channels' string='Followers (Channels)'
  • message_follower_ids One2many → mail.followers
    domain=<expr> string='Followers' args: 'mail.followers', 'res_id'
  • message_ids One2many → mail.message
    auto_join=True domain=<expr> string='Messages' args: 'mail.message', 'res_id'
  • message_is_follower Boolean
    compute='_compute_is_follower' search='_search_is_follower' args: 'Is Follower'
  • message_last_post Datetime
    help='Date of the last message posted on the record.' args: 'Last Message Date'
  • message_needaction Boolean
    compute='_get_message_needaction' help='If checked, new messages require your attention.' search='_search_message_needaction' args: 'Action Needed'
  • message_needaction_counter Integer
    compute='_get_message_needaction' help='Number of messages which requires an action' args: 'Number of Actions'
  • message_partner_ids Many2many → res.partner
    comodel_name='res.partner' compute='_get_followers' search='_search_follower_partners' string='Followers (Partners)'
  • message_unread Boolean
    compute='_get_message_unread' help='If checked new messages require your attention.' args: 'Unread Messages'
  • message_unread_counter Integer
    compute='_get_message_unread' help='Number of unread messages' args: 'Unread Messages Counter'
Public methods (32)
  • check_mail_message_access(self, res_ids, operation, model_name=None)
    @api.model
    mail.message check permission rules for related document. This method is meant to be inherited in order to implement addons-specific behavior. A common behavior would be to allow creating messages when having read access rule on the document, for portal document such as issues.
  • copy_data(self, default=None)
    @api.multi
  • create(self, values)
    @api.model
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False)
    @api.model
  • get_empty_list_help(self, help)
    @api.model
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • message_auto_subscribe(self, updated_fields, values=None)
    @api.multi
    Handle auto subscription. Two methods for auto subscription exist: - tracked res.users relational fields, such as user_id fields. Those fields must be relation fields toward a res.users record, and must have the track_visilibity attribute set. - using subtypes parent relationship: check if the current model being modified has an header record (such as a project for tasks) whose followers can be added as followers of the current records. Example of structure with project and task: - st_project_1.parent_id = st_task_1 - st_project_1.res_model = 'project.project' - st_project_1.relation_field = 'project_id' - st_task_1.model = 'project.task' :param list updated_fields: list of updated fields to track :param dict values: updated values; if None, the first record will be browsed to get the values. Added after releasing 7.0, therefore not merged with updated_fields argumment.
  • message_capable_models(self)
    @api.model
    Used by the plugin addon, based for plugin_outlook and others.
  • message_change_thread(self, new_thread)
    @api.multi
    Transfer the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : my_lead.message_change_thread(my_project_task) will transfer the context of the thread of my_lead to my_project_task
  • message_get_default_recipients(self, res_model=None, res_ids=None)
    @api.multi
  • message_get_email_values(self, notif_mail=None)
    @api.multi
    Get specific notification email values to store on the notification mail_mail. Void method, inherit it to add custom values.
  • message_get_recipient_values(self, notif_message=None, recipient_ids=None)
    @api.multi
    Get specific notification recipient values to store on the notification mail_mail. Basic method just set the recipient partners as mail_mail recipients. Inherit this method to add custom behavior like using recipient email_to to bypass the recipint_ids heuristics in the mail sending mechanism.
  • message_get_reply_to(self, res_ids, default=None)
    @api.model
    Returns the preferred reply-to email address that is basically the alias of the document, if it exists. Override this method to implement a custom behavior about reply-to for generated emails.
  • message_get_suggested_recipients(self)
    @api.multi
    Returns suggested recipients for ids. Those are a list of tuple (partner_id, partner_name, reason), to be managed by Chatter.
  • message_new(self, msg_dict, custom_values=None)
    @api.model
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :param dict context: if a ``thread_model`` value is present in the context, its value will be used to determine the model of the record to create (instead of the current model). :rtype: int :return: the id of the newly created thread object
  • message_parse(self, message, save_original=False)
    @api.model
    Parses a string or email.message.Message representing an RFC-2822 email, and returns a generic dict holding the message details. :param message: the message to parse :type message: email.message.Message | string | unicode :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'from': from, 'to': to, 'cc': cc, 'body': unified_body, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_partner_info_from_emails(self, emails, link_mail=False)
    @api.multi
    Convert a list of emails into a list partner_ids and a list new_partner_ids. The return value is non conventional because it is meant to be used by the mail widget. :return dict: partner_ids and new_partner_ids
  • message_post(self, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, content_subtype='html', **kwargs)
    @api.multi@api.returns('self', <expr>)
    Post a new message in an existing thread, returning the new mail.message ID. :param int thread_id: thread ID to post into, or list with one ID; if False/0, mail.message model will also be set as False :param str body: body of the message, usually raw HTML that will be sanitized :param str type: see mail_message.message_type field :param str content_subtype:: if plaintext: convert body into html :param int parent_id: handle reply to a previous message by adding the parent partners to the message in case of private discussion :param tuple(str,str) attachments or list id: list of attachment tuples in the form ``(name,content)``, where content is NOT base64 encoded Extra keyword arguments will be used as default column values for the new mail.message record. Special cases: - attachment_ids: supposed not attached to any document; attach them to the related document. Should only be set by Chatter. :return int: ID of newly created mail.message
  • message_post_with_template(self, template_id, **kwargs)
    @api.multi
    Helper method to send a mail with a template :param template_id : the id of the template to render to create the body of the message :param **kwargs : parameter to create a mail.compose.message woaerd (which inherit from mail.message)
  • message_post_with_view(self, views_or_xmlid, **kwargs)
    @api.multi
    Helper method to send a mail / post a message using a view_id to render using the ir.qweb engine. This method is stand alone, because there is nothing in template and composer that allows to handle views in batch. This method should probably disappear when templates handle ir ui views.
  • message_process(self, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None)
    @api.model
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). There is a special case where the target model is False: a reply to a private message. In this case, we skip the message_new / message_update step, to just post a new message using mail_thread message_post. :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: string or xmlrpclib.Binary :type dict custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • message_receive_bounce(self, email, partner, mail_id=None)
    @api.multi
    Called by ``message_process`` when a bounce email (such as Undelivered Mail Returned to Sender) is received for an existing thread. The default behavior is to check is an integer ``message_bounce`` column exists. If it is the case, its content is incremented. :param mail_id: ID of the sent email that bounced. It may not exist anymore but it could be usefull if the information was kept. This is used notably in mass mailing. :param RecordSet partner: partner matching the bounced email address, if any :param string email: email that caused the bounce
  • message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None)
    @api.model
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: * if the message replies to an existing thread by having a Message-Id that matches an existing mail_message.message_id, we take the original message model/thread_id pair and ignore custom_value as no creation will take place * if the message replies to an existing thread by having In-Reply-To or References matching odoo model/thread_id Message-Id and if this thread has messages without message_id, take this model/thread_id pair and ignore custom_value as no creation will take place (6.1 compatibility) * look for a mail.alias entry matching the message recipients and use the corresponding model, thread_id, custom_values and user_id. This could lead to a thread update or creation depending on the alias * fallback on provided ``model``, ``thread_id`` and ``custom_values`` * raise an exception as no route has been found :param string message: an email.message instance :param dict message_dict: dictionary holding parsed message variables :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :type dict custom_values: optional dictionary of default field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of routes [(model, thread_id, custom_values, user_id, alias)] :raises: ValueError, TypeError
  • message_route_process(self, message, message_dict, routes)
    @api.model
  • message_route_verify(self, message, message_dict, route, update_author=True, assert_model=True, create_fallback=True, allow_private=False, drop_alias=False)
    @api.model
    Verify route validity. Check and rules: 1 - if thread_id -> check that document effectively exists; otherwise fallback on a message_new by resetting thread_id 2 - check that message_update exists if thread_id is set; or at least that message_new exist [ - find author_id if udpate_author is set] 3 - if there is an alias, check alias_contact: 'followers' and thread_id: check on target document that the author is in the followers 'followers' and alias_parent_thread_id: check on alias parent document that the author is in the followers 'partners': check that author_id id set :param message: an email.message instance :param message_dict: dictionary of values that will be given to mail_message.create() :param route: route to check which is a tuple (model, thread_id, custom_values, uid, alias) :param update_author: update message_dict['author_id']. TDE TODO: move me :param assert_model: if an error occurs, tell whether to raise an error or just log a warning and try other processing or invalidate route :param create_fallback: if the route aims at updating a record and that record does not exists or does not support update either fallback on creating a new record in the same model or raise / warn :param allow_private: allow void model / thread_id routes, aka private discussions
  • message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, force=True)
    @api.multi
    Add partners to the records followers.
  • message_subscribe_users(self, user_ids=None, subtype_ids=None)
    @api.multi
    Wrapper on message_subscribe, using users. If user_ids is not provided, subscribe uid instead.
  • message_track(self, tracked_fields, initial_values)
    @api.multi
    Track updated values. Comparing the initial and current values of the fields given in tracked_fields, it generates a message containing the updated values. This message can be linked to a mail.message.subtype given by the ``_track_subtype`` method.
  • message_unsubscribe(self, partner_ids=None, channel_ids=None)
    @api.multi
    Remove partners from the records followers.
  • message_unsubscribe_users(self, user_ids=None)
    @api.multi
    Wrapper on message_subscribe, using users. If user_ids is not provided, unsubscribe uid instead.
  • message_update(self, msg_dict, update_vals=None)
    @api.multi
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • unlink(self)
    @api.multi
    Override unlink to delete messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • write(self, values)
    @api.multi

New fields (16)
  • field Char
    readonly=1 required=True args: 'Changed Field'
  • field_desc Char
    readonly=1 required=True args: 'Field Description'
  • field_type Char
    args: 'Field Type'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message ID'
  • new_value_char Char
    readonly=1 args: 'New Value Char'
  • new_value_datetime Datetime
    readonly=1 args: 'New Value Datetime'
  • new_value_float Float
    readonly=1 args: 'New Value Float'
  • new_value_integer Integer
    readonly=1 args: 'New Value Integer'
  • new_value_monetary Float
    readonly=1 args: 'New Value Monetary'
  • new_value_text Text
    readonly=1 args: 'New Value Text'
  • old_value_char Char
    readonly=1 args: 'Old Value Char'
  • old_value_datetime Datetime
    readonly=1 args: 'Old Value DateTime'
  • old_value_float Float
    readonly=1 args: 'Old Value Float'
  • old_value_integer Integer
    readonly=1 args: 'Old Value Integer'
  • old_value_monetary Float
    readonly=1 args: 'Old Value Monetary'
  • old_value_text Text
    readonly=1 args: 'Old Value Text'
Public methods (4)
  • create_tracking_values(self, initial_value, new_value, col_name, col_info)
    @api.model
  • get_display_value(self, type)
    @api.multi
  • get_new_display_value(self)
    @api.multi
  • get_old_display_value(self)
    @api.multi

New fields (6)
  • channel_ids Many2many → mail.channel
    domain=[('channel_type', '=', 'channel')] help='List of channels that will be added as listeners of the current document.' string='Channels' args: 'mail.channel'
  • message Html
    args: 'Message'
  • partner_ids Many2many → res.partner
    help='List of partners that will be added as follower of the current document.' string='Recipients' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' index=True args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' index=True required=True args: 'Related Document Model'
  • send_mail Boolean
    default=True help="If checked, the partners will receive an email warning they have been added in the document's followers." args: 'Send Email'
Public methods (2)
  • add_followers(self)
    @api.multi
  • default_get(self, fields)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cron_mode=True)
    @api.multi
    Send a message to Odoo's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (2)
  • alias_domain Char
    help='If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.' args: 'Alias Domain'
  • fail_counter Integer
    readonly=True args: 'Fail Mail'
Public methods (2)
  • get_values(self)
    @api.model
  • set_values(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals, context=None)
    @api.multi

New fields (3)
  • channel_ids Many2many → mail.channel
    copy=False string='Channels' args: 'mail.channel', 'mail_channel_partner', 'partner_id', 'channel_id'
  • message_bounce Integer
    default=0 help='Counter of the number of bounced emails for this contact' args: 'Bounce'
  • opt_out Boolean
    help="If opt-out is checked, this contact has refused to receive emails for mass mailing and marketing campaign. Filter 'Available for Mass Mailing' allows users to filter the partners when performing mass mailing." args: 'Opt-Out'
Public methods (6)
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first partners' id, name and email such that the name or email matches a 'search' string. Prioritize users, and then extend the research to all partners.
  • get_needaction_count(self)
    @api.model
    compute the number of needaction of the current user
  • get_starred_count(self)
    @api.model
    compute the number of starred of the current user
  • get_static_mention_suggestions(self)
    @api.model
    To be overwritten to return the id, name and email of partners used as static mention suggestions loaded once at webclient initialization and stored client side.
  • message_get_default_recipients(self)
    @api.multi
  • message_get_suggested_recipients(self)
    @api.multi

New fields (3)
  • alias_contact Selection
    related='alias_id.alias_contact' string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_id Many2one → mail.alias
    auto_join=True copy=False help="Email address internally associated with this user. Incoming emails will appear in the user's notifications." ondelete='set null' required=False args: 'mail.alias', 'Alias'
  • notification_type Selection
    default='email' help='Policy on how to handle Chatter notifications:\n- Emails: notifications are sent to your email\n- Odoo: notifications appear in your Odoo Inbox' required=True args: [('email', 'Handle by Emails'), ('inbox', 'Handle in Odoo')], 'Notification Management'
Public methods (8)
  • activity_user_count(self)
    @api.model
  • create(self, values)
    @api.model
  • message_get_suggested_recipients(self)
    @api.multi
  • message_partner_info_from_emails(self, emails, link_mail=False)
    @api.multi
  • message_post(self, **kwargs)
    @api.multi@api.returns('self', <expr>)
    Redirect the posting of message on res.users as a private discussion. This is done because when giving the context of Chatter on the various mailboxes, we do not have access to the current partner_id.
  • message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, force=True)
  • message_update(self, msg_dict, update_vals=None)
  • write(self, vals)
    @api.multi
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/10.0/mail
VERSION
VERSION 1.0
CATEGORY
CATEGORYDiscuss
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Christophe Matthieu, Martin Trigaux, Fabien Pinckaers, Olivier Dony, Thibault Delavallée, Denis Ledoux, Fabien Meghazi, Christophe Simonis, Goffin Simon, Simon Lejeune, Nicolas Martinelli, Nicolas Lempereur, Julien Legros, Richard Mathot, qdp-odoo, Géry Debongnie, Aaron Bohy, Pedro M. Baeza, Jeremy Kersten, GitHub, Lucas Perais (lpe), Damien Bouvy, Olivier Colson, Yannick Tivisse, qsm-odoo, Martin Geubelle, jem-odoo, Adrien Dieudonne, len-odoo, Julien (juc) Castiaux, Denis Vermylen, Laurent Mignon (ACSONE), XavierDo, Julien Castiaux, Abridbus
WEBSITE
WEBSITEhttps://www.odoo.com/page/enterprise-social-network
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-05 23:50:48
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web_kanban
    - web
    - bus
    - web_tour
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
Business oriented Social Networking
===================================
The Social Networking module provides a unified social network abstraction layer allowing applications to display a complete
communication history on documents with a fully-integrated email and message management system.

It enables the users to read and send messages as well as emails. It also provides a feeds page combined to a subscription mechanism that allows to follow documents and to be constantly updated about recent news.

Main Features
-------------
* Clean and renewed communication history for any Odoo document that can act as a discussion topic
* Subscription mechanism to be updated about new messages on interesting documents
* Unified feeds page to see recent messages and activity on followed documents
* User communication through the feeds page
* Threaded discussion design on documents
* Relies on the global outgoing mail server - an integrated email management system - allowing to send emails with a configurable scheduler-based processing engine
* Includes an extensible generic email composition assistant, that can turn into a mass-mailing assistant and is capable of interpreting simple *placeholder expressions* that will be replaced with dynamic data when each email is actually sent.
    

Code Analysis

Views touched (39)
XML IDNameModelTypeStatus
assets_backend mail assets ir.ui.view qweb Inherits web.assets_backend
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
email_template_form email.template.form mail.template form New
email_template_preview_form email_template.preview.form email_template.preview form New
email_template_tree email.template.tree mail.template tree New
mail_channel_partner_view_form mail.channel.partner.form mail.channel.partner form New
mail_channel_partner_view_tree mail.channel.partner.tree mail.channel.partner tree New
mail_channel_view_form mail.channel.form mail.channel form New
mail_channel_view_kanban mail.channel.kanban mail.channel kanban New
mail_channel_view_search mail.channel.search mail.channel search New
mail_channel_view_tree mail.channel.tree mail.channel tree New
mail_shortcode_view_form mail.shortcode.form mail.shortcode form New
mail_shortcode_view_tree mail.shortcode.tree mail.shortcode tree New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
message_origin_link message_origin_link ir.ui.view qweb New
message_user_assigned message_user_assigned ir.ui.view qweb New
res_partner_opt_out_search res.partner.opt_out.search res.partner filter Inherits base.view_res_partner_filter
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_email_template_search email.template.search mail.template search New
view_emails_partner_info_form res.partner.emails.info.inherit res.partner xpath Inherits base.view_partner_form
view_followers_tree mail.followers.tree mail.followers tree New
view_general_configuration_mail_alias_domain base.config.settings.mail.alias base.config.settings xpath Inherits base_setup.view_general_configuration
view_mail_alias_form mail.alias.form mail.alias form New
view_mail_alias_search mail.alias.search mail.alias search New
view_mail_alias_tree mail.alias.tree mail.alias tree New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tracking_value_form mail.tracking.value.form mail.tracking.value form New
view_mail_tracking_value_tree mail.tracking.value.tree mail.tracking.value tree New
view_mail_tree mail.mail.tree mail.mail tree New
view_message_form mail.message.form mail.message form New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.tree mail.message.subtype tree New
view_message_tree mail.message.tree mail.message tree New
view_server_action_form_template ir.actions.server.form ir.actions.server xpath Inherits base.view_server_action_form
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (24)

New fields (2)
  • alias_domain Char
    help='If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.' args: 'Alias Domain'
  • fail_counter Integer
    readonly=True args: 'Fail Mail'
Public methods (3)
  • get_default_alias_domain(self, fields)
    @api.model
  • get_default_fail_counter(self, fields)
    @api.model
  • set_alias_domain(self)
    @api.multi

New fields (3)
  • attachment_ids Many2many
    store=False string='Attachments'
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • res_id Selection
    args: _get_records, 'Sample Document'
Public methods (2)
  • default_get(self, fields)
    @api.model
  • on_change_res_id(self)
    @api.onchange('res_id')@api.multi

New fields (6)
  • body_html Html
    readonly=True related='template_id.body_html' args: 'Body'
  • email_from Char
    readonly=True related='template_id.email_from' args: 'From'
  • email_to Char
    readonly=True related='template_id.email_to' args: 'To (Emails)'
  • partner_to Char
    readonly=True related='template_id.partner_to' args: 'To (Partners)'
  • subject Char
    readonly=True related='template_id.subject' args: 'Subject'
  • template_id Many2one → mail.template
    domain="[('model_id', '=', model_id)]" ondelete='set null' args: 'mail.template', 'Email Template'
Public methods (2)
  • on_change_template_id(self)
    @api.onchange('template_id')
    Render the raw template in the server action fields.
  • run_action_email(self, action, eval_context=None)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • power_on(self, *args, **kwargs)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • unlink(self)

New fields (9)
  • alias_contact Selection
    default='everyone' help='Policy to post a message on the document using the mailgateway.\n- everyone: everyone can post\n- partners: only authenticated partners\n- followers: only followers of the related document or members of following channels\n' required=True string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_defaults Text
    default='{}' help='A Python dictionary that will be evaluated to provide default values when creating new records for this alias.' required=True args: 'Default Values'
  • alias_domain Char
    compute='_get_alias_domain' default=<expr> args: 'Alias domain'
  • alias_force_thread_id Integer
    help='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.' args: 'Record Thread ID'
  • alias_model_id Many2one → ir.model
    domain="[('field_id.name', '=', 'message_ids')]" help='The model (Odoo 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)' ondelete='cascade' required=True args: 'ir.model', 'Aliased Model'
  • alias_name Char
    help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>" args: 'Alias Name'
  • alias_parent_model_id Many2one → ir.model
    help='Parent model holding the alias. The model holding the alias reference is not necessarily the model given by alias_model_id (example: project (parent_model) and task (model))' args: 'ir.model', 'Parent Model'
  • alias_parent_thread_id Integer
    help='ID of the parent record holding the alias (example: project holding the task creation alias)' args: 'Parent Record Thread ID'
  • alias_user_id Many2one → res.users
    defaults=<expr> help='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.' args: 'res.users', 'Owner'
Public methods (5)
  • create(self, vals)
    @api.model
    Creates an email.alias record according to the values provided in ``vals``, with 2 alterations: the ``alias_name`` value may be suffixed in order to make it unique (and certain unsafe characters replaced), and he ``alias_model_id`` value will set to the model ID of the ``model_name`` context value, if provided.
  • name_get(self)
    @api.multi
    Return the mail alias display alias_name, including the implicit mail catchall domain if exists from config otherwise "New Alias". e.g. `jobs@mail.odoo.com` or `jobs` or 'New Alias'
  • open_document(self)
    @api.multi
  • open_parent_document(self)
    @api.multi
  • write(self, vals)
    @api.multi
    "give a unique alias name if given alias name is already assigned

New fields (1)
  • alias_id Many2one → mail.alias
    ondelete='restrict' required=True string='Alias' args: 'mail.alias'
Public methods (4)
  • create(self, vals)
    @api.model
    Create a record with ``vals``, and create a corresponding alias.
  • get_alias_model_name(self, vals)
    Return the model name for the alias. Incoming emails that are not replies to existing records will cause the creation of a new record of this alias model. The value may depend on ``vals``, the dict of values passed to ``create`` when a record of this model is created.
  • get_alias_values(self)
    Return values to create an alias, or to write on the alias after its creation.
  • unlink(self)
    @api.multi
    Delete the given records, and cascade-delete their corresponding alias.

New fields (17)
  • alias_id Many2one → mail.alias
    help='The email address associated with this group. New emails received will automatically create new topics.' ondelete='restrict' required=True args: 'mail.alias', 'Alias'
  • channel_last_seen_partner_ids One2many → mail.channel.partner
    string='Last Seen' args: 'mail.channel.partner', 'channel_id'
  • channel_message_ids Many2many → mail.message
    args: 'mail.message', 'mail_message_mail_channel_rel'
  • channel_partner_ids Many2many → res.partner
    string='Listeners' args: 'res.partner', 'mail_channel_partner', 'channel_id', 'partner_id'
  • channel_type Selection
    default='channel' args: [('chat', 'Chat Discussion'), ('channel', 'Channel')], 'Channel Type'
  • description Text
    args: 'Description'
  • email_send Boolean
    default=False args: 'Send messages by email'
  • group_ids Many2many → res.groups
    help='Members of those groups will automatically added as followers. Note that they will be able to manage their subscription manually if necessary.' string='Auto Subscription' args: 'res.groups'
  • group_public_id Many2one → res.groups
    default=<expr> string='Authorized Group' args: 'res.groups'
  • image Binary
    attachment=True default=_get_default_image help='This field holds the image used as photo for the group, limited to 1024x1024px.' args: 'Photo'
  • image_medium Binary
    attachment=True help='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.' args: 'Medium-sized photo'
  • image_small Binary
    attachment=True help='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.' args: 'Small-sized photo'
  • is_member Boolean
    compute='_compute_is_member' args: 'Is a member'
  • is_subscribed Boolean
    compute='_compute_is_subscribed' args: 'Is Subscribed'
  • name Char
    required=True translate=True args: 'Name'
  • public Selection
    default='groups' help='This group is visible by non members. Invisible groups can add members through the invite button.' required=True args: [('public', 'Everyone'), ('private', 'Invited people only'), ('groups', 'Selected group of users')], 'Privacy'
  • uuid Char
    copy=False default=<expr> index=True size=50 args: 'UUID'
Public methods (28)
  • action_follow(self)
    @api.multi
  • action_unfollow(self)
    @api.multi
  • channel_create(self, name, privacy='public')
    @api.model
    Create a channel and add the current partner, broadcast it (to make the user directly listen to it when polling) :param name : the name of the channel to create :param privacy : privacy of the channel. Should be 'public' or 'private'. :return dict : channel header
  • channel_fetch_listeners(self, uuid)
    @api.model
    Return the id, name and email of partners listening to the given channel
  • channel_fetch_message(self, last_id=False, limit=20)
    @api.multi
    Return message values of the current channel. :param last_id : last message id to start the research :param limit : maximum number of messages to fetch :returns list of messages values :rtype : list(dict)
  • channel_fetch_preview(self)
    @api.multi
    Return the last message of the given channels
  • channel_fetch_slot(self)
    @api.model
    Return the channels of the user grouped by 'slot' (channel, direct_message or private_group), and the mapping between partner_id/channel_id for direct_message channels. :returns dict : the grouped channels and the mapping
  • channel_fold(self, uuid, state=None)
    @api.model
    Update the fold_state of the given session. In order to syncronize web browser tabs, the change will be broadcast to himself (the current user channel). Note: the user need to be logged :param state : the new status of the session for the current user.
  • channel_get(self, partners_to, pin=True)
    @api.model
    Get the canonical private channel between some partners, create it if needed. To reuse an old channel (conversation), this one must be private, and contains only the given partners. :param partners_to : list of res.partner ids to add to the conversation :param pin : True if getting the channel should pin it for the current user :returns a channel header, or False if the users_to was False :rtype : dict
  • channel_get_and_minimize(self, partners_to)
    @api.model
  • channel_info(self, extra_info=False)
    @api.multi
    Get the informations header for the current channels :returns a list of channels values :rtype : list(dict)
  • channel_invite(self, partner_ids)
    @api.multi
    Add the given partner_ids to the current channels and broadcast the channel header to them. :param partner_ids : list of partner id to add
  • channel_join_and_get_info(self)
    @api.multi
  • channel_minimize(self, uuid, minimized=True)
    @api.model
  • channel_pin(self, uuid, pinned=False)
    @api.model
  • channel_search_to_join(self, name=None, domain=None)
    @api.model
    Return the channel info of the channel the current partner can join :param name : the name of the researched channels :param domain : the base domain of the research :returns dict : channel dict
  • channel_seen(self)
    @api.multi
  • create(self, vals)
    @api.model
  • execute_command(self, command='', **kwargs)
    @api.multi
    Executes a given command
  • get_mention_commands(self)
    @api.model@ormcache()
    Returns the allowed commands in channels
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first channels' id, name and public fields such that the name matches a 'search' string. Exclude channels of type chat (DM), and private channels the current user isn't registered to.
  • init(self)
    @api.model_cr
  • message_get_email_values(self, notif_mail=None)
    @api.multi
  • message_get_recipient_values(self, notif_message=None, recipient_ids=None)
    @api.multi
  • message_post(self, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, content_subtype='html', **kwargs)
    @api.multi@api.returns('self', <expr>)
  • message_receive_bounce(self, email, partner, mail_id=None)
    @api.multi
    Override bounce management to unsubscribe bouncing addresses
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (6)
  • channel_id Many2one → mail.channel
    ondelete='cascade' string='Channel' args: 'mail.channel'
  • fold_state Selection
    default='open' string='Conversation Fold State' args: [('open', 'Open'), ('folded', 'Folded'), ('closed', 'Closed')]
  • is_minimized Boolean
    args: 'Conversation is minimized'
  • is_pinned Boolean
    default=True args: 'Is pinned on the interface'
  • partner_id Many2one → res.partner
    ondelete='cascade' string='Recipient' args: 'res.partner'
  • seen_message_id Many2one → mail.message
    string='Last Seen' args: 'mail.message'
Public methods (0)

No public methods.

New fields (13)
  • active_domain Text
    readonly=True args: 'Active domain'
  • attachment_ids Many2many → ir.attachment
    args: 'ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    help='Delete sent emails (mass mailing only)' args: 'Delete Emails'
  • auto_delete_message Boolean
    help='Do not keep a copy of the email in the document communication history (mass mailing only)' args: 'Delete Message Copy'
  • composition_mode Selection
    default='comment' selection=_get_composition_mode_selection string='Composition mode'
  • is_log Boolean
    help='Whether the message is an internal note (comment mode only)' args: 'Log an Internal Note'
  • message_type Selection
    default='comment'
  • notify Boolean
    help='Notify followers of the document (mass post only)' args: 'Notify followers'
  • partner_ids Many2many → res.partner
    args: 'res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional Contacts'
  • subject Char
    default=False
  • subtype_id Many2one
    default=<expr>
  • template_id Many2one → mail.template
    domain="[('model', '=', model)]" index=True args: 'mail.template', 'Use template'
  • use_active_domain Boolean
    args: 'Use active domain'
Public methods (12)
  • check_access_rule(self, operation)
    @api.multi
    Access rules of mail.compose.message: - create: if - model, no res_id, I create a message in mass mail mode - then: fall back on mail.message acces rules
  • default_get(self, fields)
    @api.model
    Handle composition mode. Some details about context keys: - comment: default mode, model and ID of a record the user comments - default_model or active_model - default_res_id or active_id - reply: active_id of a message the user replies to - default_parent_id or message_id or active_id: ID of the mail.message we reply to - message.res_model or default_model - message.res_id or default_res_id - mass_mail: model and IDs of records the user mass-mails - active_ids: record IDs - default_model or active_model
  • generate_email_for_composer(self, template_id, res_ids, fields=None)
    @api.model
    Call email_template.generate_email(), get fields relevant for mail.compose.message, transform email_cc and email_to into partner_ids
  • get_mail_values(self, res_ids)
    @api.multi
    Generate the values that will be used by send_mail to create mail_messages or mail_mails.
  • get_record_data(self, values)
    @api.model
    Returns a defaults-like dict with initial values for the composition wizard when sending an email related a previous email (parent_id) or a document (model, res_id). This is based on previously computed default values.
  • onchange_template_id(self, template_id, composition_mode, model, res_id)
    @api.multi
    - mass_mailing: we cannot render, so return the template values - normal mode: return rendered values /!\ for x2many field, this onchange return command instead of ids
  • onchange_template_id_wrapper(self)
    @api.multi@api.onchange('template_id')
  • render_message(self, res_ids)
    @api.multi
    Generate template-based values of wizard, for the document records given by res_ids. This method is meant to be inherited by email_template that will produce a more complete dictionary, using Jinja2 templates. Each template is generated for all res_ids, allowing to parse the template once, and render it multiple times. This is useful for mass mailing where template rendering represent a significant part of the process. Default recipients are also computed, based on mail_thread method message_get_default_recipients. This allows to ensure a mass mailing has always some recipients specified. :param browse wizard: current mail.compose.message browse record :param list res_ids: list of record ids :return dict results: for each res_id, the generated template values for subject, body, email_from and reply_to
  • render_template(self, template, model, res_ids, post_process=False)
    @api.model
  • save_as_template(self)
    @api.multi
    hit save as template button: current form value will be a new template attached to the current document.
  • send_mail(self, auto_commit=False)
    @api.multi
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.
  • send_mail_action(self)
    @api.multi

New fields (5)
  • channel_id Many2one → mail.channel
    index=True ondelete='cascade' string='Listener' args: 'mail.channel'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' string='Related Partner' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' index=True args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' index=True required=True args: 'Related Document Model'
  • subtype_ids Many2many → mail.message.subtype
    help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall." string='Subtype' args: 'mail.message.subtype'
Public methods (3)
  • create(self, vals)
    @api.model
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (12)
  • auto_delete Boolean
    help='Permanently delete this email after sending it, to save space' args: 'Auto Delete'
  • body_html Text
    help='Rich-text/HTML message' args: 'Rich-text Contents'
  • email_cc Char
    help='Carbon copy message recipients' args: 'Cc'
  • email_to Text
    help='Message recipients (emails)' args: 'To'
  • failure_reason Text
    help='Failure reason. This is usually the exception thrown by the email server, stored to ease the debugging of mailing issues.' readonly=1 args: 'Failure Reason'
  • headers Text
    copy=False args: 'Headers'
  • mail_message_id Many2one → mail.message
    auto_join=True index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification Boolean
    help='Mail has been created to notify people of an existing mail.message' args: 'Is Notification'
  • recipient_ids Many2many → res.partner
    string='To (Partners)' args: 'res.partner'
  • references Text
    help='Message references, such as identifiers of previous messages' readonly=1 args: 'References'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible.' args: 'Scheduled Send Date'
  • state Selection
    copy=False default='outgoing' readonly=True args: [('outgoing', 'Outgoing'), ('sent', 'Sent'), ('received', 'Received'), ('exception', 'Delivery Failed'), ('cancel', 'Cancelled')], 'Status'
Public methods (11)
  • cancel(self)
    @api.multi
  • create(self, values)
    @api.model
  • default_get(self, fields)
    @api.model
  • mark_outgoing(self)
    @api.multi
  • process_email_queue(self, ids=None)
    @api.model
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! :param list ids: optional list of emails ids to send. If passed no search is performed, and these ids are used instead. :param dict context: if a 'filters' key is present in context, this value will be used as an additional filter to further restrict the outgoing messages to send (by default all 'outgoing' messages are sent).
  • send(self, auto_commit=False, raise_exception=False)
    @api.multi
    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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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
  • send_get_email_dict(self, partner=None)
    @api.multi
    Return a dictionary for specific email values, depending on a partner, or generic to the whole recipients given by mail.email_to. :param browse_record mail: mail.mail browse_record :param browse_record partner: specific recipient partner
  • send_get_mail_body(self, partner=None)
    @api.multi
    Return a specific ir_email body. The main purpose of this method is to be inherited to add custom content depending on some module.
  • send_get_mail_to(self, partner=None)
    @api.multi
    Forge the email_to with the following heuristic: - if 'partner', recipient specific (Partner Name <email>) - else fallback on mail.email_to splitting
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (26)
  • attachment_ids Many2many → ir.attachment
    help='Attachments are linked to a document through model / res_id and to the message through this field.' string='Attachments' args: 'ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id'
  • author_avatar Binary
    related='author_id.image_small' args: "Author's avatar"
  • author_id Many2one → res.partner
    default=_get_default_author help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True ondelete='set null' args: 'res.partner', 'Author'
  • body Html
    default='' sanitize_style=True strip_classes=True args: 'Contents'
  • channel_ids Many2many → mail.channel
    string='Channels' args: 'mail.channel', 'mail_message_mail_channel_rel'
  • child_ids One2many → mail.message
    args: 'mail.message', 'parent_id', 'Child Messages'
  • date Datetime
    default=fields.Datetime.now args: 'Date'
  • email_from Char
    default=_get_default_from help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_id Char
    copy=False help='Message unique identifier' index=True readonly=1 args: 'Message-Id'
  • message_type Selection
    default='email' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' oldname='type' required=True args: [('email', 'Email'), ('comment', 'Comment'), ('notification', 'System notification')], 'Type'
  • model Char
    index=True args: 'Related Document Model'
  • needaction Boolean
    compute='_get_needaction' help='Need Action' search='_search_needaction' args: 'Need Action'
  • needaction_partner_ids Many2many → res.partner
    string='Partners with Need Action' args: 'res.partner', 'mail_message_res_partner_needaction_rel'
  • no_auto_thread Boolean
    help='Answers do not go in the original document discussion thread. This has an impact on the generated message-id.' args: 'No threading for answers'
  • notification_ids One2many → mail.notification
    auto_join=True copy=False args: 'mail.notification', 'mail_message_id', 'Notifications'
  • parent_id Many2one → mail.message
    help='Initial thread message.' index=True ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • record_name Char
    help='Name get of the related document.' args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • res_id Integer
    index=True args: 'Related Document ID'
  • starred Boolean
    compute='_get_starred' help='Current user has a starred notification linked to this message' search='_search_starred' args: 'Starred'
  • starred_partner_ids Many2many → res.partner
    string='Favorited By' args: 'res.partner', 'mail_message_res_partner_starred_rel'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • tracking_value_ids One2many → mail.tracking.value
    groups='base.group_no_one' help='Tracked values are stored in a separate model. This field allow to reconstruct the tracking and to generate statistics on the model.' string='Tracking values' args: 'mail.tracking.value', 'mail_message_id'
Public methods (13)
  • check_access_rule(self, operation)
    @api.multi
    Access rules of mail.message: - read: if - author_id == pid, uid is the author OR - uid is in the recipients (partner_ids) OR - uid has been notified (needaction) OR - uid is member of a listern channel (channel_ids.partner_ids) OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id (private message) OR - pid in message_follower_ids if model, res_id OR - uid can read the parent OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid is in the recipients (partner_ids) OR - uid has write or create access on the related document if model, res_id - otherwise: raise - unlink: if - uid has write or create access on the related document if model, res_id - otherwise: raise Specific case: non employee users see only messages with subtype (aka do not see internal logs).
  • create(self, values)
    @api.model
  • init(self)
    @api.model_cr
  • mark_all_as_read(self, channel_ids=None, domain=None)
    @api.model
    Remove all needactions of the current partner. If channel_ids is given, restrict to messages written in one of those channels.
  • mark_as_unread(self, channel_ids=None)
    @api.multi
    Add needactions to messages for the current partner.
  • message_fetch(self, domain, limit=20)
    @api.model
  • message_format(self)
    @api.multi
    Get the message values in the format for web client. Since message values can be broadcasted, computed fields MUST NOT BE READ and broadcasted. :returns list(dict). Example : { 'body': HTML content of the message 'model': u'res.partner', 'record_name': u'Agrolait', 'attachment_ids': [ { 'file_type_icon': u'webimage', 'id': 45, 'name': u'sample.png', 'filename': u'sample.png' } ], 'needaction_partner_ids': [], # list of partner ids 'res_id': 7, 'tracking_value_ids': [ { 'old_value': "", 'changed_field': "Customer", 'id': 2965, 'new_value': "Axelor" } ], 'author_id': (3, u'Administrator'), 'email_from': 'sacha@pokemon.com' # email address or False 'subtype_id': (1, u'Discussions'), 'channel_ids': [], # list of channel ids 'date': '2015-06-30 08:22:33', 'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner name_get 'message_type': u'comment', 'id': 59, 'subject': False 'is_note': True # only if the subtype is internal }
  • read(self, fields=None, load='_classic_read')
    @api.multi
    Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_done(self)
    @api.multi
    Remove the needaction from messages for the current partner.
  • toggle_message_starred(self)
    @api.multi
    Toggle messages as (un)starred. Technically, the notifications related to uid are set to (un)starred.
  • unlink(self)
    @api.multi
  • unstar_all(self)
    @api.model
    Unstar messages for the current partner.
  • write(self, vals)
    @api.multi

New fields (9)
  • default Boolean
    default=True help='Activated by default when subscribing.' args: 'Default'
  • description Text
    help='Description that will be added in the message posted for this subtype. If void, the name will be added instead.' translate=True args: 'Description'
  • hidden Boolean
    help='Hide the subtype in the follower options' args: 'Hidden'
  • internal Boolean
    help='Messages with internal subtypes will be visible only by employees, aka members of base_user group' args: 'Internal Only'
  • name Char
    help='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.' required=True translate=True args: 'Message Type'
  • parent_id Many2one → mail.message.subtype
    help='Parent subtype, used for automatic subscription. This field is not correctly named. For example on a project, the parent_id of project subtypes refers to task-related subtypes.' ondelete='set null' string='Parent' args: 'mail.message.subtype'
  • relation_field Char
    help='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).' args: 'Relation field'
  • res_model Char
    help='Model the subtype applies to. If False, this subtype applies to all models.' args: 'Model'
  • sequence Integer
    default=1 help='Used to order subtypes.' args: 'Sequence'
Public methods (0)

No public methods.

New fields (5)
  • email_status Selection
    default='ready' index=True args: [('ready', 'Ready to Send'), ('sent', 'Sent'), ('bounce', 'Bounced'), ('exception', 'Exception')], 'Email Status'
  • is_email Boolean
    index=True args: 'Sent by Email'
  • is_read Boolean
    index=True args: 'Is Read'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • res_partner_id Many2one → res.partner
    index=True ondelete='cascade' required=True args: 'res.partner', 'Needaction Recipient'
Public methods (1)
  • init(self)
    @api.model_cr

New fields (4)
  • description Char
    args: 'Description'
  • shortcode_type Selection
    default='text' help='* Smiley are only used for HTML code to display an image * Text (default value) is used to substitute text with another text' required=True args: [('image', 'Smiley'), ('text', 'Canned Response')]
  • source Char
    help='The shortcut which must be replaced in the Chat Messages' index=True required=True args: 'Shortcut'
  • substitution Text
    help='The escaped html code replacing the shortcut' index=True required=True args: 'Substitution'
Public methods (0)

No public methods.

New fields (26)
  • attachment_ids Many2many → ir.attachment
    help='You may attach files to this template, to be added to all emails created from this template' args: 'ir.attachment', 'email_template_attachment_rel', 'email_template_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    default=True help='Permanently delete this email after sending it, to save space' args: 'Auto Delete'
  • body_html Html
    sanitize=False translate=True args: 'Body'
  • copyvalue Char
    help='Final placeholder expression, to be copy-pasted in the desired template field.' args: 'Placeholder Expression'
  • email_cc Char
    help='Carbon copy recipients (placeholders may be used here)' args: 'Cc'
  • email_from Char
    help="Sender address (placeholders may be used here). If not set, the default value will be the author's email alias if configured, or email address." args: 'From'
  • email_to Char
    help='Comma-separated recipient addresses (placeholders may be used here)' args: 'To (Emails)'
  • lang Char
    help='Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. ${object.partner_id.lang}.' placeholder='${object.partner_id.lang}' args: 'Language'
  • mail_server_id Many2one → ir.mail_server
    help='Optional preferred server for outgoing mails. If not set, the highest priority one will be used.' readonly=False args: 'ir.mail_server', 'Outgoing Mail Server'
  • model Char
    index=True readonly=True related='model_id.model' store=True args: 'Related Document Model'
  • model_id Many2one → ir.model
    help='The type of document this template can be used with' args: 'ir.model', 'Applies to'
  • model_object_field Many2one → ir.model.fields
    help='Select target field from the related document model.\nIf it is a relationship field you will be able to select a target field at the destination of the relationship.' string='Field' args: 'ir.model.fields'
  • name Char
    args: 'Name'
  • null_value Char
    help='Optional value to use if the target field is empty' args: 'Default Value'
  • partner_to Char
    help='Comma-separated ids of recipient partners (placeholders may be used here)' oldname='email_recipients' args: 'To (Partners)'
  • ref_ir_act_window Many2one → ir.actions.act_window
    copy=False help='Sidebar action to make this template available on records of the related document model' readonly=True args: 'ir.actions.act_window', 'Sidebar action'
  • ref_ir_value Many2one → ir.values
    copy=False help='Sidebar button to open the sidebar action' readonly=True args: 'ir.values', 'Sidebar Button'
  • reply_to Char
    help='Preferred response address (placeholders may be used here)' args: 'Reply-To'
  • report_name Char
    help='Name to use for the generated report file (may contain placeholders)\nThe extension can be omitted and will then come from the report type.' translate=True args: 'Report Filename'
  • report_template Many2one → ir.actions.report.xml
    args: 'ir.actions.report.xml', 'Optional report to print and attach'
  • scheduled_date Char
    help='If set, the queue manager will send the email after the date. If not set, the email will be send as soon as possible. Jinja2 placeholders may be used.' args: 'Scheduled Date'
  • sub_model_object_field Many2one → ir.model.fields
    help='When a relationship field is selected as first field, this field lets you select the target field within the destination document model (sub-model).' args: 'ir.model.fields', 'Sub-field'
  • sub_object Many2one → ir.model
    help='When a relationship field is selected as first field, this field shows the document model the relationship goes to.' readonly=True args: 'ir.model', 'Sub-model'
  • subject Char
    help='Subject (placeholders may be used here)' translate=True args: 'Subject'
  • use_default_to Boolean
    help='Default recipients of the record:\n- partner (using id on a partner or the partner_id field) OR\n- email (using email_from or email field)' args: 'Default recipients'
  • user_signature Boolean
    help="If checked, the user's signature will be appended to the text version of the message" args: 'Add Signature'
Public methods (14)
  • build_expression(self, field_name, sub_field_name, null_value)
    Returns a placeholder expression for use in a template field, based on the values provided in the placeholder assistant. :param field_name: main field name :param sub_field_name: sub field name (M2O) :param null_value: default value if the target value is empty :return: final placeholder expression
  • copy(self, default=None)
    @api.multi
  • create_action(self)
    @api.multi
  • default_get(self, fields)
    @api.model
  • generate_email(self, res_ids, fields=None)
    @api.multi
    Generates an email from the template for given the given model based on records given by res_ids. :param template_id: id of the template to render. :param res_id: id of the record to use for rendering the template (model is taken from template definition) :returns: a dict containing all relevant fields for creating a new mail.mail entry, with one extra key ``attachments``, in the format [(report_name, data)] where data is base64 encoded.
  • generate_recipients(self, results, res_ids)
    @api.multi
    Generates the recipients of the template. Default values can ben generated instead of the template values if requested by template or context. Emails (email_to, email_cc) can be transformed into partners if requested in the context.
  • get_email_template(self, res_ids)
    @api.multi
  • onchange_model_id(self)
    @api.onchange('model_id')
  • onchange_sub_model_object_value_field(self)
    @api.onchange('model_object_field', 'sub_model_object_field', 'null_value')
  • render_post_process(self, html)
    @api.model
  • render_template(self, template_txt, model, res_ids, post_process=False)
    @api.model
    Render the given template text, replace mako expressions ``${expr}`` with the result of evaluating these expressions with an evaluation context containing: - ``user``: browse_record of the current user - ``object``: record of the document record this mail is related to - ``context``: the context passed to the mail composition wizard :param str template_txt: the template text to render :param str model: model name of the document record this mail is related to. :param int res_ids: list of ids of document records those mails are related to.
  • send_mail(self, res_id, force_send=False, raise_exception=False, email_values=None)
    @api.multi
    Generates a new mail message for the given template and record, and schedules it for delivery through the ``mail`` module's scheduler. :param int res_id: id of the record to render the template with (model is taken from the template) :param bool force_send: if True, the generated mail.message is immediately sent after being created, as if the scheduler was executed for this message only. :param dict email_values: if set, the generated mail.message is updated with given values dict :returns: id of the mail.message that was created
  • unlink(self)
    @api.multi
  • unlink_action(self)
    @api.multi

New fields (10)
  • message_channel_ids Many2many → mail.channel
    comodel_name='mail.channel' compute='_get_followers' search='_search_follower_channels' string='Followers (Channels)'
  • message_follower_ids One2many → mail.followers
    domain=<expr> string='Followers' args: 'mail.followers', 'res_id'
  • message_ids One2many → mail.message
    auto_join=True domain=<expr> string='Messages' args: 'mail.message', 'res_id'
  • message_is_follower Boolean
    compute='_compute_is_follower' search='_search_is_follower' args: 'Is Follower'
  • message_last_post Datetime
    help='Date of the last message posted on the record.' args: 'Last Message Date'
  • message_needaction Boolean
    compute='_get_message_needaction' help='If checked, new messages require your attention.' search='_search_message_needaction' args: 'Action Needed'
  • message_needaction_counter Integer
    compute='_get_message_needaction' help='Number of messages which requires an action' args: 'Number of Actions'
  • message_partner_ids Many2many → res.partner
    comodel_name='res.partner' compute='_get_followers' search='_search_follower_partners' string='Followers (Partners)'
  • message_unread Boolean
    compute='_get_message_unread' help='If checked new messages require your attention.' args: 'Unread Messages'
  • message_unread_counter Integer
    compute='_get_message_unread' help='Number of unread messages' args: 'Unread Messages Counter'
Public methods (33)
  • check_mail_message_access(self, res_ids, operation, model_name=None)
    @api.model
    mail.message check permission rules for related document. This method is meant to be inherited in order to implement addons-specific behavior. A common behavior would be to allow creating messages when having read access rule on the document, for portal document such as issues.
  • copy_data(self, default=None)
    @api.multi
  • create(self, values)
    @api.model
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False)
    @api.model
  • get_empty_list_help(self, help)
    @api.model
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • message_auto_subscribe(self, updated_fields, values=None)
    @api.multi
    Handle auto subscription. Two methods for auto subscription exist: - tracked res.users relational fields, such as user_id fields. Those fields must be relation fields toward a res.users record, and must have the track_visilibity attribute set. - using subtypes parent relationship: check if the current model being modified has an header record (such as a project for tasks) whose followers can be added as followers of the current records. Example of structure with project and task: - st_project_1.parent_id = st_task_1 - st_project_1.res_model = 'project.project' - st_project_1.relation_field = 'project_id' - st_task_1.model = 'project.task' :param list updated_fields: list of updated fields to track :param dict values: updated values; if None, the first record will be browsed to get the values. Added after releasing 7.0, therefore not merged with updated_fields argumment.
  • message_capable_models(self)
    @api.model
    Used by the plugin addon, based for plugin_outlook and others.
  • message_change_thread(self, new_thread)
    @api.multi
    Transfer the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : my_lead.message_change_thread(my_project_issue) will transfer the context of the thread of my_lead to my_project_issue
  • message_get_default_recipients(self, res_model=None, res_ids=None)
    @api.multi
  • message_get_email_values(self, notif_mail=None)
    @api.multi
    Get specific notification email values to store on the notification mail_mail. Void method, inherit it to add custom values.
  • message_get_recipient_values(self, notif_message=None, recipient_ids=None)
    @api.multi
    Get specific notification recipient values to store on the notification mail_mail. Basic method just set the recipient partners as mail_mail recipients. Inherit this method to add custom behavior like using recipient email_to to bypass the recipint_ids heuristics in the mail sending mechanism.
  • message_get_reply_to(self, res_ids, default=None)
    @api.model
    Returns the preferred reply-to email address that is basically the alias of the document, if it exists. Override this method to implement a custom behavior about reply-to for generated emails.
  • message_get_suggested_recipients(self)
    @api.multi
    Returns suggested recipients for ids. Those are a list of tuple (partner_id, partner_name, reason), to be managed by Chatter.
  • message_mass_mailing_enabled(self)
  • message_new(self, msg_dict, custom_values=None)
    @api.model
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :param dict context: if a ``thread_model`` value is present in the context, its value will be used to determine the model of the record to create (instead of the current model). :rtype: int :return: the id of the newly created thread object
  • message_parse(self, message, save_original=False)
    @api.model
    Parses a string or email.message.Message representing an RFC-2822 email, and returns a generic dict holding the message details. :param message: the message to parse :type message: email.message.Message | string | unicode :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'from': from, 'to': to, 'cc': cc, 'body': unified_body, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_partner_info_from_emails(self, emails, link_mail=False)
    @api.multi
    Convert a list of emails into a list partner_ids and a list new_partner_ids. The return value is non conventional because it is meant to be used by the mail widget. :return dict: partner_ids and new_partner_ids
  • message_post(self, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, content_subtype='html', **kwargs)
    @api.multi@api.returns('self', <expr>)
    Post a new message in an existing thread, returning the new mail.message ID. :param int thread_id: thread ID to post into, or list with one ID; if False/0, mail.message model will also be set as False :param str body: body of the message, usually raw HTML that will be sanitized :param str type: see mail_message.type field :param str content_subtype:: if plaintext: convert body into html :param int parent_id: handle reply to a previous message by adding the parent partners to the message in case of private discussion :param tuple(str,str) attachments or list id: list of attachment tuples in the form ``(name,content)``, where content is NOT base64 encoded Extra keyword arguments will be used as default column values for the new mail.message record. Special cases: - attachment_ids: supposed not attached to any document; attach them to the related document. Should only be set by Chatter. :return int: ID of newly created mail.message
  • message_post_with_template(self, template_id, **kwargs)
    @api.multi
    Helper method to send a mail with a template :param template_id : the id of the template to render to create the body of the message :param **kwargs : parameter to create a mail.compose.message woaerd (which inherit from mail.message)
  • message_post_with_view(self, views_or_xmlid, **kwargs)
    @api.multi
    Helper method to send a mail / post a message using a view_id to render using the ir.qweb engine. This method is stand alone, because there is nothing in template and composer that allows to handle views in batch. This method should probably disappear when templates handle ir ui views.
  • message_process(self, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None)
    @api.model
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). There is a special case where the target model is False: a reply to a private message. In this case, we skip the message_new / message_update step, to just post a new message using mail_thread message_post. :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: string or xmlrpclib.Binary :type dict custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • message_receive_bounce(self, email, partner, mail_id=None)
    @api.multi
    Called by ``message_process`` when a bounce email (such as Undelivered Mail Returned to Sender) is received for an existing thread. The default behavior is to check is an integer ``message_bounce`` column exists. If it is the case, its content is incremented. :param mail_id: ID of the sent email that bounced. It may not exist anymore but it could be usefull if the information was kept. This is used notably in mass mailing. :param RecordSet partner: partner matching the bounced email address, if any :param string email: email that caused the bounce
  • message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None)
    @api.model
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: * if the message replies to an existing thread by having a Message-Id that matches an existing mail_message.message_id, we take the original message model/thread_id pair and ignore custom_value as no creation will take place * if the message replies to an existing thread by having In-Reply-To or References matching odoo model/thread_id Message-Id and if this thread has messages without message_id, take this model/thread_id pair and ignore custom_value as no creation will take place (6.1 compatibility) * look for a mail.alias entry matching the message recipients and use the corresponding model, thread_id, custom_values and user_id. This could lead to a thread update or creation depending on the alias * fallback on provided ``model``, ``thread_id`` and ``custom_values`` * raise an exception as no route has been found :param string message: an email.message instance :param dict message_dict: dictionary holding parsed message variables :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :type dict custom_values: optional dictionary of default field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of routes [(model, thread_id, custom_values, user_id, alias)] :raises: ValueError, TypeError
  • message_route_process(self, message, message_dict, routes)
    @api.model
  • message_route_verify(self, message, message_dict, route, update_author=True, assert_model=True, create_fallback=True, allow_private=False, drop_alias=False)
    @api.model
    Verify route validity. Check and rules: 1 - if thread_id -> check that document effectively exists; otherwise fallback on a message_new by resetting thread_id 2 - check that message_update exists if thread_id is set; or at least that message_new exist [ - find author_id if udpate_author is set] 3 - if there is an alias, check alias_contact: 'followers' and thread_id: check on target document that the author is in the followers 'followers' and alias_parent_thread_id: check on alias parent document that the author is in the followers 'partners': check that author_id id set :param message: an email.message instance :param message_dict: dictionary of values that will be given to mail_message.create() :param route: route to check which is a tuple (model, thread_id, custom_values, uid, alias) :param update_author: update message_dict['author_id']. TDE TODO: move me :param assert_model: if an error occurs, tell whether to raise an error or just log a warning and try other processing or invalidate route :param create_fallback: if the route aims at updating a record and that record does not exists or does not support update either fallback on creating a new record in the same model or raise / warn :param allow_private: allow void model / thread_id routes, aka private discussions
  • message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, force=True)
    @api.multi
    Add partners to the records followers.
  • message_subscribe_users(self, user_ids=None, subtype_ids=None)
    @api.multi
    Wrapper on message_subscribe, using users. If user_ids is not provided, subscribe uid instead.
  • message_track(self, tracked_fields, initial_values)
    @api.multi
    Track updated values. Comparing the initial and current values of the fields given in tracked_fields, it generates a message containing the updated values. This message can be linked to a mail.message.subtype given by the ``_track_subtype`` method.
  • message_unsubscribe(self, partner_ids=None, channel_ids=None)
    @api.multi
    Remove partners from the records followers.
  • message_unsubscribe_users(self, user_ids=None)
    @api.multi
    Wrapper on message_subscribe, using users. If user_ids is not provided, unsubscribe uid instead.
  • message_update(self, msg_dict, update_vals=None)
    @api.multi
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • unlink(self)
    @api.multi
    Override unlink to delete messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • write(self, values)
    @api.multi

New fields (16)
  • field Char
    readonly=1 required=True args: 'Changed Field'
  • field_desc Char
    readonly=1 required=True args: 'Field Description'
  • field_type Char
    args: 'Field Type'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message ID'
  • new_value_char Char
    readonly=1 args: 'New Value Char'
  • new_value_datetime Datetime
    readonly=1 args: 'New Value Datetime'
  • new_value_float Float
    readonly=1 args: 'New Value Float'
  • new_value_integer Integer
    readonly=1 args: 'New Value Integer'
  • new_value_monetary Float
    readonly=1 args: 'New Value Monetary'
  • new_value_text Text
    readonly=1 args: 'New Value Text'
  • old_value_char Char
    readonly=1 args: 'Old Value Char'
  • old_value_datetime Datetime
    readonly=1 args: 'Old Value DateTime'
  • old_value_float Float
    readonly=1 args: 'Old Value Float'
  • old_value_integer Integer
    readonly=1 args: 'Old Value Integer'
  • old_value_monetary Float
    readonly=1 args: 'Old Value Monetary'
  • old_value_text Text
    readonly=1 args: 'Old Value Text'
Public methods (4)
  • create_tracking_values(self, initial_value, new_value, col_name, col_info)
    @api.model
  • get_display_value(self, type)
    @api.multi
  • get_new_display_value(self)
    @api.multi
  • get_old_display_value(self)
    @api.multi

New fields (6)
  • channel_ids Many2many → mail.channel
    domain=[('channel_type', '=', 'channel')] help='List of channels that will be added as listeners of the current document.' string='Channels' args: 'mail.channel'
  • message Html
    args: 'Message'
  • partner_ids Many2many → res.partner
    help='List of partners that will be added as follower of the current document.' string='Recipients' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' index=True args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' index=True required=True args: 'Related Document Model'
  • send_mail Boolean
    default=True help="If checked, the partners will receive an email warning they have been added in the document's followers." args: 'Send Email'
Public methods (2)
  • add_followers(self)
    @api.multi
  • default_get(self, fields)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cron_mode=True)
    @api.multi
    Send a message to OpenERP's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals, context=None)
    @api.multi

New fields (4)
  • channel_ids Many2many → mail.channel
    copy=False string='Channels' args: 'mail.channel', 'mail_channel_partner', 'partner_id', 'channel_id'
  • message_bounce Integer
    help='Counter of the number of bounced emails for this contact' args: 'Bounce'
  • notify_email Selection
    default='always' help='Policy to receive emails for new messages pushed to your personal Inbox:\n- Never: no emails are sent\n- All Messages: for every notification you receive in your Inbox' oldname='notification_email_send' required=True args: [('none', 'Never'), ('always', 'All Messages')], 'Email Messages and Notifications'
  • opt_out Boolean
    help="If opt-out is checked, this contact has refused to receive emails for mass mailing and marketing campaign. Filter 'Available for Mass Mailing' allows users to filter the partners when performing mass mailing." args: 'Opt-Out'
Public methods (6)
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first partners' id, name and email such that the name or email matches a 'search' string. Prioritize users, and then extend the research to all partners.
  • get_needaction_count(self)
    @api.model
    compute the number of needaction of the current user
  • get_starred_count(self)
    @api.model
    compute the number of starred of the current user
  • get_static_mention_suggestions(self)
    @api.model
    To be overwritten to return the id, name and email of partners used as static mention suggestions loaded once at webclient initialization and stored client side.
  • message_get_default_recipients(self)
    @api.multi
  • message_get_suggested_recipients(self)
    @api.multi

New fields (2)
  • alias_contact Selection
    related='alias_id.alias_contact' string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_id Many2one → mail.alias
    auto_join=True copy=False help="Email address internally associated with this user. Incoming emails will appear in the user's notifications." ondelete='set null' required=False args: 'mail.alias', 'Alias'
Public methods (7)
  • create(self, values)
    @api.model
  • message_get_suggested_recipients(self)
    @api.multi
  • message_partner_info_from_emails(self, emails, link_mail=False)
    @api.multi
  • message_post(self, **kwargs)
    @api.multi@api.returns('self', <expr>)
    Redirect the posting of message on res.users as a private discussion. This is done because when giving the context of Chatter on the various mailboxes, we do not have access to the current partner_id.
  • message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, force=True)
  • message_update(self, msg_dict, update_vals=None)
  • write(self, vals)
    @api.multi
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/9.0/mail
VERSION
VERSION 1.0
CATEGORY
CATEGORYDiscuss
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Christophe Matthieu, Martin Trigaux, Fabien Pinckaers, Antony Lesuisse, Olivier Dony, Thibault Delavallée, Denis Ledoux, Fabien Meghazi, Christophe Simonis, David Monjoie, Xavier Morel, Goffin Simon, Cedric Snauwaert, Nicolas Martinelli, Nicolas Lempereur, Jérome Maes, Julien Legros, Samus CTO, Richard Mathot, qdp-odoo, Géry Debongnie, Aaron Bohy, Jeremy Kersten, Lucas Perais (lpe), Damien Bouvy, Julien De Coster, Yannick Tivisse, qsm-odoo, Martin Geubelle, Toufik Benjaa, Tanguy Charlier, Adrien Dieudonne, Valerie Pirenne
WEBSITE
WEBSITEhttps://www.odoo.com/page/enterprise-social-network
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-05 23:48:30
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web_kanban
    - web
    - bus
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
Business oriented Social Networking
===================================
The Social Networking module provides a unified social network abstraction layer allowing applications to display a complete
communication history on documents with a fully-integrated email and message management system.

It enables the users to read and send messages as well as emails. It also provides a feeds page combined to a subscription mechanism that allows to follow documents and to be constantly updated about recent news.

Main Features
-------------
* Clean and renewed communication history for any Odoo document that can act as a discussion topic
* Subscription mechanism to be updated about new messages on interesting documents
* Unified feeds page to see recent messages and activity on followed documents
* User communication through the feeds page
* Threaded discussion design on documents
* Relies on the global outgoing mail server - an integrated email management system - allowing to send emails with a configurable scheduler-based processing engine
* Includes an extensible generic email composition assistant, that can turn into a mass-mailing assistant and is capable of interpreting simple *placeholder expressions* that will be replaced with dynamic data when each email is actually sent.
    

Code Analysis

Views touched (37)
XML IDNameModelTypeStatus
assets_backend mail assets ir.ui.view qweb Inherits web.assets_backend
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
email_template_form email.template.form mail.template form New
email_template_preview_form email_template.preview.form email_template.preview form New
email_template_tree email.template.tree mail.template tree New
mail_channel_partner_view_form mail.channel.partner.form mail.channel.partner form New
mail_channel_partner_view_tree mail.channel.partner.tree mail.channel.partner tree New
mail_channel_view_form mail.channel.form mail.channel form New
mail_channel_view_kanban mail.channel.kanban mail.channel kanban New
mail_channel_view_search mail.channel.search mail.channel search New
mail_channel_view_tree mail.channel.tree mail.channel tree New
mail_shortcode_view_form mail.shortcode.form mail.shortcode form New
mail_shortcode_view_tree mail.shortcode.tree mail.shortcode tree New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
res_partner_opt_out_search res.partner.opt_out.search res.partner filter Inherits base.view_res_partner_filter
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_email_template_search email.template.search mail.template search New
view_emails_partner_info_form res.partner.emails.info.inherit res.partner xpath Inherits base.view_partner_form
view_followers_tree mail.followers.tree mail.followers tree New
view_general_configuration_mail_alias_domain base.config.settings.mail.alias base.config.settings xpath Inherits base_setup.view_general_configuration
view_mail_alias_form mail.alias.form mail.alias form New
view_mail_alias_search mail.alias.search mail.alias search New
view_mail_alias_tree mail.alias.tree mail.alias tree New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tracking_value_form mail.tracking.value.form mail.tracking.value form New
view_mail_tracking_value_tree mail.tracking.value.tree mail.tracking.value tree New
view_mail_tree mail.mail.tree mail.mail tree New
view_message_form mail.message.form mail.message form New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.tree mail.message.subtype tree New
view_message_tree mail.message.tree mail.message tree New
view_server_action_form_template ir.actions.server.form ir.actions.server xpath Inherits base.view_server_action_form
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (21)

New fields (2)
  • alias_domain Char
    help='If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.' args: 'Alias Domain'
  • fail_counter Integer
    readonly=True args: 'Fail Mail'
Public methods (3)
  • get_default_alias_domain(self)
    @api.multi
  • get_default_fail_counter(self)
    @api.multi
  • set_alias_domain(self)
    @api.multi

New fields (2)
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • res_id Selection
    args: _get_records, 'Sample Document'
Public methods (2)
  • default_get(self, fields)
    @api.model
  • on_change_res_id(self)
    @api.onchange('res_id')@api.multi

New fields (6)
  • body_html Html
    readonly=True related='template_id.body_html' args: 'Body'
  • email_from Char
    readonly=True related='template_id.email_from' args: 'From'
  • email_to Char
    readonly=True related='template_id.email_to' args: 'To (Emails)'
  • partner_to Char
    readonly=True related='template_id.partner_to' args: 'To (Partners)'
  • subject Char
    readonly=True related='template_id.subject' args: 'Subject'
  • template_id Many2one → mail.template
    domain="[('model_id', '=', model_id)]" ondelete='set null' args: 'mail.template', 'Email Template'
Public methods (2)
  • on_change_template_id(self)
    @api.onchange('template_id')
    Render the raw template in the server action fields.
  • run_action_email(self, action, eval_context=None)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • power_on(self, cr, uid, *args, **kwargs)

New fields (9)
  • alias_contact Selection
    default='everyone' help='Policy to post a message on the document using the mailgateway.\n- everyone: everyone can post\n- partners: only authenticated partners\n- followers: only followers of the related document or members of following channels\n' required=True string='Alias Contact Security' args: [('everyone', 'Everyone'), ('partners', 'Authenticated Partners'), ('followers', 'Followers only')]
  • alias_defaults Text
    default='{}' help='A Python dictionary that will be evaluated to provide default values when creating new records for this alias.' required=True args: 'Default Values'
  • alias_domain Char
    compute='_get_alias_domain' default=<expr> args: 'Alias domain'
  • alias_force_thread_id Integer
    help='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.' args: 'Record Thread ID'
  • alias_model_id Many2one → ir.model
    domain="[('field_id.name', '=', 'message_ids')]" help='The model (Odoo 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)' ondelete='cascade' required=True args: 'ir.model', 'Aliased Model'
  • alias_name Char
    help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.odoo.com>" args: 'Alias Name'
  • alias_parent_model_id Many2one → ir.model
    help='Parent model holding the alias. The model holding the alias reference is not necessarily the model given by alias_model_id (example: project (parent_model) and task (model))' args: 'ir.model', 'Parent Model'
  • alias_parent_thread_id Integer
    help='ID of the parent record holding the alias (example: project holding the task creation alias)' args: 'Parent Record Thread ID'
  • alias_user_id Many2one → res.users
    defaults=<expr> help='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.' args: 'res.users', 'Owner'
Public methods (6)
  • create(self, vals)
    @api.model
    Creates an email.alias record according to the values provided in ``vals``, with 2 alterations: the ``alias_name`` value may be suffixed in order to make it unique (and certain unsafe characters replaced), and he ``alias_model_id`` value will set to the model ID of the ``model_name`` context value, if provided.
  • migrate_to_alias(self, cr, child_model_name, child_table_name, child_model_auto_init_fct, alias_model_name, alias_id_column, alias_key, alias_prefix='', alias_force_key='', alias_defaults={}, alias_generate_name=False, 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) :param child_table_name: table name of the child class (i.e. res_users) :param child_model_auto_init_fct: pointer to the _auto_init function (i.e. super(res_users,self)._auto_init(cr, context=context)) :param alias_model_name: name of the aliased model :param alias_id_column: alias_id column (i.e. self._columns['alias_id']) :param alias_key: name of the column used for the unique name (i.e. 'login') :param alias_prefix: prefix for the unique name (i.e. 'jobs' + ...) :param alias_force_key': name of the column for force_thread_id; if empty string, not taken into account :param alias_defaults: dict, keys = mail.alias columns, values = child model column name used for default values (i.e. {'job_id': 'id'}) :param alias_generate_name: automatically generate alias name using prefix / alias key; default alias_name value is False because since 8.0 it is not required anymore
  • name_get(self)
    @api.multi
    Return the mail alias display alias_name, including the implicit mail catchall domain if exists from config otherwise "New Alias". e.g. `jobs@mail.odoo.com` or `jobs` or 'New Alias'
  • open_document(self)
    @api.multi
  • open_parent_document(self)
    @api.multi
  • write(self, vals)
    @api.multi
    "give a unique alias name if given alias name is already assigned

New fields (16)
  • alias_id Many2one → mail.alias
    help='The email address associated with this group. New emails received will automatically create new topics.' ondelete='restrict' required=True args: 'mail.alias', 'Alias'
  • channel_last_seen_partner_ids One2many → mail.channel.partner
    string='Last Seen' args: 'mail.channel.partner', 'channel_id'
  • channel_message_ids Many2many → mail.message
    args: 'mail.message', 'mail_message_mail_channel_rel'
  • channel_partner_ids Many2many → res.partner
    string='Listeners' args: 'res.partner', 'mail_channel_partner', 'channel_id', 'partner_id'
  • channel_type Selection
    default='channel' args: [('chat', 'Chat Discussion'), ('channel', 'Channel')], 'Channel Type'
  • description Text
    args: 'Description'
  • email_send Boolean
    default=False args: 'Send messages by email'
  • group_ids Many2many → res.groups
    help='Members of those groups will automatically added as followers. Note that they will be able to manage their subscription manually if necessary.' id1='mail_channel_id' id2='groups_id' rel='mail_channel_res_group_rel' string='Auto Subscription' args: 'res.groups'
  • group_public_id Many2one → res.groups
    default=<expr> string='Authorized Group' args: 'res.groups'
  • image Binary
    attachment=True default=_get_default_image help='This field holds the image used as photo for the group, limited to 1024x1024px.' args: 'Photo'
  • image_medium Binary
    attachment=True help='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.' args: 'Medium-sized photo'
  • image_small Binary
    attachment=True help='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.' args: 'Small-sized photo'
  • is_member Boolean
    compute='_compute_is_member' args: 'Is a member'
  • name Char
    required=True translate=True args: 'Name'
  • public Selection
    default='groups' help='This group is visible by non members. Invisible groups can add members through the invite button.' required=True args: [('public', 'Everyone'), ('private', 'Invited people only'), ('groups', 'Selected group of users')], 'Privacy'
  • uuid Char
    default=<expr> index=True size=50 args: 'UUID'
Public methods (26)
  • action_follow(self)
    @api.multi
  • action_unfollow(self)
    @api.multi
  • channel_create(self, name, privacy='public')
    @api.model
    Create a channel and add the current partner, broadcast it (to make the user directly listen to it when polling) :param name : the name of the channel to create :param privacy : privacy of the channel. Should be 'public' or 'private'. :return dict : channel header
  • channel_fetch_listeners(self, uuid)
    @api.model
    Return the id, name and email of partners listening to the given channel
  • channel_fetch_message(self, last_id=False, limit=20)
    @api.multi
    Return message values of the current channel. :param last_id : last message id to start the research :param limit : maximum number of messages to fetch :returns list of messages values :rtype : list(dict)
  • channel_fetch_preview(self)
    @api.multi
    Return the last message of the given channels
  • channel_fetch_slot(self)
    @api.model
    Return the channels of the user grouped by 'slot' (channel, direct_message or private_group), and the mapping between partner_id/channel_id for direct_message channels. :returns dict : the grouped channels and the mapping
  • channel_fold(self, uuid, state=None)
    @api.model
    Update the fold_state of the given session. In order to syncronize web browser tabs, the change will be broadcast to himself (the current user channel). Note: the user need to be logged :param state : the new status of the session for the current user.
  • channel_get(self, partners_to, pin=True)
    @api.model
    Get the canonical private channel between some partners, create it if needed. To reuse an old channel (conversation), this one must be private, and contains only the given partners. :param partners_to : list of res.partner ids to add to the conversation :param pin : True if getting the channel should pin it for the current user :returns a channel header, or False if the users_to was False :rtype : dict
  • channel_get_and_minimize(self, partners_to)
    @api.model
  • channel_info(self, extra_info=False)
    @api.multi
    Get the informations header for the current channels :returns a list of channels values :rtype : list(dict)
  • channel_invite(self, partner_ids)
    @api.multi
    Add the given partner_ids to the current channels and broadcast the channel header to them. :param partner_ids : list of partner id to add
  • channel_join_and_get_info(self)
    @api.multi
  • channel_minimize(self, uuid, minimized=True)
    @api.model
  • channel_pin(self, uuid, pinned=False)
    @api.model
  • channel_search_to_join(self, name=None, domain=None)
    @api.model
    Return the channel info of the channel the current partner can join :param name : the name of the researched channels :param domain : the base domain of the research :returns dict : channel dict
  • channel_seen(self)
    @api.multi
  • create(self, vals)
    @api.model
  • get_init_notifications(self)
    @api.model
    Get unread messages and old messages received less than AWAY_TIMER ago of minimized channel ONLY. This aims to set the minimized channel when refreshing the page. Note : the user need to be logged
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first channels' id, name and public fields such that the name matches a 'search' string. Exclude channels of type chat (DM), and private channels the current user isn't registered to.
  • init(self, cr)
  • message_get_email_values(self, notif_mail=None)
    @api.multi
  • message_get_recipient_values(self, notif_message=None, recipient_ids=None)
    @api.multi
  • message_post(self, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, content_subtype='html', **kwargs)
    @api.multi@api.returns('self', <expr>)
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (6)
  • channel_id Many2one → mail.channel
    ondelete='cascade' string='Channel' args: 'mail.channel'
  • fold_state Selection
    default='open' string='Conversation Fold State' args: [('open', 'Open'), ('folded', 'Folded'), ('closed', 'Closed')]
  • is_minimized Boolean
    args: 'Conversation is minimied'
  • is_pinned Boolean
    default=True args: 'Is pinned on the interface'
  • partner_id Many2one → res.partner
    ondelete='cascade' string='Recipient' args: 'res.partner'
  • seen_message_id Many2one → mail.message
    string='Last Seen' args: 'mail.message'
Public methods (0)

No public methods.

New fields (9)
  • active_domain Text
    readonly=True args: 'Active domain'
  • attachment_ids Many2many → ir.attachment
    args: 'ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', 'Attachments'
  • composition_mode Selection
    default='comment' selection=_get_composition_mode_selection string='Composition mode'
  • is_log Boolean
    help='Whether the message is an internal note (comment mode only)' args: 'Log an Internal Note'
  • notify Boolean
    help='Notify followers of the document (mass post only)' args: 'Notify followers'
  • partner_ids Many2many → res.partner
    args: 'res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional Contacts'
  • subject Char
    default=False
  • template_id Many2one → mail.template
    domain="[('model', '=', model)]" index=True args: 'mail.template', 'Use template'
  • use_active_domain Boolean
    args: 'Use active domain'
Public methods (12)
  • check_access_rule(self, operation)
    @api.multi
    Access rules of mail.compose.message: - create: if - model, no res_id, I create a message in mass mail mode - then: fall back on mail.message acces rules
  • default_get(self, fields)
    @api.model
    Handle composition mode. Some details about context keys: - comment: default mode, model and ID of a record the user comments - default_model or active_model - default_res_id or active_id - reply: active_id of a message the user replies to - default_parent_id or message_id or active_id: ID of the mail.message we reply to - message.res_model or default_model - message.res_id or default_res_id - mass_mail: model and IDs of records the user mass-mails - active_ids: record IDs - default_model or active_model
  • generate_email_for_composer(self, template_id, res_ids, fields=None)
    @api.model
    Call email_template.generate_email(), get fields relevant for mail.compose.message, transform email_cc and email_to into partner_ids
  • get_mail_values(self, res_ids)
    @api.multi
    Generate the values that will be used by send_mail to create mail_messages or mail_mails.
  • get_record_data(self, values)
    @api.model
    Returns a defaults-like dict with initial values for the composition wizard when sending an email related a previous email (parent_id) or a document (model, res_id). This is based on previously computed default values.
  • onchange_template_id(self, template_id, composition_mode, model, res_id)
    @api.multi
    - mass_mailing: we cannot render, so return the template values - normal mode: return rendered values /!\ for x2many field, this onchange return command instead of ids
  • onchange_template_id_wrapper(self)
    @api.multi@api.onchange('template_id')
  • render_message(self, res_ids)
    @api.multi
    Generate template-based values of wizard, for the document records given by res_ids. This method is meant to be inherited by email_template that will produce a more complete dictionary, using Jinja2 templates. Each template is generated for all res_ids, allowing to parse the template once, and render it multiple times. This is useful for mass mailing where template rendering represent a significant part of the process. Default recipients are also computed, based on mail_thread method message_get_default_recipients. This allows to ensure a mass mailing has always some recipients specified. :param browse wizard: current mail.compose.message browse record :param list res_ids: list of record ids :return dict results: for each res_id, the generated template values for subject, body, email_from and reply_to
  • render_template(self, template, model, res_ids, post_process=False)
    @api.model
  • save_as_template(self)
    @api.multi
    hit save as template button: current form value will be a new template attached to the current document.
  • send_mail(self, auto_commit=False)
    @api.multi
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.
  • send_mail_action(self)
    @api.multi

New fields (5)
  • channel_id Many2one → mail.channel
    index=True ondelete='cascade' string='Listener' args: 'mail.channel'
  • partner_id Many2one → res.partner
    index=True ondelete='cascade' string='Related Partner' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' index=True args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' index=True required=True args: 'Related Document Model'
  • subtype_ids Many2many → mail.message.subtype
    help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall." string='Subtype' args: 'mail.message.subtype'
Public methods (3)
  • create(self, vals)
    @api.model
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (11)
  • auto_delete Boolean
    help='Permanently delete this email after sending it, to save space' args: 'Auto Delete'
  • body_html Text
    help='Rich-text/HTML message' args: 'Rich-text Contents'
  • email_cc Char
    help='Carbon copy message recipients' args: 'Cc'
  • email_to Text
    help='Message recipients (emails)' args: 'To'
  • failure_reason Text
    help='Failure reason. This is usually the exception thrown by the email server, stored to ease the debugging of mailing issues.' readonly=1 args: 'Failure Reason'
  • headers Text
    copy=False args: 'Headers'
  • mail_message_id Many2one → mail.message
    auto_join=True index=True ondelete='cascade' required=True args: 'mail.message', 'Message'
  • notification Boolean
    help='Mail has been created to notify people of an existing mail.message' args: 'Is Notification'
  • recipient_ids Many2many → res.partner
    string='To (Partners)' args: 'res.partner'
  • references Text
    help='Message references, such as identifiers of previous messages' readonly=1 args: 'References'
  • state Selection
    copy=False default='outgoing' readonly=True args: [('outgoing', 'Outgoing'), ('sent', 'Sent'), ('received', 'Received'), ('exception', 'Delivery Failed'), ('cancel', 'Cancelled')], 'Status'
Public methods (10)
  • cancel(self)
    @api.multi
  • create(self, values)
    @api.model
  • default_get(self, fields)
    @api.model
  • mark_outgoing(self)
    @api.multi
  • process_email_queue(self, ids=None)
    @api.model
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! :param list ids: optional list of emails ids to send. If passed no search is performed, and these ids are used instead. :param dict context: if a 'filters' key is present in context, this value will be used as an additional filter to further restrict the outgoing messages to send (by default all 'outgoing' messages are sent).
  • send(self, auto_commit=False, raise_exception=False)
    @api.multi
    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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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
  • send_get_email_dict(self, partner=None)
    @api.multi
    Return a dictionary for specific email values, depending on a partner, or generic to the whole recipients given by mail.email_to. :param browse_record mail: mail.mail browse_record :param browse_record partner: specific recipient partner
  • send_get_mail_body(self, partner=None)
    @api.multi
    Return a specific ir_email body. The main purpose of this method is to be inherited to add custom content depending on some module.
  • send_get_mail_to(self, partner=None)
    @api.multi
    Forge the email_to with the following heuristic: - if 'partner', recipient specific (Partner Name <email>) - else fallback on mail.email_to splitting
  • unlink(self)
    @api.multi

New fields (25)
  • attachment_ids Many2many → ir.attachment
    help='Attachments are linked to a document through model / res_id and to the messagethrough this field.' string='Attachments' args: 'ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id'
  • author_avatar Binary
    related='author_id.image_small' args: "Author's avatar"
  • author_id Many2one → res.partner
    default=_get_default_author help='Author of the message. If not set, email_from may hold an email address that did not match any partner.' index=True ondelete='set null' args: 'res.partner', 'Author'
  • body Html
    default='' help='Automatically sanitized HTML contents' args: 'Contents'
  • channel_ids Many2many → mail.channel
    string='Channels' args: 'mail.channel', 'mail_message_mail_channel_rel'
  • child_ids One2many → mail.message
    args: 'mail.message', 'parent_id', 'Child Messages'
  • date Datetime
    default=fields.Datetime.now args: 'Date'
  • email_from Char
    default=_get_default_from help='Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.' args: 'From'
  • mail_server_id Many2one → ir.mail_server
    args: 'ir.mail_server', 'Outgoing mail server'
  • message_id Char
    copy=False help='Message unique identifier' index=True readonly=1 args: 'Message-Id'
  • message_type Selection
    default='email' help='Message type: email for email message, notification for system message, comment for other messages such as user replies' oldname='type' required=True args: [('email', 'Email'), ('comment', 'Comment'), ('notification', 'System notification')], 'Type'
  • model Char
    index=True args: 'Related Document Model'
  • needaction Boolean
    compute='_get_needaction' help='Need Action' search='_search_needaction' args: 'Need Action'
  • needaction_partner_ids Many2many → res.partner
    string='Partners with Need Action' args: 'res.partner', 'mail_message_res_partner_needaction_rel'
  • no_auto_thread Boolean
    help='Answers do not go in the original document discussion thread. This has an impact on the generated message-id.' args: 'No threading for answers'
  • parent_id Many2one → mail.message
    help='Initial thread message.' index=True ondelete='set null' args: 'mail.message', 'Parent Message'
  • partner_ids Many2many → res.partner
    string='Recipients' args: 'res.partner'
  • record_name Char
    help='Name get of the related document.' args: 'Message Record Name'
  • reply_to Char
    help='Reply email address. Setting the reply_to bypasses the automatic thread creation.' args: 'Reply-To'
  • res_id Integer
    index=True args: 'Related Document ID'
  • starred Boolean
    compute='_get_starred' help='Current user has a starred notification linked to this message' search='_search_starred' args: 'Starred'
  • starred_partner_ids Many2many → res.partner
    string='Favorited By' args: 'res.partner', 'mail_message_res_partner_starred_rel'
  • subject Char
    args: 'Subject'
  • subtype_id Many2one → mail.message.subtype
    index=True ondelete='set null' args: 'mail.message.subtype', 'Subtype'
  • tracking_value_ids One2many → mail.tracking.value
    groups='base.group_no_one' help='Tracked values are stored in a separate model. This field allow to reconstructthe tracking and to generate statistics on the model.' string='Tracking values' args: 'mail.tracking.value', 'mail_message_id'
Public methods (15)
  • check_access_rule(self, operation)
    @api.multi
    Access rules of mail.message: - read: if - author_id == pid, uid is the author OR - uid is in the recipients (partner_ids) OR - uid is member of a listern channel (channel_ids.partner_ids) OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id (private message) OR - pid in message_follower_ids if model, res_id OR - uid can read the parent OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid is in the recipients (partner_ids) OR - uid has write or create access on the related document if model, res_id - otherwise: raise - unlink: if - uid has write or create access on the related document if model, res_id - otherwise: raise Specific case: non employee users see only messages with subtype (aka do not see internal logs).
  • create(self, values)
    @api.model
  • init(self, cr)
  • mark_all_as_read(self, channel_ids=None, domain=None)
    @api.model
    Remove all needactions of the current partner. If channel_ids is given, restrict to messages written in one of those channels.
  • mark_as_unread(self, channel_ids=None)
    @api.multi
    Add needactions to messages for the current partner.
  • message_fetch(self, domain, limit=20)
    @api.model
  • message_format(self)
    @api.multi
    Get the message values in the format for web client. Since message values can be broadcasted, computed fields MUST NOT BE READ and broadcasted. :returns list(dict). Example : { 'body': HTML content of the message 'model': u'res.partner', 'record_name': u'Agrolait', 'attachment_ids': [ { 'file_type_icon': u'webimage', 'id': 45, 'name': u'sample.png', 'filename': u'sample.png' } ], 'needaction_partner_ids': [], # list of partner ids 'res_id': 7, 'tracking_value_ids': [ { 'old_value': "", 'changed_field': "Customer", 'id': 2965, 'new_value': "Axelor" } ], 'author_id': (3, u'Administrator'), 'email_from': 'sacha@pokemon.com' # email address or False 'subtype_id': (1, u'Discussions'), 'channel_ids': [], # list of channel ids 'date': '2015-06-30 08:22:33', 'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner name_get 'message_type': u'comment', 'id': 59, 'subject': False 'is_note': True # only if the subtype is internal }
  • message_read(self, domain=None, thread_level=0, context=None, parent_id=False, limit=None, child_limit=None)
    @api.multi
    Read messages from mail.message, and get back a list of structured messages to be displayed as discussion threads. If IDs is set, fetch these records. Otherwise use the domain to fetch messages. After having fetch messages, their ancestors will be added to obtain well formed threads, if uid has access to them. After reading the messages, expandable messages are added in the message list. It consists in messages holding the 'read more' data: number of messages to read, domain to apply. :param list ids: optional IDs to fetch :param list domain: optional domain for searching ids if ids not set :param int parent_id: context of parent_id - if parent_id reached when adding ancestors, stop going further in the ancestor search - if set in flat mode, ancestor_id is set to parent_id :param int limit: number of messages to fetch, before adding the ancestors and expandables :param int child_limit: number of child messages to fetch :return dict: - int: number of messages read (status 'unread' to 'read') - list: list of threads [[messages_of_thread1], [messages_of_thread2]]
  • message_read_wrapper(self, cr, uid, ids=None, domain=None, context=None, thread_level=0, parent_id=False, limit=None, child_limit=None)
    @api.cr_uid_context
  • read(self, fields=None, load='_classic_read')
    @api.multi
    Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_done(self, partner_ids=None)
    @api.multi
    Remove the needaction from messages for the current partner.
  • set_message_starred(self, starred)
    @api.multi
    Set messages as (un)starred. Technically, the notifications related to uid are set to (un)starred. :param bool starred: set notification as (un)starred
  • unlink(self)
    @api.multi
  • unstar_all(self)
    @api.model
    Unstar messages for the current partner.
  • write(self, vals)
    @api.multi

New fields (9)
  • default Boolean
    default=True help='Activated by default when subscribing.' args: 'Default'
  • description Text
    help='Description that will be added in the message posted for this subtype. If void, the name will be added instead.' translate=True args: 'Description'
  • hidden Boolean
    help='Hide the subtype in the follower options' args: 'Hidden'
  • internal Boolean
    help='Messages with internal subtypes will be visible only by employees, aka members of base_user group' args: 'Internal Only'
  • name Char
    help='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.' required=True translate=True args: 'Message Type'
  • parent_id Many2one → mail.message.subtype
    help='Parent subtype, used for automatic subscription. This field is not correctly named. For example on a project, the parent_id of project subtypes refers to task-related subtypes.' ondelete='set null' string='Parent' args: 'mail.message.subtype'
  • relation_field Char
    help='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).' args: 'Relation field'
  • res_model Char
    help='Model the subtype applies to. If False, this subtype applies to all models.' args: 'Model'
  • sequence Integer
    default=1 help='Used to order subtypes.' args: 'Sequence'
Public methods (0)

No public methods.

New fields (4)
  • description Char
    args: 'Description'
  • shortcode_type Selection
    default='text' help='* Smiley are only used for HTML code to display an image * Text (default value) is use to substitute text with another text' required=True args: [('image', 'Smiley'), ('text', 'Canned Response')]
  • source Char
    help='The shortcut which must be replace in the Chat Messages' index=True required=True args: 'Shortcut'
  • substitution Char
    help='The excaped html code replacing the shortcut' index=True required=True args: 'Substitution'
Public methods (3)
  • apply_shortcode(self, message, shortcode_type=None)
    @api.model
    Apply the substitution on the given text :param message : the text where the shortcode will be applied :param shortcode_type : shortcode type that should be applied during the substitution
  • create(self, values)
    @api.model
  • write(self, values)
    @api.multi

New fields (25)
  • attachment_ids Many2many → ir.attachment
    help='You may attach files to this template, to be added to all emails created from this template' args: 'ir.attachment', 'email_template_attachment_rel', 'email_template_id', 'attachment_id', 'Attachments'
  • auto_delete Boolean
    default=True help='Permanently delete this email after sending it, to save space' args: 'Auto Delete'
  • body_html Html
    help='Rich-text/HTML version of the message (placeholders may be used here)' sanitize=False translate=True args: 'Body'
  • copyvalue Char
    help='Final placeholder expression, to be copy-pasted in the desired template field.' args: 'Placeholder Expression'
  • email_cc Char
    help='Carbon copy recipients (placeholders may be used here)' args: 'Cc'
  • email_from Char
    help="Sender address (placeholders may be used here). If not set, the default value will be the author's email alias if configured, or email address." args: 'From'
  • email_to Char
    help='Comma-separated recipient addresses (placeholders may be used here)' args: 'To (Emails)'
  • lang Char
    help='Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. ${object.partner_id.lang}.' placeholder='${object.partner_id.lang}' args: 'Language'
  • mail_server_id Many2one → ir.mail_server
    help='Optional preferred server for outgoing mails. If not set, the highest priority one will be used.' readonly=False args: 'ir.mail_server', 'Outgoing Mail Server'
  • model Char
    index=True readonly=True related='model_id.model' store=True args: 'Related Document Model'
  • model_id Many2one → ir.model
    help='The kind of document with with this template can be used' args: 'ir.model', 'Applies to'
  • model_object_field Many2one → ir.model.fields
    help='Select target field from the related document model.\nIf it is a relationship field you will be able to select a target field at the destination of the relationship.' string='Field' args: 'ir.model.fields'
  • name Char
    args: 'Name'
  • null_value Char
    help='Optional value to use if the target field is empty' args: 'Default Value'
  • partner_to Char
    help='Comma-separated ids of recipient partners (placeholders may be used here)' oldname='email_recipients' args: 'To (Partners)'
  • ref_ir_act_window Many2one → ir.actions.act_window
    copy=False help='Sidebar action to make this template available on records of the related document model' readonly=True args: 'ir.actions.act_window', 'Sidebar action'
  • ref_ir_value Many2one → ir.values
    copy=False help='Sidebar button to open the sidebar action' readonly=True args: 'ir.values', 'Sidebar Button'
  • reply_to Char
    help='Preferred response address (placeholders may be used here)' args: 'Reply-To'
  • report_name Char
    help='Name to use for the generated report file (may contain placeholders)\nThe extension can be omitted and will then come from the report type.' translate=True args: 'Report Filename'
  • report_template Many2one → ir.actions.report.xml
    args: 'ir.actions.report.xml', 'Optional report to print and attach'
  • sub_model_object_field Many2one → ir.model.fields
    help='When a relationship field is selected as first field, this field lets you select the target field within the destination document model (sub-model).' args: 'ir.model.fields', 'Sub-field'
  • sub_object Many2one → ir.model
    help='When a relationship field is selected as first field, this field shows the document model the relationship goes to.' readonly=True args: 'ir.model', 'Sub-model'
  • subject Char
    help='Subject (placeholders may be used here)' translate=True args: 'Subject'
  • use_default_to Boolean
    help='Default recipients of the record:\n- partner (using id on a partner or the partner_id field) OR\n- email (using email_from or email field)' args: 'Default recipients'
  • user_signature Boolean
    help="If checked, the user's signature will be appended to the text version of the message" args: 'Add Signature'
Public methods (14)
  • build_expression(self, field_name, sub_field_name, null_value)
    Returns a placeholder expression for use in a template field, based on the values provided in the placeholder assistant. :param field_name: main field name :param sub_field_name: sub field name (M2O) :param null_value: default value if the target value is empty :return: final placeholder expression
  • copy(self, default=None)
    @api.multi
  • create_action(self)
    @api.multi
  • default_get(self, fields)
    @api.model
  • generate_email(self, res_ids, fields=None)
    @api.multi
    Generates an email from the template for given the given model based on records given by res_ids. :param template_id: id of the template to render. :param res_id: id of the record to use for rendering the template (model is taken from template definition) :returns: a dict containing all relevant fields for creating a new mail.mail entry, with one extra key ``attachments``, in the format [(report_name, data)] where data is base64 encoded.
  • generate_recipients(self, results, res_ids)
    @api.multi
    Generates the recipients of the template. Default values can ben generated instead of the template values if requested by template or context. Emails (email_to, email_cc) can be transformed into partners if requested in the context.
  • get_email_template(self, res_ids)
    @api.multi
  • onchange_model_id(self)
    @api.onchange('model_id')
  • onchange_sub_model_object_value_field(self)
    @api.onchange('model_object_field', 'sub_model_object_field', 'null_value')
  • render_post_process(self, html)
    @api.model
  • render_template(self, template_txt, model, res_ids, post_process=False)
    @api.model
    Render the given template text, replace mako expressions ``${expr}`` with the result of evaluating these expressions with an evaluation context containing: - ``user``: browse_record of the current user - ``object``: record of the document record this mail is related to - ``context``: the context passed to the mail composition wizard :param str template_txt: the template text to render :param str model: model name of the document record this mail is related to. :param int res_ids: list of ids of document records those mails are related to.
  • send_mail(self, res_id, force_send=False, raise_exception=False)
    @api.multi
    Generates a new mail message for the given template and record, and schedules it for delivery through the ``mail`` module's scheduler. :param int res_id: id of the record to render the template with (model is taken from the template) :param bool force_send: if True, the generated mail.message is immediately sent after being created, as if the scheduler was executed for this message only. :returns: id of the mail.message that was created
  • unlink(self)
    @api.multi
  • unlink_action(self)
    @api.multi

New fields (10)
  • message_channel_ids Many2many → mail.channel
    comodel_name='mail.channel' compute='_get_followers' search='_search_follower_channels' string='Followers (Channels)'
  • message_follower_ids One2many → mail.followers
    domain=<expr> string='Followers' args: 'mail.followers', 'res_id'
  • message_ids One2many → mail.message
    auto_join=True domain=<expr> string='Messages' args: 'mail.message', 'res_id'
  • message_is_follower Boolean
    compute='_compute_is_follower' search='_search_is_follower' args: 'Is Follower'
  • message_last_post Datetime
    help='Date of the last message posted on the record.' args: 'Last Message Date'
  • message_needaction Boolean
    compute='_get_message_needaction' help='If checked, new messages require your attention.' search='_search_message_needaction' args: 'Action Needed'
  • message_needaction_counter Integer
    compute='_get_message_needaction' help='Number of messages which requires an action' args: 'Number of Actions'
  • message_partner_ids Many2many → res.partner
    comodel_name='res.partner' compute='_get_followers' search='_search_follower_partners' string='Followers (Partners)'
  • message_unread Boolean
    compute='_get_message_unread' help='If checked new messages require your attention.' args: 'Unread Messages'
  • message_unread_counter Integer
    compute='_get_message_unread' help='Number of unread messages' args: 'Unread Messages Counter'
Public methods (32)
  • check_mail_message_access(self, res_ids, operation, model_name=None)
    @api.model
    mail.message check permission rules for related document. This method is meant to be inherited in order to implement addons-specific behavior. A common behavior would be to allow creating messages when having read access rule on the document, for portal document such as issues.
  • copy_data(self, cr, uid, id, default=None, context=None)
  • create(self, values)
    @api.model
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False)
    @api.model
  • get_empty_list_help(self, help)
    @api.model
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • message_auto_subscribe(self, updated_fields, values=None)
    @api.multi
    Handle auto subscription. Two methods for auto subscription exist: - tracked res.users relational fields, such as user_id fields. Those fields must be relation fields toward a res.users record, and must have the track_visilibity attribute set. - using subtypes parent relationship: check if the current model being modified has an header record (such as a project for tasks) whose followers can be added as followers of the current records. Example of structure with project and task: - st_project_1.parent_id = st_task_1 - st_project_1.res_model = 'project.project' - st_project_1.relation_field = 'project_id' - st_task_1.model = 'project.task' :param list updated_fields: list of updated fields to track :param dict values: updated values; if None, the first record will be browsed to get the values. Added after releasing 7.0, therefore not merged with updated_fields argumment.
  • message_capable_models(self)
    @api.model
    Used by the plugin addon, based for plugin_outlook and others.
  • message_change_thread(self, new_thread)
    @api.multi
    Transfer the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : my_lead.message_change_thread(my_project_issue) will transfer the context of the thread of my_lead to my_project_issue
  • message_get_default_recipients(self, res_model=None, res_ids=None)
    @api.multi
  • message_get_email_values(self, notif_mail=None)
    @api.multi
    Get specific notification email values to store on the notification mail_mail. Void method, inherit it to add custom values.
  • message_get_recipient_values(self, notif_message=None, recipient_ids=None)
    @api.multi
    Get specific notification recipient values to store on the notification mail_mail. Basic method just set the recipient partners as mail_mail recipients. Inherit this method to add custom behavior like using recipient email_to to bypass the recipint_ids heuristics in the mail sending mechanism.
  • message_get_reply_to(self, res_ids, default=None)
    @api.model
    Returns the preferred reply-to email address that is basically the alias of the document, if it exists. Override this method to implement a custom behavior about reply-to for generated emails.
  • message_get_suggested_recipients(self)
    @api.multi
    Returns suggested recipients for ids. Those are a list of tuple (partner_id, partner_name, reason), to be managed by Chatter.
  • message_mass_mailing_enabled(self)
  • message_new(self, msg_dict, custom_values=None)
    @api.model
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :param dict context: if a ``thread_model`` value is present in the context, its value will be used to determine the model of the record to create (instead of the current model). :rtype: int :return: the id of the newly created thread object
  • message_parse(self, message, save_original=False)
    @api.model
    Parses a string or email.message.Message representing an RFC-2822 email, and returns a generic dict holding the message details. :param message: the message to parse :type message: email.message.Message | string | unicode :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'from': from, 'to': to, 'cc': cc, 'body': unified_body, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_partner_info_from_emails(self, emails, link_mail=False)
    @api.multi
    Convert a list of emails into a list partner_ids and a list new_partner_ids. The return value is non conventional because it is meant to be used by the mail widget. :return dict: partner_ids and new_partner_ids
  • message_post(self, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, content_subtype='html', **kwargs)
    @api.multi@api.returns('self', <expr>)
    Post a new message in an existing thread, returning the new mail.message ID. :param int thread_id: thread ID to post into, or list with one ID; if False/0, mail.message model will also be set as False :param str body: body of the message, usually raw HTML that will be sanitized :param str type: see mail_message.type field :param str content_subtype:: if plaintext: convert body into html :param int parent_id: handle reply to a previous message by adding the parent partners to the message in case of private discussion :param tuple(str,str) attachments or list id: list of attachment tuples in the form ``(name,content)``, where content is NOT base64 encoded Extra keyword arguments will be used as default column values for the new mail.message record. Special cases: - attachment_ids: supposed not attached to any document; attach them to the related document. Should only be set by Chatter. :return int: ID of newly created mail.message
  • message_post_with_template(self, template_id, **kwargs)
    @api.multi
    Helper method to send a mail with a template :param template_id : the id of the template to render to create the body of the message :param **kwargs : parameter to create a mail.compose.message woaerd (which inherit from mail.message)
  • message_process(self, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None)
    @api.model
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). There is a special case where the target model is False: a reply to a private message. In this case, we skip the message_new / message_update step, to just post a new message using mail_thread message_post. :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: string or xmlrpclib.Binary :type dict custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None)
    @api.model
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: 1. If the message replies to an existing thread_id, and properly contains the thread model in the 'In-Reply-To' header, use this model/thread_id pair, and ignore custom_value (not needed as no creation will take place) 2. Look for a mail.alias entry matching the message recipient, and use the corresponding model, thread_id, custom_values and user_id. 3. Fallback to the ``model``, ``thread_id`` and ``custom_values`` provided. 4. If all the above fails, raise an exception. :param string message: an email.message instance :param dict message_dict: dictionary holding message variables :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :type dict custom_values: optional dictionary of default field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of [model, thread_id, custom_values, user_id, alias] :raises: ValueError, TypeError
  • message_route_process(self, message, message_dict, routes)
    @api.model
  • message_route_verify(self, message, message_dict, route, update_author=True, assert_model=True, create_fallback=True, allow_private=False)
    @api.model
    Verify route validity. Check and rules: 1 - if thread_id -> check that document effectively exists; otherwise fallback on a message_new by resetting thread_id 2 - check that message_update exists if thread_id is set; or at least that message_new exist [ - find author_id if udpate_author is set] 3 - if there is an alias, check alias_contact: 'followers' and thread_id: check on target document that the author is in the followers 'followers' and alias_parent_thread_id: check on alias parent document that the author is in the followers 'partners': check that author_id id set
  • message_set_read(self)
    @api.multi
  • message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, force=True)
    @api.multi
    Add partners to the records followers.
  • message_subscribe_users(self, user_ids=None, subtype_ids=None)
    @api.multi
    Wrapper on message_subscribe, using users. If user_ids is not provided, subscribe uid instead.
  • message_track(self, tracked_fields, initial_values)
    @api.multi
  • message_unsubscribe(self, partner_ids=None, channel_ids=None)
    @api.multi
    Remove partners from the records followers.
  • message_unsubscribe_users(self, user_ids=None)
    @api.multi
    Wrapper on message_subscribe, using users. If user_ids is not provided, unsubscribe uid instead.
  • message_update(self, msg_dict, update_vals=None)
    @api.multi
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • unlink(self)
    @api.multi
    Override unlink to delete messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • write(self, values)
    @api.multi

New fields (16)
  • field Char
    readonly=1 required=True args: 'Changed Field'
  • field_desc Char
    readonly=1 required=True args: 'Field Description'
  • field_type Char
    args: 'Field Type'
  • mail_message_id Many2one → mail.message
    index=True ondelete='cascade' required=True args: 'mail.message', 'Message ID'
  • new_value_char Char
    readonly=1 args: 'New Value Char'
  • new_value_datetime Datetime
    readonly=1 args: 'New Value Datetime'
  • new_value_float Float
    readonly=1 args: 'New Value Float'
  • new_value_integer Integer
    readonly=1 args: 'New Value Integer'
  • new_value_monetary Float
    readonly=1 args: 'New Value Monetary'
  • new_value_text Text
    readonly=1 args: 'New Value Text'
  • old_value_char Char
    readonly=1 args: 'Old Value Char'
  • old_value_datetime Datetime
    readonly=1 args: 'Old Value DateTime'
  • old_value_float Float
    readonly=1 args: 'Old Value Float'
  • old_value_integer Integer
    readonly=1 args: 'Old Value Integer'
  • old_value_monetary Float
    readonly=1 args: 'Old Value Monetary'
  • old_value_text Text
    readonly=1 args: 'Old Value Text'
Public methods (3)
  • create_tracking_values(self, initial_value, new_value, col_name, col_info)
    @api.model
  • get_new_display_value(self)
    @api.multi
  • get_old_display_value(self)
    @api.multi

New fields (6)
  • channel_ids Many2many → mail.channel
    domain=[('channel_type', '=', 'channel')] help='List of channels that will be added as listeners of the current document.' string='Channels' args: 'mail.channel'
  • message Html
    args: 'Message'
  • partner_ids Many2many → res.partner
    help='List of partners that will be added as follower of the current document.' string='Recipients' args: 'res.partner'
  • res_id Integer
    help='Id of the followed resource' index=True args: 'Related Document ID'
  • res_model Char
    help='Model of the followed resource' index=True required=True args: 'Related Document Model'
  • send_mail Boolean
    default=True help="If checked, the partners will receive an email warning they have been added in the document's followers." args: 'Send Email'
Public methods (2)
  • add_followers(self)
    @api.multi
  • default_get(self, fields)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cr, uid, ids, cron_mode=True, context=None)
    Send a message to OpenERP's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals, context=None)
    @api.multi

New fields (3)
  • channel_ids Many2many → mail.channel
    copy=False string='Channels' args: 'mail.channel', 'mail_channel_partner', 'partner_id', 'channel_id'
  • notify_email Selection
    default='always' help='Policy to receive emails for new messages pushed to your personal Inbox:\n- Never: no emails are sent\n- All Messages: for every notification you receive in your Inbox' oldname='notification_email_send' required=True args: [('none', 'Never'), ('always', 'All Messages')], 'Email Messages and Notifications'
  • opt_out Boolean
    help="If opt-out is checked, this contact has refused to receive emails for mass mailing and marketing campaign. Filter 'Available for Mass Mailing' allows users to filter the partners when performing mass mailing." args: 'Opt-Out'
Public methods (5)
  • get_mention_suggestions(self, search, limit=8)
    @api.model
    Return 'limit'-first partners' id, name and email such that the name or email matches a 'search' string. Prioritize users, and then extend the research to all partners.
  • get_needaction_count(self)
    @api.model
    compute the number of needaction of the current user
  • get_static_mention_suggestions(self)
    @api.model
    To be overwritten to return the id, name and email of partners used as static mention suggestions loaded once at webclient initialization and stored client side.
  • message_get_default_recipients(self)
    @api.multi
  • message_get_suggested_recipients(self)
    @api.multi

New fields (2)
  • alias_id Many2one → mail.alias
    auto_join=True copy=False help="Email address internally associated with this user. Incoming emails will appear in the user's notifications." ondelete='restrict' required=True args: 'mail.alias', 'Alias'
  • chatter_needaction_auto Boolean
    args: 'Automatically set needaction as Read'
Public methods (9)
  • copy_data(self, *args, **kwargs)
  • create(self, values)
    @api.model
  • message_get_partner_info_from_emails(self, cr, uid, emails, link_mail=False, context=None)
    @api.cr_uid_context
  • message_get_suggested_recipients(self)
    @api.multi
  • message_post(self, **kwargs)
    @api.multi
    Redirect the posting of message on res.users as a private discussion. This is done because when giving the context of Chatter on the various mailboxes, we do not have access to the current partner_id.
  • message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, force=True)
  • message_update(self, msg_dict, update_vals=None)
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/8.0/mail
VERSION
VERSION 1.0
CATEGORY
CATEGORYSocial Network
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOpenERP SA
MAINTAINERS
MAINTAINERSOpenERP SA
COMMITTERS
COMMITTERSRaphael Collet, Atul Patel (OpenERP), Stephane Wirtel, Odoo Translation Bot, Turkesh Patel (Open ERP), Christophe Matthieu, ajay javiya (OpenERP), Martin Trigaux, Ajay Chauhan (OpenERP), Foram Katharotiya (OpenERP), Fabien Pinckaers, Antony Lesuisse, Olivier Dony, Thibault Delavallée, Vo Minh Thu, Launchpad Translations on behalf of openerp, Quentin (OpenERP), Denis Ledoux, Fabien Meghazi, niv-openerp, Christophe Simonis, David Monjoie, Xavier Morel, Goffin Simon, Bhumi Thakkar (Open ERP), Cedric Snauwaert, Vishmita, Nicolas Martinelli, Vidhin Mehta (OpenERP), Kersten Jeremy, Amit Bhavsar (Open ERP), Paramjit Singh Sahota, Nicolas Lempereur, Anand Patel (OpenERP), Vidhin Mehta, Julien Legros, xmo-odoo, Samus CTO, Amit Vora, Richard Mathot, qdp-odoo, Géry Debongnie, jke-openerp, Aaron Bohy, Thibault Delavallee, Vishmita Jadeja (openerp), Kuldeep Joshi, ged-odoo, Jeremy Kersten, Kunal Chavda (Open ERP), ima-openerp, GitHub, Darshan Kalola (OpenERP), Jitendra Prajapati (OpenERP), Chirag Dodiya (OpenERP), ssh-odoo, Jaydeep Barot, Pooja Zankhariya (OpenERP), Mantavya Gajjar, Jignesh Rathod (OpenERP), Gaurav Panchal, Priket Trivedi (OpenERP Trainee), Mehul Mehta (OpenERP Trainee), Chris Petsos, Jérôme
WEBSITE
WEBSITEhttps://www.odoo.com/page/enterprise-social-network
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-05 23:45:39
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web_kanban
    - web
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
Business oriented Social Networking
===================================
The Social Networking module provides a unified social network abstraction layer allowing applications to display a complete
communication history on documents with a fully-integrated email and message management system.

It enables the users to read and send messages as well as emails. It also provides a feeds page combined to a subscription mechanism that allows to follow documents and to be constantly updated about recent news.

Main Features
-------------
* Clean and renewed communication history for any OpenERP document that can act as a discussion topic
* Subscription mechanism to be updated about new messages on interesting documents
* Unified feeds page to see recent messages and activity on followed documents
* User communication through the feeds page
* Threaded discussion design on documents
* Relies on the global outgoing mail server - an integrated email management system - allowing to send emails with a configurable scheduler-based processing engine
* Includes an extensible generic email composition assistant, that can turn into a mass-mailing assistant and is capable of interpreting simple *placeholder expressions* that will be replaced with dynamic data when each email is actually sent.
    

Code Analysis

Views touched (26)
XML IDNameModelTypeStatus
assets_backend mail assets ir.ui.view qweb Inherits web.assets_backend
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
view_document_file_kanban ir.attachment kanban ir.attachment kanban New
view_emails_partner_info_form res.partner.emails.info.inherit res.partner xpath Inherits base.view_partner_form
view_followers_tree mail.followers.tree mail.followers tree New
view_general_configuration_mail_alias_domain base.config.settings.mail.alias base.config.settings xpath Inherits base_setup.view_general_configuration
view_group_form mail.group.form mail.group form New
view_group_kanban mail.group.kanban mail.group kanban New
view_group_search mail.group.search mail.group search New
view_group_tree mail.group.tree mail.group tree New
view_mail_alias_form mail.alias.form mail.alias form New
view_mail_alias_search mail.alias.search mail.alias search New
view_mail_alias_tree mail.alias.tree mail.alias tree New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tree mail.mail.tree mail.mail tree New
view_message_form mail.message.form mail.message form New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.tree mail.message.subtype tree New
view_message_tree mail.message.tree mail.message tree New
view_notification_tree mail.notification.tree mail.notification tree New
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (16)

New fields (0)

No new fields.

Public methods (2)
  • get_default_alias_domain(self, cr, uid, ids, context=None)
  • set_alias_domain(self, cr, uid, ids, context=None)

New fields (0)

No new fields.

Public methods (1)
  • get_attachment_type(self, cr, uid, ids, name, args, context=None)

New fields (0)

No new fields.

Public methods (6)
  • create(self, cr, uid, vals, context=None)
    Creates an email.alias record according to the values provided in ``vals``, with 2 alterations: the ``alias_name`` value may be suffixed in order to make it unique (and certain unsafe characters replaced), and he ``alias_model_id`` value will set to the model ID of the ``model_name`` context value, if provided.
  • migrate_to_alias(self, cr, child_model_name, child_table_name, child_model_auto_init_fct, alias_model_name, alias_id_column, alias_key, alias_prefix='', alias_force_key='', alias_defaults={}, alias_generate_name=False, 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) :param child_table_name: table name of the child class (i.e. res_users) :param child_model_auto_init_fct: pointer to the _auto_init function (i.e. super(res_users,self)._auto_init(cr, context=context)) :param alias_model_name: name of the aliased model :param alias_id_column: alias_id column (i.e. self._columns['alias_id']) :param alias_key: name of the column used for the unique name (i.e. 'login') :param alias_prefix: prefix for the unique name (i.e. 'jobs' + ...) :param alias_force_key': name of the column for force_thread_id; if empty string, not taken into account :param alias_defaults: dict, keys = mail.alias columns, values = child model column name used for default values (i.e. {'job_id': 'id'}) :param alias_generate_name: automatically generate alias name using prefix / alias key; default alias_name value is False because since 8.0 it is not required anymore
  • name_get(self, cr, uid, ids, context=None)
    Return the mail alias display alias_name, including the implicit mail catchall domain if exists from config otherwise "New Alias". e.g. `jobs@mail.odoo.com` or `jobs` or 'New Alias'
  • open_document(self, cr, uid, ids, context=None)
  • open_parent_document(self, cr, uid, ids, context=None)
  • write(self, cr, uid, ids, vals, context=None)
    "give a unique alias name if given alias name is already assigned

New fields (0)

No new fields.

Public methods (9)
  • check_access_rule(self, cr, uid, ids, operation, context=None)
    Access rules of mail.compose.message: - create: if - model, no res_id, I create a message in mass mail mode - then: fall back on mail.message acces rules
  • default_get(self, cr, uid, fields, context=None)
    Handle composition mode. Some details about context keys: - comment: default mode, model and ID of a record the user comments - default_model or active_model - default_res_id or active_id - reply: active_id of a message the user replies to - default_parent_id or message_id or active_id: ID of the mail.message we reply to - message.res_model or default_model - message.res_id or default_res_id - mass_mail: model and IDs of records the user mass-mails - active_ids: record IDs - default_model or active_model
  • get_mail_values(self, cr, uid, wizard, res_ids, context=None)
    Generate the values that will be used by send_mail to create mail_messages or mail_mails.
  • get_record_data(self, cr, uid, values, context=None)
    Returns a defaults-like dict with initial values for the composition wizard when sending an email related a previous email (parent_id) or a document (model, res_id). This is based on previously computed default values.
  • render_message(self, cr, uid, wizard, res_id, context=None)
  • render_message_batch(self, cr, uid, wizard, res_ids, context=None)
    Generate template-based values of wizard, for the document records given by res_ids. This method is meant to be inherited by email_template that will produce a more complete dictionary, using Jinja2 templates. Each template is generated for all res_ids, allowing to parse the template once, and render it multiple times. This is useful for mass mailing where template rendering represent a significant part of the process. Default recipients are also computed, based on mail_thread method message_get_default_recipients. This allows to ensure a mass mailing has always some recipients specified. :param browse wizard: current mail.compose.message browse record :param list res_ids: list of record ids :return dict results: for each res_id, the generated template values for subject, body, email_from and reply_to
  • render_template(self, cr, uid, template, model, res_id, context=None)
  • render_template_batch(self, cr, uid, template, model, res_ids, context=None, post_process=False)
    Render the given template text, replace mako-like expressions ``${expr}`` with the result of evaluating these expressions with an evaluation context containing: * ``user``: browse_record of the current user * ``object``: browse_record of the document record this mail is related to * ``context``: the context passed to the mail composition wizard :param str template: the template text to render :param str model: model name of the document record this mail is related to :param list res_ids: list of record ids
  • send_mail(self, cr, uid, ids, context=None)
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals)
    @api.model
  • unlink(self)
    @api.multi
  • write(self, vals)
    @api.multi

New fields (0)

No new fields.

Public methods (8)
  • action_follow(self, cr, uid, ids, context=None)
    Wrapper because message_subscribe_users take a user_ids=None that receive the context without the wrapper.
  • action_unfollow(self, cr, uid, ids, context=None)
    Wrapper because message_unsubscribe_users take a user_ids=None that receive the context without the wrapper.
  • create(self, cr, uid, vals, context=None)
  • get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None)
    Show the suggestion of groups if display_groups_suggestions if the user perference allows it.
  • message_get_email_values(self, cr, uid, id, notif_mail=None, context=None)
  • message_get_recipient_values(self, cr, uid, id, notif_message=None, recipient_ids=None, context=None)
  • unlink(self, cr, uid, ids, context=None)
  • write(self, cr, uid, ids, vals, context=None)

New fields (0)

No new fields.

Public methods (11)
  • cancel(self, cr, uid, ids, context=None)
  • create(self, cr, uid, values, context=None)
  • default_get(self, cr, uid, fields, context=None)
  • mark_outgoing(self, cr, uid, ids, context=None)
  • process_email_queue(self, cr, uid, ids=None, context=None)
    @api.cr_uid
    Send immediately queued messages, committing after each message is sent - this is not transactional and should not be called during another transaction! :param list ids: optional list of emails ids to send. If passed no search is performed, and these ids are used instead. :param dict context: if a 'filters' key is present in context, this value will be used as an additional filter to further restrict the outgoing messages to send (by default all 'outgoing' messages are sent).
  • 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). Emails successfully delivered are marked as 'sent', and those that fail to be deliver are marked as 'exception', and the corresponding error mail is output in the server logs. :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
  • send_get_email_dict(self, cr, uid, mail, partner=None, context=None)
    Return a dictionary for specific email values, depending on a partner, or generic to the whole recipients given by mail.email_to. :param browse_record mail: mail.mail browse_record :param browse_record partner: specific recipient partner
  • 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.
  • send_get_mail_subject(self, cr, uid, mail, force=False, partner=None, context=None)
    If subject is void, set the subject as 'Re: <Resource>' or 'Re: <mail.parent_id.subject>' :param boolean force: force the subject replacement
  • send_get_mail_to(self, cr, uid, mail, partner=None, context=None)
    Forge the email_to with the following heuristic: - if 'partner', recipient specific (Partner Name <email>) - else fallback on mail.email_to splitting
  • unlink(self, cr, uid, ids, context=None)

New fields (0)

No new fields.

Public methods (12)
  • check_access_rule(self, cr, uid, ids, operation, context=None)
    Access rules of mail.message: - read: if - author_id == pid, uid is the author, OR - mail_notification (id, pid) exists, uid has been notified, OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id, I create a private message OR - pid in message_follower_ids if model, res_id OR - mail_notification (parent_id.id, pid) exists, uid has been notified of the parent, OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid has write or create access on the related document if model, res_id - otherwise: raise - unlink: if - uid has write or create access on the related document if model, res_id - otherwise: raise
  • create(self, cr, uid, values, context=None)
  • default_get(self, cr, uid, fields, context=None)
  • download_attachment(self, cr, uid, id_message, attachment_id, context=None)
    Return the content of linked attachments.
  • init(self, cr)
  • message_read(self, cr, uid, ids=None, domain=None, message_unload_ids=None, thread_level=0, context=None, parent_id=False, limit=None)
    @api.cr_uid_context
    Read messages from mail.message, and get back a list of structured messages to be displayed as discussion threads. If IDs is set, fetch these records. Otherwise use the domain to fetch messages. After having fetch messages, their ancestors will be added to obtain well formed threads, if uid has access to them. After reading the messages, expandable messages are added in the message list (see ``_message_read_add_expandables``). It consists in messages holding the 'read more' data: number of messages to read, domain to apply. :param list ids: optional IDs to fetch :param list domain: optional domain for searching ids if ids not set :param list message_unload_ids: optional ids we do not want to fetch, because i.e. they are already displayed somewhere :param int parent_id: context of parent_id - if parent_id reached when adding ancestors, stop going further in the ancestor search - if set in flat mode, ancestor_id is set to parent_id :param int limit: number of messages to fetch, before adding the ancestors and expandables :return list: list of message structure for the Chatter widget
  • read(self, cr, uid, ids, fields=None, context=None, load='_classic_read')
    Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_read(self, cr, uid, msg_ids, read, create_missing=True, context=None)
    @api.cr_uid_ids_context
    Set messages as (un)read. Technically, the notifications related to uid are set to (un)read. If for some msg_ids there are missing notifications (i.e. due to load more or thread parent fetching), they are created. :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
  • set_message_starred(self, cr, uid, msg_ids, starred, create_missing=True, context=None)
    @api.cr_uid_ids_context
    Set messages as (un)starred. Technically, the notifications related to uid are set to (un)starred. :param bool starred: set notification as (un)starred :param bool create_missing: create notifications for missing entries (i.e. when acting on displayed messages not notified)
  • unlink(self, cr, uid, ids, context=None)
  • vote_toggle(self, cr, uid, ids, context=None)
    Toggles vote. Performed using read to avoid access rights issues. Done as SUPERUSER_ID because uid may vote for a message he cannot modify.
  • write(self, vals)
    @api.multi

New fields (0)

No new fields.

Public methods (4)
  • get_partners_to_email(self, cr, uid, ids, message, context=None)
    Return the list of partners to notify, based on their preferences. :param browse_record message: mail.message to notify :param list partners_to_notify: optional list of partner ids restricting the notifications to process
  • get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None, user_signature=True)
    Format a standard footer for notification emails (such as pushed messages notification or invite emails). Format: <p>--<br /> Administrator </p> <div> <small>Sent from <a ...>Your Company</a> using <a ...>OpenERP</a>.</small> </div>
  • init(self, cr)
  • update_message_notification(self, cr, uid, ids, message_id, partner_ids, context=None)

New fields (0)

No new fields.

Public methods (35)
  • check_mail_message_access(self, cr, uid, mids, operation, model_obj=None, context=None)
    @api.cr_uid_ids_context
    mail.message check permission rules for related document. This method is meant to be inherited in order to implement addons-specific behavior. A common behavior would be to allow creating messages when having read access rule on the document, for portal document such as issues.
  • copy_data(self, cr, uid, id, default=None, context=None)
  • create(self, cr, uid, values, context=None)
    Chatter override : - subscribe uid - subscribe followers of parent - log a creation message
  • fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False)
  • get_empty_list_help(self, cr, uid, help, context=None)
    Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information.
  • get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None)
    Return a list of suggested threads, sorted by the numbers of followers
  • message_auto_subscribe(self, cr, uid, ids, updated_fields, context=None, values=None)
    Handle auto subscription. Two methods for auto subscription exist: - tracked res.users relational fields, such as user_id fields. Those fields must be relation fields toward a res.users record, and must have the track_visilibity attribute set. - using subtypes parent relationship: check if the current model being modified has an header record (such as a project for tasks) whose followers can be added as followers of the current records. Example of structure with project and task: - st_project_1.parent_id = st_task_1 - st_project_1.res_model = 'project.project' - st_project_1.relation_field = 'project_id' - st_task_1.model = 'project.task' :param list updated_fields: list of updated fields to track :param dict values: updated values; if None, the first record will be browsed to get the values. Added after releasing 7.0, therefore not merged with updated_fields argumment.
  • message_capable_models(self, cr, uid, context=None)
    Used by the plugin addon, based for plugin_outlook and others.
  • message_change_thread(self, cr, uid, id, new_res_id, new_model, context=None)
    Transfert the list of the mail thread messages from an model to another :param id : the old res_id of the mail.message :param new_res_id : the new res_id of the mail.message :param new_model : the name of the new model of the mail.message Example : self.pool.get("crm.lead").message_change_thread(self, cr, uid, 2, 4, "project.issue", context) will transfert thread of the lead (id=2) to the issue (id=4)
  • message_get_default_recipients(self, cr, uid, ids, context=None)
  • message_get_email_values(self, cr, uid, id, notif_mail=None, context=None)
    Get specific notification email values to store on the notification mail_mail. Void method, inherit it to add custom values.
  • message_get_recipient_values(self, cr, uid, id, notif_message=None, recipient_ids=None, context=None)
    Get specific notification recipient values to store on the notification mail_mail. Basic method just set the recipient partners as mail_mail recipients. Inherit this method to add custom behavior like using recipient email_to to bypass the recipint_ids heuristics in the mail sending mechanism.
  • message_get_reply_to(self, cr, uid, ids, default=None, context=None)
    Returns the preferred reply-to email address that is basically the alias of the document, if it exists.
  • message_get_subscription_data(self, cr, uid, ids, user_pid=None, context=None)
    Wrapper to get subtypes data.
  • message_get_suggested_recipients(self, cr, uid, ids, context=None)
    Returns suggested recipients for ids. Those are a list of tuple (partner_id, partner_name, reason), to be managed by Chatter.
  • message_mark_as_read(self, cr, uid, ids, context=None)
    Set as read.
  • message_mark_as_unread(self, cr, uid, ids, context=None)
    Set as unread.
  • message_new(self, cr, uid, msg_dict, custom_values=None, context=None)
    Called by ``message_process`` when a new message is received for a given thread model, if the message did not belong to an existing thread. The default behavior is to create a new record of the corresponding model (based on some very basic info extracted from the message). Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse`` for details. :param dict custom_values: optional dictionary of additional field values to pass to create() when creating the new thread record. Be careful, these values may override any other values coming from the message. :param dict context: if a ``thread_model`` value is present in the context, its value will be used to determine the model of the record to create (instead of the current model). :rtype: int :return: the id of the newly created thread object
  • message_parse(self, cr, uid, message, save_original=False, context=None)
    Parses a string or email.message.Message representing an RFC-2822 email, and returns a generic dict holding the message details. :param message: the message to parse :type message: email.message.Message | string | unicode :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'from': from, 'to': to, 'cc': cc, 'body': unified_body, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} }
  • message_partner_info_from_emails(self, cr, uid, id, emails, link_mail=False, context=None)
    Convert a list of emails into a list partner_ids and a list new_partner_ids. The return value is non conventional because it is meant to be used by the mail widget. :return dict: partner_ids and new_partner_ids
  • message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', subtype=None, parent_id=False, attachments=None, context=None, content_subtype='html', **kwargs)
    @api.cr_uid_ids_context
    Post a new message in an existing thread, returning the new mail.message ID. :param int thread_id: thread ID to post into, or list with one ID; if False/0, mail.message model will also be set as False :param str body: body of the message, usually raw HTML that will be sanitized :param str type: see mail_message.type field :param str content_subtype:: if plaintext: convert body into html :param int parent_id: handle reply to a previous message by adding the parent partners to the message in case of private discussion :param tuple(str,str) attachments or list id: list of attachment tuples in the form ``(name,content)``, where content is NOT base64 encoded Extra keyword arguments will be used as default column values for the new mail.message record. Special cases: - attachment_ids: supposed not attached to any document; attach them to the related document. Should only be set by Chatter. :return int: ID of newly created mail.message
  • message_process(self, cr, uid, model, message, custom_values=None, save_original=False, strip_attachments=False, thread_id=None, context=None)
    Process an incoming RFC2822 email message, relying on ``mail.message.parse()`` for the parsing operation, and ``message_route()`` to figure out the target model. Once the target model is known, its ``message_new`` method is called with the new message (if the thread record did not exist) or its ``message_update`` method (if it did). There is a special case where the target model is False: a reply to a private message. In this case, we skip the message_new / message_update step, to just post a new message using mail_thread message_post. :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :param message: source of the RFC2822 message :type message: string or xmlrpclib.Binary :type dict custom_values: optional dictionary of field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param bool save_original: whether to keep a copy of the original email source attached to the message after it is imported. :param bool strip_attachments: whether to strip all attachments before processing the message, in order to save some space. :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. When provided, this overrides the automatic detection based on the message headers.
  • 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
  • message_route(self, cr, uid, message, message_dict, model=None, thread_id=None, custom_values=None, context=None)
    Attempt to figure out the correct target model, thread_id, custom_values and user_id to use for an incoming message. Multiple values may be returned, if a message had multiple recipients matching existing mail.aliases, for example. The following heuristics are used, in this order: 1. If the message replies to an existing thread_id, and properly contains the thread model in the 'In-Reply-To' header, use this model/thread_id pair, and ignore custom_value (not needed as no creation will take place) 2. Look for a mail.alias entry matching the message recipient, and use the corresponding model, thread_id, custom_values and user_id. 3. Fallback to the ``model``, ``thread_id`` and ``custom_values`` provided. 4. If all the above fails, raise an exception. :param string message: an email.message instance :param dict message_dict: dictionary holding message variables :param string model: the fallback model to use if the message does not match any of the currently configured mail aliases (may be None if a matching alias is supposed to be present) :type dict custom_values: optional dictionary of default field values to pass to ``message_new`` if a new record needs to be created. Ignored if the thread record already exists, and also if a matching mail.alias was found (aliases define their own defaults) :param int thread_id: optional ID of the record/thread from ``model`` to which this mail should be attached. Only used if the message does not reply to an existing thread and does not match any mail alias. :return: list of [model, thread_id, custom_values, user_id, alias] :raises: ValueError, TypeError
  • message_route_process(self, cr, uid, message, message_dict, routes, context=None)
  • message_route_verify(self, cr, uid, message, message_dict, route, update_author=True, assert_model=True, create_fallback=True, allow_private=False, context=None)
    Verify route validity. Check and rules: 1 - if thread_id -> check that document effectively exists; otherwise fallback on a message_new by resetting thread_id 2 - check that message_update exists if thread_id is set; or at least that message_new exist [ - find author_id if udpate_author is set] 3 - if there is an alias, check alias_contact: 'followers' and thread_id: check on target document that the author is in the followers 'followers' and alias_parent_thread_id: check on alias parent document that the author is in the followers 'partners': check that author_id id set
  • message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None)
    Add partners to the records followers.
  • message_subscribe_users(self, cr, uid, ids, user_ids=None, subtype_ids=None, context=None)
    Wrapper on message_subscribe, using users. If user_ids is not provided, subscribe uid instead.
  • message_track(self, cr, uid, ids, tracked_fields, initial_values, context=None)
  • message_unsubscribe(self, cr, uid, ids, partner_ids, context=None)
    Remove partners from the records followers.
  • message_unsubscribe_users(self, cr, uid, ids, user_ids=None, context=None)
    Wrapper on message_subscribe, using users. If user_ids is not provided, unsubscribe uid instead.
  • message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None)
    Called by ``message_process`` when a new message is received for an existing thread. The default behavior is to update the record with update_vals taken from the incoming email. Additional behavior may be implemented by overriding this method. :param dict msg_dict: a map containing the email details and attachments. See ``message_process`` and ``mail.message.parse()`` for details. :param dict update_vals: a dict containing values to update records given their ids; if the dict is None or is void, no write operation is performed.
  • read_followers_data(self, cr, uid, follower_ids, context=None)
  • unlink(self, cr, uid, ids, context=None)
    Override unlink to delete messages and followers. This cannot be cascaded, because link is done through (res_model, res_id).
  • write(self, cr, uid, ids, values, context=None)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • update_notification(self, cr, uid, ids, cron_mode=True, context=None)
    Send a message to OpenERP's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean

New fields (0)

No new fields.

Public methods (1)
  • write(self, cr, uid, ids, vals, context=None)

New fields (0)

No new fields.

Public methods (2)
  • message_get_default_recipients(self, cr, uid, ids, context=None)
  • message_get_suggested_recipients(self, cr, uid, ids, context=None)

New fields (0)

No new fields.

Public methods (9)
  • copy_data(self, *args, **kwargs)
  • create(self, cr, uid, data, context=None)
  • message_get_partner_info_from_emails(self, cr, uid, emails, link_mail=False, context=None)
  • message_get_suggested_recipients(self, cr, uid, ids, context=None)
  • message_post(self, cr, uid, thread_id, context=None, **kwargs)
    @api.cr_uid_ids_context
    Redirect the posting of message on res.users as a private discussion. This is done because when giving the context of Chatter on the various mailboxes, we do not have access to the current partner_id.
  • message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None)
  • message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None)
  • stop_showing_groups_suggestions(self, cr, uid, user_id, context=None)
    Update display_groups_suggestions value to False
  • unlink(self, cr, uid, ids, context=None)

New fields (0)

No new fields.

Public methods (1)
  • write(self, cr, uid, ids, vals, context=None)
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/7.0/mail
VERSION
VERSION 1.0
CATEGORY
CATEGORYSocial Network
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOpenERP SA
MAINTAINERS
MAINTAINERSOpenERP SA
COMMITTERS
COMMITTERSRaphael Collet, Twinkle Christian (OpenERP), Cecile Tonglet, Rucha (Open ERP), Atul Patel (OpenERP), Jalpesh Patel (OpenERP), Randhir Mayatra (OpenERP), Stephane Wirtel, Odoo Translation Bot, Turkesh Patel (Open ERP), Numerigraphe - Lionel Sausin, Christophe Matthieu, Pinakin Nayi (OpenERP), Harry (OpenERP), Antonin Bourguignon, pankita shah (Open ERP), ajay javiya (OpenERP), Martin Trigaux, Ajay Chauhan (OpenERP), Foram Katharotiya (OpenERP), Bhumika (OpenERP), Purnendu Singh (OpenERP), Saurang Suthar (OpenERP), Fabien Pinckaers, Antony Lesuisse, Bharat Devnani (OpenERP), Saurang Suthar, Olivier Dony, Twinkle (OpenERP), Divyesh Makwana (Open ERP), Thibault Delavallée, Vo Minh Thu, Hardik, Josse Colpaert, pso (OpenERP), Sbh (Openerp), Amit Patel (OpenERP), Launchpad Translations on behalf of openerp, vta vta@openerp.com, Quentin (OpenERP), Kuldeep Joshi (OpenERP), Nimesh (Open ERP), Denis Ledoux, ara@tinyerp.com, Mayur Maheshwari (OpenERP), Jigar Amin - OpenERP, Sanjay Gohel (Open ERP), Alexis de Lattre, help, Fabien Meghazi, niv-openerp, ggh-openerp, Christophe Simonis, Xavier Morel, Jiten (OpenERP), Goffin Simon, Khushboo Bhatt (Open ERP), dle@openerp.com, Bhumi Thakkar (Open ERP), Amit Patel, Frédéric van der Essen, Gilles Major, Ravi Gohil, Chris Biersbach, Hardik Ansodariya, Phil Frost, Nicolas Martinelli, Jigar Amin, Minh Tran, RGA(OpenERP), Paramjit Singh Sahota, Nicolas Lempereur, Jérome Maes, Hiral Patel (OpenERP), Anand Patel (OpenERP), Georges Grogero, Nimesh Contractor (OpenERP), Amit Dodiya (OpenERP), Stefan Rijnhart, nwi-openerp, Thibault Delavallee, Jean-Baptiste Quenot, Jamin Shah (OpenERP), Vishmita Jadeja (openerp)
WEBSITE
WEBSITEhttp://www.openerp.com
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-05 23:43:10
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_setup
    - web_kanban
    - web
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
Business oriented Social Networking
===================================
The Social Networking module provides a unified social network abstraction layer allowing applications to display a complete
communication history on documents with a fully-integrated email and message management system.

It enables the users to read and send messages as well as emails. It also provides a feeds page combined to a subscription mechanism that allows to follow documents and to be constantly updated about recent news.

Main Features
-------------
* Clean and renewed communication history for any OpenERP document that can act as a discussion topic
* Subscription mechanism to be updated about new messages on interesting documents
* Unified feeds page to see recent messages and activity on followed documents
* User communication through the feeds page
* Threaded discussion design on documents
* Relies on the global outgoing mail server - an integrated email management system - allowing to send emails with a configurable scheduler-based processing engine
* Includes an extensible generic email composition assistant, that can turn into a mass-mailing assistant and is capable of interpreting simple *placeholder expressions* that will be replaced with dynamic data when each email is actually sent.
    

Code Analysis

Views touched (24)
XML IDNameModelTypeStatus
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
mail_wizard_invite_form Add Followers mail.wizard.invite form New
view_emails_partner_info_form res.partner.emails.info.inherit res.partner xpath Inherits base.view_partner_form
view_followers_tree mail.followers.tree mail.followers tree New
view_general_configuration_mail_alias_domain base.config.settings.mail.alias base.config.settings xpath Inherits base_setup.view_general_configuration
view_group_form mail.group.form mail.group form New
view_group_kanban mail.group.kanban mail.group kanban New
view_group_search mail.group.search mail.group search New
view_group_tree mail.group.tree mail.group tree New
view_mail_alias_form mail.alias.form mail.alias form New
view_mail_alias_search mail.alias.search mail.alias search New
view_mail_alias_tree mail.alias.tree mail.alias tree New
view_mail_form mail.mail.form mail.mail form New
view_mail_message_subtype_form mail.message.subtype.form mail.message.subtype form New
view_mail_search mail.mail.search mail.mail search New
view_mail_subscription_form mail.followers.form mail.followers form New
view_mail_tree mail.mail.tree mail.mail tree New
view_message_form mail.message.form mail.message form New
view_message_search mail.message.search mail.message search New
view_message_subtype_tree mail.message.subtype.tree mail.message.subtype tree New
view_message_tree mail.message.tree mail.message tree New
view_notification_tree mail.notification.tree mail.notification tree New
view_users_form_mail res.users.form.mail res.users data Inherits base.view_users_form
view_users_form_simple_modif_mail res.users.preferences.form.mail res.users data Inherits base.view_users_form_simple_modif
Models touched (12)

New fields (0)

No new fields.

Public methods (2)
  • get_default_alias_domain(self, cr, uid, ids, context=None)
  • set_alias_domain(self, cr, uid, ids, context=None)

New fields (0)

No new fields.

Public methods (3)
  • create_unique_alias(self, cr, uid, vals, model_name=None, context=None)
    Creates an email.alias record according to the values provided in ``vals``, with 2 alterations: the ``alias_name`` value may be suffixed in order to make it unique (and certain unsafe characters replaced), and he ``alias_model_id`` value will set to the model ID of the ``model_name`` value, if provided,
  • 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)
    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) :param child_table_name: table name of the child class (i.e. res_users) :param child_model_auto_init_fct: pointer to the _auto_init function (i.e. super(res_users,self)._auto_init(cr, context=context)) :param alias_id_column: alias_id column (i.e. self._columns['alias_id']) :param alias_key: name of the column used for the unique name (i.e. 'login') :param alias_prefix: prefix for the unique name (i.e. 'jobs' + ...) :param alias_force_key': name of the column for force_thread_id; if empty string, not taken into account :param alias_defaults: dict, keys = mail.alias columns, values = child model column name used for default values (i.e. {'job_id': 'id'})
  • name_get(self, cr, uid, ids, context=None)
    Return the mail alias display alias_name, inclusing the implicit mail catchall domain from config. e.g. `jobs@openerp.my.openerp.com` or `sales@openerp.my.openerp.com`

New fields (0)

No new fields.

Public methods (7)
  • check_access_rule(self, cr, uid, ids, operation, context=None)
    Access rules of mail.compose.message: - create: if - model, no res_id, I create a message in mass mail mode - then: fall back on mail.message acces rules
  • default_get(self, cr, uid, fields, context=None)
    Handle composition mode. Some details about context keys: - comment: default mode, model and ID of a record the user comments - default_model or active_model - default_res_id or active_id - reply: active_id of a message the user replies to - default_parent_id or message_id or active_id: ID of the mail.message we reply to - message.res_model or default_model - message.res_id or default_res_id - mass_mail: model and IDs of records the user mass-mails - active_ids: record IDs - default_model or active_model
  • get_message_data(self, cr, uid, message_id, context=None)
    Returns a defaults-like dict with initial values for the composition wizard when replying to the given message (e.g. including the quote of the initial message, and the correct recipients). :param int message_id: id of the mail.message to which the user is replying.
  • get_record_data(self, cr, uid, model, res_id, context=None)
    Returns a defaults-like dict with initial values for the composition wizard when sending an email related to the document record identified by ``model`` and ``res_id``. :param str model: model name of the document record this mail is related to. :param int res_id: id of the document record this mail is related to
  • render_message(self, cr, uid, wizard, res_id, context=None)
    Generate an email from the template for given (wizard.model, res_id) pair. This method is meant to be inherited by email_template that will produce a more complete dictionary.
  • render_template(self, cr, uid, template, model, res_id, context=None)
    Render the given template text, replace mako-like expressions ``${expr}`` with the result of evaluating these expressions with an evaluation context containing: * ``user``: browse_record of the current user * ``object``: browse_record of the document record this mail is related to * ``context``: the context passed to the mail composition wizard :param str template: the template text to render :param str model: model name of the document record this mail is related to. :param int res_id: id of the document record this mail is related to.
  • send_mail(self, cr, uid, ids, context=None)
    Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (5)
  • action_follow(self, cr, uid, ids, context=None)
    Wrapper because message_subscribe_users take a user_ids=None that receive the context without the wrapper.
  • action_unfollow(self, cr, uid, ids, context=None)
    Wrapper because message_unsubscribe_users take a user_ids=None that receive the context without the wrapper.
  • create(self, cr, uid, vals, context=None)
  • unlink(self, cr, uid, ids, context=None)
  • write(self, cr, uid, ids, vals, context=None)

New fields (0)

No new fields.

Public methods (15)
  • check_access_rule(self, cr, uid, ids, operation, context=None)
    Access rules of mail.message: - read: if - author_id == pid, uid is the author, OR - mail_notification (id, pid) exists, uid has been notified, OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id, I create a private message OR - pid in message_follower_ids if model, res_id OR - mail_notification (parent_id.id, pid) exists, uid has been notified of the parent, OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid has write or create access on the related document if model, res_id - otherwise: raise - unlink: if - uid has write or create access on the related document if model, res_id - otherwise: raise
  • check_partners_email(self, cr, uid, partner_ids, context=None)
    Verify that selected partner_ids have an email_address defined. Otherwise throw a warning.
  • copy(self, cr, uid, id, default=None, context=None)
    Overridden to avoid duplicating fields that are unique to each email
  • create(self, cr, uid, values, context=None)
  • default_get(self, cr, uid, fields, context=None)
  • download_attachment(self, cr, uid, id_message, attachment_id, context=None)
    Return the content of linked attachments.
  • init(self, cr)
  • message_quote_context(self, cr, uid, id, context=None, limit=3, add_original=False)
    1. message.parent_id = False: new thread, no quote_context 2. get the lasts messages in the thread before message 3. get the message header 4. add an expandable between them :param dict quote_context: options for quoting :return string: html quote
  • message_read(self, cr, uid, ids=None, domain=None, message_unload_ids=None, thread_level=0, context=None, parent_id=False, limit=None)
    Read messages from mail.message, and get back a list of structured messages to be displayed as discussion threads. If IDs is set, fetch these records. Otherwise use the domain to fetch messages. After having fetch messages, their ancestors will be added to obtain well formed threads, if uid has access to them. After reading the messages, expandable messages are added in the message list (see ``_message_read_add_expandables``). It consists in messages holding the 'read more' data: number of messages to read, domain to apply. :param list ids: optional IDs to fetch :param list domain: optional domain for searching ids if ids not set :param list message_unload_ids: optional ids we do not want to fetch, because i.e. they are already displayed somewhere :param int parent_id: context of parent_id - if parent_id reached when adding ancestors, stop going further in the ancestor search - if set in flat mode, ancestor_id is set to parent_id :param int limit: number of messages to fetch, before adding the ancestors and expandables :return list: list of message structure for the Chatter widget
  • name_get(self, cr, uid, ids, context=None)
  • read(self, cr, uid, ids, fields=None, context=None, load='_classic_read')
    Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them.
  • set_message_read(self, cr, uid, msg_ids, read, create_missing=True, context=None)
    Set messages as (un)read. Technically, the notifications related to uid are set to (un)read. If for some msg_ids there are missing notifications (i.e. due to load more or thread parent fetching), they are created. :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
  • set_message_starred(self, cr, uid, msg_ids, starred, create_missing=True, context=None)
    Set messages as (un)starred. Technically, the notifications related to uid are set to (un)starred. :param bool starred: set notification as (un)starred :param bool create_missing: create notifications for missing entries (i.e. when acting on displayed messages not notified)
  • unlink(self, cr, uid, ids, context=None)
  • vote_toggle(self, cr, uid, ids, context=None)
    Toggles vote. Performed using read to avoid access rights issues. Done as SUPERUSER_ID because uid may vote for a message he cannot modify.

New fields (0)

No new fields.

Public methods (2)
  • get_partners_to_notify(self, cr, uid, message, partners_to_notify=None, context=None)
    Return the list of partners to notify, based on their preferences. :param browse_record message: mail.message to notify :param list partners_to_notify: optional list of partner ids restricting the notifications to process
  • init(self, cr)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • write(self, cr, uid, ids, vals, context=None)

New fields (0)

No new fields.

Public methods (2)
  • message_get_suggested_recipients(self, cr, uid, ids, context=None)
  • message_post(self, cr, uid, thread_id, **kwargs)
    Override related to res.partner. In case of email message, set it as private: - add the target partner in the message partner_ids - set thread_id as None, because this will trigger the 'private' aspect of the message (model=False, res_id=False)

New fields (0)

No new fields.

Public methods (10)
  • create(self, cr, uid, data, context=None)
  • message_create_partners_from_emails(self, cr, uid, emails, context=None)
  • message_get_partner_info_from_emails(self, cr, uid, emails, link_mail=False, context=None)
  • message_get_suggested_recipients(self, cr, uid, ids, context=None)
  • message_post(self, cr, uid, thread_id, context=None, **kwargs)
    Redirect the posting of message on res.users to the related partner. This is done because when giving the context of Chatter on the various mailboxes, we do not have access to the current partner_id.
  • message_post_user_api(self, cr, uid, thread_id, context=None, **kwargs)
    Redirect the posting of message on res.users to the related partner. This is done because when giving the context of Chatter on the various mailboxes, we do not have access to the current partner_id.
  • message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None)
  • message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None)
  • unlink(self, cr, uid, ids, context=None)
  • write(self, cr, uid, ids, vals, context=None)

New fields (0)

No new fields.

Public methods (1)
  • write(self, cr, uid, ids, vals, context=None)
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/6.1/mail
VERSION
VERSION 1.0
CATEGORY
CATEGORYHidden/Dependency
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOpenERP SA
MAINTAINERS
MAINTAINERSOpenERP SA
COMMITTERS
COMMITTERSRaphael Collet, Stephane Wirtel, Harry (OpenERP), Fabien Pinckaers, Antony Lesuisse, Olivier Dony, Vo Minh Thu, Launchpad Translations on behalf of openerp, Quentin (OpenERP), Kuldeep Joshi (OpenERP), Xavier ALT, Xavier Morel, Chris Biersbach, Carlos Vásquez, Israel Fermin Montilla, Rifakat Haradwala (Open ERP), tfr@openerp.com, Dhara (OpenERP), Ravi Gohil (Open ERP)
WEBSITE
WEBSITEhttp://www.openerp.com
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-05 23:41:35
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - base
    - base_tools
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
A generic email subsystem with message storage and queuing
==========================================================

This email subsystem is not intended to be used as as standalone
application, but to provide a unified email abstraction that all
other applications can use.

The main features are:

    * Relies on the global Outgoing Mail Servers configured in the 
      Administration menu for delivering outgoing mail
    * Provides an API for sending messages and archiving them,
      grouped by conversation
    * Any OpenERP document can act as a conversation topic, provided
      it includes the necessary support for handling incoming emails
      (see the ``mail.thread`` class for more details). 
    * Includes queuing mechanism with automated configurable
      scheduler-based processing
    * Includes a generic email composition assistant, that can turn
      into a mass-mailing assistant, and is capable of interpreting
      simple *placeholder expressions* that will be replaced with
      dynamic data when each email is actually sent.
      This generic assistant is easily extensible to provide advanced
      features (see ``email_template`` for example, which adds email
      templating features to this assistant)

    

Code Analysis

Views touched (8)
XML IDNameModelTypeStatus
base.view_crm_partner_info_History res.partner.crm.history.inherit1 res.partner xpath Inherits base.view_partner_form
email_compose_message_wizard_form mail.compose.message.form mail.compose.message form New
view_email_message_form mail.message.form mail.message form New
view_email_message_search mail.message.search mail.message search New
view_email_message_tree mail.message.tree mail.message tree New
view_emails_partner_info_form res.partner.emails.info.inherit res.partner page Inherits base.view_partner_form
view_mailgate_thread_form mail.thread.form mail.thread form New
view_mailgate_thread_tree mail.thread.tree mail.thread tree New
Models touched (0)

No models found for this module.