示例#1
0
    def send_get_mail_body(self, partner=None):
        """ Override to add the tracking URL to the body and to add
        Statistic_id in shorted urls """
        # TDE: temporary addition (mail was parameter) due to semi-new-API
        self.ensure_one()
        body = super(MailMail, self).send_get_mail_body(partner=partner)

        links_blacklist = ['/unsubscribe_from_list']

        if self.mailing_id and body and self.statistics_ids:
            for match in re.findall(URL_REGEX, self.body_html):

                href = match[0]
                url = match[1]

                if not [s for s in links_blacklist if s in href]:
                    new_href = href.replace(url, url + '/m/' + str(self.statistics_ids[0].id))
                    body = body.replace(href, new_href)

        # prepend <base> tag for images using absolute urls
        domain = self.env["ir.config_parameter"].get_param("web.base.url")
        base = "<base href='%s'>" % domain
        body = tools.append_content_to_html(base, body, plaintext=False, container_tag='div')
        # resolve relative image url to absolute for outlook.com
        def _sub_relative2absolute(match):
            return match.group(1) + urlparse.urljoin(domain, match.group(2))
        body = re.sub('(<img(?=\s)[^>]*\ssrc=")(/[^/][^"]+)', _sub_relative2absolute, body)
        body = re.sub(r'(<[^>]+\bstyle="[^"]+\burl\(\'?)(/[^/\'][^\'")]+)', _sub_relative2absolute, body)

        # generate tracking URL
        if self.statistics_ids:
            tracking_url = self._get_tracking_url(partner)
            if tracking_url:
                body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div')
        return body
示例#2
0
 def reply_mail(self):
     ctx = {}
     signature = self.env['res.users'].browse(self._uid).signature or ''
     body_html = tools.append_content_to_html('',
                                              signature,
                                              plaintext=False)
     body_html = tools.append_content_to_html(body_html,
                                              self.body_html,
                                              plaintext=False)
     if self.email_from:
         ctx.update({
             'default_email_to': self.email_from,
             'default_subject': "Re: " + self.subject or "/",
             'default_body_html': body_html,
             'default_references': self.message_id,
             'form_view_ref': 'email_management.pop_up_compose_mail',
         })
     return {
         'name': 'Reply Email',
         'view_mode': 'form',
         'view_type': 'form',
         'context': ctx,
         'res_model': 'mail.inbox',
         'type': 'ir.actions.act_window',
         'target': 'new',
         'res_id': False,
     }
示例#3
0
    def send_get_mail_body(self, partner=None):
        """ Override to add the tracking URL to the body and to add
        Statistic_id in shorted urls """
        # TDE: temporary addition (mail was parameter) due to semi-new-API
        self.ensure_one()
        body = super(MailMail, self).send_get_mail_body(partner=partner)

        links_blacklist = ['/unsubscribe_from_list']

        if self.mailing_id and body and self.statistics_ids:
            for match in re.findall(URL_REGEX, self.body_html):

                href = match[0]
                url = match[1]

                if not [s for s in links_blacklist if s in href]:
                    new_href = href.replace(url, url + '/m/' + str(self.statistics_ids[0].id))
                    body = body.replace(href, new_href)

        # prepend <base> tag for images using absolute urls
        domain = self.env["ir.config_parameter"].get_param("web.base.url")
        base = "<base href='%s'>" % domain
        body = tools.append_content_to_html(base, body, plaintext=False, container_tag='div')
        # resolve relative image url to absolute for outlook.com
        def _sub_relative2absolute(match):
            return match.group(1) + urlparse.urljoin(domain, match.group(2))
        body = re.sub('(<img(?=\s)[^>]*\ssrc=")(/[^/][^"]+)', _sub_relative2absolute, body)
        body = re.sub(r'(<[^>]+\bstyle="[^"]+\burl\(\'?)(/[^/\'][^\'")]+)', _sub_relative2absolute, body)

        # generate tracking URL
        if self.statistics_ids:
            tracking_url = self._get_tracking_url(partner)
            if tracking_url:
                body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div')
        return body
    def _send_prepare_body(self):
        """ Override to add the tracking URL to the body and to add
        trace ID in shortened urls """
        # TDE: temporary addition (mail was parameter) due to semi-new-API
        self.ensure_one()
        body = super(MailMail, self)._send_prepare_body()

        if self.mailing_id and body and self.mailing_trace_ids:
            for match in re.findall(tools.URL_REGEX, self.body_html):
                href = match[0]
                url = match[1]

                parsed = werkzeug.urls.url_parse(url, scheme='http')

                if parsed.scheme.startswith('http') and parsed.path.startswith('/r/'):
                    new_href = href.replace(url, url + '/m/' + str(self.mailing_trace_ids[0].id))
                    body = body.replace(href, new_href)

            # generate tracking URL
            tracking_url = self._get_tracking_url()
            body = tools.append_content_to_html(
                body,
                '<img src="%s"/>' % tracking_url,
                plaintext=False,
            )

        body = self.env['mail.render.mixin']._replace_local_links(body)

        return body
示例#5
0
    def _do_notify_email(self, cr, uid, email_pids, message, force_send=False, user_signature=True, context=None):

        # compute email body (signature, company data)
        body_html = message.body
        # add user signature except for mail groups, where users are usually adding their own signatures already
        user_id = message.author_id and message.author_id.user_ids and message.author_id.user_ids[0] and message.author_id.user_ids[0].id or None
        signature_company = self.get_signature_footer(cr, uid, user_id, res_model=message.model, res_id=message.res_id, context=context, user_signature=(user_signature and message.model != 'mail.group'))
        if signature_company:
            body_html = tools.append_content_to_html(body_html, signature_company, plaintext=False, container_tag='div')
        # compute email references
        references = message.parent_id.message_id if message.parent_id else False

        # custom values
        custom_values = dict()
        if message.model and message.res_id and self.pool.get(message.model) and hasattr(self.pool[message.model], 'message_get_email_values'):
            custom_values = self.pool[message.model].message_get_email_values(cr, uid, message.res_id, message, context=context)

        # create email values
        max_recipients = 50
        chunks = [email_pids[x:x + max_recipients] for x in xrange(0, len(email_pids), max_recipients)]
        email_ids = []
        for chunk in chunks:
            mail_values = {
                'mail_message_id': message.id,
                'auto_delete': True,
                'body_html': body_html,
                'recipient_ids': [(4, id) for id in chunk],
                'references': references,
            }
            mail_values.update(custom_values)
            email_ids.append(self.pool.get('mail.mail').create(cr, uid, mail_values, context=context))
        if force_send and len(chunks) < 2:  # for more than 50 followers, use the queue system
            self.pool.get('mail.mail').send(cr, uid, email_ids, context=context)
        return True
示例#6
0
 def test_append_to_html(self):
     test_samples = [
         ('<!DOCTYPE...><HTML encoding="blah">some <b>content</b></HtMl>',
          '--\nYours truly', True, True, False,
          '<!DOCTYPE...><html encoding="blah">some <b>content</b>\n<pre>--\nYours truly</pre>\n</html>'
          ),
         ('<!DOCTYPE...><HTML encoding="blah">some <b>content</b></HtMl>',
          '--\nYours truly', True, False, False,
          '<!DOCTYPE...><html encoding="blah">some <b>content</b>\n<p>--<br/>Yours truly</p>\n</html>'
          ),
         ('<html><body>some <b>content</b></body></html>',
          '--\nYours & <truly>', True, True, False,
          '<html><body>some <b>content</b>\n<pre>--\nYours &amp; &lt;truly&gt;</pre>\n</body></html>'
          ),
         ('<html><body>some <b>content</b></body></html>',
          '<!DOCTYPE...>\n<html><body>\n<p>--</p>\n<p>Yours truly</p>\n</body>\n</html>',
          False, False, False,
          '<html><body>some <b>content</b>\n\n\n<p>--</p>\n<p>Yours truly</p>\n\n\n</body></html>'
          ),
     ]
     for html, content, plaintext_flag, preserve_flag, container_tag, expected in test_samples:
         self.assertEqual(
             append_content_to_html(html, content, plaintext_flag,
                                    preserve_flag, container_tag), expected,
             'append_content_to_html is broken')
示例#7
0
 def send_email(self, options):
     """
     Send by mail the followup to the customer
     """
     partner = self.env['res.partner'].browse(options.get('partner_id'))
     email = self.env['res.partner'].browse(partner.address_get(['invoice'])['invoice']).email
     options['keep_summary'] = True
     if email and email.strip():
         # When printing we need te replace the \n of the summary by <br /> tags
         body_html = self.with_context(print_mode=True, mail=True, lang=partner.lang or self.env.user.lang).get_html(options)
         start_index = body_html.find(b'<span>', body_html.find(b'<div class="o_account_reports_summary">'))
         end_index = start_index > -1 and body_html.find(b'</span>', start_index) or -1
         if end_index > -1:
             replaced_msg = body_html[start_index:end_index].replace(b'\n', b'<br />')
             body_html = body_html[:start_index] + replaced_msg + body_html[end_index:]
         msg = _('Follow-up email sent to %s') % email
         # Remove some classes to prevent interactions with messages
         msg += '<br>' + body_html.decode('utf-8')\
             .replace('o_account_reports_summary', '')\
             .replace('o_account_reports_edit_summary_pencil', '')\
             .replace('fa-pencil', '')
         msg_id = partner.message_post(body=msg)
         email = self.env['mail.mail'].create({
             'mail_message_id': msg_id.id,
             'subject': _('%s Payment Reminder') % (self.env.user.company_id.name) + ' - ' + partner.name,
             'body_html': append_content_to_html(body_html, self.env.user.signature or '', plaintext=False),
             'email_from': self.env.user.email or '',
             'email_to': email,
             'body': msg,
         })
         partner.message_subscribe([partner.id])
         return True
     raise UserError(_('Could not send mail to partner because it does not have any email address defined'))
示例#8
0
 def send_mail_test(self):
     self.ensure_one()
     mails = self.env['mail.mail']
     mailing = self.mass_mailing_id
     test_emails = tools.email_split(self.email_to)
     for test_mail in test_emails:
         # Convert links in absolute URLs before the application of the shortener
         mailing.write({'body_html': self.env['mail.template']._replace_local_links(mailing.body_html)})
         mail_values = {
             'email_from': mailing.email_from,
             'reply_to': mailing.reply_to,
             'email_to': test_mail,
             'subject': mailing.name,
             'body_html': '',
             'notification': True,
             'mailing_id': mailing.id,
             'attachment_ids': [(4, attachment.id) for attachment in mailing.attachment_ids],
         }
         mail = self.env['mail.mail'].create(mail_values)
         unsubscribe_url = mail._get_unsubscribe_url(test_mail)
         body = tools.append_content_to_html(mailing.body_html, unsubscribe_url, plaintext=False, container_tag='p')
         mail.write({'body_html': body})
         mails |= mail
     mails.send()
     return True
示例#9
0
文件: mail_mail.py 项目: EdyKend/odoo
    def _send_prepare_body(self):
        """ Override to add the tracking URL to the body and to add
        Statistic_id in shorted urls """
        # TDE: temporary addition (mail was parameter) due to semi-new-API
        self.ensure_one()
        body = super(MailMail, self)._send_prepare_body()

        if self.mailing_id and body and self.statistics_ids:
            for match in re.findall(URL_REGEX, self.body_html):
                href = match[0]
                url = match[1]

                parsed = werkzeug.urls.url_parse(url, scheme='http')

                if parsed.scheme.startswith('http') and parsed.path.startswith('/r/'):
                    new_href = href.replace(url, url + '/m/' + str(self.statistics_ids[0].id))
                    body = body.replace(href, new_href)

            # generate tracking URL
            tracking_url = self._get_tracking_url()
            if tracking_url:
                body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div')

        body = self.env['mail.thread']._replace_local_links(body)

        return body
 def send_email(self):
     partner = self.env['res.partner'].browse(
         self.partner_id.address_get(['invoice'])['invoice'])
     email = partner.email_collections and partner.email_collections or partner.email
     if email and email.strip():
         email = self.env['mail.mail'].create({
             'subject':
             _('%s Payment Reminder') % (self.env.user.company_id.name) +
             ' - ' + self.partner_id.name,
             'body_html':
             append_content_to_html(self.with_context(
                 public=True, mode='print').get_html(),
                                    self.env.user.signature,
                                    plaintext=False),
             'email_from':
             self.env.user.email or '',
             'email_to':
             email,
         })
         msg = self._get_email_sent_log()
         msg += '<br>' + ustr(
             self.with_context(public=True, mode='print').get_html())
         self.partner_id.message_post(
             body=msg, subtype='account_reports.followup_logged_action')
         return True
     return False
示例#11
0
    def _moderate_send_reject_email(self, subject, comment):
        for message in self:
            if not message.email_from:
                continue

            body_html = append_content_to_html('<div>%s</div>' % ustr(comment),
                                               message.body,
                                               plaintext=False)
            body_html = self.env['mail.render.mixin']._replace_local_links(
                body_html)
            self.env['mail.mail'].sudo().create({
                'author_id':
                self.env.user.partner_id.id,
                'auto_delete':
                True,
                'body_html':
                body_html,
                'email_from':
                self.env.user.email_formatted
                or self.env.company.catchall_formatted,
                'email_to':
                message.email_from,
                'references':
                message.mail_message_id.message_id,
                'subject':
                subject,
                'state':
                'outgoing',
            })
示例#12
0
    def send_get_mail_body(self, partner=None):
        """ Override to add the tracking URL to the body and to add
        Statistic_id in shorted urls """
        # TDE: temporary addition (mail was parameter) due to semi-new-API
        self.ensure_one()
        body = super(MailMail, self).send_get_mail_body(partner=partner)

        if self.mailing_id and body and self.statistics_ids:
            for match in re.findall(URL_REGEX, self.body_html):
                href = match[0]
                url = match[1]

                parsed = werkzeug.urls.url_parse(url, scheme='http')

                if parsed.scheme.startswith('http') and parsed.path.startswith('/r/'):
                    new_href = href.replace(url, url + '/m/' + str(self.statistics_ids[0].id))
                    body = body.replace(href, new_href)

        body = self.env['mail.thread']._replace_local_links(body)

        # generate tracking URL
        if self.statistics_ids:
            tracking_url = self._get_tracking_url(partner)
            if tracking_url:
                body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div')
        return body
 def send_email(self, options):
     partner = self.env['res.partner'].browse(options.get('partner_id'))
     # José Candelas
     # original = email = self.env['res.partner'].browse(partner.address_get(['invoice'])['invoice']).email
     email = partner.email
     if email and email.strip():
         body_html = self.with_context(print_mode=True,
                                       mail=True,
                                       keep_summary=True).get_html(options)
         msg = self.get_post_message(options)
         msg += '<br>' + body_html.decode('utf-8')
         msg_id = partner.message_post(
             body=msg, subtype='account_reports.followup_logged_action')
         email = self.env['mail.mail'].create({
             'mail_message_id':
             msg_id.id,
             'subject':
             _('%s Payment Reminder') % (self.env.user.company_id.name) +
             ' - ' + partner.name,
             'body_html':
             append_content_to_html(body_html,
                                    self.env.user.signature or '',
                                    plaintext=False),
             'email_from':
             self.env.user.email or '',
             'email_to':
             email,
             'body':
             msg,
         })
         return True
     raise UserError(
         _('Could not send mail to partner because it does not have any email address defined'
           ))
示例#14
0
 def _send_prepare_body(self):
     """ Short-circuit parent method for mail groups, replace the default
         footer with one appropriate for mailing-lists."""
     if self.model == 'mail.channel' and self.res_id:
         # no super() call on purpose, no private links that could be quoted!
         channel = self.env['mail.channel'].browse(self.res_id)
         base_url = self.env['ir.config_parameter'].sudo().get_param(
             'web.base.url')
         vals = {
             'maillist':
             _('Mailing-List'),
             'post_to':
             _('Post to'),
             'unsub':
             _('Unsubscribe'),
             'mailto':
             'mailto:%s@%s' % (channel.alias_name, channel.alias_domain),
             'group_url':
             '%s/groups/%s' % (base_url, slug(channel)),
             'unsub_url':
             '%s/groups?unsubscribe' % (base_url, ),
         }
         footer = """_______________________________________________
                     %(maillist)s: %(group_url)s
                     %(post_to)s: %(mailto)s
                     %(unsub)s: %(unsub_url)s
                 """ % vals
         body = tools.append_content_to_html(self.body,
                                             footer,
                                             container_tag='div')
         return body
     else:
         return super(MailMail, self)._send_prepare_body()
示例#15
0
    def 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
        """
        if template_id and composition_mode == 'mass_mail':
            template = self.env['mail.template'].browse(template_id)
            fields = ['subject', 'body_html', 'email_from', 'reply_to', 'mail_server_id']
            values = dict((field, getattr(template, field)) for field in fields if getattr(template, field))
            if template.attachment_ids:
                values['attachment_ids'] = [att.id for att in template.attachment_ids]
            if template.mail_server_id:
                values['mail_server_id'] = template.mail_server_id.id
            if template.user_signature and 'body_html' in values:
                signature = self.env.user.signature
                values['body_html'] = tools.append_content_to_html(values['body_html'], signature, plaintext=False)
            if template.report_template:
                attachment = self.env['ir.attachment']
                attach = self.generate_attachment_from_report(template_id, res_id)
                for attach_fname, attach_datas in attach[res_id].pop('attachments', []):
                    data_attach = {
                        'name': attach_fname,
                        'datas': attach_datas,
                        'datas_fname': attach_fname,
                        'res_model': 'mail.compose.message',
                        'res_id': 0,
                        'type': 'binary',
                    }
                values.setdefault('attachment_ids', list()).append(attachment.create(data_attach).id)

        elif template_id:
            values = self.generate_email_for_composer(template_id, [res_id])[res_id]
            # transform attachments into attachment_ids; not attached to the document because this will
            # be done further in the posting process, allowing to clean database if email not send
            Attachment = self.env['ir.attachment']
            for attach_fname, attach_datas in values.pop('attachments', []):
                data_attach = {
                    'name': attach_fname,
                    'datas': attach_datas,
                    'datas_fname': attach_fname,
                    'res_model': 'mail.compose.message',
                    'res_id': 0,
                    'type': 'binary',  # override default_type from context, possibly meant for another model!
                }
                values.setdefault('attachment_ids', list()).append(Attachment.create(data_attach).id)
        else:
            default_values = self.with_context(default_composition_mode=composition_mode, default_model=model, default_res_id=res_id).default_get(['composition_mode', 'model', 'res_id', 'parent_id', 'partner_ids', 'subject', 'body', 'email_from', 'reply_to', 'attachment_ids', 'mail_server_id'])
            values = dict((key, default_values[key]) for key in ['subject', 'body', 'partner_ids', 'email_from', 'reply_to', 'attachment_ids', 'mail_server_id'] if key in default_values)

        if values.get('body_html'):
            values['body'] = values.pop('body_html')

        # This onchange should return command instead of ids for x2many field.
        # ORM handle the assignation of command list on new onchange (api.v8),
        # this force the complete replacement of x2many field with
        # command and is compatible with onchange api.v7
        values = self._convert_to_write(values)

        return {'value': values}
 def tracking_img_add(self, email):
     self.ensure_one()
     tracking_url = self._get_mail_tracking_img()
     if tracking_url:
         body = tools.append_content_to_html(
             email.get('body', ''), tracking_url, plaintext=False,
             container_tag='div')
         email['body'] = body
     return email
示例#17
0
    def 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
        """
        if template_id and composition_mode == 'mass_mail':

            template = self.env['mail.template'].browse(template_id)
            print('-------------', template)
            fields = [
                'subject', 'body_html', 'email_from', 'reply_to',
                'mail_server_id'
            ]
            values = dict((field, getattr(template, field)) for field in fields
                          if getattr(template, field))
            if template.attachment_ids:
                values['attachment_ids'] = [
                    att.id for att in template.attachment_ids
                ]
            if template.mail_server_id:
                values['mail_server_id'] = template.mail_server_id.id
            if template.user_signature and 'body_html' in values:
                signature = self.env.user.signature
                values['body_html'] = tools.append_content_to_html(
                    values['body_html'], signature, plaintext=False)
        elif template_id:

            values = self.generate_email_for_composer(template_id,
                                                      [res_id])[res_id]
            print('-----------onchange_template_id in else condition')

        else:
            default_values = self.with_context(
                default_composition_mode=composition_mode,
                default_model=model,
                default_res_id=res_id).default_get([
                    'composition_mode', 'model', 'res_id', 'parent_id',
                    'partner_ids', 'subject', 'body', 'email_from', 'reply_to',
                    'attachment_ids', 'mail_server_id'
                ])
            values = dict((key, default_values[key]) for key in [
                'subject', 'body', 'partner_ids', 'email_from', 'reply_to',
                'attachment_ids', 'mail_server_id'
            ] if key in default_values)

        if values.get('body_html'):
            values['body'] = values.pop('body_html')

        # This onchange should return command instead of ids for x2many field.
        # ORM handle the assignation of command list on new onchange (api.v8),
        # this force the complete replacement of x2many field with
        # command and is compatible with onchange api.v7
        values = self._convert_to_write(values)

        return {'value': values}
示例#18
0
    def _notify_members(self, message):
        """Send the given message to all members of the mail group (except the author)."""
        self.ensure_one()

        if message.mail_group_id != self:
            raise UserError(_('The group of the message do not match.'))

        if not message.mail_message_id.reply_to:
            _logger.error('The alias or the catchall domain is missing, group might not work properly.')

        base_url = self.get_base_url()
        body = self.env['mail.render.mixin']._replace_local_links(message.body)
        access_token = self._generate_group_access_token()
        mail_values = []
        for batch_members in tools.split_every(GROUP_SEND_BATCH_SIZE, self.member_ids):
            for member in batch_members:
                if member.email_normalized == message.email_from_normalized:
                    # Do not send the email to his author
                    continue

                # SMTP headers related to the subscription
                email_url_encoded = urls.url_quote(member.email_normalized)
                headers = {
                    'List-Archive': f'<{base_url}/groups/{slug(self)}>',
                    'List-Subscribe': f'<{base_url}/groups?email={email_url_encoded}>',
                    'List-Unsubscribe': f'<{base_url}/groups?unsubscribe&email={email_url_encoded}>',
                }

                # Add the footer (member specific) in the body
                template_values = {
                    'mailto': f'{self.alias_name}@{self.alias_domain}',
                    'group_url': f'{base_url}/groups/{slug(self)}',
                    'unsub_url':  f'{base_url}/groups?unsubscribe&group_id={self.id}&token={access_token}'
                }
                template = self.env.ref('mail_group.mail_group_footer')
                footer = template._render(template_values, engine='ir.qweb', minimal_qcontext=True)
                member_body = tools.append_content_to_html(body, footer)

                mail_values.append({
                    'auto_delete': True,
                    'attachment_ids': message.attachment_ids.ids,
                    'body_html': member_body,
                    'email_from': message.email_from,
                    'email_to': member.email,
                    'headers': json.dumps(headers),
                    'mail_message_id': message.mail_message_id.id,
                    'message_id': message.mail_message_id.message_id,
                    'model': 'mail.group',
                    'reply_to': message.mail_message_id.reply_to,
                    'res_id': self.id,
                    'subject': message.subject,
                })

            if mail_values:
                self.env['mail.mail'].sudo().create(mail_values)
示例#19
0
文件: test_mail.py 项目: 10537/odoo
 def test_append_to_html(self):
     test_samples = [
         ('<!DOCTYPE...><HTML encoding="blah">some <b>content</b></HtMl>', '--\nYours truly', True, True, False,
          '<!DOCTYPE...><html encoding="blah">some <b>content</b>\n<pre>--\nYours truly</pre>\n</html>'),
         ('<!DOCTYPE...><HTML encoding="blah">some <b>content</b></HtMl>', '--\nYours truly', True, False, False,
          '<!DOCTYPE...><html encoding="blah">some <b>content</b>\n<p>--<br/>Yours truly</p>\n</html>'),
         ('<html><body>some <b>content</b></body></html>', '<!DOCTYPE...>\n<html><body>\n<p>--</p>\n<p>Yours truly</p>\n</body>\n</html>', False, False, False,
          '<html><body>some <b>content</b>\n\n\n<p>--</p>\n<p>Yours truly</p>\n\n\n</body></html>'),
     ]
     for html, content, plaintext_flag, preserve_flag, container_tag, expected in test_samples:
         self.assertEqual(append_content_to_html(html, content, plaintext_flag, preserve_flag, container_tag), expected, 'append_content_to_html is broken')
示例#20
0
    def generate_sms(self, res_ids, fields=None):
        self.ensure_one()
        multi_mode = True
        if isinstance(res_ids, pycompat.integer_types):
            res_ids = [res_ids]
            multi_mode = False
        if fields is None:
            fields = ['body_html']

        res_ids_to_templates = self.get_email_template(res_ids)
        # templates: res_id -> template; template -> res_ids
        templates_to_res_ids = {}
        for res_id, template in res_ids_to_templates.items():
            templates_to_res_ids.setdefault(template, []).append(res_id)

        results = dict()
        for template, template_res_ids in templates_to_res_ids.items():
            Template = self.env['sms.template']
            # generate fields value for all res_ids linked to the current template
            if template.lang:
                Template = Template.with_context(
                    lang=template._context.get('lang')
                )
            for field in fields:
                Template = Template.with_context(safe=field in {'subject'})
                generated_field_values = Template._render_template(
                    getattr(template, field), template.model, template_res_ids,
                    post_process=(field == 'body_html'))
                for res_id, field_value in generated_field_values.items():
                    results.setdefault(res_id, dict())[field] = field_value
            # update values for all res_ids
            for res_id in template_res_ids:
                values = results[res_id]
                # body: add user signature, sanitize
                if 'body_html' in fields and template.user_signature:
                    signature = self.env.user.signature
                    if signature:
                        values['body_html'] = tools.append_content_to_html(
                            values['body_html'],
                            signature,
                            plaintext=False
                        )
                if values.get('body_html'):
                    values['message'] = tools.html_sanitize(
                        values['body_html']
                    )
                # technical settings
                values.update(
                    model=template.model,
                    res_id=res_id or False,
                )

        return multi_mode and results or results[res_ids[0]]
    def send_message_on_whatsapp(self):
        Param = self.env['res.config.settings'].sudo().get_values()
        res_partner_id = self.env['res.partner'].search([('id', '=', self.user_id.partner_id.id)])
        res_user_id = self.env['res.users'].search([('id', '=', self.env.user.id)])
        if res_partner_id.country_id.phone_code and res_partner_id.mobile:
            msg = ''
            if self.project_id.name:
                msg += "*Project:* "+self.project_id.name
            if self.name:
                msg += "\n*Task name:* "+self.name
            if self.date_deadline:
                msg+= "\n*Deadline:* "+str(self.date_deadline)
            if len(self.description) > 11:
                msg += "\n*Description:* "+self.cleanhtml(self.description)
            msg = "Hello " + res_partner_id.name + "," + "\nNew task assigned to you" + "\n" + msg

            # msg = "Hello " + res_partner_id.name+","+ "\nNew task assigned to you"+"\n"+"*Project:* "+self.project_id.name+"\n*Task name:* "+self.name+"\n*Deadline:* "+str(
            #     self.date_deadline)+"\n*Description:* "+self.cleanhtml(self.description)
            if res_user_id.has_group('pragmatic_odoo_whatsapp_integration.group_project_enable_signature'):
                user_signature = self.cleanhtml(res_user_id.signature)
                msg += "\n\n" + user_signature

            url = 'https://api.chat-api.com/instance' + Param.get('whatsapp_instance_id') + '/sendMessage?token=' + Param.get('whatsapp_token')
            headers = {
                "Content-Type": "application/json",
            }
            whatsapp_msg_number = res_partner_id.mobile
            whatsapp_msg_number_without_space = whatsapp_msg_number.replace(" ", "");
            whatsapp_msg_number_without_code = whatsapp_msg_number_without_space.replace('+' + str(res_partner_id.country_id.phone_code), "")
            tmp_dict = {
                # "phone": "+" + str(res_partner_id.country_id.phone_code) + "" + res_partner_id.mobile,
                "phone": "+" + str(res_partner_id.country_id.phone_code) + "" + whatsapp_msg_number_without_code,
                # "body": "Hello "+res_partner_id.name+","+ "\nNew task assigned to you"+"\n"+"*"+"Project:"+"*"+self.project_id.name
               "body": msg

            }
            response = requests.post(url, json.dumps(tmp_dict), headers=headers)

            if response.status_code == 201 or response.status_code == 200:
                _logger.info("\nSend Message successfully")
                response_dict = response.json()
                self.whatsapp_msg_id = response_dict.get('id')
                mail_message_obj = self.env['mail.message']
                comment = "fa fa-whatsapp"
                body_html = tools.append_content_to_html('<div class = "%s"></div>' % tools.ustr(comment), msg)
                body_msg = self.convert_to_html(body_html)

                if self.env['ir.config_parameter'].sudo().get_param('pragmatic_odoo_whatsapp_integration.group_project_display_chatter_message'):
                    mail_message_id = mail_message_obj.sudo().create({
                        'res_id': self.id,
                        'model': 'project.task',
                        'body': body_msg,
                    })
 def onchange_template_id(self, template_id, composition_mode, model, res_id):
     """
     Append the quote of previous e-mail to the body of the message.
     """
     result = super().onchange_template_id(
         template_id, composition_mode, model, res_id
     )
     reply_quote = self.env.context.get("reply_quote")
     if reply_quote:
         result["value"]["body"] = append_content_to_html(
             result["value"]["body"], "<br/><br/>" + reply_quote, plaintext=False
         )
     return result
示例#23
0
 def tracking_img_add(self, email):
     self.ensure_one()
     tracking_url = self._get_mail_tracking_img()
     if tracking_url:
         content = email.get('body', '')
         content = re.sub(
             r'<img[^>]*data-odoo-tracking-email=["\'][0-9]*["\'][^>]*>',
             '', content)
         body = tools.append_content_to_html(
             content, tracking_url, plaintext=False,
             container_tag='div')
         email['body'] = body
     return email
示例#24
0
 def onchange_template_id(self, template_id, composition_mode, model,
                          res_id):
     """
     Append the quote of previous e-mail to the body of the message.
     """
     result = super(MailComposer, self).onchange_template_id(
         template_id, composition_mode, model, res_id
     )
     reply_quote = self.env.context.get('reply_quote')
     if reply_quote:
         result['value']['body'] = append_content_to_html(
             result['value']['body'],
             '<br/><br/>' + reply_quote, plaintext=False)
     return result
示例#25
0
    def send_email(self, options):
        if options and "partner_id" in options:
            partner_id = self.env['res.partner'].browse(
                options.get('partner_id'))
            email = self.env['res.partner'].browse(
                partner_id.address_get(['invoice'])['invoice']).email
            if email and email.strip():
                # Get report lines, containing invoice number
                lines = self.env['account.followup.report'].with_context(
                    lang=partner_id.lang, public=True).get_lines(options)
                ids = []
                for line in lines:
                    if line['name'] == '':
                        continue
                    if line['action'][1]:
                        ids.append(line['action'][1])

                #Get all invoices related to numbers then browse it.
                invoices = self.env['account.invoice'].search([('id', 'in',
                                                                ids)])
                for invoice in invoices:
                    # Create ir.attachment and PDF for invoice when it doesn't exists
                    pdf = self.env.ref(
                        'account.account_invoices').sudo().render_qweb_pdf(
                            [invoice.id])[0]
                attachments = self.env['ir.attachment'].search([
                    ('res_id', 'in', invoices.mapped('id')),
                    ('res_model', '=', "account.invoice")
                ]).mapped('id')

                # Attach to all related PDF to email
                email = self.env['mail.mail'].create({
                    'subject':
                    _('%s Payment Reminder') % self.env.user.company_id.name,
                    'body_html':
                    append_content_to_html(self.with_context(
                        public=True, mode='print').get_html(options),
                                           self.env.user.signature,
                                           plaintext=False),
                    'email_from':
                    self.env.user.email or '',
                    'email_to':
                    email,
                    'attachment_ids': [(6, 0, attachments)]
                })
                msg = _(': Sent a followup email')
                partner_id.message_post(
                    body=msg, subtype='account_reports.followup_logged_action')
                return True
        return False
示例#26
0
    def 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
        """
        if template_id and composition_mode == 'mass_mail':
            template = self.env['mail.template'].browse(template_id)
            fields = ['subject', 'body_html', 'email_from', 'reply_to', 'mail_server_id']
            values = dict((field, getattr(template, field)) for field in fields if getattr(template, field))
            if template.attachment_ids:
                values['attachment_ids'] = [att.id for att in template.attachment_ids]
            if template.mail_server_id:
                values['mail_server_id'] = template.mail_server_id.id
            if template.user_signature and 'body_html' in values:
                signature = self.env.user.signature
                values['body_html'] = tools.append_content_to_html(values['body_html'], signature, plaintext=False)
        elif template_id:
            values = self.generate_email_for_composer(template_id, [res_id])[res_id]
            # transform attachments into attachment_ids; not attached to the document because this will
            # be done further in the posting process, allowing to clean database if email not send
            attachment_ids = []
            Attachment = self.env['ir.attachment']
            for attach_fname, attach_datas in values.pop('attachments', []):
                data_attach = {
                    'name': attach_fname,
                    'datas': attach_datas,
                    'datas_fname': attach_fname,
                    'res_model': 'mail.compose.message',
                    'res_id': 0,
                    'type': 'binary',  # override default_type from context, possibly meant for another model!
                }
                attachment_ids.append(Attachment.create(data_attach).id)
            if values.get('attachment_ids', []) or attachment_ids:
                values['attachment_ids'] = [(5,)] + values.get('attachment_ids', []) + attachment_ids
        else:
            default_values = self.with_context(default_composition_mode=composition_mode, default_model=model, default_res_id=res_id).default_get(['composition_mode', 'model', 'res_id', 'parent_id', 'partner_ids', 'subject', 'body', 'email_from', 'reply_to', 'attachment_ids', 'mail_server_id'])
            values = dict((key, default_values[key]) for key in ['subject', 'body', 'partner_ids', 'email_from', 'reply_to', 'attachment_ids', 'mail_server_id'] if key in default_values)

        if values.get('body_html'):
            values['body'] = values.pop('body_html')

        # This onchange should return command instead of ids for x2many field.
        # ORM handle the assignation of command list on new onchange (api.v8),
        # this force the complete replacement of x2many field with
        # command and is compatible with onchange api.v7
        values = self._convert_to_write(values)

        return {'value': values}
    def onchange_template_id(self):

        template = self.env['mail.template'].browse(self.template_id.id)

        if template:
            attributes = ['subject', 'body_html', 'email_from']
            values = dict((attribute, getattr(template, attribute))
                          for attribute in attributes
                          if getattr(template, attribute))

            if template.user_signature and 'body_html' in values:
                signature = self.env.user.signature
                values['body_html'] = tools.append_content_to_html(
                    values['body_html'], signature, plaintext=False)

        return values
示例#28
0
    def test_clean_email_body(self):
        template = self.env.ref('mail_group.mail_group_footer')
        footer = template._render({'group_url': 'Test remove footer'},
                                  engine='ir.qweb',
                                  minimal_qcontext=True)
        body = append_content_to_html("<div>Test email body</div>",
                                      footer,
                                      plaintext=False)

        result = self.env['mail.group']._clean_email_body(body)
        self.assertIn('Test email body', result,
                      'Should have kept the original email body')
        self.assertNotIn('Test remove footer', result,
                         'Should have removed the mailing list footer')
        self.assertNotIn('o_mg_message_footer', result,
                         'Should have removed the entire HTML element')
示例#29
0
 def check_template_change(self):
     """ - mass_mailing: we cannot render, so return the template values
         - normal mode: return rendered values """
     if self.template_id and self.template_id.id:
         self.subject = self.template_id.subject
         self.body_html = self.template_id.body_html
         self.reply_to = self.template_id.reply_to
         self.mail_server_id = self.template_id.mail_server_id
         if self.template_id.attachment_ids:
             self.attachment_ids = [att.id for att in template.attachment_ids]
         if self.template_id.mail_server_id:
             self.mail_server_id = self.template_id.mail_server_id.id
         if self.template_id.user_signature and self.body_html:
             signature = self.env['res.users'].browse(self._uid).signature
             self.body = tools.append_content_to_html(self.body, signature, plaintext=False)
     else:
         if not self.body_html:
             signature = self.env['res.users'].browse(self._uid).signature
             self.body_html = signature
示例#30
0
 def get_body_html(self, options):
     partner = self.env['res.partner'].browse(options.get('partner_id'))
     options['keep_summary'] = True
     body_html = self.with_context(print_mode=True, mail=True, lang=partner.lang or self.env.user.lang).get_html(options)    
     body = append_content_to_html(body_html, self.env.user.signature or '', plaintext=False)
     body = body.replace("<thead>", "<tbody>")
     body = body.replace("</thead>", "</tbody>")
     body = body.replace("<th>", "<td>")
     body = body.replace("</th>", "</td>")
     body = body.replace("<thead", "<tbody")
     body = body.replace("<th", "<td")
     template = self.env.ref('fal_customer_statement.email_subject_fal_customer_statement')
     template.sudo().write({'body_html': body})
     res = {
         'default_partner_ids': [partner.id],
         'default_template_id': template.id,
         'default_model' : 'account.followup.report',
     }
     return res
示例#31
0
 def send_get_mail_body(self, partner=None):
     """ add a signin link inside the body of a mail.mail
         :param mail: mail.mail browse_record
         :param partner: browse_record of the specific recipient partner
         :return: the resulting body_html
     """
     partner_obj = self.env['res.partner']
     body = self.body_html
     if partner:
         self = self.with_context(signup_valid=True)
         partner = partner_obj.sudo().browse(partner.id)
         text = _(
             """<p>Access your messages and personal documents through <a href="%s">our Customer Portal</a></p>"""
         ) % partner.signup_url
         # partner is an user: add a link to the document if read access
         if partner.user_ids and self.model and self.res_id \
                 and self.check_access_rights('read', raise_exception=False):
             related_user = partner.user_ids[0]
             try:
                 self.env[self.model].check_access_rule('read')
                 if 'Your timesheet is pending' in body:
                     url = partner.with_context(
                         signup_valid=True
                     )._get_signup_url_for_action(
                         action=
                         'bista_iugroup.action_event_user_form_timesheet_language',
                         res_id=self.res_id,
                         view_type='form',
                         model=self.model)[partner.id]
                 else:
                     url = partner.with_context(
                         signup_valid=True)._get_signup_url_for_action(
                             action='',
                             res_id=self.res_id,
                             view_type='form',
                             model=self.model)[partner.id]
                 text = _(
                     """<p>Access this document <a href="%s">directly in IUX</a></p>"""
                 ) % url
             except Exception, e:
                 pass
         body = tools.append_content_to_html(
             body, ("<div><p>%s</p></div>" % text), plaintext=False)
示例#32
0
 def create(self, vals):
     action = super().create(vals)
     commercial_partner = self.env['res.partner'].browse(
         vals['commercial_partner_id'])
     xmlid = 'account_invoice_overdue_reminder.'\
             'overdue_invoice_reminder_mail_template'
     mail_tpl = self.env.ref(xmlid)
     mail_tpl_lang = mail_tpl.with_context(lang=commercial_partner.lang or 'en_US')
     mail_subject = mail_tpl_lang._render_template(
         mail_tpl_lang.subject, self._name, action.id)
     mail_body = mail_tpl_lang._render_template(
         mail_tpl_lang.body_html, self._name, action.id)
     if mail_tpl.user_signature:
         signature = self.env.user.signature
         if signature:
             mail_body = tools.append_content_to_html(
                 mail_body, signature, plaintext=False)
     mail_body = tools.html_sanitize(mail_body)
     action.write({
         'mail_subject': mail_subject,
         'mail_body': mail_body,
         })
     return action
示例#33
0
    def send_email(self, options):

        partner = self.env['res.partner'].browse(options.get('partner_id'))
        email = self.env['res.partner'].browse(partner.address_get(['invoice'])['invoice']).email
        template = self.env.ref('customer_statement_email.email_sustomer_statements')
        template_obj = self.env['mail.template']
        mail_mail_obj = self.env['mail.mail']
        attachment_obj = self.env['ir.attachment']
        if email and email.strip():
            values = template.generate_email(partner.id)
            atta_id = ''
            for attachment in values.get('attachments', []):
                attachment_data = {
                    'name': partner.name + ' Customer Statement',
                    'datas_fname': partner.name + " Customer Statement.pdf",
                    'datas': attachment[1],
                    'res_model': 'res.partner',
                    'res_id': partner.id
                }
                atta_id = (attachment_obj.create(attachment_data).id)
            body_html = self.with_context(print_mode=True, mail=True, keep_summary=True).get_html(options)
            html_body = b'<style>table {display:none}</style>'
            body_html = html_body + body_html
            msg = _('Follow-up email sent to %s') % email
            msg += '<br>' + body_html.decode('utf-8')
            msg_id = partner.message_post(body=msg, subtype='account_reports.followup_logged_action')
            msg_id.write({'attachment_ids': [(6, 0, [atta_id])]})
            email = self.env['mail.mail'].with_context(default_mail_message_id=msg_id).create({
                'subject': _('%s Customer Statement') % (self.env.user.company_id.name) + ' - ' + partner.name,
                'body_html': append_content_to_html(body_html, self.env.user.signature or '', plaintext=False),
                'email_from': self.env.user.email or '',
                'email_to': email,
                'body': msg,
            })
            return True
        raise UserError(_('Could not send mail to partner because it does not have any email address defined'))
示例#34
0
 def send_get_mail_body(self, partner=None):
     """ Short-circuit parent method for mail groups, replace the default
         footer with one appropriate for mailing-lists."""
     if self.model == 'mail.channel' and self.res_id:
         # no super() call on purpose, no private links that could be quoted!
         channel = self.env['mail.channel'].browse(self.res_id)
         base_url = self.env['ir.config_parameter'].get_param('web.base.url')
         vals = {
             'maillist': _('Mailing-List'),
             'post_to': _('Post to'),
             'unsub': _('Unsubscribe'),
             'mailto': 'mailto:%s@%s' % (channel.alias_name, channel.alias_domain),
             'group_url': '%s/groups/%s' % (base_url, slug(channel)),
             'unsub_url': '%s/groups?unsubscribe' % (base_url,),
         }
         footer = """_______________________________________________
                     %(maillist)s: %(group_url)s
                     %(post_to)s: %(mailto)s
                     %(unsub)s: %(unsub_url)s
                 """ % vals
         body = tools.append_content_to_html(self.body, footer, container_tag='div')
         return body
     else:
         return super(MailMail, self).send_get_mail_body(partner=partner)
示例#35
0
    def 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 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.
        """
        self.ensure_one()
        multi_mode = True
        if isinstance(res_ids, (int, long)):
            res_ids = [res_ids]
            multi_mode = False
        if fields is None:
            fields = [
                "subject",
                "body_html",
                "email_from",
                "email_to",
                "partner_to",
                "email_cc",
                "reply_to",
                "scheduled_date",
            ]

        res_ids_to_templates = self.get_email_template(res_ids)

        # templates: res_id -> template; template -> res_ids
        templates_to_res_ids = {}
        for res_id, template in res_ids_to_templates.iteritems():
            templates_to_res_ids.setdefault(template, []).append(res_id)

        results = dict()
        for template, template_res_ids in templates_to_res_ids.iteritems():
            Template = self.env["mail.template"]
            # generate fields value for all res_ids linked to the current template
            if template.lang:
                Template = Template.with_context(lang=template._context.get("lang"))
            for field in fields:
                Template = Template.with_context(safe=field in {"subject"})
                generated_field_values = Template.render_template(
                    getattr(template, field), template.model, template_res_ids, post_process=(field == "body_html")
                )
                for res_id, field_value in generated_field_values.iteritems():
                    results.setdefault(res_id, dict())[field] = field_value
            # compute recipients
            if any(field in fields for field in ["email_to", "partner_to", "email_cc"]):
                results = template.generate_recipients(results, template_res_ids)
            # update values for all res_ids
            for res_id in template_res_ids:
                values = results[res_id]
                # body: add user signature, sanitize
                if "body_html" in fields and template.user_signature:
                    signature = self.env.user.signature
                    if signature:
                        values["body_html"] = tools.append_content_to_html(
                            values["body_html"], signature, plaintext=False
                        )
                if values.get("body_html"):
                    values["body"] = tools.html_sanitize(values["body_html"])
                # technical settings
                values.update(
                    mail_server_id=template.mail_server_id.id or False,
                    auto_delete=template.auto_delete,
                    model=template.model,
                    res_id=res_id or False,
                    attachment_ids=[attach.id for attach in template.attachment_ids],
                )

            # Add report in attachments: generate once for all template_res_ids
            if template.report_template and not "report_template_in_attachment" in self.env.context:
                for res_id in template_res_ids:
                    attachments = []
                    report_name = self.render_template(template.report_name, template.model, res_id)
                    report = template.report_template
                    report_service = report.report_name

                    if report.report_type in ["qweb-html", "qweb-pdf"]:
                        result, format = Template.env["report"].get_pdf([res_id], report_service), "pdf"
                    else:
                        result, format = odoo_report.render_report(
                            self._cr, self._uid, [res_id], report_service, {"model": template.model}, Template._context
                        )

                    # TODO in trunk, change return format to binary to match message_post expected format
                    result = base64.b64encode(result)
                    if not report_name:
                        report_name = "report." + report_service
                    ext = "." + format
                    if not report_name.endswith(ext):
                        report_name += ext
                    attachments.append((report_name, result))
                    results[res_id]["attachments"] = attachments

        return multi_mode and results or results[res_ids[0]]
示例#36
0
    def 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 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.
        """
        self.ensure_one()
        multi_mode = True
        if isinstance(res_ids, pycompat.integer_types):
            res_ids = [res_ids]
            multi_mode = False
        if fields is None:
            fields = [
                'subject', 'body_html', 'email_from', 'email_to', 'partner_to',
                'email_cc', 'reply_to', 'scheduled_date'
            ]

        res_ids_to_templates = self.get_email_template(res_ids)

        # templates: res_id -> template; template -> res_ids
        templates_to_res_ids = {}
        for res_id, template in res_ids_to_templates.items():
            templates_to_res_ids.setdefault(template, []).append(res_id)

        results = dict()
        for template, template_res_ids in templates_to_res_ids.items():
            Template = self.env['mail.template']
            # generate fields value for all res_ids linked to the current template
            if template.lang:
                Template = Template.with_context(
                    lang=template._context.get('lang'))
            for field in fields:
                Template = Template.with_context(safe=field in {'subject'})
                generated_field_values = Template.render_template(
                    getattr(template, field),
                    template.model,
                    template_res_ids,
                    post_process=(field == 'body_html'))
                for res_id, field_value in generated_field_values.items():
                    results.setdefault(res_id, dict())[field] = field_value
            # compute recipients
            if any(field in fields
                   for field in ['email_to', 'partner_to', 'email_cc']):
                results = template.generate_recipients(results,
                                                       template_res_ids)
            # update values for all res_ids
            for res_id in template_res_ids:
                values = results[res_id]
                # body: add user signature, sanitize
                if 'body_html' in fields and template.user_signature:
                    signature = self.env.user.signature
                    if signature:
                        values['body_html'] = tools.append_content_to_html(
                            values['body_html'], signature, plaintext=False)
                if values.get('body_html'):
                    values['body'] = tools.html_sanitize(values['body_html'])
                # technical settings
                values.update(
                    mail_server_id=template.mail_server_id.id or False,
                    auto_delete=template.auto_delete,
                    model=template.model,
                    res_id=res_id or False,
                    attachment_ids=[
                        attach.id for attach in template.attachment_ids
                    ],
                )

            # Add report in attachments: generate once for all template_res_ids
            if template.report_template:
                for res_id in template_res_ids:
                    attachments = []
                    report_name = self.render_template(template.report_name,
                                                       template.model, res_id)
                    report = template.report_template
                    report_service = report.report_name

                    if report.report_type not in ['qweb-html', 'qweb-pdf']:
                        raise UserError(
                            _('Unsupported report type %s found.') %
                            report.report_type)
                    result, format = report.render_qweb_pdf([res_id])

                    # TODO in trunk, change return format to binary to match message_post expected format
                    result = base64.b64encode(result)
                    if not report_name:
                        report_name = 'report.' + report_service
                    ext = "." + format
                    if not report_name.endswith(ext):
                        report_name += ext
                    attachments.append((report_name, result))
                    results[res_id]['attachments'] = attachments

        return multi_mode and results or results[res_ids[0]]
示例#37
0
    def 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.
        """
        self.ensure_one()
        multi_mode = True
        if isinstance(res_ids, pycompat.integer_types):
            res_ids = [res_ids]
            multi_mode = False
        if fields is None:
            fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'scheduled_date']

        res_ids_to_templates = self.get_email_template(res_ids)

        # templates: res_id -> template; template -> res_ids
        templates_to_res_ids = {}
        for res_id, template in res_ids_to_templates.items():
            templates_to_res_ids.setdefault(template, []).append(res_id)

        results = dict()
        for template, template_res_ids in templates_to_res_ids.items():
            Template = self.env['mail.template']
            # generate fields value for all res_ids linked to the current template
            if template.lang:
                Template = Template.with_context(lang=template._context.get('lang'))
            for field in fields:
                Template = Template.with_context(safe=field in {'subject'})
                generated_field_values = Template.render_template(
                    getattr(template, field), template.model, template_res_ids,
                    post_process=(field == 'body_html'))
                for res_id, field_value in generated_field_values.items():
                    results.setdefault(res_id, dict())[field] = field_value
            # compute recipients
            if any(field in fields for field in ['email_to', 'partner_to', 'email_cc']):
                results = template.generate_recipients(results, template_res_ids)
            # update values for all res_ids
            for res_id in template_res_ids:
                values = results[res_id]
                # body: add user signature, sanitize
                if 'body_html' in fields and template.user_signature:
                    signature = self.env.user.signature
                    if signature:
                        values['body_html'] = tools.append_content_to_html(values['body_html'], signature, plaintext=False)
                if values.get('body_html'):
                    values['body'] = tools.html_sanitize(values['body_html'])
                # technical settings
                values.update(
                    mail_server_id=template.mail_server_id.id or False,
                    auto_delete=template.auto_delete,
                    model=template.model,
                    res_id=res_id or False,
                    attachment_ids=[attach.id for attach in template.attachment_ids],
                )

            # Add report in attachments: generate once for all template_res_ids
            if template.report_template:
                for res_id in template_res_ids:
                    attachments = []
                    report_name = self.render_template(template.report_name, template.model, res_id)
                    report = template.report_template
                    report_service = report.report_name

                    if report.report_type not in ['qweb-html', 'qweb-pdf']:
                        raise UserError(_('Unsupported report type %s found.') % report.report_type)
                    result, format = report.render_qweb_pdf([res_id])

                    # TODO in trunk, change return format to binary to match message_post expected format
                    result = base64.b64encode(result)
                    if not report_name:
                        report_name = 'report.' + report_service
                    ext = "." + format
                    if not report_name.endswith(ext):
                        report_name += ext
                    attachments.append((report_name, result))
                    results[res_id]['attachments'] = attachments

        return multi_mode and results or results[res_ids[0]]
示例#38
0
    def fetch_mail(self):
        for server in self:
            count, failed = 0, 0
            pop_server = None
            if server.type == 'pop':
                _logger.info('Server tpye is POP')
                try:
                    while True:
                        pop_server = server.connect()
                        (num_messages, total_size) = pop_server.stat()
                        pop_server.list()
                        _logger.info('Server tpye is POP inside while')
                        _logger.info('total_size = %d', total_size)
                        _logger.info('num_messages = %d', num_messages)
                        for num in range(
                                1,
                                min(MAX_POP_MESSAGES, num_messages) + 1):
                            _logger.info(
                                'Server tpye is POP inside while INSIDE FOR')
                            (header, messages, octets) = pop_server.retr(num)
                            message = (b'\n').join(messages)
                            res_id = None
                            response = {
                                'errorCode': 100,
                                'message': 'File Uploaded Successfully'
                            }
                            try:
                                if isinstance(message, xmlrpclib.Binary):
                                    message = bytes(message.data)
                                if isinstance(message, pycompat.text_type):
                                    message = message.encode('utf-8')
                                extract = getattr(email, 'message_from_bytes',
                                                  email.message_from_string)
                                message = extract(message)
                                if not isinstance(message, Message):
                                    message = pycompat.to_native(message)
                                    message = email.message_from_string(
                                        message)
                                email_to = tools.decode_message_header(
                                    message, 'To')
                                match = re.search(r'[\w\.-]+@[\w\.-]+',
                                                  email_to)
                                email_to = str(match.group(0))
                                _logger.info('Email to %r', email_to)
                                # if email_to == INCOMING_EMAIL_ID:
                                _Attachment = namedtuple(
                                    'Attachment', ('fname', 'content', 'info'))
                                attachments = []
                                body = u''
                                email_from = tools.decode_message_header(
                                    message, 'From')
                                _logger.info('Email from %r', email_from)
                                match = re.search(r'[\w\.-]+@[\w\.-]+',
                                                  email_from)
                                email_from = str(match.group(0))
                                subject = tools.decode_message_header(
                                    message, 'Subject')
                                tmpl_type = None
                                if 'Inventory' in subject:
                                    tmpl_type = "Inventory"
                                elif 'Requirement' in subject:
                                    tmpl_type = "Requirement"
                                if message.get_content_maintype() != 'text':
                                    alternative = False
                                    for part in message.walk():
                                        if part.get_content_type(
                                        ) == 'multipart/alternative':
                                            alternative = True
                                        if part.get_content_maintype(
                                        ) == 'multipart':
                                            continue  # skip container
                                        filename = part.get_param(
                                            'filename', None,
                                            'content-disposition')
                                        if not filename:
                                            filename = part.get_param(
                                                'name', None)
                                        if filename:
                                            if isinstance(filename, tuple):
                                                filename = email.utils.collapse_rfc2231_value(
                                                    filename).strip()
                                            else:
                                                filename = tools.decode_smtp_header(
                                                    filename)
                                        encoding = part.get_content_charset()
                                        if filename and part.get('content-id'):
                                            inner_cid = part.get(
                                                'content-id').strip('><')
                                            attachments.append(
                                                _Attachment(
                                                    filename,
                                                    part.get_payload(
                                                        decode=True),
                                                    {'cid': inner_cid}))
                                            continue
                                        if filename or part.get(
                                                'content-disposition', ''
                                        ).strip().startswith('attachment'):
                                            attachments.append(
                                                _Attachment(
                                                    filename or 'attachment',
                                                    part.get_payload(
                                                        decode=True), {}))
                                            continue
                                        if part.get_content_type(
                                        ) == 'text/plain' and (not alternative
                                                               or not body):
                                            body = tools.append_content_to_html(
                                                body,
                                                tools.ustr(part.get_payload(
                                                    decode=True),
                                                           encoding,
                                                           errors='replace'),
                                                preserve=True)
                                        elif part.get_content_type(
                                        ) == 'text/html':
                                            body = tools.ustr(
                                                part.get_payload(decode=True),
                                                encoding,
                                                errors='replace')
                                        else:
                                            attachments.append(
                                                _Attachment(
                                                    filename or 'attachment',
                                                    part.get_payload(
                                                        decode=True), {}))
                                    if len(attachments) > 0:
                                        encoding = message.get_content_charset(
                                        )
                                        plain_text = html2text.HTML2Text()
                                        message_payload = plain_text.handle(
                                            tools.ustr(body,
                                                       encoding,
                                                       errors='replace'))
                                        if '- Forwarded message -' in message_payload:
                                            messages = message_payload.split(
                                                '- Forwarded message -')
                                            _logger.info(
                                                'Forwarded message payload: %r',
                                                messages)
                                            total_parts = len(messages)
                                            originator_part = messages[
                                                total_parts - 1]
                                            _logger.info(
                                                'originator_part: %r',
                                                originator_part)
                                            match = re.search(
                                                r'[\w\.-]+@[\w\.-]+',
                                                originator_part)
                                            _logger.info('match: %r', match)
                                            if match:
                                                email_from_domain = re.search(
                                                    "@[\w.]+",
                                                    email_from).group(0)
                                                _logger.info(
                                                    'email_from_domain: %r',
                                                    email_from_domain)
                                                email_to_domain = re.search(
                                                    "@[\w.]+",
                                                    email_to).group(0)
                                                _logger.info(
                                                    'email_to_domain: %r',
                                                    email_to_domain)
                                                if email_to_domain != email_from_domain:
                                                    email_from = None
                                                else:
                                                    email_from = str(
                                                        match.group(0))
                                                    _logger.info(
                                                        'email_to_domain email_from: %r',
                                                        email_from)
                                        #_logger.info('message payload: %r %r', message_payload, email_from)
                                        if not email_from is None:
                                            users_model = self.env[
                                                'res.partner'].search([
                                                    ("email", "=", email_from)
                                                ])
                                            if users_model:
                                                if len(users_model) == 1:
                                                    user_attachment_dir = ATTACHMENT_DIR + str(
                                                        datetime.now(
                                                        ).strftime("%d%m%Y")
                                                    ) + "/" + str(
                                                        users_model.id) + "/"
                                                    if not os.path.exists(
                                                            os.path.dirname(
                                                                user_attachment_dir
                                                            )):
                                                        try:
                                                            os.makedirs(
                                                                os.path.
                                                                dirname(
                                                                    user_attachment_dir
                                                                ))
                                                        except OSError as exc:
                                                            if exc.errno != errno.EEXIST:
                                                                raise
                                                    for attachment in attachments:
                                                        filename = getattr(
                                                            attachment,
                                                            'fname')
                                                        if not filename is None:
                                                            try:
                                                                file_contents_bytes = getattr(
                                                                    attachment,
                                                                    'content')
                                                                file_path = user_attachment_dir + str(
                                                                    filename)
                                                                file_ref = open(
                                                                    str(file_path
                                                                        ),
                                                                    "wb+")
                                                                file_ref.write(
                                                                    file_contents_bytes
                                                                )
                                                                file_ref.close(
                                                                )
                                                                response = self.env[
                                                                    'sps.document.process'].process_document(
                                                                        users_model,
                                                                        file_path,
                                                                        tmpl_type,
                                                                        filename,
                                                                        'Email'
                                                                    )
                                                            except Exception as e:
                                                                _logger.info(
                                                                    str(e))
                                                else:
                                                    _logger.error(
                                                        'Presents Same Email Id for multiple users %r',
                                                        email_from)
                                                    response = dict(
                                                        errorCode=101,
                                                        message=
                                                        'Presents Same Email Id for multiple users : '
                                                        + str(email_from))
                                            else:
                                                _logger.info(
                                                    'user not found for %r',
                                                    email_from)
                                                response = dict(
                                                    errorCode=102,
                                                    message=
                                                    'User not found for : ' +
                                                    str(email_from))
                                        else:
                                            _logger.info(
                                                'domain not matched for forwarded email'
                                            )
                                            response = dict(
                                                errorCode=103,
                                                message=
                                                'Domain not matched for forwarded email : '
                                                + str(email_from))
                                    else:
                                        _logger.info("No attachements found")
                                        response = dict(
                                            errorCode=104,
                                            message='No attachements found : '
                                            + str(email_from))
                                else:
                                    _logger.info('Not a Multipart email')
                                    response = dict(
                                        errorCode=105,
                                        message='Not a Multipart email' +
                                        str(email_from))
                                pop_server.dele(num)

                                if "errorCode" in response:
                                    self.send_mail(
                                        "Sending Email Response as " +
                                        str(response['message']) +
                                        " for user " + str(email_from))

                            except Exception:
                                _logger.info(
                                    'Failed to process mail from %s server %s.',
                                    server.type,
                                    server.name,
                                    exc_info=True)
                                failed += 1

                            if res_id and server.action_id:
                                server.action_id.with_context({
                                    'active_id':
                                    res_id,
                                    'active_ids': [res_id],
                                    'active_model':
                                    self.env.context.get(
                                        "thread_model", server.object_id.model)
                                }).run()
                            self.env.cr.commit()
                        _logger.info('num_messages = %d', num_messages)
                        if num_messages < MAX_POP_MESSAGES:
                            break
                        pop_server.quit()
                        _logger.info(
                            "Fetched %d email(s) on %s server %s; %d succeeded, %d failed.",
                            num_messages, server.type, server.name,
                            (num_messages - failed), failed)
                except Exception:
                    _logger.info(
                        "General failure when trying to fetch mail from %s server %s.",
                        server.type,
                        server.name,
                        exc_info=True)
                finally:
                    _logger.info('Server tpye is POP inside finally')
                    if pop_server:
                        pop_server.quit()
            server.write({'date': fields.Datetime.now()})

        return super(IncomingMailCronModel, self).fetch_mail()