Ejemplo n.º 1
0
 def _lead_create_contact(self,
                          cr,
                          uid,
                          lead,
                          name,
                          is_company,
                          parent_id=False,
                          context=None):
     partner = self.pool.get('res.partner')
     vals = {
         'name': name,
         'user_id': lead.user_id.id,
         'comment': lead.description,
         'section_id': lead.section_id.id or False,
         'parent_id': parent_id,
         'phone': lead.phone,
         'mobile': lead.mobile,
         'email': lead.email_from and tools.email_split(lead.email_from)[0],
         'fax': lead.fax,
         'title': lead.title and lead.title.id or False,
         'function': lead.function,
         'street': lead.street,
         'street2': lead.street2,
         'zip': lead.zip,
         'city': lead.city,
         'country_id': lead.country_id and lead.country_id.id or False,
         'state_id': lead.state_id and lead.state_id.id or False,
         'is_company': is_company,
         'customer': True,
         'supplier': False,
         'type': 'contact',
         'website': lead.website
     }
     partner = partner.create(cr, uid, vals, context=context)
     return partner
Ejemplo n.º 2
0
 def _message_find_user_id(self, cr, uid, message, context=None):
     from_local_part = tools.email_split(decode(message.get('From')))[0]
     # FP Note: canonification required, the minimu: .lower()
     user_ids = self.pool.get('res.users').search(cr, uid, ['|',
         ('login', '=', from_local_part),
         ('email', '=', from_local_part)], context=context)
     return user_ids[0] if user_ids else uid
Ejemplo n.º 3
0
    def 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
        """
        body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context)
        subject = self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context)
        body_alternative = tools.html2plaintext(body)
        email_to = [partner.email] if partner else tools.email_split(mail.email_to)
        return {"body": body, "body_alternative": body_alternative, "subject": subject, "email_to": email_to}
Ejemplo n.º 4
0
    def find_or_create(self, cr, uid, email, context=None):
        """ Find a partner with the given ``email`` or use :py:method:`~.name_create`
            to create one

            :param str email: email-like string, which should contain at least one email,
                e.g. ``"Raoul Grosbedon <*****@*****.**>"``"""
        assert email, 'an email is required for find_or_create to work'
        emails = tools.email_split(email)
        if emails:
            email = emails[0]
        ids = self.search(cr, uid, [('email','ilike',email)], context=context)
        if not ids:
            return self.name_create(cr, uid, email, context=context)[0]
        return ids[0]
 def generate_email_for_composer(self, cr, uid, template_id, res_id, context=None):
     """ Call email_template.generate_email(), get fields relevant for
         mail.compose.message, transform email_cc and email_to into partner_ids """
     template_values = self.pool.get('email.template').generate_email(cr, uid, template_id, res_id, context=context)
     # filter template values
     fields = ['body', 'body_html', 'subject', 'email_to', 'email_cc', 'attachments']
     values = dict((field, template_values[field]) for field in fields if template_values.get(field))
     values['body'] = values.pop('body_html', '')
     # transform email_to, email_cc into partner_ids
     values['partner_ids'] = []
     mails = tools.email_split(values.pop('email_to', '') + ' ' + values.pop('email_cc', ''))
     for mail in mails:
         partner_id = self.pool.get('res.partner').find_or_create(cr, uid, mail, context=context)
         values['partner_ids'].append(partner_id)
     return values
Ejemplo n.º 6
0
    def onchange_email(self, cr, uid, ids, email, context=None):
        context = context or {}
        warning = {}

        if not email:
            return {}

        if not tools.email_split(email):
            warning = {
                'title':
                _('Email Format Warning!'),
                'message':
                _('The email is not well formatted, it should be [email protected]'
                  )
            }

        return {
            'warning': warning,
        }
Ejemplo n.º 7
0
 def _lead_create_contact(self, cr, uid, lead, name, is_company, parent_id=False, context=None):
     partner = self.pool.get('res.partner')
     vals = { 'name': name,
         'user_id': lead.user_id.id,
         'comment': lead.description,
         'section_id': lead.section_id.id or False,
         'parent_id': parent_id,
         'phone': lead.phone,
         'mobile': lead.mobile,
         'email': lead.email_from and tools.email_split(lead.email_from)[0],
         'fax': lead.fax,
         'title': lead.title and lead.title.id or False,
         'function': lead.function,
         'street': lead.street,
         'street2': lead.street2,
         'zip': lead.zip,
         'city': lead.city,
         'country_id': lead.country_id and lead.country_id.id or False,
         'state_id': lead.state_id and lead.state_id.id or False,
         'is_company': is_company,
         'type': 'contact'
     }
     partner = partner.create(cr, uid,vals, context)
     return partner
Ejemplo n.º 8
0
    def do_action(self, cr, uid, action, model_obj, obj, context=None):
        """ Do Action
            @param self: The object pointer
            @param cr: the current row, from the database cursor,
            @param uid: the current user’s ID for security checks,
            @param action: pass action
            @param model_obj: pass Model object
            @param context: A standard dictionary for contextual values """
        if context is None:
            context = {}

        if action.server_action_id:
            context.update({'active_id':obj.id, 'active_ids':[obj.id]})
            self.pool.get('ir.actions.server').run(cr, uid, [action.server_action_id.id], context)
        write = {}

        if hasattr(obj, 'user_id') and action.act_user_id:
            obj.user_id = action.act_user_id
            write['user_id'] = action.act_user_id.id
        if hasattr(obj, 'date_action_last'):
            write['date_action_last'] = time.strftime('%Y-%m-%d %H:%M:%S')
        if hasattr(obj, 'state') and action.act_state:
            obj.state = action.act_state
            write['state'] = action.act_state

        if hasattr(obj, 'categ_id') and action.act_categ_id:
            obj.categ_id = action.act_categ_id
            write['categ_id'] = action.act_categ_id.id

        model_obj.write(cr, uid, [obj.id], write, context)

        if hasattr(model_obj, 'remind_user') and action.act_remind_user:
            model_obj.remind_user(cr, uid, [obj.id], context, attach=action.act_remind_attach)
        if hasattr(model_obj, 'remind_partner') and action.act_remind_partner:
            model_obj.remind_partner(cr, uid, [obj.id], context, attach=action.act_remind_attach)
        if action.act_method:
            getattr(model_obj, 'act_method')(cr, uid, [obj.id], action, context)

        emails = []
        if hasattr(obj, 'user_id') and action.act_mail_to_user:
            if obj.user_id:
                emails.append(obj.user_id.email)

        if action.act_mail_to_watchers:
            emails += (action.act_email_cc or '').split(',')
        if action.act_mail_to_email:
            emails += (action.act_mail_to_email or '').split(',')

        locals_for_emails = {
            'user' : self.pool.get('res.users').browse(cr, uid, uid, context=context),
            'obj' : obj,
        }

        if action.act_email_to:
            emails.append(safe_eval(action.act_email_to, {}, locals_for_emails))

        emails = filter(None, emails)
        if len(emails) and action.act_mail_body:
            emails = list(set(emails))
            email_from = safe_eval(action.act_email_from, {}, locals_for_emails)
            emails = tools.email_split(','.join(filter(None, emails)))
            email_froms = tools.email_split(email_from)
            if email_froms:
                self.email_send(cr, uid, obj, emails, action.act_mail_body, emailfrom=email_froms[0])
        return True
Ejemplo n.º 9
0
# -*- coding: utf-8 -*-
Ejemplo n.º 10
0
    def message_route(self, cr, uid, message, 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 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]
        """
        assert isinstance(message, Message), 'message must be an email.message.Message at this point'
        message_id = message.get('Message-Id')

        # 1. Verify if this is a reply to an existing thread
        references = decode_header(message, 'References') or decode_header(message, 'In-Reply-To')
        ref_match = references and tools.reference_re.search(references)
        if ref_match:
            thread_id = int(ref_match.group(1))
            model = ref_match.group(2) or model
            model_pool = self.pool.get(model)
            if thread_id and model and model_pool and model_pool.exists(cr, uid, thread_id) \
                and hasattr(model_pool, 'message_update'):
                _logger.debug('Routing mail with Message-Id %s: direct reply to model: %s, thread_id: %s, custom_values: %s, uid: %s',
                              message_id, model, thread_id, custom_values, uid)
                return [(model, thread_id, custom_values, uid)]

        # 2. Look for a matching mail.alias entry
        # Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values
        # for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value.
        rcpt_tos = decode_header(message, 'Delivered-To') or \
             ','.join([decode_header(message, 'To'),
                       decode_header(message, 'Cc'),
                       decode_header(message, 'Resent-To'),
                       decode_header(message, 'Resent-Cc')])
        local_parts = [e.split('@')[0] for e in tools.email_split(rcpt_tos)]
        if local_parts:
            mail_alias = self.pool.get('mail.alias')
            alias_ids = mail_alias.search(cr, uid, [('alias_name', 'in', local_parts)])
            if alias_ids:
                routes = []
                for alias in mail_alias.browse(cr, uid, alias_ids, context=context):
                    user_id = alias.alias_user_id.id
                    if not user_id:
                        user_id = self._message_find_user_id(cr, uid, message, context=context)
                    routes.append((alias.alias_model_id.model, alias.alias_force_thread_id, \
                                   eval(alias.alias_defaults), user_id))
                _logger.debug('Routing mail with Message-Id %s: direct alias match: %r', message_id, routes)
                return routes

        # 3. Fallback to the provided parameters, if they work
        model_pool = self.pool.get(model)
        if not thread_id:
            # Legacy: fallback to matching [ID] in the Subject
            match = tools.res_re.search(decode_header(message, 'Subject'))
            thread_id = match and match.group(1)
        assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \
            "No possible route found for incoming message with Message-Id %s. " \
            "Create an appropriate mail.alias or force the destination model." % message_id
        if thread_id and not model_pool.exists(cr, uid, thread_id):
            _logger.warning('Received mail reply to missing document %s! Ignoring and creating new document instead for Message-Id %s',
                            thread_id, message_id)
            thread_id = None
        _logger.debug('Routing mail with Message-Id %s: fallback to model:%s, thread_id:%s, custom_values:%s, uid:%s',
                      message_id, model, thread_id, custom_values, uid)
        return [(model, thread_id, custom_values, uid)]
Ejemplo n.º 11
0
 def _message_find_partners(self, cr, uid, message, header_fields=['From'], context=None):
     """ Find partners related to some header fields of the message. """
     s = ', '.join([decode(message.get(h)) for h in header_fields if message.get(h)])
     return [partner_id for email in tools.email_split(s)
             for partner_id in self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', email)], context=context)]
Ejemplo n.º 12
0
    def send(self, cr, uid, ids, auto_commit=False, recipient_ids=None, 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 list recipient_ids: specific list of res.partner recipients.
                If set, one email is sent to each partner. Its is possible to
                tune the sent email through ``send_get_mail_body`` and ``send_get_mail_subject``.
                If not specified, one email is sent to mail_mail.email_to.
            :return: True
        """
        ir_mail_server = self.pool.get("ir.mail_server")
        for mail in self.browse(cr, uid, ids, context=context):
            try:
                # handle attachments
                attachments = []
                for attach in mail.attachment_ids:
                    attachments.append((attach.datas_fname, base64.b64decode(attach.datas)))
                # specific behavior to customize the send email for notified partners
                email_list = []
                if recipient_ids:
                    for partner in self.pool.get("res.partner").browse(cr, uid, recipient_ids, context=context):
                        email_list.append(self.send_get_email_dict(cr, uid, mail, partner=partner, context=context))
                else:
                    email_list.append(self.send_get_email_dict(cr, uid, mail, context=context))

                # build an RFC2822 email.message.Message object and send it without queuing
                for email in email_list:
                    msg = ir_mail_server.build_email(
                        email_from=mail.email_from,
                        email_to=email.get("email_to"),
                        subject=email.get("subject"),
                        body=email.get("body"),
                        body_alternative=email.get("body_alternative"),
                        email_cc=tools.email_split(mail.email_cc),
                        reply_to=mail.reply_to,
                        attachments=attachments,
                        message_id=mail.message_id,
                        references=mail.references,
                        object_id=mail.res_id and ("%s-%s" % (mail.res_id, mail.model)),
                        subtype="html",
                        subtype_alternative="plain",
                    )
                    res = ir_mail_server.send_email(
                        cr, uid, msg, mail_server_id=mail.mail_server_id.id, context=context
                    )
                if res:
                    mail.write({"state": "sent", "message_id": res})
                else:
                    mail.write({"state": "exception"})
                mail.refresh()
                if mail.state == "sent":
                    self._postprocess_sent_message(cr, uid, mail, context=context)
            except Exception:
                _logger.exception("failed sending mail.mail %s", mail.id)
                mail.write({"state": "exception"})

            if auto_commit == True:
                cr.commit()
        return True