Creating and editing mass mailing in multiple language is managed with
the change 05daa15.
But currently the language the mass mailing is sent in, is the language
of the "Process Mass Mailing Queue" (root user if not changed) so all
the recipients will receive the mail in the root user language has at
the time the given batch of mails is sended.
So this is different from what someone could expect by it being
translatable. In any case the recipients list could be based on a lead,
a partner a mass mailing contact or other and a language could not be
determinable in stable (a mass mailing contact does not have a language
for example).
If the system worked, there is also a usability downside in the meaning
that someone could duplicate a mail and not check all translation and
not be aware that the mail he see is maybe not the mail that will be
received (if translations have not all been completed).
In stable to have the same behavior in any case and lessen the usability
burden of users thinking erroneously the mass mailing may be sent in
several languages depending on a not-existing heuristic, this changeset
remove the translatability of mass mailing content.
This has the following effect:
no translation editing appear,
the mass mailing is edited and sent in one and the same language,
If someone want to send a mass mailing in several language, currently in
Odoo it would then require to:
duplicate the mass mailing,
change the domains of recipients base on choosen heuristic,
edit the duplicated mass mailing in the choosen language
opw-746445
opw-746776
closes#17718
The model MassMailing overrides read_group to handle the case when
it is grouped by field state, which is of type selection. However,
it sets as value for each group the array [key, name] of the
selection option, which is incorrect (it should set key as value,
like the default read_group does, and as the name is known client
side anyway).
This case was handled by the old views, but it isn't by the new
ones, which are less permissive. We choose to fix the read_group
override instead of allowing both cases in JS, as it is always
better to have a clear and single API.
In Python 3, all of these were "consolidated" under urllib(.request,
.parse, .errors) which is inconvenient.
Since we already have hard dependencies on requests and
werkzeug(.urls, which is a backport of Python 3's unicode-aware
urllib.parse) migrate *everything* to that.
A sticking point is urllib2.URLError, those were (mostly) replaced by
the slightly more general IOError which URLError extends.
In Python 3:
* various builtins and dict methods were changed to return
view/iterable objects rather than lists
* and the separate Python 2 view/iterable builtins and methods were
removed altogether
This is problematic when using these items as list (which the happens
repeatedly in Odoo), but more viciously when iterating *multiple times*
over them (which also happens, which I've messed up multiple times while
writing this, and which is a pain to debug even when you've just created
the issue).
Convert all code using these to semantics-matching cross-version
helper functions to get the LCD behaviour between P2 and P3, and
forbid the builtins via lint.
issue #8530
It is safer to avoid duplicates within a campaign,
so this should be turned on by default. Especially true
because campaign are often created without opening the
form view (quick create)
Also improved the description of the boolean option,
and made it editable in the form view, in case someone
wants ho really create a multi-step campaign.
Indeed due to onchange being trigerred at creation it breaks trying to
set default_mailing_domain when creating a new mailing through the web
client.
As setting domain and then changing model should not be the primary use
case of mass mailing, people will have to update their domain manually
instead of seeing it reset to a void domain.
link_tracker use a regex to determine the content of
a 'href' tag, taking the 'mailto:xxxx@yyyy.zz' case
into account. mass_mailing use another regex that simply
don't.
So when sending a mass mailing containing email link,
the email will be appended by url path of tracking
url '/m/<stat_id>'.
This commit makes mass_mailing use the same regex as
link_tracker (which is in the dependencies of mass_mailing).
opw-727779
The mass-mailing App suffered from severe issues due to its inability
to detect and handle duplicates "at the email level", and the absence
of any global blacklist system, leading to lack of user trust.
Mailing-lists typically include multiple records with the same email,
and it is critical to avoid sending them the same email several times.
A related problem is the unsubscription of an email that is present
in other records (duplicates). Opting out the first email should
automatically blacklist it for other records as well.
Ideally we should have a global blacklist table in order to
share the unsubscription requests globally across models (Leads,
Partners, Mailing-list contacts). It would also allow importing
it from other blacklist systems. (TODO for master)
This commit introduces a partial solution, made of several
small changes:
- In mail.mail: double-check that an outgoing email has the
correct status (`outgoing`) before sending it. This allows
adding emails in the queue and cancelling them before they
actually get sent.
- In crm.lead: force predictable recipients for mass-mailing,
by always using the email of the lead rather than the email
of the linked partner when there is one. This simplifies the
computation of the blacklist and seen list. Other areas in
the codebase already assume as much.
- In mass.mailing:
+ Before sending out a mailing-list batch, compute the
blacklist (all opted-out emails) and the seen_list
(emails who previously received this mail) to make
sure we only ever target valid recipients.
+ While delivering the mass-mailing, any email targeting
an address that is in the blacklist or "seen list" is
canceled before being sent. The corresponding statistics
entry is considered "not delivered".
Also updates the "seen list" continuously.
+ When a mass-mail belongs to a campaign with the
"unique AB/B testing" flag, the "seen list" is
common to the whole campaign, as an extra safety.
+ Auto-delete mass-mailing test messages sent with the
test wizard, to avoid polluting the mail_mail table
Note: this fix uses a simple regex for efficiently extracting
the blacklist in pure SQL from different models, and doing so,
assumes that each record only holds a single email
(no comma-separated adresses). This should be sufficient for
most cases. The regex:
([^ ,;<@]+@[^> ,;]+)
Passlib's consteq() function only works when both values are
of the same type.
`_unsubscribe_token` uses hmac.hexdigest() which always returns
byte-strings, so we need to ensure that the token passed in GET
parameters is cast to byte-string too.
In addition, _unsubscribe_token() is expected to always derive
the same token for the same list, res_id and email. It already
takes care of ID passed as strings/int, but failed to make sure
that the email can be passed as a byte-string or unicode-string.
Forcing it to unicode before deriving the token takes care of that.
The mailing._unsubscribe_token() method expected the record ID
as an integer, but accepted strings and generated a different
token for the string representation of an integer (!)
The unsubscribe controller was passing a string by mistake.
mailing._unsubscribe_token will still expect integers but if
the string representation of an integer is passed it will be
silently cast to an integer, and will generate the same token.
_rec_name in mass mailing is source_id which is an integer, it does not accept
a char value.
Instead specify the `name` value, which will create a utm.source.
Closes#13765