Before this commit:
when new snippet is drop in mass_mailing after first delete everything and
exiting from codeview a traceback occurs.
After this commit:
Now, a new snippet can be dropped in empty mass_mailing.
Task-3178818
closesodoo/odoo#129865
X-original-commit: 8e93f3c65ada549c51b841d1f39a3422be6f3e27
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Improve low-level checks of recipients in mail asserts. Sometimes 'email_to'
cannot be easily deduced from given input (partners, records customers, ...)
when some record -> email transformations are involved e.g. when dealing
with multiple emails input, double encapsulation, ...
Those tools are about to be used in upcoming tests and fixes.
Task-3438381 (TestMail: backport tools)
Prepares Task-2612945 (Mail: Defensive email formatting)
X-original-commit: bdbe846329ed51e4c5e3b75740e8f594edf7b138
Part-of: odoo/odoo#129839
PURPOSE
Purpose of this commit is to backport some improvements done in mail testing
tools done in newer versions. Some of them are required for incoming tests
to be added, other just to try to ease writing tests across versions.
SPECIFICATIONS
Partial backport of odoo/odoo@94208cb8b4
Improve finding outgoing mails and emails when batch methods (mass mailing)
create similar emails, that can be distinguished notably by the subject
in addition to from / to.
Partial backport of odoo/odoo@c98f259736
Add a method to check MailMail, based on a given record. When having duplicates
to differentiate in a given mailing, having just recipients is not sufficient
as multiple emails may match a given recipients list. Checking model / res_id
is another method for finding emails.
Partial backport of odoo/odoo@a3e404e17e
Add some information and values propagation in some custom asserts in mail
test tooling.
Partial backport of odoo/odoo@b915617569
Allow to return <mail.mail> records and found outgoing emails when using
asserts. It eases doing checks in some specific tests e.g. checking
notification layout usage in emails. Indeed this is quite low level and
does not really deserves its own assert tooling methods.
Partial backport of odoo/odoo@bbf4783ac6
Improve checks and asserts done when asserting content of produced
mailing content (mails, traces, ...).
Task-3438381 (TestMail: backport tools)
Prepares Task-2612945 (Mail: Defensive email formatting)
X-original-commit: 2bc28c804a92f206133c352c046dcdd4971fd4a6
Part-of: odoo/odoo#129839
Base64 img src were converted to inline images but background images
were omitted. This commit fixes that.
opw-3374767
closesodoo/odoo#129645
X-original-commit: a10d1d305696f7ece38e7d3446c067338c411ea2
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Better tag selection
====================
The block was originally hooked onto the `external` tag under the
assumption that this was the tag used to allow external requests.
It's not, it's the tag for the "external" test suite, which is only
one of the test suites allowed to perform external calls. Hook again
onto `standard`, this might have some false positives (allow requests
which we'd rather block), but it should have a lot less false
negatives (block requests we want to allow).
Make Overrides Easier
=====================
Currently `_request_handler` raises a regular `ConnectionError`, this
is an issue because it passes some requests through, which could
themselves trigger genuine `ConnectionError`.
When overriding `_request_handler` to implement fallbacks for bespoke
URL mocks, these two cases need to be distinguishable as overrides
likely want to handle blocked requests, not actual failures.
Therefore `_request_handler` should a dedicated exception. This
exception should be a subclass of `ConnectionError`, so that blocked
requests are treated as regular connection failures by normal Odoo
code.
Class-scope
===========
Originally `_request_handler` was scoped on the instance with the idea
that it'd be a `mock` object, which individual tests could
`configure_mock`. This turned out not to work correctly, because
`Mock.side_effect` does not receive a `self`, hence the `Session` was
inaccessible and it was not possible to passthrough local requests.
While I moved to a regular `lambda` (because a direct method didn't
work either), I forgot to remove the `request_mock` attribute, and
didn't think that the block could now be lifted up to the class
scope. Doing this, requests performed during a "standard" test case's
`setUpClass` are now also blocked, which they very much should be.
closesodoo/odoo#128977
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Base64 images get converted to attachments. However, if they are in a
mso comment, they were not converted.
X-original-commit: 2fa0694227a7beb6a000c2e8219fdd8c073cf348
Part-of: odoo/odoo#124465
Prior to this fix, elements with background images were converted to
images via the html2canvas library. This made them work in Outlook at
the cost of several tradeoffs:
- the process was slow and asynchronous
- there could be no interactivity (links, buttons, etc.) in the
converted element
- responsive behavior was wonky: if only a slice of the image was shown
when it was converted (due to background-size cover behavior), the
rest was lost so if more width was needed in mobile, we would be
zooming on that slice, making it sometimes irrelevant and pixelated
This replaces all that with a conversion to VML, which is a vector
format supported by Outlook. This conversion is done only for Outlook,
which means that all other clients are getting the original background
element again.
There is a way to keep the background-size cover behavior in VML, using
the "aspect" attribute with value "atleast" but this only works on
v-fill elements and sadly putting the image on a v-fill element bugs in
Windows Mail (which is the default mail client on Windows 10 and 11) and
this client can't be singled out of mso conditionals. To get around this
issue, since this is only for desktop clients, we assume the width of
the screen to be large and mimick the cover behavior by cropping the
image to the target size. This allows us to put the image on the v-image
element and have proper rendering in Outlook and Windows Mail on
desktop.
Note:
When retrieving the image by URL in Python in order to crop it, we need
to ensure we have an absolute path. This is done - perhaps seemingly
naively - by checking if the URL contains '//'. Here's the reasoning
behind that choice. To check if a URL is absolute, we could use
`urllib.parse.urlparse` and check if it has a scheme but that would lead
to `www.odoo.com/path` being considered relative (and thus we'd add a
host to the URL even though there's already one). Instead, we could
check it it has a netloc but that would lead to the same issue since the
documentation of `urlparse` says:
> Following the syntax specifications in
[RFC 1808](https://datatracker.ietf.org/doc/html/rfc1808.html), urlparse
recognizes a netloc only if it is properly introduced by ‘//’.
Still, it would be more technically correct since `//some/path` would be
considered absolute (which it should be since it resolves to
`<current_scheme>//some/path`).
Base on that documentation, it seems that simply checking if the URL
contains '//' is pretty much equivalent to checking if it has a scheme,
with the double advantage that it's simpler and that it works for
`//some/path` as well. However, note that it doesn't solve the issue of
`www.odoo.com/path`.
In summary, here are the results with the current method:
```
http://www.odoo.com/path -> http://www.google.com/path // OK
some/path -> http://localhost:8069/some/path // OK
/some/path -> http://localhost:8069/some/path // OK
//some/path -> //some/path // OK
www.odoo.com/path -> http://localhost:8069/www.google.com/path // WRONG
```
X-original-commit: 9561ba31917024825705c876442139405e7a7957
Part-of: odoo/odoo#124465
In this commit we remove overrides of create / write on subscription model to
make 'unsubscription_date' an editable computed field instead.
While being there, tracking on blacklist model is ordered, as a side dish
to prepare other mailing improvements.
Prepares Task-2150462 (Mass Mailing: Improve subscription management)
closesodoo/odoo#122106
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Rename tours, reorder tests and test files, perform a quick linting of UI
or tours related tests. Purpose is to prepare files to add some new tests
in mass mailing.
Each tour now belongs to a single file to ease maintenance and update as
well as seeing feature coverage. No real change should occur with this
commit except some test data (setup, test input).
Prepares Task-2150462 (Mass Mailing: Improve subscription management)
Part-of: odoo/odoo#122106
This commit adds a basic tour for creating a mailing from a campaign's
"Mailing" tab, via the list view of the `mailing_mail_ids` one2Many field.
closesodoo/odoo#119918
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
* = bus, calendar, crm_livechat, hr, hr_holidays, im_livechat, mail_bot,
mass_mailing, privacy_lookup, test_discuss_full, test_mail,
test_mail_full, website_crm_livechat, website_livechat, base
In preparation of splitting discuss and mail modules.
Part of task-3265211
closesodoo/odoo#118354
Related: odoo/upgrade#4553
Related: odoo/enterprise#39661
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
A mailing based on the "basic" theme is a particular case where there is
no SnippetsMenu and the floating toolbar is present instead. This commit
includes a tour for this previously untested case/flow.
Part-of: odoo/odoo#117166
Bug
===
Since 6185f14807 we check the <mail.mail>
existence before marking the <mailing.trace> as opened, but since
57ae1b9b8b61f5f4719a8a81e9d0d21fab58cfda we remove the <mail.mail>
automatically when we send them.
The result is that this endpoint always raise a 500 error.
To be: the <mail.mail> existence shouldn't be checked in this endpoint
(the token is valid for the raw integer id).
Task-3234519
closesodoo/odoo#115842
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
When the user schedules a datetime for the emailing campaign, it creates
a ir.cron.trigger entry that should run the Mail Marketing: Process queue.
This fix tries to take this into account to calculate a next_departure
datetime closer to the true moment job will be run.
When the schedule datetime is between now() and the next call datetime
for the cron job (nextcall field), current logic will always chose
nextcall given the use of max(). This can be confusing for the end-user
as the information banner in the form view will indicate the nextcall date,
which in some cases can be way farther in the futur.
While a ir.cron.trigger is not a 100% guarantee that the cron job will
run at that specific time, it will give better feedback to the user for
when he should expected his mailing campaign to be send out.
Main changes:
simplified logic in _compute_next_departure to take into account
the implicit creation of cron.triggers (methods action_launch and
action_schedule)
added test_mailing_next_departure to simulate "Send", "Cancel" and
"Schedule Date" buttons on mass_mailing form view. Check ir.cron.trigger
model for presence of triggers for cron job "Mail Marketing: Process queue"
and assert if cron.trigger was created as expected
opw-3137819
original commit b98494d
some trailing whitespace got linted from commit 4cebf5
closesodoo/odoo#115068
X-original-commit: f82dec9e6433dc027391978420237efaa1d0be7d
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
Purpose
=======
The bounce emails aren't stored in Odoo, which can complicate the
debugging of the email sending.
Now, we store this bounce email, and we allow the user to read it from
the interface, so he can easily find the issue when an email sending
fail.
Specifications
==============
The bounce email is stored on the mail notification for standard emails
sending, and on the mailing traces when using mass mailing.
For some email providers (e.g. Yahoo), the "Final-Recipient" header is
not present. Normally, it allows us to retrieve the original recipient
of the email which bounced and then the partner. So if this header is
not there in a bounce email, we take the first recipient of the parent
<mail.message>.
Change the way that we parse the email body, for the bounce email.
For most email providers, the first mail body is the one that contains
the error and the next one contains the parent email body. So, the
current logic might ignore this body for Outlook and Yahoo.
Task-2116296
closesodoo/odoo#105923
Related: odoo/enterprise#34051
Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
RATIONALE
Improve usage of composer in comment or email mode: support batch-posting in
comment, support more configuration from templates, improve global model.
SPECIFICATIONS
Support a real res_ids field on mail.compose.message model. Instead of relying
on active_ids from context, store it once for all at composer level and use
it in code. Active_ids usage is still done at default_get level, using it to
populate the field.
Improve usage of domain, renamed to res_domain to match other document related
fields naming. Add support of a res_domain_user_id field allowing to set the
user from which the domain should be evaluated.
Composer now runs on a list of IDs. Mass mail mode and comment mode are now
distinct from running on a singleton or on more records. Rendered or raw
mode is not triggered by
* mass mailing mode: always display raw mode, whatever the number of records;
* comment mode: display rendered mode when having a single record (like the
previous comment mode). Display raw mode when having either no records
either at least two records.
Task-3035101 (Mail: Support batch-posting from composer)
Part-of: odoo/odoo#99482
Purpose is to rewrite value generation as code is messy with a lot of dict
updates, rewriting key on top of existing keys until reaching the final value.
In this commit we better split computation, to have computation that is static
(currently, posting a comment as composer holds final code) separated from
dynamic computation (posting a mass mailing, as rendering is done based on
qweb or inline template value).
It allows to better understand how composer and template fields are used when
sending emails or posting messages. This commit should not change anything
functionally, even if some values are weirdly computed. Future commits will
improve support of composer / template fields, notably through computed field
and less cross computation.
Also split sending methods: do a mailing in batch in case of mass mailing
(allowing commit per batch), and simply loop on records to post a message
in case of comment (or mass post).
Task-2710804 (Mail: Clean MailThread Posting API)
Prepares Task-2088884 (Mail: Use editable computed stored fields in composer)
Part-of: odoo/odoo#99482
In this commit we add a method to check MailMail, based on a given record.
When having duplicates to differentiate in a given mailing, having just
recipients is not sufficient as multiple emails may match a given recipients
list. Checking model / res_id is another method for finding emails.
This will be used notably to add tests for exclusion list and duplicates
management in standard mail composer, outside of mass mailing context.
While being at it, use subTests when having loops checking values. That
way it is easier to fix tests that have several failing values in the same
global assertMailMail_* .
Task-3132710 (Mail: Configurable composer)
Part-of: odoo/odoo#99482
When there is not enough recipients for the A/B testing percentage,
we pick a minimum of one recipients (if there is at least one) to
avoid sending a/b test to no one.
task-2713198
closesodoo/odoo#107488
X-original-commit: e1fa7b10250efc790452f02490ab84d2183698ff
Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
Before this commit
- When we were comparing versions, there was no such filter as
mailing type. Due to this it will display both SMS and mail
type records in it.
With this commit
- We have added '('mailing_type', '=', self.mailing_type)' in domain
of compare version.
TaskId-2713198
X-original-commit: e8542e24597ad25b68104c03d4d4ed41e1efac82
Part-of: odoo/odoo#107488
Before this commit when creating a mailing contact with a mailing
list opt_out at creation the unsubscription_date wasn't set.
Indeed, from the mailing contact view the mailing list uses an
editable list that passes all the values at create even when not set
contrary to when one update the contact only the changed values are
passed. This commit fix this issue.
Task-3070852
closesodoo/odoo#106682
X-original-commit: e7c22094068ce5cdff7f30178cea6d4f39f09137
Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
Signed-off-by: Hoste Patrick (pko) <pko@odoo.com>
Right now, on an existing mailing, if we enable the a/b testing and there's
already a campaign set, we remove it and add a newly create campaign that
matches the name of current mailing. Also, while duplicating a campaign, the
`ab_testing_completed` field should not be copied over.
This commit improves the behavior and only creates a new campaign if there's
not one already set on a record, and by preventing `ab_testing_completed`
from being copied.
TaskID-2653806
Part-of: odoo/odoo#77768
When importing email in mass mailing through the form (not with an excel file),
incorrect email lines were concatenated with the following next valid email
line, resulting to an incorrect import.
This solves the problem by ignoring incorrect email lines.
Technical note: the test test_mailing_contact_import has been slightly modified
to include invalid lines in the text to import, not only at the end but also at
the beginning and in the middle (the test fails before the fix and not after).
Task-2924241
X-original-commit: bd4a933f2b3259c3482b811227de0e06c7018969
Part-of: odoo/odoo#97560
In the web client, in a real use case, it's not possible
to write on fields which are invisible,
as it's not possible to write on fields which are readonly.
This is a first step in the goal to change the behavior
of the `groups=` attribute in the back-end views,
to remove them for the view instead of making them invisible.
This is mainly to reduce the diff of the revision that will introduce
the mentioned above behavior change.
As nodes with `groups=` will be removed from the view
when the user doesn't have the group, it's no longer possible
to set a value on a field having a `groups=` the user doesn't have
in the `Form` test class, as the field will no longer be at all in the
view.
However, these unit tests shouldn't have been able to set values
on invisible fields in the first place.
This revision therefore aims to correct the unit tests setting value
on fields which were invisible because the user executing the
test was not part of the required group(s) for these fields
to be visible in the view.
closesodoo/odoo#94337
Related: odoo/enterprise#28936
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
Improve link tracker tests :
* add missing test for trace tracking in mass mailing. We generate a trace
and find a short link in it, in order to test the tracking in mass
mailing;
* add tests for side effects of mass mailing routes: update of trace status,
clicks, ...
* wrap base url locally instead of globally in MockTracker class to ease
specific setup in classes;
Prepares Task-2150462 (Mass Mailing: Unsubscribe flow improvement)
closesodoo/odoo#94660
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
When we use the "Retry" button in case of a failed SMS mailing, it puts
the mailing back to the queue, which will be processed when on the next
cron call of `Mail Marketing: Process queue` (generally on the next
day). However, it should immediately generate a cron trigger in this
case so that SMS(s) can be sent right away.
The same goes for Email Marketing, where it should immediately generate
a cron trigger so the mailing can be sent immediately.
With this commit, instead of simply putting the mailing back to the
queue, we utilize the method `action_put_in_queue` which immediately
generates the cron trigger in both cases.
taskID-2760101
closesodoo/odoo#94269
X-original-commit: 572a7effb271ad134bb936751292668ae7b2b590
Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Add a model and a test allowing to test the seen list using raw SQL based
on partner_id field. Test indicates a not stored partner_id field currently
crashes beyond redemption.
Task-2852943
X-original-commit: a15bda3bed339a0ac422a3c82ec9cc295a11a785
Part-of: odoo/odoo#94532
There was an issue when a mailing save failed: the edited body of the mailing
was lost.
Impacted versions:
- 15.0 and higher
Steps to reproduce:
1. Create a mailing "Start from scratch" and add some elements
2. Do not fill in the subject (or at least one required field)
3. Save (it should fail because of the empty required field)
Current behavior:
- The edited template is lost
Expected behavior:
- Keep the edited template even if the save failed
This commit fixes the problem by properly awaiting the promise _doAction so that
the field's value will be set correctly.
The testing tour `mass_mailing_editor_tour` is updated to check that the
body_arch is kept after a failed save.
This issue was introduced in 15.0 with:
95754eb6a4
Task-2856742
closesodoo/odoo#92186
X-original-commit: bc81178d541587f757d76932449d35ed426699aa
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Before this commit, this bug was present in edit mode:
- Go into edit mode on an empty page.
- Click on the THEME tab on the right.
- Click on the empty "DRAG BUILDING BLOCKS HERE" area.
- Click on the THEME tab again.
- The content of THEME is empty.
It was because since this commit [1], clicking on an 'oeStructure'
activate the Blocks tab but without updating the options in the tabs.
Another similar bug was present when clicking the style tab and then
clicking on the theme tab.
About the first bug, actually a call of '_updateRightPanelContent' is
already done in '_activateSnippet()' (and the Blocks tab is activate by
default) so we only have to use '_activateSnippet(false)' to activate
the Blocks tab. This commit also remove '_updateRightPanelContent' from
the click event of the Blocks tab where it was not necessary.
For the second bug, we can't do the same fix, because it's not possible
to activate the options tab with only '_activateSnippet(false)' so we
had to combine the two functions.
[1]: https://github.com/odoo/odoo/commit/fbe048c202ff7878984adf26bef0651a45851f0a
task-2794266
closesodoo/odoo#88537
X-original-commit: 52d32e26c34bef10823582ef5c1f840492b73d7a
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Purpose
=======
Ensure that the names of the UTMs models (campaign, medium and source)
are unique.
If not, generate automatically an unique name.
The name field is no more translatable; it makes no sense to translate
a technical which will be added in the URL, and can even cause issues
(the UTM record is not recognized because of the translation).
For the campaign, we keep a "translatable" name which is called
"title".
For the UTM source, use a mixin to generate automatically the name of
the source based on the content (_rec_name) of the record. So we remove
the override of create / write / copy in the different models and
ensure consistency between those models.
Task-2245823
closesodoo/odoo#60501
Related: odoo/enterprise#21882
Related: odoo/upgrade#1863
Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
Purpose
=======
Allows the user to easily import mailing contacts.
Specification
=============
Add a button "import" on the top of the mailing contact list view. This
button open the wizard <mailing.contact.import>.
So the user can select the mailing list and import his contacts with a
text field, one line for each contact.
Task-2703521
closesodoo/odoo#82333
Related: odoo/enterprise#23263
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This improves performance of `classToStyle` by first selecting which
nodes and which rules will be concerned.
When parsing the css rules, we computed their specificity and normalized
their styles one by one. This applies these processes only on the
concerned rules, all at once.
X-original-commit: bb28624dcd69efe1aff546b37e66c05c001a5927
Part-of: odoo/odoo#84513
Co-authored-by: Nicolas Bayet <nby@odoo.com>
Co-authored-by: Antoine Guenet <age@odoo.com>
Activities and mailing trace are linked to documents through a model and
a many2one reference field. The latter one is required but is implemented like
an integer field, meaning writing 0 is actually a valid value for 'required'.
In this commit we add a constraint to ensure we never update activities with
a void res_id value. Same for mailing traces. This allows to remove the
required attribute on fields to avoid having redundant sql constraints.
Source: internal feedback about activities with 0 as res_id
Task-2694133
Part-of: odoo/odoo#81292
The mail-safe font is applied to a style in <head> for emails. But the
way it was applied, <div>s were forgotten. Since most of those are
converted to tables when converting body_arch to body_html, it resulted
in visible font differences between body_arch and body_html.
Part-of: odoo/odoo#83233
Right now, in our mass mailing, marketing users refine the audience they are
going to reach with our beautiful domain selector/editor. The problem here
is that the criteria that 'filters' audience can be very common and might be
used in many mailings.
Such filters have to be re-created manually each time they are needed unless
one duplicates a sent mailing. Another possible workaround is to access this
form view while in debug mode so that one can copy and paste those domain
expressions. Unfortunately, none of those solutions are either ideal or
convenient. Especially during the onboarding where new users are not very
familiar with those notions yet.
This commit allow users to save filters on the mass mailings. That way
favorite filters can be re-used on the next mailing. For that, we added
a new model 'mailing.filter'. We do not use existing 'ir.filter' model as
its usage is not completely the same and as we do not want to bloat view
filters with filters created on the fly in marketing application. This new
model contains the following fields:
- name (given by user while saving the filter)
- mailing_domain
- mailing_model_id (m2o for the recipient model)
- mailing_model_name (technical name of recipient model)
Users can create the filters by setting domain and then hitting hollow star
icon next to 'Filter' m2o and saving it with the name they want. Same way
to delete the saved filter, user simply have to click the filled star icon
when filter is already set. This is done through a new widget that adds its
own behavior on top of m2o widget.
The saved filters can be also managed with a new menu named 'Favorite Filters'
under 'Configuration' menu of Email marketing.
Task-2092853
closesodoo/odoo#70859
Related: odoo/enterprise#21049
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
PURPOSE
This commit consolidates UTM usage across all applications.
Global purpose is to avoid having undesired side-effects, such as unlinking an
utm.source/utm.medium/utm.campaign and at the same time cascading the deletion
to various records without noticing.
SPECS
ALLOW MORE PEOPLE TO CLEAN UTM RECORDS
Currently, not even the system administrator can delete utm.mediums and
utm.sources (he can only delete campaigns).
These were considered as "technical records", but allowing some cleanup is
a good idea since these records are often automatically generated and can
create a lot of unnecessary noise in the database.
That's why we now allow the following groups to delete all UTM records
(sources, mediums and campaigns):
- group_system
- group_mass_mailing_user
- group_social_manager (enterprise)
PREVENT DELETION
For some use cases, removing an utm.source/utm.medium/utm.campaign would
cascade delete the related record, which was unintended / hidden side effect.
These combinations were secured by preventing to unlink:
- mailing.mailing source_id field
Trying to delete the utm.source will throw an error message
- mailing.mailing medium_id field
Trying to delete the utm.medium will throw an error message
- hr.recruitment.source source_id field
Trying to delete the utm.source will throw an error message
ADDING CLEAN ERROR MESSAGES
When trying to delete an UTM record that is linked with ondelete="restrict", we
improved the error message to give a clear explication to the user, e.g:
"You can't delete these UTM sources as they are linked to the following
mailings in the Mass Mailing APP, and deleting the source would break the
statistics: Newsletter"
SPECIFY 'ondelete' strategy
For a lot of uses of sources/mediums/campaigns, the 'ondelete' strategy was not
specified, leading to the confusion of "is this really how we want to handle
this?".
A lot of ondelete="set null" have been added in various field definitions to
ensure that this is the desired and logical strategy we want for that
specific model.
PREVENT REMOVING HARDCODED UTM RECORDS
In some functional flows, UTM records are hardcoded using their direct
record reference.
This is notably the case for the recruitment process and its creation of
aliases, and for the Email / SMS Marketing flows.
As deleting them would break these flows, we prevent their deletion in a
"api.ondelete" method.
ENFORCE NEW RULES WITH TESTS
A lot of python tests have been added to make sure we enforce the decisions
taken here above.
LINKS
ENT PR odoo/enterprise#19048
Task-2459480
closesodoo/odoo#72239
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This adds a series of CSS styles to the `<head>` of mailings in order to
ensure better mail client compatibility.
task-2554899
X-original-commit: ace475defca0c143d707f7b53d9f19a9db6cfe3e
Part-of: odoo/odoo#77724
This brings a series of improvements to the mechanism in place to
convert the output html of mass mailing into html that is more compliant
with the main mail clients' requirements.
The biggest change is the automatic conversion of Bootstrap grids into
table structures. Currently all templates in `mass_mailing` are designed
with tables so they work in mailings as is. That has limitations though
as it makes it less easy to edit with snippets such as those used in the
website builder. This new automatic conversion from Bootstrap grid will
allow us to adapt the mailing and snippet templates and be more free
within `mass_mailing`.
Note: Because of the limited support of media queries in emails, this
doesn't support the mixing and matching of column options
(e.g., `"col-4 col-sm-6"` and `"col col-4"` aren't supported).
Other changes include:
- The conversion of Bootstrap cards to table structures
- The conversion of Bootstrap list-groups to table structures
- The conversion of snippets (.o_mail_snippet_general) and mailings
(.o_layout) into table structures
- The conversion of all rgb colors to hexadecimal
- The conversion of all "rem" sizes to "px"
- Various small corrections to the output styles
task-2554899
X-original-commit: e2e00939e09220051f6f4ecfb7bb3276105387bf
Part-of: odoo/odoo#77724
Jinja as a templating engine was problematic in differents respect:
- introduce external dependency to Odoo (less controll)
- add another templating mechanism in the stack
- specific feature in qweb cannot be reused
- difficulty in rendering easily editable templates
- more knowledge required with no betterment
By replacing jinja with qweb we can now build tools to edit a qweb
that will work with the previously jinja encoded document
(essentially `mail.template` records).
There is a catch however. Some email fields (eg. email_to) used jinja
syntax for rendering dynamic variables (ie. ${object.something} and
${object.something_that_should_not_be_escaped | safe}).
We still want user to use dynamic variables for some char fields (eg.
subject, from, to, ...). We made a new rendering engine called
"inline_template" that will render an expression enclosed by `{{` and
`}}`.
To be able to edit the templates from the backend interface, a
plugin to the Odoo editor has been made for seamlessly edit the
document.
This qweb plugin includes:
- make dynamic variables (eg. `<t t-out="variable"/>`) not editable
(for preventing the user to shoot himself in the foot)
- group and hide related logical branching (ie. t-if, t-elif, and t-else)
in order to see only one at once
- a floating select input to switch visibility of a particular logical
branching
Task-27033
X-original-commit: odoo/odoo@68182baff4
Part-of: odoo/odoo#77377
Since the introduction of Odoo Editor, `field_html`'s `_getValue` uses
`wysiwyg.getValue`. This conflicts with the mechanism of `mass_mailing`
which modifies the html of the editable area in place to save an
"e-mailable" version on the `body_html` field, then relies on
`_getValue` to reset the original html (`body_arch`).
This ensures the field has a value before modifying the html in place,
so we can manually restore it instead of relying on a side effect of the
old behavior of `_getValue`.
Part-of: odoo/odoo#75901
Manage correctly a/b testing in mass_mailing.
We can now organize a mass_mailing campaign by testing
multiple mailings for the recipients targeted (subject,
templates, design, ...)
For this a new tab on the mailing record is added to better
promote the existence of the feature.
When an user has the group to manage mailing campaign, he can
access the tab A/B Test. This tab allows to enable A/B testing
for the mailing. If there is no campaign set for the mailing,
one is automatically created allowing the user to continue
smoothly.
Once A/B testing enable, the percentage of recipients use can be
set for each mailings. Also, the user can choose the deciding factor
that will set the final mailing as winner.
In a case, the user is not in manual mode, he can set the schedule datetime
for sending the final mailing.
task-2123242
COM PR: odoo/odoo#75622
ENT PR: odoo/enterprise#20454
UPG PR: odoo/upgrade#2781
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
PURPOSE
Improve modeling and performances of mass mailing by manually updating trace
status instead of using complex computed fields and lessening fields usage.
Remove some fields and keep only relevant metrics to simplify and clean trace
model.
SPECIFICATIONS
In this commit we clean the way trace state is managed. Currently it is a
computed field based on several datetime fields. However this generates a
lot of noise in the table as well as unnecessary computation
* there are several columns (one for each state) storing datetime at
which status was reached. Generally only 2 or 3 contain relevant
information;
* state could be set in code directly to avoid a computed field based on
many triggers;
* recomputing it each time a date changes is not necessarily necessary;
* state value can always be updated manually as this is main done through
some automated server update (mailgateway, link clicks, ...);
As trace states and its triggers should not be updated manually it is better
to synchronize it in code flow. When there is an exception or update done
through sending or gateway status is updated as well accordingly. Various
datetime fields are also updated at the same time. In order to align with
notification model mail and sms trace status are updated to a classic field.
Only last status update is now kept as there is no need to store the entire
history of status change.
We keep only a datetime for relevant metrics: open, reply and click. Other
datetime bring no real value. Knowing when a trace was in error or bounced
is not necessary. Indeed exception generally indicates a server issue (at
sending), cancel indicates a data issue (at sending) and bounce depends on
customer email server.
Status update is removed as using write_date is sufficient. Once created
traces are updated only when an external event occurs (opened, replied, ...).
It allows to simplify trace model.
We also rename ignored field into canceled to match naming use through mail
and sms.
QUERY COUNTERS
This change has some positive update on query counters when sending mailings
as traces have less unnecessary status update compared to priori this change.
LINKS
Task ID-2377974
Community PR odoo/odoo#61467
Enterprise PR odoo/enterprise#14633
Upgrade PR odoo/upgrade#1907
RATIONALE
Currently there are differences between mail and sms error management
especially when sending them in batch (mass mode). Moreover cancel
(ignored) and error (exception) states meaning is not clear. Finally
some failure types management between mail and sms can be cleaned.
SPECIFICATIONS
Meaning of ignored / error we want to enforce now is
* error: there was something wrong at sending and user has an action to
perform, i.e. server failed -> check its logs;
* canceled: invalid recipients due to contact information or mailing
configuration (blacklist, opt out, void or invalid email or phone number).
In indicates issues linked to records themselves;
In this task we also add failure information granularity on mailing traces
linked to email like what is done currently on SMS. This can be related to
mailing (blacklist, optout, duplicates) or related to recipient (no recipient,
incorrectly formatted).
We also correctly distinguish optout from blacklist when sending SMS.
SPECIFIC USE CASES
* recipient without email / number: mail / sms is set as canceled, trace is
ignored;
* recipient with invalid email (no @) / number (formatting impossible):
mail / sms is set as canceled, trace is ignored;
-> we now distinguish when possible a void email from a wrong email using
a newly-added selection key (mail_email_missing);
* recipient with email / number blacklisted: mail / sms is canceled, trace
is ignored;
* recipient with email / number that optouted from mailing: mail / sms is
canceled, trace is ignored;
* recipient with email that bounces: mail is sent and will be set as bounce
when receiving bounce in gateway; trace follow same path;
* recipient with number that bounces: not supported as currently no support
of bounce through IAP;
* mail server error, IAP error: mail / sms is set as exception / error,
trace is set in exception;
This means we introduce new failure types on mailing.trace model to reflect
those failure types
* ``mail_missing``: missing email (different from wrong value);
* ``mail_bl``: blacklisted;
* ``mail_optout``: optouted;
* ``mail_dup``: duplicated email skipped during mass email send;
We introduce ``sms_optout`` on SMS and trace models as it was merged with
blacklist previously. Now both errors are distinguished.
LINKS
Task ID-2377974
Community PR odoo/odoo#61467
Enterprise PR odoo/enterprise#14633
Upgrade PR odoo/upgrade#1907
Purpose
=======
Remove the "email_send" field on the <mail.channel> (mass_mailing named
on the JS side).
This feature will be introduced with a new model (<mail.group>) in a
new module in the next commit.
Remove the email notification support on the channel, so now the mail
channels work only by chat.
Remove the "subject" on the Discuss side because this was used only on
"email" channel.
Technical
=========
In the mail channel model we can drop the usage of the blacklist as well
as the usage of the "email_to" field. Those two features were mainly
used for mailing list and have no utility for "chat like" channel.
Links
=====
Task-2510267
See odoo/odoo/pull/71599
See odoo/enterprise/pull/19296
See odoo/upgrade/pull/2600