mirror of
https://github.com/bringout/oca-ocb-mail.git
synced 2026-04-21 09:02:01 +02:00
Initial commit: Mail packages
This commit is contained in:
commit
4e53507711
1948 changed files with 751201 additions and 0 deletions
97
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/README.md
Normal file
97
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/README.md
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
Odoo Mass Mailing
|
||||
-----------------
|
||||
|
||||
Easily send mass mailing to your leads, opportunities or customers
|
||||
with Odoo <a href="https://www.odoo.com/app/email-marketing">Email Marketing</a>. Track
|
||||
marketing campaigns performance to improve conversion rates. Design
|
||||
professional emails and reuse templates in a few clicks.
|
||||
|
||||
Send Professional Emails
|
||||
------------------------
|
||||
|
||||
Import database of prospects or filter on existing leads, opportunities and
|
||||
customers in just a few clicks.
|
||||
|
||||
Define email templates to reuse content or specific design for your newsletter.
|
||||
Setup several email servers with their own IP/domain to optimise opening rates.
|
||||
|
||||
Organize Marketing Campaigns
|
||||
----------------------------
|
||||
|
||||
Design, Send, Track by Campaigns with our <a href="https://www.odoo.com/app/email-marketing">Lead Automation</a> app.
|
||||
|
||||
Get real time statistics on campaigns performance to improve your conversion
|
||||
rate. Track mails sent, received, opened and answered.
|
||||
|
||||
Easily manage your marketing campaigns, discussion groups, leads and
|
||||
opportunities in one simple and powerful platform.
|
||||
|
||||
Integrated with Odoo Apps
|
||||
-------------------------
|
||||
|
||||
Get access to mass mailing features from every Odoo app to improve the way your
|
||||
users communicate.
|
||||
|
||||
Send template of emails from Odoo <a href="https://www.odoo.com/app/email-marketing">CRM opportunities</a>, select leads based
|
||||
on marketing segments, send <a href="https://www.odoo.com/app/recruitment">job offers</a> and automate
|
||||
answers to applicants, reuse email template in the lead automation marketing
|
||||
campaigns.
|
||||
|
||||
Answers to your emails appears automatically in the history of every document
|
||||
with the social network module.
|
||||
|
||||
Clean Your Lead Database
|
||||
------------------------
|
||||
|
||||
Get a clean lead database that improves over the time using the performance of
|
||||
your mails. Odoo handle bounce mails efficiently, flag erroneous leads
|
||||
accordingly and gives you statistics on the quality of your leads.
|
||||
|
||||
One click emails send
|
||||
---------------------
|
||||
|
||||
The marketing department will love working on campaigns. But you can also give
|
||||
a one click mass mailing facility to all others users on their own prospects or
|
||||
documents.
|
||||
|
||||
Select a few documents (e.g. leads, support tickets, suppliers, applicants,
|
||||
...) and send emails to their contacts in one click, reusing existing emails
|
||||
templates.
|
||||
|
||||
Follow-up On Answers
|
||||
--------------------
|
||||
|
||||
The chatter feature enables you to communicate faster and more efficiently with
|
||||
your customer. Get documents created automatically (leads, opportunities,
|
||||
tasks, ...) based on answers to your mass mailing campaigns Follow the
|
||||
discussion directly on the business documents within Odoo or via email.
|
||||
|
||||
Get all the negotiations and discussions attached to the right document and
|
||||
relevent managers notified on specific events.
|
||||
|
||||
Campaigns Dashboard
|
||||
-------------------
|
||||
|
||||
Get the insights you need to make smarter marketing campaign. Track statistics
|
||||
per campaign: bounce rates, sent mails, best content, etc. The clear dashboards
|
||||
gives you a direct overview of your campaign performance.
|
||||
|
||||
Fully Integrated With Others Apps
|
||||
---------------------------------
|
||||
|
||||
Define automated actions (e.g. ask a salesperson to call, send an email, ...)
|
||||
based on triggers (no activity since 20 days, answered a promotional email,
|
||||
etc.)
|
||||
|
||||
Optimize campaigns from lead to close, on every channel. Make smarter decisions
|
||||
about where to invest and show the impact of your marketing activities on your
|
||||
company's bottom line.
|
||||
|
||||
Integrate a contact form in your website easily. Forms submissions create leads
|
||||
automatically in Odoo CRM. Leads can be used in marketing campaigns.
|
||||
|
||||
Manage your <a href="https://www.odoo.com/app/crm">sales funnel</a> with no
|
||||
effort. Attract leads, follow-up on phone calls and meetings. Analyse the
|
||||
quality of your leads to make informed decisions and save time by integrating
|
||||
emails directly into the application.
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import controllers
|
||||
from . import models
|
||||
from . import report
|
||||
from . import wizard
|
||||
141
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/__manifest__.py
Normal file
141
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/__manifest__.py
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
{
|
||||
'name': 'Email Marketing',
|
||||
'summary': 'Design, send and track emails',
|
||||
'version': '2.5',
|
||||
'sequence': 60,
|
||||
'website': 'https://www.odoo.com/app/email-marketing',
|
||||
'category': 'Marketing/Email Marketing',
|
||||
'depends': [
|
||||
'contacts',
|
||||
'mail',
|
||||
'utm',
|
||||
'link_tracker',
|
||||
'web_editor',
|
||||
'web_kanban_gauge',
|
||||
'social_media',
|
||||
'web_tour',
|
||||
'digest',
|
||||
],
|
||||
'data': [
|
||||
'security/res_groups_data.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'data/digest_data.xml',
|
||||
'data/ir_attachment_data.xml',
|
||||
'data/ir_config_parameter_data.xml',
|
||||
'data/ir_cron_data.xml',
|
||||
'data/ir_module_data.xml',
|
||||
'data/mailing_data_templates.xml',
|
||||
'data/mailing_list_data.xml',
|
||||
'data/res_users_data.xml',
|
||||
'wizard/mail_compose_message_views.xml',
|
||||
'wizard/mailing_contact_import_views.xml',
|
||||
'wizard/mailing_contact_to_list_views.xml',
|
||||
'wizard/mailing_list_merge_views.xml',
|
||||
'wizard/mailing_mailing_test_views.xml',
|
||||
'wizard/mailing_mailing_schedule_date_views.xml',
|
||||
'report/mailing_trace_report_views.xml',
|
||||
'views/mailing_filter_views.xml',
|
||||
'views/mailing_trace_views.xml',
|
||||
'views/link_tracker_views.xml',
|
||||
'views/mailing_contact_views.xml',
|
||||
'views/mailing_contact_subscription_views.xml',
|
||||
'views/mailing_list_views.xml',
|
||||
'views/mailing_mailing_views.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
'views/utm_campaign_views.xml',
|
||||
'views/mailing_menus.xml',
|
||||
'views/assets.xml',
|
||||
'views/mailing_templates_portal_layouts.xml',
|
||||
'views/mailing_templates_portal_management.xml',
|
||||
'views/mailing_templates_portal_unsubscribe.xml',
|
||||
'views/themes_templates.xml',
|
||||
'views/snippets_themes.xml',
|
||||
'views/snippets/s_alert.xml',
|
||||
'views/snippets/s_blockquote.xml',
|
||||
'views/snippets/s_call_to_action.xml',
|
||||
'views/snippets/s_coupon_code.xml',
|
||||
'views/snippets/s_cover.xml',
|
||||
'views/snippets/s_color_blocks_2.xml',
|
||||
'views/snippets/s_company_team.xml',
|
||||
'views/snippets/s_comparisons.xml',
|
||||
'views/snippets/s_event.xml',
|
||||
'views/snippets/s_features.xml',
|
||||
'views/snippets/s_features_grid.xml',
|
||||
'views/snippets/s_hr.xml',
|
||||
'views/snippets/s_image_text.xml',
|
||||
'views/snippets/s_masonry_block.xml',
|
||||
'views/snippets/s_media_list.xml',
|
||||
'views/snippets/s_numbers.xml',
|
||||
'views/snippets/s_picture.xml',
|
||||
'views/snippets/s_product_list.xml',
|
||||
'views/snippets/s_rating.xml',
|
||||
'views/snippets/s_references.xml',
|
||||
'views/snippets/s_showcase.xml',
|
||||
'views/snippets/s_text_block.xml',
|
||||
'views/snippets/s_text_highlight.xml',
|
||||
'views/snippets/s_text_image.xml',
|
||||
'views/snippets/s_three_columns.xml',
|
||||
'views/snippets/s_title.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/mass_mailing_demo.xml',
|
||||
],
|
||||
'application': True,
|
||||
'assets': {
|
||||
'mass_mailing.mailing_assets': [
|
||||
'mass_mailing/static/src/scss/mailing_portal.scss',
|
||||
'mass_mailing/static/src/js/mailing_portal.js',
|
||||
],
|
||||
'web.assets_backend': [
|
||||
'mass_mailing/static/src/scss/mailing_filter_widget.scss',
|
||||
'mass_mailing/static/src/scss/mass_mailing.scss',
|
||||
'mass_mailing/static/src/scss/mass_mailing_mobile.scss',
|
||||
'mass_mailing/static/src/scss/mass_mailing_mobile_preview.scss',
|
||||
'mass_mailing/static/src/css/email_template.css',
|
||||
'mass_mailing/static/src/views/*.js',
|
||||
'mass_mailing/static/src/js/mailing_m2o_filter.js',
|
||||
'mass_mailing/static/src/js/mass_mailing.js',
|
||||
'mass_mailing/static/src/js/mass_mailing_design_constants.js',
|
||||
'mass_mailing/static/src/js/mass_mailing_mobile_preview.js',
|
||||
'mass_mailing/static/src/js/mass_mailing_html_field.js',
|
||||
'mass_mailing/static/src/js/mailing_mailing_view_form_full_width.js',
|
||||
'mass_mailing/static/src/xml/mailing_filter_widget.xml',
|
||||
'mass_mailing/static/src/xml/mass_mailing.xml',
|
||||
'mass_mailing/static/src/views/*.xml',
|
||||
],
|
||||
'mass_mailing.assets_mail_themes': [
|
||||
'mass_mailing/static/src/scss/themes/**/*',
|
||||
],
|
||||
'mass_mailing.assets_mail_themes_edition': [
|
||||
('include', 'web._assets_helpers'),
|
||||
'web/static/src/scss/pre_variables.scss',
|
||||
'web/static/lib/bootstrap/scss/_variables.scss',
|
||||
'mass_mailing/static/src/scss/mass_mailing.ui.scss',
|
||||
],
|
||||
'web_editor.assets_wysiwyg': [
|
||||
'mass_mailing/static/src/js/snippets.editor.js',
|
||||
'mass_mailing/static/src/js/wysiwyg.js',
|
||||
'mass_mailing/static/src/xml/mass_mailing.editor.xml',
|
||||
'mass_mailing/static/src/scss/mass_mailing.wysiwyg.scss',
|
||||
],
|
||||
'web.assets_common': [
|
||||
'mass_mailing/static/src/js/tours/**/*',
|
||||
],
|
||||
'web.assets_frontend': [
|
||||
'mass_mailing/static/src/js/tours/**/*',
|
||||
],
|
||||
'web.qunit_suite_tests': [
|
||||
'mass_mailing/static/tests/mass_mailing_favourite_filter_tests.js',
|
||||
'mass_mailing/static/src/js/mass_mailing_snippets.js',
|
||||
'mass_mailing/static/src/snippets/s_media_list/options.js',
|
||||
'mass_mailing/static/src/snippets/s_showcase/options.js',
|
||||
'mass_mailing/static/src/snippets/s_rating/options.js',
|
||||
'mass_mailing/static/tests/mass_mailing_html_tests.js',
|
||||
'mass_mailing/static/tests/mailing_mailing_view_form_tests.js',
|
||||
],
|
||||
},
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import main
|
||||
|
|
@ -0,0 +1,296 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import base64
|
||||
import urllib.parse
|
||||
|
||||
from odoo import _, exceptions, http, tools
|
||||
from odoo.http import request, Response
|
||||
from odoo.tools import consteq
|
||||
from lxml import etree
|
||||
from werkzeug.exceptions import BadRequest, NotFound
|
||||
|
||||
|
||||
class MassMailController(http.Controller):
|
||||
|
||||
def _valid_unsubscribe_token(self, mailing_id, res_id, email, token):
|
||||
if not (mailing_id and res_id and email and token):
|
||||
return False
|
||||
mailing = request.env['mailing.mailing'].sudo().browse(mailing_id)
|
||||
return consteq(mailing._unsubscribe_token(res_id, email), token)
|
||||
|
||||
def _log_blacklist_action(self, blacklist_entry, mailing_id, description):
|
||||
mailing = request.env['mailing.mailing'].sudo().browse(mailing_id)
|
||||
model_display = mailing.mailing_model_id.display_name
|
||||
blacklist_entry._message_log(body=description + " ({})".format(model_display))
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# SUBSCRIPTION MANAGEMENT
|
||||
# ------------------------------------------------------------
|
||||
|
||||
# csrf is disabled here because it will be called by the MUA with unpredictable session at that time
|
||||
@http.route(['/mail/mailing/<int:mailing_id>/unsubscribe_oneclick'], type='http', website=True, auth='public',
|
||||
methods=["POST"], csrf=False)
|
||||
def mailing_unsubscribe_oneclick(self, mailing_id, email=None, res_id=None, token="", **post):
|
||||
self.mailing(mailing_id, email=email, res_id=res_id, token=token, **post)
|
||||
return Response(status=200)
|
||||
|
||||
@http.route('/mailing/<int:mailing_id>/confirm_unsubscribe', type='http', website=True, auth='public')
|
||||
def mailing_confirm_unsubscribe(self, mailing_id, email=None, res_id=None, token="", **post):
|
||||
mailing = request.env['mailing.mailing'].sudo().browse(mailing_id)
|
||||
# Check access (note that this will also raise AccessDenied if the mailing does not exist)
|
||||
if not self._valid_unsubscribe_token(mailing_id, res_id, email, str(token)):
|
||||
raise exceptions.AccessDenied()
|
||||
|
||||
unsubscribed_str = _("Are you sure you want to unsubscribe from our mailing list?")
|
||||
# Display list name if list is public
|
||||
if mailing.mailing_model_real == 'mailing.contact':
|
||||
unsubscribed_lists = ', '.join(mailing_list.name for mailing_list in mailing.contact_list_ids if mailing_list.is_public)
|
||||
if unsubscribed_lists:
|
||||
unsubscribed_str = _(
|
||||
'Are you sure you want to unsubscribe from the mailing list "%(unsubscribed_lists)s"?',
|
||||
unsubscribed_lists=unsubscribed_lists
|
||||
)
|
||||
unsubscribe_btn = _("Unsubscribe")
|
||||
|
||||
template = etree.fromstring("""
|
||||
<t t-call="mass_mailing.layout">
|
||||
<div class="container o_unsubscribe_form">
|
||||
<form action="/mailing/confirm_unsubscribe" method="POST" class="col-lg-6 offset-lg-3 mt-4">
|
||||
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
|
||||
<input type="hidden" name="email" t-att-value="email"/>
|
||||
<input type="hidden" name="mailing_id" t-att-value="mailing_id"/>
|
||||
<input type="hidden" name="res_id" t-att-value="res_id"/>
|
||||
<input type="hidden" name="token" t-att-value="token"/>
|
||||
<div id="info_state" class="alert alert-success">
|
||||
<div class="text-center">
|
||||
<p t-out="unsubscribed_str"/>
|
||||
<button type="submit" class="btn btn-primary" t-out="unsubscribe_btn"/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</t>
|
||||
""")
|
||||
return request.env['ir.qweb']._render(template, {
|
||||
'main_object': mailing,
|
||||
'token': token,
|
||||
'email': email,
|
||||
'mailing_id': mailing_id,
|
||||
'unsubscribed_str': unsubscribed_str,
|
||||
'res_id': res_id,
|
||||
'unsubscribe_btn': unsubscribe_btn,
|
||||
})
|
||||
|
||||
# kept for backwards compatibility, must eventually be merged with mailing/<mailing_id>/unsubscribe
|
||||
@http.route('/mailing/confirm_unsubscribe', type='http', website=True, auth='public', methods=['POST'])
|
||||
def mailing_confirm_unsubscribe_post(self, mailing_id, email=None, res_id=None, token="", **post):
|
||||
url_params = urllib.parse.urlencode({'email': email, 'res_id': res_id, 'token': token})
|
||||
url = f'/mail/mailing/{int(mailing_id)}/unsubscribe?{url_params}'
|
||||
return request.redirect(url)
|
||||
|
||||
# todo: merge this route with /mail/mailing/confirm_unsubscribe on next minor version
|
||||
@http.route(['/mail/mailing/<int:mailing_id>/unsubscribe'], type='http', website=True, auth='public')
|
||||
def mailing(self, mailing_id, email=None, res_id=None, token="", **post):
|
||||
mailing = request.env['mailing.mailing'].sudo().browse(mailing_id)
|
||||
if mailing.exists():
|
||||
res_id = res_id and int(res_id)
|
||||
if not self._valid_unsubscribe_token(mailing_id, res_id, email, str(token)):
|
||||
raise exceptions.AccessDenied()
|
||||
|
||||
if mailing.mailing_model_real == 'mailing.contact':
|
||||
# Unsubscribe directly + Let the user choose their subscriptions
|
||||
mailing.update_opt_out(email, mailing.contact_list_ids.ids, True)
|
||||
|
||||
contacts = request.env['mailing.contact'].sudo().search([('email_normalized', '=', tools.email_normalize(email))])
|
||||
subscription_list_ids = contacts.mapped('subscription_list_ids')
|
||||
# In many user are found : if user is opt_out on the list with contact_id 1 but not with contact_id 2,
|
||||
# assume that the user is not opt_out on both
|
||||
# TODO DBE Fixme : Optimise the following to get real opt_out and opt_in
|
||||
opt_out_list_ids = subscription_list_ids.filtered(lambda rel: rel.opt_out).mapped('list_id')
|
||||
opt_in_list_ids = subscription_list_ids.filtered(lambda rel: not rel.opt_out).mapped('list_id')
|
||||
opt_out_list_ids = set([list.id for list in opt_out_list_ids if list not in opt_in_list_ids])
|
||||
|
||||
unique_list_ids = set([list.list_id.id for list in subscription_list_ids])
|
||||
list_ids = request.env['mailing.list'].sudo().browse(unique_list_ids).filtered('active')
|
||||
unsubscribed_list = ', '.join(str(list.name) for list in mailing.contact_list_ids if list.is_public)
|
||||
return request.render('mass_mailing.page_unsubscribe', {
|
||||
'contacts': contacts,
|
||||
'list_ids': list_ids,
|
||||
'opt_out_list_ids': opt_out_list_ids,
|
||||
'unsubscribed_list': unsubscribed_list,
|
||||
'email': email,
|
||||
'mailing_id': mailing_id,
|
||||
'res_id': res_id,
|
||||
'show_blacklist_button': request.env['ir.config_parameter'].sudo().get_param('mass_mailing.show_blacklist_buttons'),
|
||||
})
|
||||
else:
|
||||
opt_in_lists = request.env['mailing.contact.subscription'].sudo().search([
|
||||
('contact_id.email_normalized', '=', email),
|
||||
('opt_out', '=', False)
|
||||
]).mapped('list_id').filtered('active')
|
||||
blacklist_rec = request.env['mail.blacklist'].sudo()._add(email)
|
||||
self._log_blacklist_action(
|
||||
blacklist_rec, mailing_id,
|
||||
_("""Requested blacklisting via unsubscribe link."""))
|
||||
return request.render('mass_mailing.page_unsubscribed', {
|
||||
'email': email,
|
||||
'mailing_id': mailing_id,
|
||||
'res_id': res_id,
|
||||
'list_ids': opt_in_lists,
|
||||
'show_blacklist_button': request.env['ir.config_parameter'].sudo().get_param(
|
||||
'mass_mailing.show_blacklist_buttons'),
|
||||
})
|
||||
return request.redirect('/web')
|
||||
|
||||
@http.route('/mail/mailing/unsubscribe', type='json', auth='public')
|
||||
def unsubscribe(self, mailing_id, opt_in_ids, opt_out_ids, email, res_id, token):
|
||||
mailing = request.env['mailing.mailing'].sudo().browse(mailing_id)
|
||||
if mailing.exists():
|
||||
if not self._valid_unsubscribe_token(mailing_id, res_id, email, token):
|
||||
return 'unauthorized'
|
||||
mailing.update_opt_out(email, opt_in_ids, False)
|
||||
mailing.update_opt_out(email, opt_out_ids, True)
|
||||
return True
|
||||
return 'error'
|
||||
|
||||
@http.route('/mailing/feedback', type='json', auth='public')
|
||||
def send_feedback(self, mailing_id, res_id, email, feedback, token):
|
||||
mailing = request.env['mailing.mailing'].sudo().browse(mailing_id)
|
||||
if mailing.exists() and email:
|
||||
if not self._valid_unsubscribe_token(mailing_id, res_id, email, token):
|
||||
return 'unauthorized'
|
||||
model = request.env[mailing.mailing_model_real]
|
||||
records = model.sudo().search([('email_normalized', '=', tools.email_normalize(email))])
|
||||
for record in records:
|
||||
record.sudo().message_post(body=_("Feedback from %(email)s: %(feedback)s", email=email, feedback=feedback))
|
||||
return bool(records)
|
||||
return 'error'
|
||||
|
||||
@http.route(['/unsubscribe_from_list'], type='http', website=True, multilang=False, auth='public', sitemap=False)
|
||||
def unsubscribe_placeholder_link(self, **post):
|
||||
"""Dummy route so placeholder is not prefixed by language, MUST have multilang=False"""
|
||||
raise NotFound()
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# TRACKING
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@http.route('/mail/track/<int:mail_id>/<string:token>/blank.gif', type='http', auth='public')
|
||||
def track_mail_open(self, mail_id, token, **post):
|
||||
""" Email tracking. """
|
||||
if not consteq(token, tools.hmac(request.env(su=True), 'mass_mailing-mail_mail-open', mail_id)):
|
||||
raise BadRequest()
|
||||
|
||||
request.env['mailing.trace'].sudo().set_opened(domain=[('mail_mail_id_int', 'in', [mail_id])])
|
||||
response = Response()
|
||||
response.mimetype = 'image/gif'
|
||||
response.data = base64.b64decode(b'R0lGODlhAQABAIAAANvf7wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==')
|
||||
|
||||
return response
|
||||
|
||||
@http.route('/r/<string:code>/m/<int:mailing_trace_id>', type='http', auth="public")
|
||||
def full_url_redirect(self, code, mailing_trace_id, **post):
|
||||
# don't assume geoip is set, it is part of the website module
|
||||
# which mass_mailing doesn't depend on
|
||||
country_code = request.geoip.get('country_code')
|
||||
|
||||
request.env['link.tracker.click'].sudo().add_click(
|
||||
code,
|
||||
ip=request.httprequest.remote_addr,
|
||||
country_code=country_code,
|
||||
mailing_trace_id=mailing_trace_id
|
||||
)
|
||||
redirect_url = request.env['link.tracker'].get_url_from_code(code)
|
||||
if not redirect_url:
|
||||
raise NotFound()
|
||||
return request.redirect(redirect_url, code=301, local=False)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# MAILING MANAGEMENT
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@http.route('/mailing/report/unsubscribe', type='http', website=True, auth='public')
|
||||
def turn_off_mailing_reports(self, token, user_id):
|
||||
if not token or not user_id:
|
||||
raise NotFound()
|
||||
user_id = int(user_id)
|
||||
correct_token = consteq(token, request.env['mailing.mailing']._get_unsubscribe_token(user_id))
|
||||
user = request.env['res.users'].sudo().browse(user_id)
|
||||
if correct_token and user.has_group('mass_mailing.group_mass_mailing_user'):
|
||||
request.env['ir.config_parameter'].sudo().set_param('mass_mailing.mass_mailing_reports', False)
|
||||
if user.has_group('base.group_system'):
|
||||
menu_id = request.env.ref('mass_mailing.menu_mass_mailing_global_settings').id
|
||||
return request.render('mass_mailing.mailing_report_deactivated', {'menu_id': menu_id})
|
||||
return request.render('mass_mailing.mailing_report_deactivated')
|
||||
raise NotFound()
|
||||
|
||||
@http.route(['/mailing/<int:mailing_id>/view'], type='http', website=True, auth='public')
|
||||
def view(self, mailing_id, email=None, res_id=None, token=""):
|
||||
mailing = request.env['mailing.mailing'].sudo().browse(mailing_id)
|
||||
if mailing.exists():
|
||||
res_id = int(res_id) if res_id else False
|
||||
if not self._valid_unsubscribe_token(mailing_id, res_id, email, str(token)) and not request.env.user.has_group('mass_mailing.group_mass_mailing_user'):
|
||||
raise exceptions.AccessDenied()
|
||||
|
||||
html_markupsafe = mailing._render_field('body_html', [res_id])[res_id]
|
||||
# Update generic URLs (without parameters) to final ones
|
||||
html_markupsafe = html_markupsafe.replace('/unsubscribe_from_list',
|
||||
mailing._get_unsubscribe_url(email, res_id))
|
||||
|
||||
return request.render('mass_mailing.view', {
|
||||
'body': html_markupsafe,
|
||||
})
|
||||
|
||||
return request.redirect('/web')
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# BLACKLIST
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@http.route('/mailing/blacklist/check', type='json', auth='public')
|
||||
def blacklist_check(self, mailing_id, res_id, email, token):
|
||||
if not self._valid_unsubscribe_token(mailing_id, res_id, email, token):
|
||||
return 'unauthorized'
|
||||
if email:
|
||||
record = request.env['mail.blacklist'].sudo().with_context(active_test=False).search([('email', '=', tools.email_normalize(email))])
|
||||
if record['active']:
|
||||
return True
|
||||
return False
|
||||
return 'error'
|
||||
|
||||
@http.route('/mailing/blacklist/add', type='json', auth='public')
|
||||
def blacklist_add(self, mailing_id, res_id, email, token):
|
||||
if not self._valid_unsubscribe_token(mailing_id, res_id, email, token):
|
||||
return 'unauthorized'
|
||||
if email:
|
||||
blacklist_rec = request.env['mail.blacklist'].sudo()._add(email)
|
||||
self._log_blacklist_action(
|
||||
blacklist_rec, mailing_id,
|
||||
_("""Requested blacklisting via unsubscription page."""))
|
||||
return True
|
||||
return 'error'
|
||||
|
||||
@http.route('/mailing/blacklist/remove', type='json', auth='public')
|
||||
def blacklist_remove(self, mailing_id, res_id, email, token):
|
||||
if not self._valid_unsubscribe_token(mailing_id, res_id, email, token):
|
||||
return 'unauthorized'
|
||||
if email:
|
||||
blacklist_rec = request.env['mail.blacklist'].sudo()._remove(email)
|
||||
self._log_blacklist_action(
|
||||
blacklist_rec, mailing_id,
|
||||
_("""Requested de-blacklisting via unsubscription page."""))
|
||||
return True
|
||||
return 'error'
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# MISCELLANEOUS
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@http.route('/mailing/get_preview_assets', type='json', auth='user')
|
||||
def get_mobile_preview_styling(self):
|
||||
""" This route allows a rpc call to get the styling needed for email template conversion.
|
||||
We do this to avoid duplicating the template."""
|
||||
if not request.env.user.has_group('mass_mailing.group_mass_mailing_user'):
|
||||
raise NotFound
|
||||
return request.env['ir.qweb']._render('mass_mailing.iframe_css_assets_edit')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<template id="digest_mail_main" inherit_id="digest.digest_mail_main">
|
||||
<xpath expr="//div[hasclass('by_odoo')]/t[last()]" position="after">
|
||||
<t t-if="mailing_report_token">
|
||||
–
|
||||
<a t-attf-href="/mailing/report/unsubscribe?token=#{mailing_report_token}&user_id=#{user_id}"
|
||||
target="_blank" style="text-decoration: none;">
|
||||
<span style="color: #8f8f8f;">Turn off Mailing Reports</span>
|
||||
</a>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="0">
|
||||
<!-- Snippets' Default Images -->
|
||||
<record id="mass_mailing.s_cover_default_image" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_cover_default_image.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_cover.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_media_list_default_image_1" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_media_list_default_image_1.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_media_list_1.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_media_list_default_image_2" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_media_list_default_image_2.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_media_list_2.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_media_list_default_image_3" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_media_list_default_image_3.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_media_list_3.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_company_team_default_image_1" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_company_team_default_image_1.png</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_team_member_1.png</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_company_team_default_image_2" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_company_team_default_image_2.png</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_team_member_2.png</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_company_team_default_image_3" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_company_team_default_image_3.png</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_team_member_3.png</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_company_team_default_image_4" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_company_team_default_image_4.png</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_team_member_4.png</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_reference_default_image_1" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_reference_default_image_1.png</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_references_1.png</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_reference_default_image_2" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_reference_default_image_2.png</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_references_2.png</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_reference_default_image_3" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_reference_default_image_3.png</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_references_3.png</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_reference_default_image_4" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_reference_default_image_4.png</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_references_4.png</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_product_list_default_image_1" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_product_list_default_image_1.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_product_1.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_product_list_default_image_2" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_product_list_default_image_2.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_product_2.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_product_list_default_image_3" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_product_list_default_image_3.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_product_3.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_blockquote_default_image" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_blockquote_default_image.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_team_member_2.png</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_image_text_default_image" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_image_text_default_image.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_image_text.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_event_default_image_1" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_event_default_image_1.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_event_1.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_event_default_image_2" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_event_default_image_2.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_event_2.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_masonry_block_default_image_1" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_masonry_block_default_image_1.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_masonry_block_1.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_masonry_block_default_image_2" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_masonry_block_default_image_2.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_masonry_block_2.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_picture_default_image" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_picture_default_image.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_picture.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_text_image_default_image" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_text_image_default_image.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_text_image.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_three_columns_default_image_1" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_three_columns_default_image_1.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_three_cols_1.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_three_columns_default_image_2" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_three_columns_default_image_2.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_three_cols_2.jpg</field>
|
||||
</record>
|
||||
<record id="mass_mailing.s_three_columns_default_image_3" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">s_three_columns_default_image_3.jpg</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/mass_mailing/static/src/img/theme_default/s_default_image_three_cols_3.jpg</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- Enable Mass Mailing Reports -->
|
||||
<function model="ir.config_parameter"
|
||||
name="set_param"
|
||||
eval="('mass_mailing.mass_mailing_reports', 'True')"/>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- Cron that processes the mass mailing queue -->
|
||||
<record id="ir_cron_mass_mailing_queue" model="ir.cron">
|
||||
<field name="name">Mail Marketing: Process queue</field>
|
||||
<field name="model_id" ref="model_mailing_mailing"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model._process_mass_mailing_queue()</field>
|
||||
<field name="user_id" ref="base.user_root" />
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">days</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall" />
|
||||
</record>
|
||||
<!-- Cron that processes the a/b testing -->
|
||||
<record id="ir_cron_mass_mailing_ab_testing" model="ir.cron">
|
||||
<field name="name">Mail Marketing: A/B Testing</field>
|
||||
<field name="model_id" ref="model_utm_campaign"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model._cron_process_mass_mailing_ab_testing()</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">days</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field name="doall" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="0">
|
||||
<record model="ir.module.category" id="base.module_category_marketing_email_marketing">
|
||||
<field name="sequence">19</field>
|
||||
<field name="description">Helps you manage your mass mailing to design
|
||||
professional emails and reuse templates.</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!--
|
||||
Reference: https://litmus.com/community/learning/24-how-to-code-a-responsive-email-from-scratch
|
||||
https://www.campaignmonitor.com/css/link-element/link-in-head/
|
||||
-->
|
||||
<template id="mass_mailing_mail_layout">
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="format-detection" content="telephone=no"/>
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE" />
|
||||
|
||||
<t t-call="mass_mailing.mass_mailing_mail_style"/>
|
||||
|
||||
<!--
|
||||
Prevent Outlook from distorting images with DPI scaling (see
|
||||
https://www.htmlemailcheck.com/knowledge-base/dpi-scaling-in-outlook-2007-2013/):
|
||||
-->
|
||||
<!--[if mso]>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG/>
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<t t-out="body"/>
|
||||
</body>
|
||||
</html>
|
||||
</template>
|
||||
|
||||
<template id="mass_mailing_mail_style">
|
||||
<style>
|
||||
.o_layout * {
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
.o_layout :not(.fa) {
|
||||
font-family: Arial,Helvetica Neue,Helvetica,sans-serif;
|
||||
}
|
||||
/* Remove space around the email design. */
|
||||
html,
|
||||
body {
|
||||
margin: 0 auto !important;
|
||||
padding: 0 !important;
|
||||
height: 100% !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* Stop Outlook resizing small text. */
|
||||
* {
|
||||
-ms-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
/* Stop Outlook from adding extra spacing to tables. */
|
||||
table,
|
||||
td {
|
||||
mso-table-lspace: 0pt !important;
|
||||
mso-table-rspace: 0pt !important;
|
||||
}
|
||||
|
||||
/* Use a better rendering method when resizing images in Outlook IE. */
|
||||
img {
|
||||
-ms-interpolation-mode:bicubic;
|
||||
}
|
||||
|
||||
/* Prevent Windows 10 Mail from underlining links. Styles for underlined links should be inline. */
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
@media screen and (max-width: 768px) {
|
||||
.o_mail_snippet_general .container {
|
||||
width: 100% !important;
|
||||
}
|
||||
.s_header_social table td, .s_header_text_social table td, .s_header_logo table td,
|
||||
.o_mail_block_footer_social td,
|
||||
.s_showcase td,
|
||||
.s_mail_product_list td,
|
||||
.s_references td {
|
||||
text-align: center !important;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1135px) {
|
||||
.o_stacking_wrapper {
|
||||
width: 100% !important;
|
||||
height: unset !important;
|
||||
}
|
||||
td {
|
||||
max-width: inherit !important;
|
||||
}
|
||||
img:only-child:not(.img-fluid) {
|
||||
object-fit: cover;
|
||||
min-width: 100% !important;
|
||||
}
|
||||
.o_desktop_h100 {
|
||||
height: unset !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</template>
|
||||
</data>
|
||||
|
||||
<data noupdate="0">
|
||||
<template id="ab_testing_description" name="Mass Mailing: A/B Test Description">
|
||||
<div name="ab_testing_description" class="mb-2">
|
||||
<t t-if="mailing.ab_testing_completed">
|
||||
<p t-if="mailing.ab_testing_pc == 100">
|
||||
This <t t-out="mailing.mailing_type_description"/> is the winner of the A/B testing campaign and has been sent to all remaining recipients.
|
||||
</p>
|
||||
<p t-else="">The winner has already been sent. Use <b>Compare Version</b> to get an overview of this A/B testing campaign.</p>
|
||||
</t>
|
||||
<t t-elif="mailing.ab_testing_mailings_count >= 2">
|
||||
<p>
|
||||
A sample of <b><t t-out="mailing.ab_testing_pc"/>% of recipients</b> will receive this <b><t t-out="mailing.mailing_type_description"/></b>, and <t t-out="other_ab_testing_pc"/>% receive one of the
|
||||
<b><t t-out="mailing.ab_testing_mailings_count - 1"/> other versions</b> from the same campaign.
|
||||
</p>
|
||||
<p>
|
||||
<t t-if="mailing.ab_testing_winner_selection == 'manual'">Don't forget to send your preferred version</t>
|
||||
<t t-elif="not mailing.ab_testing_schedule_datetime">Since the date and time for this test has not been scheduled, don't forget to manually send your preferred version.</t>
|
||||
<t t-else="">
|
||||
Then on <b><t t-out="mailing.ab_testing_schedule_datetime.strftime('%b %d, %Y')"/></b> the <t t-out="mailing.mailing_type_description"/> having the <b><t t-out="ab_testing_winner_selection_description"/></b> will be sent
|
||||
</t> to the remaining <t t-out="remaining_ab_testing_pc"/>% of recipients.
|
||||
</p>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<p>
|
||||
A sample of <b><t t-out="mailing.ab_testing_pc"/>% of recipients</b> will receive this <b><t t-out="mailing.mailing_type_description"/></b>.
|
||||
</p>
|
||||
<p>Try different variations in the campaign to compare their <t t-out="ab_testing_winner_selection_description"/>.</p>
|
||||
<p>
|
||||
<t t-if="mailing.ab_testing_winner_selection != 'manual'">Once the best version is identified, we will send the best one to the remaining recipients.</t>
|
||||
<t t-else="">
|
||||
The actual <t t-out="mailing.mailing_type_description"/> will be sent to the remaining recipients.
|
||||
</t>
|
||||
</p>
|
||||
</t>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="mass_mailing.mass_mailing_kpi_link_trackers" name="Marketing: mailing link trackers statistic">
|
||||
<div class="global_layout" t-if="link_trackers">
|
||||
<table bgcolor="#ffffff" cellspacing="0" cellpadding="0" width="650" align="center" border="0" style="width: 100%; max-width: 650px;">
|
||||
<tr>
|
||||
<td style="width: 100%;">
|
||||
<table cellspacing="0" cellpadding="0" border="0" width="580" align="center" style="width:100%; max-width:580px;">
|
||||
<tr>
|
||||
<td align="left">
|
||||
<span style="color:#282f33; font-size: 15px; font-weight: bold; line-height: 30px">
|
||||
<t t-esc="'Click Rate Report on %i %s Sent' % (object.expected, mailing_type)"/>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="margin: 0; padding:0;">
|
||||
<table cellspacing="0" cellpadding="0" border="0" width="580" align="center" style="width:100%; max-width:580px;border-collapse: collapse;">
|
||||
<tr style="color: #875a7b; font-size: 16px; font-weight: 500;">
|
||||
<td style="width: 70%;padding: 10px 0; text-align: center; border: 1px solid #e7e7e7;">Button Label</td>
|
||||
<td style="width: 30%;padding: 10px 0; text-align: center; border: 1px solid #e7e7e7;">%Click (Total)</td>
|
||||
</tr>
|
||||
<tr t-foreach="link_trackers" t-as="link_tracker" style="color: #888888; font-size: 15px; font-weight: 300;">
|
||||
<td style="width: 70%;padding: 10px 0; border: 1px solid #e7e7e7;">
|
||||
<a t-att-href="link_tracker.absolute_url" target="_blank" style="color: #56b3b5; text-decoration: none;" t-esc="link_tracker.label or link_tracker.url"/>
|
||||
</td>
|
||||
<td style="width: 30%;padding: 10px 0; text-align: center; border: 1px solid #e7e7e7;">
|
||||
<t t-esc="int(link_tracker.count * 100 / object.sent) if object.sent else 0"/>% (<t t-esc="link_tracker.count"/>)
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="mailing_list_data" model="mailing.list">
|
||||
<field name="name">Newsletter</field>
|
||||
</record>
|
||||
<record id="mass_mailing_contact_0" model="mailing.contact">
|
||||
<field name="name" model="res.users" eval="obj().env.ref('base.user_admin').name"/>
|
||||
<field name="email" model="res.users" eval="obj().env.ref('base.user_admin').email"/>
|
||||
<field name="list_ids" eval="[(6,0,[ref('mass_mailing.mailing_list_data')])]"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,296 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="mass_mail_attach_1" model="ir.attachment">
|
||||
<field name="datas">bWlncmF0aW9uIHRlc3Q=</field>
|
||||
<field name="name">SampleDoc.doc</field>
|
||||
</record>
|
||||
|
||||
<!-- Create Extra Mailing List for Demo -->
|
||||
<record id="mailing_list_1" model="mailing.list">
|
||||
<field name="name">Imported Contacts</field>
|
||||
</record>
|
||||
|
||||
<!-- Create Contacts -->
|
||||
<record id="mass_mail_contact_1" model="mailing.contact">
|
||||
<field name="name">Aristide Antario</field>
|
||||
<field name="email">alexandre.antario@example.com</field>
|
||||
<field name="list_ids" eval="[(6,0,[ref('mass_mailing.mailing_list_data')])]"/>
|
||||
</record>
|
||||
<record id="mass_mail_contact_2" model="mailing.contact">
|
||||
<field name="name">Beverly Bridge</field>
|
||||
<field name="email">beverly.bridge@example.com</field>
|
||||
<field name="list_ids" eval="[(6,0,[ref('mass_mailing.mailing_list_data')])]"/>
|
||||
</record>
|
||||
<record id="mass_mail_contact_3" model="mailing.contact">
|
||||
<field name="name">Carol Cartridge</field>
|
||||
<field name="email">carol.cartridge@example.com</field>
|
||||
<field name="list_ids" eval="[(6,0,[ref('mass_mailing.mailing_list_data'),ref('mass_mailing.mailing_list_1')])]"/>
|
||||
</record>
|
||||
<record id="mass_mail_contact_4" model="mailing.contact">
|
||||
<field name="name">David Dawson</field>
|
||||
<field name="email">david.dawson@example.com</field>
|
||||
</record>
|
||||
<record id="mass_mail_contact_5" model="mailing.contact">
|
||||
<field name="name">Elsa Ericson</field>
|
||||
<field name="email">elsa.ericson@example.com</field>
|
||||
<field name="message_bounce">5</field>
|
||||
<field name="list_ids" eval="[(6,0,[ref('mass_mailing.mailing_list_data')])]"/>
|
||||
</record>
|
||||
<record id="mass_mail_contact_6" model="mailing.contact">
|
||||
<field name="name">Franz Faubourg</field>
|
||||
<field name="email">franz.faubourg@example.com</field>
|
||||
<field name="list_ids" eval="[(6,0,[ref('mass_mailing.mailing_list_1')])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Create Opt-out Records -->
|
||||
<record id="mass_mail_contact_list_rel_1" model="mailing.contact.subscription">
|
||||
<field name="list_id" ref="mass_mailing.mailing_list_data"/>
|
||||
<field name="contact_id" ref="mass_mailing.mass_mail_contact_4"/>
|
||||
<field name="opt_out">True</field>
|
||||
</record>
|
||||
<record id="mass_mail_contact_list_rel_2" model="mailing.contact.subscription">
|
||||
<field name="list_id" ref="mass_mailing.mailing_list_data"/>
|
||||
<field name="contact_id" ref="mass_mailing.mass_mail_contact_6"/>
|
||||
<field name="opt_out">True</field>
|
||||
</record>
|
||||
|
||||
<!-- Create Blacklist Records -->
|
||||
<record id="blacklist_1" model="mail.blacklist">
|
||||
<field name="email">elsa.ericson@example.com</field>
|
||||
</record>
|
||||
|
||||
<!-- Create campaign and mailings -->
|
||||
<record id="utm_source_0" model="utm.source">
|
||||
<field name="name">Newsletter 1</field>
|
||||
</record>
|
||||
<record id="mass_mail_campaign_1" model="utm.campaign">
|
||||
<field name="name">Newsletter</field>
|
||||
<field name="stage_id" ref="utm.campaign_stage_1"/>
|
||||
<field name="user_id" ref="base.user_admin"/>
|
||||
<field name="tag_ids" eval="[(6,0,[ref('utm.utm_tag_1')])]"/>
|
||||
</record>
|
||||
|
||||
<record id="mass_mail_1" model="mailing.mailing">
|
||||
<field name="name">Newsletter 1</field>
|
||||
<field name="subject">Monthly Newsletter</field>
|
||||
<field name="state">done</field>
|
||||
<field name="user_id" ref="base.user_admin"/>
|
||||
<field name="email_from">info@yourcompany.example.com</field>
|
||||
<field name="sent_date" eval="(DateTime.today() - relativedelta(days=5)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="campaign_id" ref="mass_mail_campaign_1"/>
|
||||
<field name="source_id" ref="mass_mailing.utm_source_0"/>
|
||||
<field name="mailing_model_id" ref="base.model_res_partner"/>
|
||||
<field name="mailing_domain" eval="[('parent_id', '=', ref('base.res_partner_4'))]"/>
|
||||
<field name="reply_to_mode">new</field>
|
||||
<field name="reply_to">Info <info@yourcompany.example.com></field>
|
||||
<field name="body_arch" type="html">
|
||||
<div class="o_layout o_default_theme oe_unremovable oe_unmovable" data-name="Mailing">
|
||||
<div class="container o_mail_wrapper oe_unremovable oe_unmovable" style="border-collapse:collapse;">
|
||||
<div class="row">
|
||||
<div class="col o_mail_no_options o_mail_wrapper_td bg-white oe_structure o_editable" style="text-align:left;width:100%;">
|
||||
<div class="o_mail_block_header_logo" data-snippet="s_mail_block_header_logo">
|
||||
<div class="o_mail_snippet_general" style="margin:0px auto 0px auto;background-color:rgb(255, 255, 255);max-width:600px;width:100%;">
|
||||
<div class="container o_mail_h_padding" style="padding:0 20px 0 20px;width:100%;border-collapse:separate;">
|
||||
<div class="row">
|
||||
<div valign="center" width="30%" class="col text-center o_mail_v_padding pb0" style="padding:20px 0 0px 0;vertical-align:middle;text-align:center;">
|
||||
<a href="http://www.example.com" style="text-decoration:none;font-weight:bold;background-color:transparent;color:rgb(100, 89, 116);">
|
||||
<img border="0" src="/mass_mailing/static/src/img/theme_default/s_default_image_header_logo.png" style="border-style:none;height:auto;vertical-align:middle;max-width:400px;width:auto"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_mail_block_footer_separator" data-snippet="s_hr" style="margin:0 20px 0 20px;">
|
||||
<div class="o_mail_snippet_general" style="margin:0px auto 0px auto;background-color:rgb(255, 255, 255);max-width:600px;width:100%;">
|
||||
<div class="container" style="width:100%;border-collapse:separate;">
|
||||
<div class="row">
|
||||
<div valign="top" style="padding:20px 0 20px 0;text-align:left;vertical-align:top;width:100%;" class="col o_mail_v_padding o_mail_no_colorpicker">
|
||||
<div style="background-color:rgb(245, 245, 245);height:2px;width:100%;" class="separator"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_mail_block_text" data-snippet="s_text_block">
|
||||
<div class="o_mail_snippet_general" style="margin:0px auto 0px auto;background-color:rgb(255, 255, 255);max-width:600px;width:100%;">
|
||||
<div class="container" style="width:100%;border-collapse:separate;">
|
||||
<div class="row">
|
||||
<div class="col-12 o_mail_h_padding o_mail_v_padding o_mail_no_colorpicker" style="padding:20px;text-align:left;vertical-align:top;">
|
||||
<p style="margin:0px 0 1rem 0;font-size:14px;">
|
||||
Great stories have personality. Consider telling a great story that provides personality. Writing a story with personality for potential clients will assist with making a relationship connection. This shows up in small quirks like word choices or phrases. Write from your point of view, not from someone else's experience.
|
||||
<br/>Great stories are for everyone even when only written for just one person. If you try to write with a wide general audience in mind, your story will ring false and be bland. No one will be interested. Write for one person. If it’s genuine for the one, it’s genuine for the rest.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_mail_block_footer_social o_mail_footer_social_center" data-snippet="s_mail_block_footer_social">
|
||||
<div class="o_mail_snippet_general" style="margin:0px auto 0px auto;background-color:rgb(255, 255, 255);max-width:600px;width:100%;">
|
||||
<div align="center" class="container" style="border-style:solid none none none;padding:20px 0 20px 0;border-top-color:rgb(245, 245, 245);border-top-width:2px;width:100%;border-collapse:separate;">
|
||||
<div class="row">
|
||||
<div class="col o_mail_footer_links o_default_snippet_text" style="padding:10px 0 10px 0;text-align:center;vertical-align:middle;">
|
||||
<a href="/unsubscribe_from_list" class="btn btn-link o_default_snippet_text" style="text-decoration:none;border-radius:0.25rem;border-style:solid;padding:0px;cursor:pointer;line-height:1.5;font-size:12px;border-start-color:transparent;border-bottom-color:transparent;border-end-color:transparent;border-top-color:transparent;border-start-width:1px;border-bottom-width:1px;border-end-width:1px;border-top-width:1px;user-select:none;vertical-align:middle;white-space:nowrap;text-align:center;font-weight:bold;display:inline-block;background-color:transparent;color:rgb(100, 89, 116);">Unsubscribe</a> |
|
||||
|
||||
<a href="/contactus" class="btn btn-link o_default_snippet_text" style="text-decoration:none;border-radius:0.25rem;border-style:solid;padding:0px;cursor:pointer;line-height:1.5;font-size:12px;border-start-color:transparent;border-bottom-color:transparent;border-end-color:transparent;border-top-color:transparent;border-start-width:1px;border-bottom-width:1px;border-end-width:1px;border-top-width:1px;user-select:none;vertical-align:middle;white-space:nowrap;text-align:center;font-weight:bold;display:inline-block;background-color:transparent;color:rgb(100, 89, 116);">Contact</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col" style="text-align:left;vertical-align:middle;">
|
||||
<p class="o_mail_footer_copy" style="margin:0px 0 1rem 0;text-align:center;font-weight:bold;color:rgb(147, 146, 146);font-size:9px;">
|
||||
<img src="/web_editor/font_to_img/61945/rgb(147,146,146)/9" data-class="fa fa-copyright" style="border-style:none;max-width:100%;width:100%;vertical-align:middle;height: auto; width: auto;"/>2018 All Rights Reserved
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div align="center" class="container" style="width:100%;border-collapse:separate;">
|
||||
<div class="row">
|
||||
<div align="center" style="padding:16px 0 16px 0;" class="col pt16 pb16">
|
||||
Powered by <a target="_blank" href="https://www.odoo.com" style="text-decoration:none;background-color:transparent;color:#875A7B;">Odoo</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</field>
|
||||
<field name="attachment_ids" eval="[(4, ref('mass_mail_attach_1'))]"/>
|
||||
</record>
|
||||
<!-- Generate link tracker information from it -->
|
||||
<function model="mailing.mailing" name="convert_links" eval="[ref('mass_mailing.mass_mail_1')]"/>
|
||||
|
||||
<record id="mass_mail_1_stat_0" model="mailing.trace">
|
||||
<field name="mass_mailing_id" ref="mass_mail_1"/>
|
||||
<field name="message_id">1111000@odoo.com</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="res_id" ref="base.res_partner_address_7"/>
|
||||
<field name="email">billy.fox45@example.com</field>
|
||||
<field name="trace_status">reply</field>
|
||||
<field name="sent_datetime" eval="(DateTime.today() - relativedelta(days=5)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="open_datetime" eval="(DateTime.today() - relativedelta(days=4)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="reply_datetime" eval="(DateTime.today() - relativedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="write_date" eval="(DateTime.today() - relativedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
</record>
|
||||
<record id="mass_mail_1_stat_1" model="mailing.trace">
|
||||
<field name="mass_mailing_id" ref="mass_mail_1"/>
|
||||
<field name="message_id">1111001@odoo.com</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="res_id" ref="base.res_partner_address_13"/>
|
||||
<field name="email">kim.snyder96@example.com</field>
|
||||
<field name="trace_status">reply</field>
|
||||
<field name="sent_datetime" eval="(DateTime.today() - relativedelta(days=5)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="open_datetime" eval="(DateTime.today() - relativedelta(days=2)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="reply_datetime" eval="(DateTime.today() - relativedelta(days=0)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="write_date" eval="(DateTime.today() - relativedelta(days=0)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
</record>
|
||||
<record id="mass_mail_1_stat_2" model="mailing.trace">
|
||||
<field name="mass_mailing_id" ref="mass_mail_1"/>
|
||||
<field name="message_id">1111002@odoo.com</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="res_id" ref="base.res_partner_address_14"/>
|
||||
<field name="email">edith.sanchez68@example.com</field>
|
||||
<field name="trace_status">open</field>
|
||||
<field name="sent_datetime" eval="(DateTime.today() - relativedelta(days=5)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="open_datetime" eval="(DateTime.today() - relativedelta(days=2)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="write_date" eval="(DateTime.today() - relativedelta(days=2)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
</record>
|
||||
<record id="mass_mail_1_stat_3" model="mailing.trace">
|
||||
<field name="mass_mailing_id" ref="mass_mail_1"/>
|
||||
<field name="message_id">1111003@odoo.com</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="res_id" ref="base.res_partner_address_24"/>
|
||||
<field name="email">theodore.gardner36@example.com</field>
|
||||
<field name="trace_status">open</field>
|
||||
<field name="sent_datetime" eval="(DateTime.today() - relativedelta(days=5)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="open_datetime" eval="(DateTime.today() - relativedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="write_date" eval="(DateTime.today() - relativedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
</record>
|
||||
<record id="mass_mail_1_stat_4" model="mailing.trace">
|
||||
<field name="mass_mailing_id" ref="mass_mail_1"/>
|
||||
<field name="message_id">1111004@odoo.com</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="res_id" ref="base.res_partner_address_32"/>
|
||||
<field name="email">sandra.neal80@example.com</field>
|
||||
<field name="trace_status">sent</field>
|
||||
<field name="sent_datetime" eval="(DateTime.today() - relativedelta(days=5)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="write_date" eval="(DateTime.today() - relativedelta(days=5)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
</record>
|
||||
<record id="mass_mail_1_stat_5" model="mailing.trace">
|
||||
<field name="mass_mailing_id" ref="mass_mail_1"/>
|
||||
<field name="message_id">1111005@odoo.com</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="res_id" ref="base.res_partner_address_33"/>
|
||||
<field name="email">julie.richards84@example.com</field>
|
||||
<field name="trace_status">error</field>
|
||||
<field name="sent_datetime" eval="False"/>
|
||||
</record>
|
||||
<record id="mass_mail_1_stat_6" model="mailing.trace">
|
||||
<field name="mass_mailing_id" ref="mass_mail_1"/>
|
||||
<field name="message_id">1111006@odoo.com</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="res_id" ref="base.res_partner_address_34"/>
|
||||
<field name="email">travis.mendoza24@example.com</field>
|
||||
<field name="trace_status">bounce</field>
|
||||
<field name="sent_datetime" eval="(DateTime.today() - relativedelta(days=5)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="write_date" eval="(DateTime.today() - relativedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
</record>
|
||||
<record id="mass_mail_1_stat_7" model="mailing.trace">
|
||||
<field name="mass_mailing_id" ref="mass_mail_1"/>
|
||||
<field name="message_id">1111007@odoo.com</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="res_id" ref="base.res_partner_address_34"/>
|
||||
<field name="email">travis.mendoza24@example.com</field>
|
||||
<field name="trace_status">bounce</field>
|
||||
<field name="sent_datetime" eval="False"/>
|
||||
</record>
|
||||
|
||||
<!-- Generate some clicks -->
|
||||
<function model="link.tracker.click" name="add_click">
|
||||
<value model="link.tracker.code"
|
||||
search="[('link_id.url', '=', 'http://www.example.com')]"
|
||||
use="code"/>
|
||||
<value name="ip">100.01.02.03</value>
|
||||
<value name="country_code">BE</value>
|
||||
<value name="mailing_trace_id" eval="ref('mass_mail_1_stat_0')"/>
|
||||
</function>
|
||||
<function model="link.tracker.click" name="add_click">
|
||||
<value model="link.tracker.code"
|
||||
search="[('link_id.url', '=', 'http://www.example.net/page/contactus')]"
|
||||
use="code"/>
|
||||
<value name="ip">100.01.02.03</value>
|
||||
<value name="country_code">BE</value>
|
||||
<value name="mailing_trace_id" eval="ref('mass_mail_1_stat_0')"/>
|
||||
</function>
|
||||
<function model="link.tracker.click" name="add_click">
|
||||
<value model="link.tracker.code"
|
||||
search="[('link_id.url', '=', 'http://www.example.com')]"
|
||||
use="code"/>
|
||||
<value name="ip">100.01.02.04</value>
|
||||
<value name="country_code">BE</value>
|
||||
<value name="mailing_trace_id" eval="ref('mass_mail_1_stat_1')"/>
|
||||
</function>
|
||||
<function model="link.tracker.click" name="add_click">
|
||||
<value model="link.tracker.code"
|
||||
search="[('link_id.url', '=', 'http://www.example.net/page/contactus')]"
|
||||
use="code"/>
|
||||
<value name="ip">100.01.02.04</value>
|
||||
<value name="country_code">BE</value>
|
||||
<value name="mailing_trace_id" eval="ref('mass_mail_1_stat_0')"/>
|
||||
</function>
|
||||
<function model="link.tracker.click" name="add_click">
|
||||
<value model="link.tracker.code"
|
||||
search="[('link_id.url', '=', 'http://www.example.com')]"
|
||||
use="code"/>
|
||||
<value name="ip">100.01.02.05</value>
|
||||
<value name="country_code">BE</value>
|
||||
<value name="mailing_trace_id" eval="ref('mass_mail_1_stat_2')"/>
|
||||
</function>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="base.default_user" model="res.users">
|
||||
<field name="groups_id" eval="[(4,ref('mass_mailing.group_mass_mailing_user'))]"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
.. _changelog:
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
`trunk (saas-2)`
|
||||
----------------
|
||||
|
||||
- added module
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
Mass Mailing module documentation
|
||||
=================================
|
||||
|
||||
Mass Mailing documentation topics
|
||||
'''''''''''''''''''''''''''''''''
|
||||
|
||||
Changelog
|
||||
'''''''''
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
changelog.rst
|
||||
4969
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/af.po
Normal file
4969
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/af.po
Normal file
File diff suppressed because it is too large
Load diff
4965
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/am.po
Normal file
4965
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/am.po
Normal file
File diff suppressed because it is too large
Load diff
5218
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ar.po
Normal file
5218
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ar.po
Normal file
File diff suppressed because it is too large
Load diff
5073
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/az.po
Normal file
5073
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/az.po
Normal file
File diff suppressed because it is too large
Load diff
4988
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/be.po
Normal file
4988
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/be.po
Normal file
File diff suppressed because it is too large
Load diff
5043
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/bg.po
Normal file
5043
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/bg.po
Normal file
File diff suppressed because it is too large
Load diff
4984
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/bs.po
Normal file
4984
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/bs.po
Normal file
File diff suppressed because it is too large
Load diff
5296
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ca.po
Normal file
5296
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ca.po
Normal file
File diff suppressed because it is too large
Load diff
5168
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/cs.po
Normal file
5168
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/cs.po
Normal file
File diff suppressed because it is too large
Load diff
5142
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/da.po
Normal file
5142
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/da.po
Normal file
File diff suppressed because it is too large
Load diff
5287
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/de.po
Normal file
5287
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/de.po
Normal file
File diff suppressed because it is too large
Load diff
2447
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/el.po
Normal file
2447
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/el.po
Normal file
File diff suppressed because it is too large
Load diff
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/en_GB.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/en_GB.po
Normal file
File diff suppressed because one or more lines are too long
5272
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es.po
Normal file
5272
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es.po
Normal file
File diff suppressed because it is too large
Load diff
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_BO.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_BO.po
Normal file
File diff suppressed because one or more lines are too long
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_CL.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_CL.po
Normal file
File diff suppressed because one or more lines are too long
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_CO.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_CO.po
Normal file
File diff suppressed because one or more lines are too long
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_CR.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_CR.po
Normal file
File diff suppressed because one or more lines are too long
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_DO.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_DO.po
Normal file
File diff suppressed because one or more lines are too long
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_EC.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_EC.po
Normal file
File diff suppressed because one or more lines are too long
5261
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_MX.po
Normal file
5261
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_MX.po
Normal file
File diff suppressed because it is too large
Load diff
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_PE.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_PE.po
Normal file
File diff suppressed because one or more lines are too long
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_PY.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_PY.po
Normal file
File diff suppressed because one or more lines are too long
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_VE.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/es_VE.po
Normal file
File diff suppressed because one or more lines are too long
5233
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/et.po
Normal file
5233
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/et.po
Normal file
File diff suppressed because it is too large
Load diff
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/eu.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/eu.po
Normal file
File diff suppressed because one or more lines are too long
5061
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fa.po
Normal file
5061
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fa.po
Normal file
File diff suppressed because it is too large
Load diff
5286
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fi.po
Normal file
5286
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fi.po
Normal file
File diff suppressed because it is too large
Load diff
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fo.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fo.po
Normal file
File diff suppressed because one or more lines are too long
5287
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fr.po
Normal file
5287
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fr.po
Normal file
File diff suppressed because it is too large
Load diff
1900
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fr_BE.po
Normal file
1900
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fr_BE.po
Normal file
File diff suppressed because it is too large
Load diff
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fr_CA.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/fr_CA.po
Normal file
File diff suppressed because one or more lines are too long
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/gl.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/gl.po
Normal file
File diff suppressed because one or more lines are too long
4977
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/gu.po
Normal file
4977
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/gu.po
Normal file
File diff suppressed because it is too large
Load diff
5111
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/he.po
Normal file
5111
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/he.po
Normal file
File diff suppressed because it is too large
Load diff
5002
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/hi.po
Normal file
5002
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/hi.po
Normal file
File diff suppressed because it is too large
Load diff
5021
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/hr.po
Normal file
5021
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/hr.po
Normal file
File diff suppressed because it is too large
Load diff
5024
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/hu.po
Normal file
5024
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/hu.po
Normal file
File diff suppressed because it is too large
Load diff
4965
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/hy.po
Normal file
4965
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/hy.po
Normal file
File diff suppressed because it is too large
Load diff
5215
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/id.po
Normal file
5215
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/id.po
Normal file
File diff suppressed because it is too large
Load diff
4995
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/is.po
Normal file
4995
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/is.po
Normal file
File diff suppressed because it is too large
Load diff
5272
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/it.po
Normal file
5272
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/it.po
Normal file
File diff suppressed because it is too large
Load diff
5082
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ja.po
Normal file
5082
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ja.po
Normal file
File diff suppressed because it is too large
Load diff
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ka.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ka.po
Normal file
File diff suppressed because one or more lines are too long
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/kab.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/kab.po
Normal file
File diff suppressed because one or more lines are too long
4980
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/km.po
Normal file
4980
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/km.po
Normal file
File diff suppressed because it is too large
Load diff
5104
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ko.po
Normal file
5104
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ko.po
Normal file
File diff suppressed because it is too large
Load diff
2472
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/lb.po
Normal file
2472
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/lb.po
Normal file
File diff suppressed because it is too large
Load diff
4973
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/lo.po
Normal file
4973
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/lo.po
Normal file
File diff suppressed because it is too large
Load diff
5029
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/lt.po
Normal file
5029
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/lt.po
Normal file
File diff suppressed because it is too large
Load diff
5014
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/lv.po
Normal file
5014
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/lv.po
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/mk.po
Normal file
1882
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/mk.po
Normal file
File diff suppressed because one or more lines are too long
4974
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ml.po
Normal file
4974
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ml.po
Normal file
File diff suppressed because it is too large
Load diff
5051
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/mn.po
Normal file
5051
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/mn.po
Normal file
File diff suppressed because it is too large
Load diff
4979
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ms.po
Normal file
4979
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ms.po
Normal file
File diff suppressed because it is too large
Load diff
5016
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/nb.po
Normal file
5016
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/nb.po
Normal file
File diff suppressed because it is too large
Load diff
1879
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ne.po
Normal file
1879
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ne.po
Normal file
File diff suppressed because one or more lines are too long
5271
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/nl.po
Normal file
5271
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/nl.po
Normal file
File diff suppressed because it is too large
Load diff
4969
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/no.po
Normal file
4969
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/no.po
Normal file
File diff suppressed because it is too large
Load diff
5296
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/pl.po
Normal file
5296
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/pl.po
Normal file
File diff suppressed because it is too large
Load diff
5021
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/pt.po
Normal file
5021
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/pt.po
Normal file
File diff suppressed because it is too large
Load diff
5253
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/pt_BR.po
Normal file
5253
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/pt_BR.po
Normal file
File diff suppressed because it is too large
Load diff
5279
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ro.po
Normal file
5279
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ro.po
Normal file
File diff suppressed because it is too large
Load diff
5212
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ru.po
Normal file
5212
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ru.po
Normal file
File diff suppressed because it is too large
Load diff
5076
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sk.po
Normal file
5076
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sk.po
Normal file
File diff suppressed because it is too large
Load diff
5075
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sl.po
Normal file
5075
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sl.po
Normal file
File diff suppressed because it is too large
Load diff
4965
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sq.po
Normal file
4965
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sq.po
Normal file
File diff suppressed because it is too large
Load diff
5161
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sr.po
Normal file
5161
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sr.po
Normal file
File diff suppressed because it is too large
Load diff
1885
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sr@latin.po
Normal file
1885
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sr@latin.po
Normal file
File diff suppressed because one or more lines are too long
5261
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sv.po
Normal file
5261
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sv.po
Normal file
File diff suppressed because it is too large
Load diff
4965
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sw.po
Normal file
4965
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/sw.po
Normal file
File diff suppressed because it is too large
Load diff
4965
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ta.po
Normal file
4965
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/ta.po
Normal file
File diff suppressed because it is too large
Load diff
5165
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/th.po
Normal file
5165
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/th.po
Normal file
File diff suppressed because it is too large
Load diff
5274
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/tr.po
Normal file
5274
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/tr.po
Normal file
File diff suppressed because it is too large
Load diff
5238
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/uk.po
Normal file
5238
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/uk.po
Normal file
File diff suppressed because it is too large
Load diff
5221
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/vi.po
Normal file
5221
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/vi.po
Normal file
File diff suppressed because it is too large
Load diff
5093
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/zh_CN.po
Normal file
5093
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/zh_CN.po
Normal file
File diff suppressed because it is too large
Load diff
5064
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/zh_TW.po
Normal file
5064
odoo-bringout-oca-ocb-mass_mailing/mass_mailing/i18n/zh_TW.po
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import ir_http
|
||||
from . import ir_mail_server
|
||||
from . import ir_model
|
||||
from . import link_tracker
|
||||
from . import mailing_contact_subscription
|
||||
from . import mailing_contact
|
||||
from . import mailing_list
|
||||
from . import mailing_trace
|
||||
from . import mailing
|
||||
from . import mailing_filter
|
||||
from . import mail_mail
|
||||
from . import mail_render_mixin
|
||||
from . import mail_thread
|
||||
from . import res_company
|
||||
from . import res_config_settings
|
||||
from . import res_partner
|
||||
from . import res_users
|
||||
from . import utm_campaign
|
||||
from . import utm_medium
|
||||
from . import utm_source
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class IrHttp(models.AbstractModel):
|
||||
_inherit = "ir.http"
|
||||
|
||||
@classmethod
|
||||
def _get_translation_frontend_modules_name(cls):
|
||||
mods = super()._get_translation_frontend_modules_name()
|
||||
return mods + ["mass_mailing"]
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import _, fields, models
|
||||
from odoo.tools.misc import format_date
|
||||
|
||||
|
||||
class IrMailServer(models.Model):
|
||||
_name = 'ir.mail_server'
|
||||
_inherit = ['ir.mail_server']
|
||||
|
||||
active_mailing_ids = fields.One2many(
|
||||
comodel_name='mailing.mailing',
|
||||
inverse_name='mail_server_id',
|
||||
string='Active mailing using this mail server',
|
||||
readonly=True,
|
||||
domain=[('state', '!=', 'done'), ('active', '=', True)])
|
||||
|
||||
def _active_usages_compute(self):
|
||||
def format_usage(mailing_id):
|
||||
base = _('Mass Mailing "%s"', mailing_id.display_name)
|
||||
if not mailing_id.schedule_date:
|
||||
return base
|
||||
details = _('(scheduled for %s)', format_date(self.env, mailing_id.schedule_date))
|
||||
return f'{base} {details}'
|
||||
|
||||
usages_super = super(IrMailServer, self)._active_usages_compute()
|
||||
default_mail_server_id = self.env['mailing.mailing']._get_default_mail_server_id()
|
||||
for record in self:
|
||||
usages = []
|
||||
if default_mail_server_id == record.id:
|
||||
usages.append(_('Email Marketing uses it as its default mail server to send mass mailings'))
|
||||
usages.extend(map(format_usage, record.active_mailing_ids))
|
||||
if usages:
|
||||
usages_super.setdefault(record.id, []).extend(usages)
|
||||
return usages_super
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models, _
|
||||
|
||||
|
||||
class IrModel(models.Model):
|
||||
_inherit = 'ir.model'
|
||||
|
||||
is_mailing_enabled = fields.Boolean(
|
||||
string="Mailing Enabled",
|
||||
compute='_compute_is_mailing_enabled', search='_search_is_mailing_enabled',
|
||||
help="Whether this model supports marketing mailing capabilities (notably email and SMS).",
|
||||
)
|
||||
|
||||
def _compute_is_mailing_enabled(self):
|
||||
for model in self:
|
||||
model.is_mailing_enabled = getattr(self.env[model.model], '_mailing_enabled', False)
|
||||
|
||||
def _search_is_mailing_enabled(self, operator, value):
|
||||
if operator not in ('=', '!='):
|
||||
raise ValueError(_("Searching Mailing Enabled models supports only direct search using '='' or '!='."))
|
||||
|
||||
valid_models = self.env['ir.model']
|
||||
for model in self.search([]):
|
||||
if model.model not in self.env or model.is_transient():
|
||||
continue
|
||||
if getattr(self.env[model.model], '_mailing_enabled', False):
|
||||
valid_models |= model
|
||||
|
||||
search_is_mailing_enabled = (operator == '=' and value) or (operator == '!=' and not value)
|
||||
if search_is_mailing_enabled:
|
||||
return [('id', 'in', valid_models.ids)]
|
||||
return [('id', 'not in', valid_models.ids)]
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue