mirror of
https://github.com/bringout/oca-ocb-mail.git
synced 2026-04-21 10:02:09 +02:00
142 lines
6.2 KiB
Python
142 lines
6.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import werkzeug
|
|
from werkzeug.exceptions import NotFound
|
|
|
|
from odoo import http, _
|
|
from odoo.addons.phone_validation.tools import phone_validation
|
|
from odoo.http import request
|
|
|
|
|
|
class MailingSMSController(http.Controller):
|
|
|
|
def _check_trace(self, mailing_id, trace_code):
|
|
try:
|
|
mailing = request.env['mailing.mailing'].sudo().search([('id', '=', mailing_id)])
|
|
except:
|
|
mailing = False
|
|
if not mailing:
|
|
return {'error': 'mailing_error'}
|
|
trace = request.env['mailing.trace'].sudo().search([
|
|
('trace_type', '=', 'sms'),
|
|
('sms_code', '=', trace_code),
|
|
('mass_mailing_id', '=', mailing.id)
|
|
])
|
|
if not trace:
|
|
return {'error': 'trace_error'}
|
|
return {'trace': trace}
|
|
|
|
@http.route(['/sms/<int:mailing_id>/<string:trace_code>'], type='http', website=True, auth='public')
|
|
def blacklist_page(self, mailing_id, trace_code, **post):
|
|
""" Main entry point for unsubscribe links. Verify trace code (should
|
|
match mailing and trace), then check number can be sanitized. """
|
|
check_res = self._check_trace(mailing_id, trace_code)
|
|
found_traces = check_res.get('trace')
|
|
if not found_traces:
|
|
return request.redirect('/odoo')
|
|
|
|
valid_trace = request.env['mailing.trace'].sudo()
|
|
sanitized_number = False
|
|
sms_number = post.get('sms_number', '').strip()
|
|
if sms_number:
|
|
country = request.env['res.country'].sudo()
|
|
if country_code := request.geoip.country_code:
|
|
country = request.env['res.country'].search([('code', '=', country_code)], limit=1)
|
|
if not country:
|
|
country = request.env.company.country_id
|
|
try:
|
|
# Sanitize the phone number
|
|
sanitized_number = phone_validation.phone_format(
|
|
sms_number,
|
|
country.code,
|
|
country.phone_code,
|
|
force_format='E164',
|
|
raise_exception=True,
|
|
)
|
|
except Exception: # noqa: BLE001
|
|
sanitized_number = False
|
|
|
|
if sanitized_number:
|
|
valid_trace = found_traces.filtered(lambda t: t.sms_number == sanitized_number)
|
|
|
|
# trace found -> number valid, code matching
|
|
if valid_trace:
|
|
return request.redirect(
|
|
f'/sms/{mailing_id}/unsubscribe/{trace_code}?{werkzeug.urls.url_encode({"sms_number": sanitized_number})}'
|
|
)
|
|
|
|
# otherwise: generate error message, loop on same page
|
|
unsubscribe_error = False
|
|
if sms_number and not sanitized_number:
|
|
unsubscribe_error = _('Oops! The phone number seems to be incorrect. Please make sure to include the country code.')
|
|
if sanitized_number and not valid_trace:
|
|
unsubscribe_error = _('Oops! Number not found')
|
|
return request.render('mass_mailing_sms.blacklist_main', {
|
|
'mailing_id': mailing_id,
|
|
'sms_number': sms_number,
|
|
'trace_code': trace_code,
|
|
'unsubscribe_error': unsubscribe_error,
|
|
})
|
|
|
|
|
|
@http.route(['/sms/<int:mailing_id>/unsubscribe/<string:trace_code>'], type='http', website=True, auth='public')
|
|
def blacklist_number(self, mailing_id, trace_code, **post):
|
|
""" Effectively opt-out or enter number in block list. """
|
|
check_res = self._check_trace(mailing_id, trace_code)
|
|
if not check_res.get('trace'):
|
|
return request.redirect('/odoo')
|
|
# parse and validate number
|
|
sms_number = post.get('sms_number', '').strip(' ')
|
|
tocheck_number = sms_number
|
|
|
|
trace = check_res['trace'].filtered(lambda r: r.sms_number == tocheck_number)[:1] if tocheck_number else False
|
|
# compute opt-out / blacklist information
|
|
lists_optout = request.env['mailing.list'].sudo()
|
|
lists_optin = request.env['mailing.list'].sudo()
|
|
if tocheck_number and trace:
|
|
mailing_list_ids = trace.mass_mailing_id.contact_list_ids
|
|
if mailing_list_ids:
|
|
subscriptions = request.env['mailing.subscription'].sudo().search([
|
|
('list_id', 'in', mailing_list_ids.ids),
|
|
('contact_id.phone_sanitized', '=', tocheck_number),
|
|
])
|
|
subscriptions.write({'opt_out': True})
|
|
lists_optout = subscriptions.mapped('list_id')
|
|
else:
|
|
blacklist_rec = request.env['phone.blacklist'].sudo().add(tocheck_number)
|
|
blacklist_rec._message_log(
|
|
body=_('Blacklist through SMS Marketing unsubscribe (mailing ID: %(mailing_id)s - model: %(model)s)',
|
|
mailing_id=trace.mass_mailing_id.id, model=trace.mass_mailing_id.mailing_model_id.display_name))
|
|
lists_optin = request.env['mailing.subscription'].sudo().search([
|
|
('contact_id.phone_sanitized', '=', tocheck_number),
|
|
('list_id', 'not in', mailing_list_ids.ids),
|
|
('opt_out', '=', False),
|
|
]).mapped('list_id')
|
|
|
|
return request.render('mass_mailing_sms.blacklist_number', {
|
|
'mailing_id': mailing_id,
|
|
'trace_code': trace_code,
|
|
'sms_number': sms_number,
|
|
'lists_optin': lists_optin,
|
|
'lists_optout': lists_optout,
|
|
})
|
|
|
|
@http.route('/r/<string:code>/s/<int:sms_id_int>', type='http', auth="public")
|
|
def sms_short_link_redirect(self, code, sms_id_int, **post):
|
|
if sms_id_int:
|
|
trace_id = request.env['mailing.trace'].sudo().search([('sms_id_int', '=', int(sms_id_int))]).id
|
|
else:
|
|
trace_id = False
|
|
|
|
if not request.env['ir.http'].is_a_bot():
|
|
request.env['link.tracker.click'].sudo().add_click(
|
|
code,
|
|
ip=request.httprequest.remote_addr,
|
|
country_code=request.geoip.country_code,
|
|
mailing_trace_id=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)
|