def send_get_mail_body(self, cr, uid, ids, partner=None, context=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 body = super(MailMail, self).send_get_mail_body(cr, uid, ids, partner=partner, context=context) mail = self.browse(cr, uid, ids[0], context=context) links_blacklist = ['/unsubscribe_from_list'] if mail.mailing_id and body and mail.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.pool.get("ir.config_parameter").get_param(cr, uid, "web.base.url", context=context) base = "<base href='%s'>" % domain body = tools.append_content_to_html(base, body, plaintext=False, container_tag='div') # generate tracking URL if mail.statistics_ids: tracking_url = self._get_tracking_url(cr, uid, mail, partner, context=context) if tracking_url: body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div') return body
def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None, user_signature=True): footer = super(mail_notification, self).get_signature_footer(cr, uid, user_id, res_model, res_id, context, user_signature) footer = "" if not user_id: return footer # add user signature user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0] if user_signature: if user.signature: signature = user.signature else: signature = "--<br />%s" % user.name footer = tools.append_content_to_html(footer, signature, plaintext=False) # add company signature if user.company_id.website: website_url = ('http://%s' % user.company_id.website) if not user.company_id.website.lower().startswith(('http:', 'https:')) \ else user.company_id.website company = "<a style='color:inherit' href='%s'>%s</a>" % (website_url, user.company_id.name) else: company = user.company_id.name sent_by = _('Sent by %(company)s using %(odoo)s') signature_company = '<br /><small>%s</small>' % (sent_by % { 'company': company, 'odoo': "<a style='color:inherit' href=''>Perceive</a>" }) footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') return footer
def get_signature_footer(self, user_id, res_model=None, res_id=None, user_signature=True): """ Generate Footer in mail notifications. """ footer = "" user = self.env['res.users'].browse([user_id]) if user_signature: footer = tools.append_content_to_html(footer, u"<p>{}</p>".format( user.name), plaintext=False) website = user.company_id.website website_url = ('http://%s' % website) if not website.lower().startswith( ('http:', 'https:')) else website signature = u"""<br/>-- <br/> Wiadomość wysłana przez <a href='{url}'>{name}</a> poprzez aplikację (C) 2015 GooDoo.ee.""".format( url=website_url, name=user.company_id.name, ) footer = tools.append_content_to_html(footer, signature, plaintext=False, container_tag='div') return footer
def send_get_mail_body(self, cr, uid, ids, partner=None, context=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 body = super(MailMail, self).send_get_mail_body(cr, uid, ids, partner=partner, context=context) mail = self.browse(cr, uid, ids[0], context=context) links_blacklist = ['/unsubscribe_from_list'] if mail.mailing_id and body and mail.statistics_ids: for match in re.findall(URL_REGEX, mail.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(mail.statistics_ids[0].id)) body = body.replace(href, new_href) # prepend <base> tag for images using absolute urls domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "web.base.url", context=context) 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 mail.statistics_ids: tracking_url = self._get_tracking_url(cr, uid, mail, partner, context=context) if tracking_url: body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div') return body
def send_get_mail_body(self, cr, uid, ids, partner=None, context=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 body = super(MailMail, self).send_get_mail_body(cr, uid, ids, partner=partner, context=context) mail = self.browse(cr, uid, ids[0], context=context) if mail.mailing_id and body and mail.statistics_ids: for match in re.findall(URL_REGEX, mail.body_html): href = match[0] url = match[1] parsed = urlparse.urlparse(url, scheme='http') if parsed.scheme.startswith('http') and parsed.path.startswith('/r/'): new_href = href.replace(url, url + '/m/' + str(mail.statistics_ids[0].id)) body = body.replace(href, new_href) # prepend <base> tag for images using absolute urls domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "web.base.url", context=context) 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 mail.statistics_ids: tracking_url = self._get_tracking_url(cr, uid, mail, partner, context=context) if tracking_url: body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div') return body
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None): """ Override to add the tracking URL to the body. """ body = super(MailMail, self).send_get_mail_body(cr, uid, mail, partner=partner, context=context) # prepend <base> tag for images using absolute urls domain = self.pool.get("ir.config_parameter").get_param( cr, uid, "web.base.url", context=context) base = "<base href='%s'>" % domain body = tools.append_content_to_html(base, body, plaintext=False, container_tag='div') # generate tracking URL if mail.statistics_ids: tracking_url = self._get_tracking_url(cr, uid, mail, partner, context=context) if tracking_url: body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div') return body
def _message_extract_payload_receipt(self, message, save_original=False): """Extract body as HTML and attachments from the mail message""" attachments = [] body = u'' if save_original: attachments.append(('original_email.eml', message.as_string())) if not message.is_multipart() or \ 'text/' in message.get('content-type', ''): encoding = message.get_content_charset() body = message.get_payload(decode=True) body = tools.ustr(body, encoding, errors='replace') if message.get_content_type() == 'text/plain': # text/plain -> <pre/> body = tools.append_content_to_html(u'', body, preserve=True) else: 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): # RFC2231 filename = email.utils.collapse_rfc2231_value( filename).strip() else: filename = decode(filename) encoding = part.get_content_charset() # None if attachment # 1) Explicit Attachments -> attachments if filename or part.get('content-disposition', '')\ .strip().startswith('attachment'): attachments.append((filename or 'attachment', part.get_payload(decode=True)) ) continue # 2) text/plain -> <pre/> 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) # 3) text/html -> raw elif part.get_content_type() == 'text/html': continue # 4) Anything else -> attachment else: attachments.append((filename or 'attachment', part.get_payload(decode=True)) ) return body, attachments
def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None, user_signature=True): """ Format a standard footer for notification emails (such as pushed messages notification or invite emails). Format: <p>--<br /> Administrator </p> <div> <small>Sent from <a ...>Your Company</a> using <a ...>OpenERP</a>.</small> </div> """ footer = "" if not user_id: return footer # add user signature user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0] if user_signature: if user.signature: signature = user.signature else: signature = "--<br />%s" % user.name footer = tools.append_content_to_html(footer, signature, plaintext=False) # add company signature if user.company_id.website: website_url = ('http://%s' % user.company_id.website) if not user.company_id.website.lower().startswith(('http:', 'https:')) \ else user.company_id.website company = "<a style='color:inherit' href='%s'>%s</a>" % ( website_url, user.company_id.name) else: company = user.company_id.name sent_by = _('Sent by %(company)s using %(odoo)s') signature_company = '<br /><small>%s</small>' % (sent_by % { 'company': company, 'odoo': "<a style='color:inherit' href='https://cubicerp.com/'>Cubic ERP</a>" }) footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') return footer
def _message_extract_payload(self, cr, uid, message, save_original=False): """Extract body as HTML and attachments from the mail message""" attachments = [] body = u'' if save_original: attachments.append(('original_email.eml', message.as_string())) if not message.is_multipart() or 'text/' in message.get('content-type', ''): encoding = message.get_content_charset() body = message.get_payload(decode=True) body = tools.ustr(body, encoding, errors='replace') if message.get_content_type() == 'text/plain': body = tools.append_content_to_html(u'', body, preserve=True) else: alternative = (message.get_content_type() == 'multipart/alternative') for part in message.walk(): if part.get_content_maintype() == 'multipart': continue filename = part.get_filename() encoding = part.get_content_charset() if filename or part.get('content-disposition', '').strip().startswith('attachment'): attachments.append((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': html = tools.ustr(part.get_payload(decode=True), encoding, errors='replace') if alternative: body = html else: body = tools.append_content_to_html(body, html, plaintext=False) else: attachments.append((filename or 'attachment', part.get_payload(decode=True))) return body, attachments
def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None, user_signature=True): """ Format a standard footer for notification emails (such as pushed messages notification or invite emails). Format: <p>--<br /> Administrator </p> <div> <small>Sent from <a ...>Your Company</a> using <a ...>OpenERP</a>.</small> </div> """ footer = "" if not user_id: return footer # add user signature user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0] if user_signature: if user.signature: signature = user.signature else: signature = "--<br />%s" % user.name footer = tools.append_content_to_html(footer, signature, plaintext=False) #######################TO MAKE SIGNATURE UNCLICKABLE FOR CRM HELPDESK ########################## # if (context.get('default_res_model') and context.get('default_res_model') == 'crm.helpdesk') or (context.get('default_model') and context.get('default_model') == 'crm.helpdesk'): # helpdesk_rec = self.pool.get('crm.helpdesk').browse(cr, uid, context.get('default_res_id')) # case_str = _('Ticket# %(id)s about Helpdesk %(Query)s') # case_string = '<br /><small>%s</small>' % (case_str % { # 'id' : helpdesk_rec.id, # 'Query' : helpdesk_rec.name}) # # footer = tools.append_content_to_html(footer, case_string, plaintext=False, container_tag='div') ############################################### else: # add company signature if user.company_id.website: website_url = ('http://%s' % user.company_id.website) if not user.company_id.website.lower().startswith(('http:', 'https:')) \ else user.company_id.website company = "<a style='color:inherit' href='%s'>%s</a>" % (website_url, user.company_id.name) else: company = user.company_id.name sent_by = _('Sent by %(company)s using %(odoo)s') signature_company = '<br /><small>%s</small>' % (sent_by % { 'company': company, 'odoo': "<a style='color:inherit' href='https://www.odoo.com/'>Odoo</a>" }) footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') return footer
def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None, user_signature=True): footer = super(mail_notification, self).get_signature_footer(cr, uid, user_id, res_model, res_id, context, user_signature) footer = "" if not user_id: return footer # add user signature user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0] if user_signature: if user.signature: signature = user.signature else: signature = "--<br />%s" % user.name footer = tools.append_content_to_html(footer, signature, plaintext=False) # add company signature if user.company_id.website: website_url = ('http://%s' % user.company_id.website) if not user.company_id.website.lower().startswith(('http:', 'https:')) \ else user.company_id.website company = "<a style='color:inherit' href='%s'>%s</a>" % ( website_url, user.company_id.name) else: company = user.company_id.name sent_by = _('Sent by %(company)s using %(odoo)s') signature_company = '<br /><small>%s</small>' % (sent_by % { 'company': company, 'odoo': "<a style='color:inherit' href='https://bma8.officebrain.com/'>OfficeBrainBMA</a>" }) footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') return footer
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None): """ Override to add the tracking URL to the body. """ body = super(MailMail, self).send_get_mail_body(cr, uid, mail, partner=partner, context=context) # prepend <base> tag for images using absolute urls domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "web.base.url", context=context) base = "<base href='%s'>" % domain body = tools.append_content_to_html(base, body, plaintext=False, container_tag='div') # generate tracking URL if mail.statistics_ids: tracking_url = self._get_tracking_url(cr, uid, mail, partner, context=context) if tracking_url: body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div') return body
def add_followers(self): email_from = self.env['mail.message']._get_default_from() for wizard in self: Model = self.env[wizard.res_model] document = Model.browse(wizard.res_id) # filter partner_ids to get the new followers, to avoid sending email to already following partners new_partners = wizard.partner_ids - document.message_partner_ids new_channels = wizard.channel_ids - document.message_channel_ids document.message_subscribe(new_partners.ids, new_channels.ids) model_ids = self.env['ir.model'].search([('model', '=', wizard.res_model)]) model_name = model_ids.name_get()[0][1] # send an email if option checked and if a message exists (do not send void emails) if wizard.send_mail and wizard.message and not wizard.message == '<br>': # when deleting the message, cleditor keeps a <br> # TDE FIXME: use a template + _notification methods # add signature signature = self.env.user.signature wizard.message = tools.append_content_to_html(wizard.message, signature, plaintext=False, container_tag='div') # send mail to new followers self.env['mail.mail'].create({ 'model': wizard.res_model, 'res_id': wizard.res_id, 'record_name': document.name_get()[0][1], 'email_from': email_from, 'reply_to': email_from, 'subject': _('Invitation to follow %s: %s') % (model_name, document.name_get()[0][1]), 'body_html': '%s' % wizard.message, 'auto_delete': True, 'message_id': self.env['mail.message']._get_message_id({'no_auto_thread': True}), 'recipient_ids': [(4, id) for id in new_partners.ids]}).send() return {'type': 'ir.actions.act_window_close'}
def _notify_email(self, cr, uid, ids, message_id, force_send=False, user_signature=True, context=None): message = self.pool['mail.message'].browse(cr, SUPERUSER_ID, message_id, context=context) # compute partners email_pids = self.get_partners_to_email(cr, uid, ids, message, context=None) if not email_pids: return True # compute email body (signature, company data) body_html = message.body 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 if user_signature: signature_company = self.get_signature_footer(cr, uid, user_id, res_model=message.model, res_id=message.res_id, context=context) 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 # 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, } 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
def send_mail_test(self, cr, uid, ids, context=None): Mail = self.pool['mail.mail'] for wizard in self.browse(cr, uid, ids, context=context): mailing = wizard.mass_mailing_id test_emails = tools.email_split(wizard.email_to) mail_ids = [] for test_mail in test_emails: 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_mail_obj = Mail.browse(cr, uid, Mail.create(cr, uid, mail_values, context=context), context=context) unsubscribe_url = Mail._get_unsubscribe_url(cr, uid, mail_mail_obj, test_mail, context=context) body = tools.append_content_to_html(mailing.body_html, unsubscribe_url, plaintext=False, container_tag='p') Mail.write(cr, uid, mail_mail_obj.id, {'body_html': mailing.body_html}, context=context) mail_ids.append(mail_mail_obj.id) Mail.send(cr, uid, mail_ids, context=context) self.pool['mail.mass_mailing'].write(cr, uid, [mailing.id], {'state': 'test'}, context=context) return True
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None): """ Return a specific ir_email body. The main purpose of this method is to be inherited by Portal, to add a link for signing in, in each notification email a partner receives. :param browse_record mail: mail.mail browse_record :param browse_record partner: specific recipient partner """ body = mail.body_html # partner is a user, link to a related document (incentive to install portal) if partner and partner.user_ids and mail.model and mail.res_id \ and self.check_access_rights(cr, partner.user_ids[0].id, 'read', raise_exception=False): related_user = partner.user_ids[0] try: self.pool.get(mail.model).check_access_rule(cr, related_user.id, [mail.res_id], 'read', context=context) base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') # the parameters to encode for the query and fragment part of url query = {'db': cr.dbname} fragment = { 'login': related_user.login, 'model': mail.model, 'id': mail.res_id, } url = urljoin(base_url, "?%s#%s" % (urlencode(query), urlencode(fragment))) text = _("""<p>Access this document <a href="%s">directly in OpenERP</a></p>""") % url body = tools.append_content_to_html(body, ("<div><p>%s</p></div>" % text), plaintext=False) except except_orm, e: pass
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", )
def _notify_email(self, cr, uid, ids, message_id, force_send=False, user_signature=True, context=None): message = self.pool['mail.message'].browse(cr, SUPERUSER_ID, message_id, context=context) # compute partners email_pids = self.get_partners_to_email(cr, uid, ids, message, context=None) if not email_pids: return True # compute email body (signature, company data) body_html = message.body 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 if user_signature: signature_company = self.get_signature_footer(cr, uid, user_id, res_model=message.model, res_id=message.res_id, context=context) 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 # create email values max_recipients = 100 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, } email_ids.append(self.pool.get('mail.mail').create(cr, uid, mail_values, context=context)) if force_send and len(chunks) < 6: # for more than 500 followers, use the queue system self.pool.get('mail.mail').send(cr, uid, email_ids, context=context) return True
def generate_email(self, cr, uid, template_id, res_id, context=None): """Generates an email from the template for given (model, res_id) pair. :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. """ if context is None: context = {} report_xml_pool = self.pool.get('ir.actions.report.xml') template = self.get_email_template(cr, uid, template_id, res_id, context) values = {} for field in ['subject', 'body_html', 'email_from', 'email_to', 'email_recipients', 'email_cc', 'reply_to']: values[field] = self.render_template(cr, uid, getattr(template, field), template.model, res_id, context=context) \ or False if template.user_signature: signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature values['body_html'] = tools.append_content_to_html(values['body_html'], signature) if values['body_html']: values['body'] = tools.html_sanitize(values['body_html']) 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) attachments = [] # Add report in attachments if template.report_template: report_name = self.render_template(cr, uid, template.report_name, template.model, res_id, context=context) report_service = 'report.' + report_xml_pool.browse(cr, uid, template.report_template.id, context).report_name # Ensure report is rendered using template's language ctx = context.copy() if template.lang: ctx['lang'] = self.render_template(cr, uid, template.lang, template.model, res_id, context) service = netsvc.LocalService(report_service) (result, format) = service.create(cr, uid, [res_id], {'model': template.model}, ctx) # 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_service ext = "." + format if not report_name.endswith(ext): report_name += ext attachments.append((report_name, result)) attachment_ids = [] # Add template attachments for attach in template.attachment_ids: attachment_ids.append(attach.id) values['attachments'] = attachments values['attachment_ids'] = attachment_ids return values
def add_followers(self, cr, uid, ids, context=None): for wizard in self.browse(cr, uid, ids, context=context): model_obj = self.pool.get(wizard.res_model) document = model_obj.browse(cr, uid, wizard.res_id, context=context) # filter partner_ids to get the new followers, to avoid sending email to already following partners new_follower_ids = [p.id for p in wizard.partner_ids if p.id not in document.message_follower_ids] model_obj.message_subscribe(cr, uid, [wizard.res_id], new_follower_ids, context=context) # send an email only if a personal message exists if wizard.message and not wizard.message == '<br>': # when deleting the message, cleditor keeps a <br> # add signature user_id = self.pool.get("res.users").read(cr, uid, [uid], fields=["signature"], context=context)[0] signature = user_id and user_id["signature"] or '' if signature: wizard.message = tools.append_content_to_html(wizard.message, signature, plaintext=True, container_tag='div') # FIXME 8.0: use notification_email_send, send a wall message and let mail handle email notification + message box for follower_id in new_follower_ids: mail_mail = self.pool.get('mail.mail') # the invite wizard should create a private message not related to any object -> no model, no res_id mail_id = mail_mail.create(cr, uid, { 'model': wizard.res_model, 'res_id': wizard.res_id, 'subject': 'Invitation to follow %s' % document.name_get()[0][1], 'body_html': '%s' % wizard.message, 'auto_delete': True, }, context=context) mail_mail.send(cr, uid, [mail_id], recipient_ids=[follower_id], context=context) return {'type': 'ir.actions.act_window_close'}
def send_mail_test(self, cr, uid, ids, context=None): Mail = self.pool['mail.mail'] for wizard in self.browse(cr, uid, ids, context=context): mailing = wizard.mass_mailing_id test_emails = tools.email_split(wizard.email_to) mail_ids = [] for test_mail in test_emails: # Convert links in absolute URLs before the application of the shortener self.pool['mail.mass_mailing'].write(cr, uid, [mailing.id], {'body_html': self.pool['mail.template']._replace_local_links(cr, uid, mailing.body_html, context)}, context=context) 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_mail_obj = Mail.browse(cr, uid, Mail.create(cr, uid, mail_values, context=context), context=context) unsubscribe_url = Mail._get_unsubscribe_url(cr, uid, mail_mail_obj, test_mail, context=context) body = tools.append_content_to_html(mailing.body_html, unsubscribe_url, plaintext=False, container_tag='p') Mail.write(cr, uid, mail_mail_obj.id, {'body_html': mailing.body_html}, context=context) mail_ids.append(mail_mail_obj.id) Mail.send(cr, uid, mail_ids, context=context) return True
def send_get_mail_body(self, cr, uid, ids, partner=None, context=None): """ Short-circuit parent method for mail groups, replace the default footer with one appropriate for mailing-lists.""" # TDE: temporary addition (mail was parameter) due to semi-new-API mail = self.browse(cr, uid, ids[0], context=context) if mail.model == 'mail.group' and mail.res_id: # no super() call on purpose, no private links that could be quoted! group = self.pool['mail.group'].browse(cr, uid, mail.res_id, context=context) base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url') vals = { 'maillist': _('Mailing-List'), 'post_to': _('Post to'), 'unsub': _('Unsubscribe'), 'mailto': 'mailto:%s@%s' % (group.alias_name, group.alias_domain), 'group_url': '%s/groups/%s' % (base_url, slug(group)), '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(mail.body, footer, container_tag='div') return body else: return super(MailMail, self).send_get_mail_body(cr, uid, ids, partner=partner, context=context)
def add_followers(self, cr, uid, ids, context=None): for wizard in self.browse(cr, uid, ids, context=context): model_obj = self.pool.get(wizard.res_model) document = model_obj.browse(cr, uid, wizard.res_id, context=context) # filter partner_ids to get the new followers, to avoid sending email to already following partners new_follower_ids = [p.id for p in wizard.partner_ids if p.id not in document.message_follower_ids] model_obj.message_subscribe(cr, uid, [wizard.res_id], new_follower_ids, context=context) # send an email if wizard.message: # add signature user_id = self.pool.get("res.users").read(cr, uid, [uid], fields=["signature"], context=context)[0] signature = user_id and user_id["signature"] or '' if signature: wizard.message = tools.append_content_to_html(wizard.message, signature, plaintext=True, container_tag='div') # FIXME 8.0: use notification_email_send, send a wall message and let mail handle email notification + message box for follower_id in new_follower_ids: mail_mail = self.pool.get('mail.mail') # the invite wizard should create a private message not related to any object -> no model, no res_id mail_id = mail_mail.create(cr, uid, { 'model': wizard.res_model, 'res_id': wizard.res_id, 'subject': 'Invitation to follow %s' % document.name_get()[0][1], 'body_html': '%s' % wizard.message, 'auto_delete': True, }, context=context) mail_mail.send(cr, uid, [mail_id], recipient_ids=[follower_id], context=context) return {'type': 'ir.actions.act_window_close'}
def add_followers(self, cr, uid, ids, context=None): for wizard in self.browse(cr, uid, ids, context=context): model_obj = self.pool[wizard.res_model] document = model_obj.browse(cr, uid, wizard.res_id, context=context) # filter partner_ids to get the new followers, to avoid sending email to already following partners new_follower_ids = [p.id for p in wizard.partner_ids if p not in document.message_follower_ids] model_obj.message_subscribe(cr, uid, [wizard.res_id], new_follower_ids, context=context) ir_model = self.pool.get('ir.model') model_ids = ir_model.search(cr, uid, [('model', '=', model_obj._name)], context=context) model_name = ir_model.name_get(cr, uid, model_ids, context=context)[0][1] # send an email if option checked and if a message exists (do not send void emails) if wizard.send_mail and wizard.message and not wizard.message == '<br>': # when deleting the message, cleditor keeps a <br> # add signature # FIXME 8.0: use notification_email_send, send a wall message and let mail handle email notification + message box signature_company = self.pool.get('mail.notification').get_signature_footer(cr, uid, user_id=uid, res_model=wizard.res_model, res_id=wizard.res_id, context=context) wizard.message = tools.append_content_to_html(wizard.message, signature_company, plaintext=False, container_tag='div') # send mail to new followers # the invite wizard should create a private message not related to any object -> no model, no res_id mail_mail = self.pool.get('mail.mail') mail_id = mail_mail.create(cr, uid, { 'model': wizard.res_model, 'res_id': wizard.res_id, 'subject': _('Invitation to follow %s: %s') % (model_name, document.name_get()[0][1]), 'body_html': '%s' % wizard.message, 'auto_delete': True, 'recipient_ids': [(4, id) for id in new_follower_ids] }, context=context) mail_mail.send(cr, uid, [mail_id], context=context) return {'type': 'ir.actions.act_window_close'}
def onchange_template_id(self, cr, uid, ids, template_id, composition_mode, model, res_id, context=None): """ - mass_mailing: we cannot render, so return the template values - normal mode: return rendered values """ if template_id and composition_mode == 'mass_mail': fields = ['subject', 'body_html', 'email_from', 'reply_to', 'mail_server_id'] template = self.pool['email.template'].browse(cr, uid, template_id, context=context) 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.pool.get('res.users').browse(cr, uid, uid, context).signature values['body_html'] = tools.append_content_to_html(values['body_html'], signature) elif template_id: values = self.generate_email_for_composer_batch(cr, uid, template_id, [res_id], context=context)[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 ir_attach_obj = self.pool.get('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(ir_attach_obj.create(cr, uid, data_attach, context=context)) else: values = self.default_get(cr, uid, ['subject', 'body', 'email_from', 'email_to', 'email_cc', 'partner_to', 'reply_to', 'attachment_ids', 'mail_server_id'], context=context) if values.get('body_html'): values['body'] = values.pop('body_html') return {'value': values}
def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None, user_signature=True): footer = "" if not user_id: return footer # add user signature user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0] if user_signature: if user.signature: signature = user.signature else: signature = "--<br />%s" % user.name footer = tools.append_content_to_html(footer, signature, plaintext=False) return footer
def send_get_email_dict(self, cr, uid, mail, partner=None, context=None): email_to = self.send_get_mail_to(cr, uid, mail, partner=partner, context=context) body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context) if mail.mailing_id and body and email_to: emails = tools.email_split(email_to[0]) has_email_to = emails and emails[0] or False unsubscribe_url = self._get_unsubscribe_url(cr, uid, mail, has_email_to, context=context) if unsubscribe_url: if body.count('__UNSUBSCRIBE_URL__') > 0: body = body.replace('__UNSUBSCRIBE_URL__', unsubscribe_url) else: unsubscribe_link = '<small><a href="%s">%s</a></small>' % (unsubscribe_url, _('Click to unsubscribe')) body = tools.append_content_to_html(body,unsubscribe_link, plaintext=False, container_tag='p') html_version_url = self._get_html_version_url(cr, uid, mail, has_email_to, context=context) body = body.replace('__HTML_VERSION_URL__', html_version_url) body_alternative = tools.html2plaintext(body) res = { 'body': body, 'body_alternative': body_alternative, 'subject': self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context), 'email_to': email_to, } return res
def get_signature_footer(self, user_id, res_model=None, res_id=None, user_signature=True): """Generate signature footer only with the chosen parts. Now, you can set ``skip_signature_user=True`` in the context to remove the user signature (it's the same as ``user_signature=False``), and ``skip_signature_company=True`` to remove the company's. """ user = self.env["res.users"].browse(user_id) parts = list() if user_signature and not self.env.context.get("skip_signature_user"): parts.append(self._get_signature_footer_user(user)) if not self.env.context.get("skip_signature_company"): parts.append(self._get_signature_footer_company(user)) footer = "" for part in parts: footer = tools.append_content_to_html(footer, part, plaintext=False) return footer
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
def _notify_email(self, cr, uid, ids, message_id, force_send=False, user_signature=True, context=None): message = self.pool['mail.message'].browse(cr, SUPERUSER_ID, message_id, context=context) # compute partners email_pids = self.get_partners_to_email(cr, uid, ids, message, context=None) if not email_pids: return True # compute email body (signature, company data) body_html = message.body 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 if user_signature: signature_company = self.get_signature_footer(cr, uid, user_id, res_model=message.model, res_id=message.res_id, context=context) 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 # create email values mail_values = { 'mail_message_id': message.id, 'auto_delete': True, 'body_html': body_html, 'recipient_ids': [(4, id) for id in email_pids], 'references': references, } email_notif_id = self.pool.get('mail.mail').create(cr, uid, mail_values, context=context) if force_send: self.pool.get('mail.mail').send(cr, uid, [email_notif_id], context=context) return True
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 generate_email(self, cr, uid, template_id, res_id, context=None): """Generates an email from the template for given (model, res_id) pair. :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 expected by :py:meth:`mail_thread.message_post`. """ if context is None: context = {} report_xml_pool = self.pool.get('ir.actions.report.xml') template = self.get_email_template(cr, uid, template_id, res_id, context) values = {} for field in ['subject', 'body_html', 'email_from', 'email_to', 'email_recipients', 'email_cc', 'reply_to']: values[field] = self.render_template(cr, uid, getattr(template, field), template.model, res_id, context=context) \ or False if template.user_signature: signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature values['body_html'] = tools.append_content_to_html(values['body_html'], signature) if values['body_html']: values['body'] = tools.html_sanitize(values['body_html']) 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) attachments = [] # Add report in attachments if template.report_template: report_name = self.render_template(cr, uid, template.report_name, template.model, res_id, context=context) report_service = 'report.' + report_xml_pool.browse(cr, uid, template.report_template.id, context).report_name # Ensure report is rendered using template's language ctx = context.copy() if template.lang: ctx['lang'] = self.render_template(cr, uid, template.lang, template.model, res_id, context) service = netsvc.LocalService(report_service) (result, format) = service.create(cr, uid, [res_id], {'model': template.model}, ctx) result = base64.b64encode(result) if not report_name: report_name = report_service ext = "." + format if not report_name.endswith(ext): report_name += ext attachments.append((report_name, result)) attachment_ids = [] # Add template attachments for attach in template.attachment_ids: attachment_ids.append(attach.id) values['attachments'] = attachments values['attachment_ids'] = attachment_ids return values
def _notify_email(self, cr, uid, ids, message_id, force_send=False, user_signature=True, context=None): message = self.pool['mail.message'].browse(cr, SUPERUSER_ID, message_id, context=context) # compute partners email_pids = self.get_partners_to_email(cr, uid, ids, message, context=None) if not email_pids: return True # compute email body (signature, company data) body_html = message.body 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 if user_signature: signature_company = self.get_signature_footer( cr, uid, user_id, res_model=message.model, res_id=message.res_id, context=context) 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 # create email values mail_values = { 'mail_message_id': message.id, 'auto_delete': True, 'body_html': body_html, 'recipient_ids': [(4, id) for id in email_pids], 'references': references, } email_notif_id = self.pool.get('mail.mail').create(cr, uid, mail_values, context=context) if force_send: self.pool.get('mail.mail').send(cr, uid, [email_notif_id], context=context) return True
def send_get_email_dict(self, cr, uid, mail, partner=None, context=None): res = super(MailMail, self).send_get_email_dict(cr, uid, mail, partner, context=context) if mail.mailing_id and res.get('body') and res.get('email_to'): email_to = tools.email_split(res.get('email_to')[0]) unsubscribe_url = self._get_unsubscribe_url(cr, uid, mail, email_to, context=context) if unsubscribe_url: res['body'] = tools.append_content_to_html(res['body'], unsubscribe_url, plaintext=False, container_tag='p') return res
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
def generate_sms_batch(self, cr, uid, sms_template_id, res_ids, context=None, fields=None): """Generates an sms from the template for given the given model based on records given by res_ids. :param sms_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 sms.sms entry(smsclient), with one extra key ``attachments``, in the format [(report_name, data)] where data is base64 encoded. """ if context is None: context = {} if fields is None: fields = ['body_html', 'sms_from', 'sms_to'] report_xml_pool = self.pool.get('ir.actions.report.xml') res_ids_to_templates = self.get_sms_template_batch(cr, uid, sms_template_id, res_ids, context) # 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(): # generate fields value for all res_ids linked to the current template for field in fields: generated_field_values = self.render_template_batch( cr, uid, getattr(template, field), template.model, template_res_ids, post_process=(field == 'body_html'), context=context) for res_id, field_value in generated_field_values.iteritems(): results.setdefault(res_id, dict())[field] = field_value # compute recipients #results = self.generate_recipients_batch(cr, uid, results, template.id, template_res_ids, context=context) # 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.pool.get('res.users').browse(cr, uid, uid, context).signature values['body_html'] = tools.append_content_to_html(values['body_html'], signature) if values.get('body_html'): values['body'] = tools.html_sanitize(values['body_html']) # technical settings values.update( sms_server_id=template.sms_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 return results
def send_get_email_dict(self, cr, uid, mail, partner=None, context=None): res = super(MailMail, self).send_get_email_dict(cr, uid, mail, partner, context=context) if mail.mailing_id and res.get('body') and res.get('email_to'): emails = tools.email_split(res.get('email_to')[0]) email_to = emails and emails[0] or False unsubscribe_url = self._get_unsubscribe_url(cr, uid, mail, email_to, context=context) if unsubscribe_url: res['body'] = tools.append_content_to_html(res['body'], unsubscribe_url, plaintext=False, container_tag='p') return res
def write_comment(self, cr, uid, ids, module, rec_id, context=None): """ write comment and send email """ if not context: context = {} # With this option we disable the signature on the email of the user that is sending the email. It also changes the footer from: # Sent by Law Tracking using OpenERP. Access your messages and documents through our Customer Portal # to # Access your messages and documents through our Customer Portal context = dict(context, mail_notify_user_signature=False) template = False signature_template = False try: template = self.pool.get('ir.model.data').get_object( cr, uid, module, rec_id) signature_template = self.pool.get('ir.model.data').get_object( cr, uid, 'law_tracking_x', 'company_signature') except ValueError: raise user = self.pool.get('res.users').browse(cr, uid, uid, context=context) if 'lang' not in context: if user.lang: context = dict(context, lang=user.lang) signature_mail = self.pool.get('email.template').generate_email( cr, uid, signature_template.id, user.company_id.id, context=context) partner_match_ids = context.get('partner_match_ids', []) for record in self.browse(cr, uid, ids, context): try: print 'contexttttttttttttttt', context mail = self.pool.get('email.template').generate_email( cr, uid, template.id, record.id, context=context) subtype = 'mail.mt_comment' body_html = mail['body_html'] body_html = tools.append_content_to_html( mail['body_html'], signature_mail['body_html'], plaintext=False, container_tag='div') self.message_post(cr, uid, [record.id], subject=mail['subject'], body=body_html, type='comment', subtype=subtype, context=context, partner_ids=partner_match_ids) except Exception: raise
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None): """Return a specific ir_email body. The main purpose of this method is to be inherited to add custom content depending on some module.""" body = mail.body_html # generate footer link = self._get_partner_access_link(cr, uid, mail, partner, context=context) if link: body = tools.append_content_to_html(body, link, plaintext=False, container_tag='div') return body
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None): """ Override to add the tracking URL to the body. """ body = super(MailMail, self).send_get_mail_body(cr, uid, mail, partner=partner, context=context) # generate tracking URL if mail.statistics_ids: tracking_url = self._get_tracking_url(cr, uid, mail, partner, context=context) if tracking_url: body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div') return body
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None): """ Override to add the tracking URL to the body. """ body = super(MailMail, self).send_get_mail_body(cr, uid, mail, partner=partner, context=context) # prepend <base> tag for images using absolute urls domain = self.pool.get("ir.config_parameter").get_param( cr, uid, "web.base.url", context=context) 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) + urllib.parse.urljoin( domain, match.group(2)) # Regex: https://regex101.com/r/aE8uG5/3 body = re.sub('(<img(?=\s)[^>]*\ssrc=["\'])(/[^/][^"\']+)', _sub_relative2absolute, body) # Regex: https://regex101.com/r/kT3lD5/2 body = re.sub( r'(<[^>]+\bstyle=["\'][^"\']+\burl\([\'"]?)(/[^/\'"][^\'")]+)', _sub_relative2absolute, body) # generate tracking URL if mail.statistics_ids: tracking_url = self._get_tracking_url(cr, uid, mail, partner, context=context) if tracking_url: body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div') return body
def add_followers(self): email_from = self.env['mail.message']._get_default_from() for wizard in self: Model = self.env[wizard.res_model] document = Model.browse(wizard.res_id) # filter partner_ids to get the new followers, to avoid sending email to already following partners new_partners = wizard.partner_ids - document.message_partner_ids new_channels = wizard.channel_ids - document.message_channel_ids document.message_subscribe(new_partners.ids, new_channels.ids) model_ids = self.env['ir.model'].search([('model', '=', wizard.res_model)]) model_name = model_ids.name_get()[0][1] # send an email if option checked and if a message exists (do not send void emails) if wizard.send_mail and wizard.message and not wizard.message == '<br>': # when deleting the message, cleditor keeps a <br> # add signature # FIXME 8.0: use notification_email_send, send a wall message and let mail handle email notification + message box signature_company = self.env[ 'res.partner'].get_signature_footer( user_id=self._uid, res_model=wizard.res_model, res_id=wizard.res_id) wizard.message = tools.append_content_to_html( wizard.message, signature_company, plaintext=False, container_tag='div') # send mail to new followers self.env['mail.mail'].create({ 'model': wizard.res_model, 'res_id': wizard.res_id, 'record_name': document.name_get()[0][1], 'email_from': email_from, 'reply_to': email_from, 'subject': _('Invitation to follow %s: %s') % (model_name, document.name_get()[0][1]), 'body_html': '%s' % wizard.message, 'auto_delete': True, 'message_id': self.env['mail.message']._get_message_id( {'no_auto_thread': True}), 'recipient_ids': [(4, id) for id in new_partners.ids] }).send() return {'type': 'ir.actions.act_window_close'}
def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None, user_signature=True): """ Format a standard footer for notification emails (such as pushed messages notification or invite emails). Format: <p>--<br /> Administrator </p> <div> <small>Sent from <a ...>Your Company</a> using <a ...>OpenERP</a>.</small> </div> """ footer = "" if not user_id: return footer # add user signature user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0] if user_signature: if user.signature: signature = user.signature else: signature = "--<br />%s" % user.name footer = tools.append_content_to_html(footer, signature, plaintext=False) # add company signature if user.company_id.website: website_url = ( ("http://%s" % user.company_id.website) if not user.company_id.website.lower().startswith(("http:", "https:")) else user.company_id.website ) company = "<a style='color:inherit' href='%s'>%s</a>" % (website_url, user.company_id.name) else: company = user.company_id.name sent_by = _("Sent by %(company)s using %(odoo)s") signature_company = "<br /><small>%s</small>" % ( sent_by % {"company": company, "odoo": "<a style='color:inherit' href='https://www.odoo.com/'>Odoo</a>"} ) footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag="div") return footer
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')
def get_signature_footer(self, user_id, res_model=None, res_id=None, user_signature=True): """ Generate Footer in mail notifications. """ footer = "" user = self.env['res.users'].browse([user_id]) if user_signature: footer = tools.append_content_to_html(footer, u"<p>{}</p>".format(user.name), plaintext=False) website = user.company_id.website website_url = ('http://%s' % website) if not website.lower().startswith(('http:', 'https:')) else website signature = u"""<br/>-- <br/> Wiadomość wysłana przez <a href='{url}'>{name}</a> poprzez aplikację (C) 2015 GooDoo.ee.""".format( url=website_url, name=user.company_id.name, ) footer = tools.append_content_to_html(footer, signature, plaintext=False, container_tag='div') return footer
def _notify_email(self, cr, uid, ids, message_id, force_send=False, user_signature=True, context=None): message = self.pool['mail.message'].browse(cr, SUPERUSER_ID, message_id, context=context) # compute partners email_pids = self.get_partners_to_email(cr, uid, ids, message, context=context) if not email_pids: return True # 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: if message.model and message.res_id and self.pool.get(message.model) and hasattr(self.pool[message.model], 'message_get_recipient_values'): recipient_values = self.pool[message.model].message_get_recipient_values(cr, uid, message.res_id, notif_message=message, recipient_ids=chunk, context=context) else: recipient_values = self.pool['mail.thread'].message_get_recipient_values(cr, uid, message.res_id, notif_message=message, recipient_ids=chunk, context=context) mail_values = { 'mail_message_id': message.id, 'auto_delete': (context or {}).get('mail_auto_delete', True), 'mail_server_id': (context or {}).get('mail_server_id', False), 'body_html': body_html, 'references': references, } mail_values.update(custom_values) mail_values.update(recipient_values) email_ids.append(self.pool.get('mail.mail').create(cr, uid, mail_values, context=context)) # NOTE: # 1. for more than 50 followers, use the queue system # 2. do not send emails immediately if the registry is not loaded, # to prevent sending email during a simple update of the database # using the command-line. if force_send and len(chunks) < 2 and \ (not self.pool._init or getattr(threading.currentThread(), 'testing', False)): self.pool.get('mail.mail').send(cr, uid, email_ids, context=context) return True
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None): """Return a specific ir_email body. The main purpose of this method is to be inherited to add custom content depending on some module.""" body = mail.body_html # generate access links for notifications or emails linked to a specific document with auto threading link = None if mail.notification or (mail.model and mail.res_id and not mail.no_auto_thread): link = self._get_partner_access_link(cr, uid, mail, partner, context=context) if link: body = tools.append_content_to_html(body, link, plaintext=False, container_tag='div') return body
def get_signature_footer(self, user_id, res_model=None, res_id=None, user_signature=True): """ Format a standard footer for notification emails (such as pushed messages notification or invite emails). Format: <p>--<br /> Administrator </p> <div> <small>Sent from <a ...>Your Company</a> using <a ...>Odoo</a>.</small> </div> """ footer = "" if not user_id: return footer # add user signature user = self.env.user if user_signature: if self.env.user.signature: signature = user.signature else: signature = "--<br />%s" % user.name footer = tools.append_content_to_html(footer, signature, plaintext=False) # add company signature if user.company_id.website: website_url = ('http://%s' % user.company_id.website) if not user.company_id.website.lower().startswith(('http:', 'https:')) \ else user.company_id.website company = "<a style='color:inherit' href='%s'>%s</a>" % (website_url, user.company_id.name) else: company = user.company_id.name sent_by = _('Sent by %(company)s using %(odoo)s') signature_company = '<br /><small>%s</small>' % (sent_by % { 'company': company, 'odoo': "<a style='color:inherit' href='https://www.odoo.com/'>Odoo</a>" }) footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') return footer
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
def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None): """ Format a standard footer for notification emails (such as pushed messages notification or invite emails). Format: <p>--<br /> Administrator </p> <div> <small>Sent by <a ...>Your Company</a> using <a ...>OpenERP</a>.</small> OR <small>Sent by Administrator using <a ...>OpenERP</a>.</small> </div> """ footer = "" if not user_id: return footer # add user signature user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0] if user.signature: signature = plaintext2html(user.signature) else: signature = "--<br />%s" % user.name footer = tools.append_content_to_html(footer, signature, plaintext=False, container_tag='p') # add company signature if user.company_id.website: website_url = ('http://%s' % user.company_id.website) if not user.company_id.website.lower().startswith(('http:', 'https:')) \ else user.company_id.website company = "<a style='color:inherit' href='%s'>%s</a>" % (website_url, user.company_id.name) else: company = user.company_id.name sent_by = _('Sent by %(company)s using %(openerp)s.') signature_company = '<small>%s</small>' % (sent_by % { 'company': company, 'openerp': "<a style='color:inherit' href='https://www.openerp.com/'>OpenERP</a>" }) footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') return footer
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None): """ Override to add the tracking URL to the body. """ body = super(MailMail, self).send_get_mail_body(cr, uid, mail, partner=partner, context=context) # prepend <base> tag for images using absolute urls domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "web.base.url", context=context) 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)) # Regex: https://regex101.com/r/aE8uG5/3 body = re.sub('(<img(?=\s)[^>]*\ssrc=["\'])(/[^/][^"\']+)', _sub_relative2absolute, body) # Regex: https://regex101.com/r/kT3lD5/2 body = re.sub(r'(<[^>]+\bstyle=["\'][^"\']+\burl\([\'"]?)(/[^/\'"][^\'")]+)', _sub_relative2absolute, body) # generate tracking URL if mail.statistics_ids: tracking_url = self._get_tracking_url(cr, uid, mail, partner, context=context) if tracking_url: body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div') return body
def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None): """ Format a standard footer for notification emails (such as pushed messages notification or invite emails). Format: <p>--<br /> Administrator </p> <div> <small>Send by <a ...>Your Company</a> using <a ...>OpenERP</a>.</small> OR <small>Send by Administrator using <a ...>OpenERP</a>.</small> </div> """ footer = "" if not user_id: return footer # add user signature user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0] if user.signature: signature = plaintext2html(user.signature) else: signature = "--<br />%s" % user.name footer = tools.append_content_to_html(footer, signature, plaintext=False, container_tag='p') # add company signature if user.company_id: company = user.company_id.website and "<a style='color:inherit' href='%s'>%s</a>" % (user.company_id.website, user.company_id.name) or user.company_id.name else: company = user.name signature_company = _('<small>Send by %(company)s using %(openerp)s.</small>') % { 'company': company, 'openerp': "<a style='color:inherit' href='https://www.openerp.com/'>OpenERP</a>" } footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') return footer
def _notify(self, cr, uid, msg_id, context=None): """ Send by email the notification depending on the user preferences """ if context is None: context = {} # mail_notify_noemail (do not send email) or no partner_ids: do not send, return if context.get('mail_notify_noemail'): return True # browse as SUPERUSER_ID because of access to res_partner not necessarily allowed msg = self.pool.get('mail.message').browse(cr, SUPERUSER_ID, msg_id, context=context) notify_partner_ids = self.get_partners_to_notify(cr, uid, msg, context=context) if not notify_partner_ids: return True # add the context in the email # TDE FIXME: commented, to be improved in a future branch # quote_context = self.pool.get('mail.message').message_quote_context(cr, uid, msg_id, context=context) mail_mail = self.pool.get('mail.mail') # add signature body_html = msg.body # if quote_context: # body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False) signature = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0].signature or '' if signature: body_html = tools.append_content_to_html(body_html, signature, plaintext=True, container_tag='div') # email_from: partner-user alias or partner email or mail.message email_from if msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0].alias_domain and msg.author_id.user_ids[0].alias_name: email_from = '%s <%s@%s>' % (msg.author_id.name, msg.author_id.user_ids[0].alias_name, msg.author_id.user_ids[0].alias_domain) elif msg.author_id: email_from = '%s <%s>' % (msg.author_id.name, msg.author_id.email) else: email_from = msg.email_from mail_values = { 'mail_message_id': msg.id, 'email_to': [], 'auto_delete': True, 'body_html': body_html, 'email_from': email_from, 'state': 'outgoing', } mail_values['email_to'] = ', '.join(mail_values['email_to']) email_notif_id = mail_mail.create(cr, uid, mail_values, context=context) try: return mail_mail.send(cr, uid, [email_notif_id], recipient_ids=notify_partner_ids, context=context) except Exception: return False