Merge branch 'master-hansa-05072018' into 'master-patch-july-2018'
Master hansa 05072018 See merge request flectra-hq/flectra!100
This commit is contained in:
commit
e313b2a500
@ -9,7 +9,7 @@ class AccountRegisterPayments(models.TransientModel):
|
||||
_inherit = "account.register.payments"
|
||||
|
||||
check_amount_in_words = fields.Char(string="Amount in Words")
|
||||
check_manual_sequencing = fields.Boolean(related='journal_id.check_manual_sequencing')
|
||||
check_manual_sequencing = fields.Boolean(related='journal_id.check_manual_sequencing', readonly=1)
|
||||
# Note: a check_number == 0 means that it will be attributed when the check is printed
|
||||
check_number = fields.Integer(string="Check Number", readonly=True, copy=False, default=0,
|
||||
help="Number of the check corresponding to this payment. If your pre-printed check are not already numbered, "
|
||||
@ -42,7 +42,7 @@ class AccountPayment(models.Model):
|
||||
_inherit = "account.payment"
|
||||
|
||||
check_amount_in_words = fields.Char(string="Amount in Words")
|
||||
check_manual_sequencing = fields.Boolean(related='journal_id.check_manual_sequencing')
|
||||
check_manual_sequencing = fields.Boolean(related='journal_id.check_manual_sequencing', readonly=1)
|
||||
check_number = fields.Integer(string="Check Number", readonly=True, copy=False,
|
||||
help="The selected journal is configured to print check numbers. If your pre-printed check paper already has numbers "
|
||||
"or if the current numbering is wrong, you can change it in the journal configuration page.")
|
||||
|
@ -5,7 +5,7 @@ import logging
|
||||
|
||||
from flectra import api, fields, models
|
||||
from flectra import tools, _
|
||||
from flectra.exceptions import ValidationError
|
||||
from flectra.exceptions import ValidationError, AccessError
|
||||
from flectra.modules.module import get_module_resource
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
@ -14,7 +14,7 @@ class MailAlias(models.AbstractModel):
|
||||
_inherit = 'mail.alias.mixin'
|
||||
|
||||
def _alias_check_contact_on_record(self, record, message, message_dict, alias):
|
||||
if alias.alias_contact == 'employees' and record.ids:
|
||||
if alias.alias_contact == 'employees':
|
||||
email_from = tools.decode_message_header(message, 'From')
|
||||
email_address = tools.email_split(email_from)[0]
|
||||
employee = self.env['hr.employee'].search([('work_email', 'ilike', email_address)], limit=1)
|
||||
|
@ -38,11 +38,18 @@ var GreetingMessage = Widget.extend({
|
||||
if (this.next_action != 'hr_attendance.hr_attendance_action_kiosk_mode' && this.next_action.tag != 'hr_attendance_kiosk_mode') {
|
||||
this.activeBarcode = false;
|
||||
}
|
||||
|
||||
this.attendance = action.attendance;
|
||||
// We receive the check in/out times in UTC
|
||||
// This widget only deals with display, which should be in browser's TimeZone
|
||||
this.attendance.check_in = this.attendance.check_in && moment.utc(this.attendance.check_in).local();
|
||||
this.attendance.check_out = this.attendance.check_out && moment.utc(this.attendance.check_out).local();
|
||||
this.previous_attendance_change_date = action.previous_attendance_change_date && moment.utc(action.previous_attendance_change_date).local();
|
||||
|
||||
// check in/out times displayed in the greeting message template.
|
||||
this.attendance.check_in_time = (new Date((new Date(this.attendance.check_in)).valueOf() - (new Date()).getTimezoneOffset()*60*1000)).toTimeString().slice(0,8);
|
||||
this.attendance.check_out_time = this.attendance.check_out && (new Date((new Date(this.attendance.check_out)).valueOf() - (new Date()).getTimezoneOffset()*60*1000)).toTimeString().slice(0,8);
|
||||
this.previous_attendance_change_date = action.previous_attendance_change_date;
|
||||
this.format_time = 'HH:mm:ss';
|
||||
this.attendance.check_in_time = this.attendance.check_in && this.attendance.check_in.format(this.format_time);
|
||||
this.attendance.check_out_time = this.attendance.check_out && this.attendance.check_out.format(this.format_time);
|
||||
this.employee_name = action.employee_name;
|
||||
},
|
||||
|
||||
@ -57,13 +64,13 @@ var GreetingMessage = Widget.extend({
|
||||
|
||||
welcome_message: function() {
|
||||
var self = this;
|
||||
var now = new Date((new Date(this.attendance.check_in)).valueOf() - (new Date()).getTimezoneOffset()*60*1000);
|
||||
var now = this.attendance.check_in.clone();
|
||||
this.return_to_main_menu = setTimeout( function() { self.do_action(self.next_action, {clear_breadcrumbs: true}); }, 5000);
|
||||
|
||||
if (now.getHours() < 5) {
|
||||
if (now.hours() < 5) {
|
||||
this.$('.o_hr_attendance_message_message').append(_t("Good night"));
|
||||
} else if (now.getHours() < 12) {
|
||||
if (now.getHours() < 8 && Math.random() < 0.3) {
|
||||
} else if (now.hours() < 12) {
|
||||
if (now.hours() < 8 && Math.random() < 0.3) {
|
||||
if (Math.random() < 0.75) {
|
||||
this.$('.o_hr_attendance_message_message').append(_t("The early bird catches the worm"));
|
||||
} else {
|
||||
@ -72,16 +79,16 @@ var GreetingMessage = Widget.extend({
|
||||
} else {
|
||||
this.$('.o_hr_attendance_message_message').append(_t("Good morning"));
|
||||
}
|
||||
} else if (now.getHours() < 17){
|
||||
} else if (now.hours() < 17){
|
||||
this.$('.o_hr_attendance_message_message').append(_t("Good afternoon"));
|
||||
} else if (now.getHours() < 23){
|
||||
} else if (now.hours() < 23){
|
||||
this.$('.o_hr_attendance_message_message').append(_t("Good evening"));
|
||||
} else {
|
||||
this.$('.o_hr_attendance_message_message').append(_t("Good night"));
|
||||
}
|
||||
if(this.previous_attendance_change_date){
|
||||
var last_check_out_date = new Date((new Date(this.previous_attendance_change_date)).valueOf() - (new Date()).getTimezoneOffset()*60*1000);
|
||||
if(now.valueOf() - last_check_out_date.valueOf() > 1000*60*60*24*7){
|
||||
var last_check_out_date = this.previous_attendance_change_date.clone();
|
||||
if(now - last_check_out_date > 24*7*60*60*1000){
|
||||
this.$('.o_hr_attendance_random_message').html(_t("Glad to have you back, it's been a while!"));
|
||||
} else {
|
||||
if(Math.random() < 0.02){
|
||||
@ -93,33 +100,33 @@ var GreetingMessage = Widget.extend({
|
||||
|
||||
farewell_message: function() {
|
||||
var self = this;
|
||||
var now = new Date((new Date(this.attendance.check_out)).valueOf() - (new Date()).getTimezoneOffset()*60*1000);
|
||||
var now = this.attendance.check_out.clone();
|
||||
this.return_to_main_menu = setTimeout( function() { self.do_action(self.next_action, {clear_breadcrumbs: true}); }, 5000);
|
||||
|
||||
if(this.previous_attendance_change_date){
|
||||
var last_check_in_date = new Date((new Date(this.previous_attendance_change_date)).valueOf() - (new Date()).getTimezoneOffset()*60*1000);
|
||||
if(now.valueOf() - last_check_in_date.valueOf() > 1000*60*60*12){
|
||||
var last_check_in_date = this.previous_attendance_change_date.clone();
|
||||
if(now - last_check_in_date > 1000*60*60*12){
|
||||
this.$('.o_hr_attendance_warning_message').append(_t("Warning! Last check in was over 12 hours ago.<br/>If this isn't right, please contact Human Resources."));
|
||||
clearTimeout(this.return_to_main_menu);
|
||||
this.activeBarcode = false;
|
||||
} else if(now.valueOf() - last_check_in_date.valueOf() > 1000*60*60*8){
|
||||
} else if(now - last_check_in_date > 1000*60*60*8){
|
||||
this.$('.o_hr_attendance_random_message').html(_t("Another good day's work! See you soon!"));
|
||||
}
|
||||
}
|
||||
|
||||
if (now.getHours() < 12) {
|
||||
if (now.hours() < 12) {
|
||||
this.$('.o_hr_attendance_message_message').append(_t("Have a good day!"));
|
||||
} else if (now.getHours() < 14) {
|
||||
} else if (now.hours() < 14) {
|
||||
this.$('.o_hr_attendance_message_message').append(_t("Have a nice lunch!"));
|
||||
if (Math.random() < 0.05) {
|
||||
this.$('.o_hr_attendance_random_message').html(_t("Eat breakfast as a king, lunch as a merchant and supper as a beggar"));
|
||||
} else if (Math.random() < 0.06) {
|
||||
this.$('.o_hr_attendance_random_message').html(_t("An apple a day keeps the doctor away"));
|
||||
}
|
||||
} else if (now.getHours() < 17) {
|
||||
} else if (now.hours() < 17) {
|
||||
this.$('.o_hr_attendance_message_message').append(_t("Have a good afternoon"));
|
||||
} else {
|
||||
if (now.getHours() < 18 && Math.random() < 0.2) {
|
||||
if (now.hours() < 18 && Math.random() < 0.2) {
|
||||
this.$('.o_hr_attendance_message_message').append(_t("Early to bed and early to rise, makes a man healthy, wealthy and wise"));
|
||||
} else {
|
||||
this.$('.o_hr_attendance_message_message').append(_t("Have a good evening"));
|
||||
|
@ -1,6 +1,7 @@
|
||||
flectra.define('hr_attendance.kiosk_mode', function (require) {
|
||||
"use strict";
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
var core = require('web.core');
|
||||
var Widget = require('web.Widget');
|
||||
var Session = require('web.session');
|
||||
@ -27,6 +28,8 @@ var KioskMode = Widget.extend({
|
||||
self.$el.html(QWeb.render("HrAttendanceKioskMode", {widget: self}));
|
||||
self.start_clock();
|
||||
});
|
||||
// Make a RPC call every day to keep the session alive
|
||||
self._interval = window.setInterval(this._callServer.bind(this), (60*60*1000*24));
|
||||
return $.when(def, this._super.apply(this, arguments));
|
||||
},
|
||||
|
||||
@ -55,8 +58,15 @@ var KioskMode = Widget.extend({
|
||||
destroy: function () {
|
||||
core.bus.off('barcode_scanned', this, this._onBarcodeScanned);
|
||||
clearInterval(this.clock_start);
|
||||
clearInterval(this._interval);
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
_callServer: function () {
|
||||
// Make a call to the database to avoid the auto close of the session
|
||||
return ajax.rpc("/web/webclient/version_info", {});
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
core.action_registry.add('hr_attendance_kiosk_mode', KioskMode);
|
||||
|
@ -67,7 +67,7 @@ class Contract(models.Model):
|
||||
resource_calendar_id = fields.Many2one(
|
||||
'resource.calendar', 'Working Schedule',
|
||||
default=lambda self: self.env['res.company']._company_default_get().resource_calendar_id.id)
|
||||
wage = fields.Monetary('Wage', digits=(16, 2), required=True, help="Employee's monthly gross wage.")
|
||||
wage = fields.Monetary('Wage', digits=(16, 2), required=True, track_visibility="onchange", help="Employee's monthly gross wage.")
|
||||
advantages = fields.Text('Advantages')
|
||||
notes = fields.Text('Notes')
|
||||
state = fields.Selection([
|
||||
|
@ -370,7 +370,9 @@ class HrExpense(models.Model):
|
||||
product = default_product
|
||||
else:
|
||||
expense_description = expense_description.replace(product_code.group(), '')
|
||||
product = self.env['product.product'].search([('default_code', 'ilike', product_code.group(1))]) or default_product
|
||||
products = self.env['product.product'].search([('default_code', 'ilike', product_code.group(1))]) or default_product
|
||||
product = products.filtered(lambda p: p.default_code == product_code.group(1)) or products[0]
|
||||
account = product.product_tmpl_id._get_product_accounts()['expense']
|
||||
|
||||
pattern = '[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?'
|
||||
# Match the last occurence of a float in the string
|
||||
@ -397,6 +399,8 @@ class HrExpense(models.Model):
|
||||
'unit_amount': price,
|
||||
'company_id': employee.company_id.id,
|
||||
})
|
||||
if account:
|
||||
custom_values['account_id'] = account.id
|
||||
return super(HrExpense, self).message_new(msg_dict, custom_values)
|
||||
|
||||
class HrExpenseSheet(models.Model):
|
||||
@ -512,7 +516,7 @@ class HrExpenseSheet(models.Model):
|
||||
|
||||
@api.onchange('employee_id')
|
||||
def _onchange_employee_id(self):
|
||||
self.address_id = self.employee_id.address_home_id
|
||||
self.address_id = self.employee_id.sudo().address_home_id
|
||||
self.department_id = self.employee_id.department_id
|
||||
|
||||
@api.one
|
||||
@ -599,4 +603,4 @@ class HrExpenseSheet(models.Model):
|
||||
def _check_payment_mode(self):
|
||||
payment_mode = set(self.expense_line_ids.mapped('payment_mode'))
|
||||
if len(payment_mode) > 1:
|
||||
raise ValidationError(_('You cannot report expenses with different payment modes.'))
|
||||
raise ValidationError(_('You cannot report expenses with different payment modes.'))
|
||||
|
@ -82,6 +82,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="padding-top:10px;font-size: 12px;">
|
||||
<div>Sent by ${object.company_id.name}</div>
|
||||
% if 'website_url' in object.job_id and object.job_id.website_url:
|
||||
<div>
|
||||
Discover <a href="/jobs" style="text-decoration:none;color:#717188;">our others jobs</a>.
|
||||
|
@ -36,7 +36,7 @@
|
||||
<span t-field="l.user_id.partner_id.name"/>
|
||||
</td>
|
||||
<td >
|
||||
<span t-field="l.name"/>
|
||||
<span t-field="l.name" t-options="{'widget': 'text'}"/>
|
||||
</td>
|
||||
<td t-if="show_task or show_project">
|
||||
<t t-if="show_project"><span t-field="l.project_id.name"/></t>
|
||||
|
@ -2,6 +2,7 @@
|
||||
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from datetime import date, datetime, timedelta
|
||||
import pytz
|
||||
|
||||
from flectra import api, exceptions, fields, models, _
|
||||
|
||||
@ -77,7 +78,7 @@ class MailActivity(models.Model):
|
||||
summary = fields.Char('Summary')
|
||||
note = fields.Html('Note')
|
||||
feedback = fields.Html('Feedback')
|
||||
date_deadline = fields.Date('Due Date', index=True, required=True, default=fields.Date.today)
|
||||
date_deadline = fields.Date('Due Date', index=True, required=True, default=fields.Date.context_today)
|
||||
# description
|
||||
user_id = fields.Many2one(
|
||||
'res.users', 'Assigned to',
|
||||
@ -108,8 +109,16 @@ class MailActivity(models.Model):
|
||||
|
||||
@api.depends('date_deadline')
|
||||
def _compute_state(self):
|
||||
today = date.today()
|
||||
today_default = date.today()
|
||||
|
||||
for record in self.filtered(lambda activity: activity.date_deadline):
|
||||
today = today_default
|
||||
tz = record.user_id.sudo().tz
|
||||
if tz:
|
||||
today_utc = pytz.UTC.localize(datetime.utcnow())
|
||||
today_tz = today_utc.astimezone(pytz.timezone(tz))
|
||||
today = date(year=today_tz.year, month=today_tz.month, day=today_tz.day)
|
||||
|
||||
date_deadline = fields.Date.from_string(record.date_deadline)
|
||||
diff = (date_deadline - today)
|
||||
if diff.days == 0:
|
||||
@ -132,7 +141,8 @@ class MailActivity(models.Model):
|
||||
|
||||
@api.onchange('recommended_activity_type_id')
|
||||
def _onchange_recommended_activity_type_id(self):
|
||||
self.activity_type_id = self.recommended_activity_type_id
|
||||
if self.recommended_activity_type_id:
|
||||
self.activity_type_id = self.recommended_activity_type_id
|
||||
|
||||
@api.multi
|
||||
def _check_access(self, operation):
|
||||
|
@ -505,7 +505,15 @@ class Channel(models.Model):
|
||||
partners_to_add = partners - channel.channel_partner_ids
|
||||
channel.write({'channel_last_seen_partner_ids': [(0, 0, {'partner_id': partner_id}) for partner_id in partners_to_add.ids]})
|
||||
for partner in partners_to_add:
|
||||
notification = _('<div class="o_mail_notification">joined <a href="#" class="o_channel_redirect" data-oe-id="%s">#%s</a></div>') % (self.id, self.name,)
|
||||
if partner.id != self.env.user.partner_id.id:
|
||||
notification = _('<div class="o_mail_notification">%(author)s invited %(new_partner)s to <a href="#" class="o_channel_redirect" data-oe-id="%(channel_id)s">#%(channel_name)s</a></div>') % {
|
||||
'author': self.env.user.display_name,
|
||||
'new_partner': partner.display_name,
|
||||
'channel_id': channel.id,
|
||||
'channel_name': channel.name,
|
||||
}
|
||||
else:
|
||||
notification = _('<div class="o_mail_notification">joined <a href="#" class="o_channel_redirect" data-oe-id="%s">#%s</a></div>') % (channel.id, channel.name,)
|
||||
self.message_post(body=notification, message_type="notification", subtype="mail.mt_comment", author_id=partner.id)
|
||||
|
||||
# broadcast the channel header to the added partner
|
||||
@ -674,7 +682,7 @@ class Channel(models.Model):
|
||||
msg += _(" This channel is private. People must be invited to join it.")
|
||||
else:
|
||||
channel_partners = self.env['mail.channel.partner'].search([('partner_id', '!=', partner.id), ('channel_id', '=', self.id)])
|
||||
msg = _("You are in a private conversation with <b>@%s</b>.") % channel_partners[0].partner_id.name
|
||||
msg = _("You are in a private conversation with <b>@%s</b>.") % (channel_partners[0].partner_id.name if channel_partners else _('Anonymous'))
|
||||
msg += _("""<br><br>
|
||||
You can mention someone by typing <b>@username</b>, this will grab its attention.<br>
|
||||
You can mention a channel by typing <b>#channel</b>.<br>
|
||||
|
@ -5,6 +5,7 @@ import logging
|
||||
import re
|
||||
|
||||
from email.utils import formataddr
|
||||
from openerp.http import request
|
||||
|
||||
from flectra import _, api, fields, models, modules, SUPERUSER_ID, tools
|
||||
from flectra.exceptions import UserError, AccessError
|
||||
@ -299,11 +300,12 @@ class Message(models.Model):
|
||||
|
||||
# 2. Attachments as SUPERUSER, because could receive msg and attachments for doc uid cannot see
|
||||
attachments_data = attachments.sudo().read(['id', 'datas_fname', 'name', 'mimetype'])
|
||||
safari = request and request.httprequest.user_agent.browser == 'safari'
|
||||
attachments_tree = dict((attachment['id'], {
|
||||
'id': attachment['id'],
|
||||
'filename': attachment['datas_fname'],
|
||||
'name': attachment['name'],
|
||||
'mimetype': attachment['mimetype'],
|
||||
'mimetype': 'application/octet-stream' if safari and 'video' in attachment['mimetype'] else attachment['mimetype'],
|
||||
}) for attachment in attachments_data)
|
||||
|
||||
# 3. Tracking values
|
||||
@ -422,7 +424,18 @@ class Message(models.Model):
|
||||
subtype_ids = [msg['subtype_id'][0] for msg in message_values if msg['subtype_id']]
|
||||
subtypes = self.env['mail.message.subtype'].sudo().browse(subtype_ids).read(['internal', 'description'])
|
||||
subtypes_dict = dict((subtype['id'], subtype) for subtype in subtypes)
|
||||
|
||||
# fetch notification status
|
||||
notif_dict = {}
|
||||
notifs = self.env['mail.notification'].sudo().search([('mail_message_id', 'in', list(mid for mid in message_tree)), ('is_read', '=', False)])
|
||||
for notif in notifs:
|
||||
mid = notif.mail_message_id.id
|
||||
if not notif_dict.get(mid):
|
||||
notif_dict[mid] = {'partner_id': list()}
|
||||
notif_dict[mid]['partner_id'].append(notif.res_partner_id.id)
|
||||
|
||||
for message in message_values:
|
||||
message['needaction_partner_ids'] = notif_dict.get(message['id'], dict()).get('partner_id', [])
|
||||
message['is_note'] = message['subtype_id'] and subtypes_dict[message['subtype_id'][0]]['internal']
|
||||
message['subtype_description'] = message['subtype_id'] and subtypes_dict[message['subtype_id'][0]]['description']
|
||||
if message['model'] and self.env[message['model']]._original_module:
|
||||
|
@ -126,7 +126,8 @@ class MailThread(models.AbstractModel):
|
||||
followers = self.env['mail.followers'].sudo().search([
|
||||
('res_model', '=', self._name),
|
||||
('partner_id', operator, operand)])
|
||||
return [('id', 'in', followers.mapped('res_id'))]
|
||||
# using read() below is much faster than followers.mapped('res_id')
|
||||
return [('id', 'in', [res['res_id'] for res in followers.read(['res_id'])])]
|
||||
|
||||
@api.model
|
||||
def _search_follower_channels(self, operator, operand):
|
||||
@ -139,7 +140,8 @@ class MailThread(models.AbstractModel):
|
||||
followers = self.env['mail.followers'].sudo().search([
|
||||
('res_model', '=', self._name),
|
||||
('channel_id', operator, operand)])
|
||||
return [('id', 'in', followers.mapped('res_id'))]
|
||||
# using read() below is much faster than followers.mapped('res_id')
|
||||
return [('id', 'in', [res['res_id'] for res in followers.read(['res_id'])])]
|
||||
|
||||
@api.multi
|
||||
@api.depends('message_follower_ids')
|
||||
@ -149,7 +151,8 @@ class MailThread(models.AbstractModel):
|
||||
('res_id', 'in', self.ids),
|
||||
('partner_id', '=', self.env.user.partner_id.id),
|
||||
])
|
||||
following_ids = followers.mapped('res_id')
|
||||
# using read() below is much faster than followers.mapped('res_id')
|
||||
following_ids = [res['res_id'] for res in followers.read(['res_id'])]
|
||||
for record in self:
|
||||
record.message_is_follower = record.id in following_ids
|
||||
|
||||
@ -161,9 +164,11 @@ class MailThread(models.AbstractModel):
|
||||
])
|
||||
# Cases ('message_is_follower', '=', True) or ('message_is_follower', '!=', False)
|
||||
if (operator == '=' and operand) or (operator == '!=' and not operand):
|
||||
return [('id', 'in', followers.mapped('res_id'))]
|
||||
# using read() below is much faster than followers.mapped('res_id')
|
||||
return [('id', 'in', [res['res_id'] for res in followers.read(['res_id'])])]
|
||||
else:
|
||||
return [('id', 'not in', followers.mapped('res_id'))]
|
||||
# using read() below is much faster than followers.mapped('res_id')
|
||||
return [('id', 'not in', [res['res_id'] for res in followers.read(['res_id'])])]
|
||||
|
||||
@api.multi
|
||||
def _get_message_unread(self):
|
||||
@ -1373,7 +1378,13 @@ class MailThread(models.AbstractModel):
|
||||
located in tools. """
|
||||
if not body:
|
||||
return body, attachments
|
||||
root = lxml.html.fromstring(body)
|
||||
try:
|
||||
root = lxml.html.fromstring(body)
|
||||
except ValueError:
|
||||
# In case the email client sent XHTML, fromstring will fail because 'Unicode strings
|
||||
# with encoding declaration are not supported'.
|
||||
root = lxml.html.fromstring(body.encode('utf-8'))
|
||||
|
||||
postprocessed = False
|
||||
to_remove = []
|
||||
for node in root.iter():
|
||||
|
@ -58,6 +58,8 @@ class Users(models.Model):
|
||||
|
||||
# create a welcome message
|
||||
user._create_welcome_message()
|
||||
# Auto-subscribe to channels
|
||||
self.env['mail.channel'].search([('group_ids', 'in', user.groups_id.ids)])._subscribe_users()
|
||||
return user
|
||||
|
||||
@api.multi
|
||||
@ -127,16 +129,19 @@ class Users(models.Model):
|
||||
def activity_user_count(self):
|
||||
query = """SELECT m.id, count(*), act.res_model as model,
|
||||
CASE
|
||||
WHEN now()::date - act.date_deadline::date = 0 Then 'today'
|
||||
WHEN now()::date - act.date_deadline::date > 0 Then 'overdue'
|
||||
WHEN now()::date - act.date_deadline::date < 0 Then 'planned'
|
||||
WHEN %(today)s::date - act.date_deadline::date = 0 Then 'today'
|
||||
WHEN %(today)s::date - act.date_deadline::date > 0 Then 'overdue'
|
||||
WHEN %(today)s::date - act.date_deadline::date < 0 Then 'planned'
|
||||
END AS states
|
||||
FROM mail_activity AS act
|
||||
JOIN ir_model AS m ON act.res_model_id = m.id
|
||||
WHERE user_id = %s
|
||||
WHERE user_id = %(user_id)s
|
||||
GROUP BY m.id, states, act.res_model;
|
||||
"""
|
||||
self.env.cr.execute(query, [self.env.uid])
|
||||
self.env.cr.execute(query, {
|
||||
'today': fields.Date.context_today(self),
|
||||
'user_id': self.env.uid,
|
||||
})
|
||||
activity_data = self.env.cr.dictfetchall()
|
||||
model_ids = [a['id'] for a in activity_data]
|
||||
model_names = {n[0]:n[1] for n in self.env['ir.model'].browse(model_ids).name_get()}
|
||||
|
@ -32,6 +32,7 @@ function _readActivities(self, ids) {
|
||||
model: 'mail.activity',
|
||||
method: 'read',
|
||||
args: [ids],
|
||||
context: (self.record && self.record.getContext()) || self.getSession().user_context,
|
||||
}).then(function (activities) {
|
||||
// convert create_date and date_deadline to moments
|
||||
_.each(activities, function (activity) {
|
||||
@ -108,6 +109,7 @@ var AbstractActivityField = AbstractField.extend({
|
||||
method: 'action_feedback',
|
||||
args: [[id]],
|
||||
kwargs: {feedback: feedback},
|
||||
context: this.record.getContext(),
|
||||
});
|
||||
},
|
||||
_scheduleActivity: function (id, previous_activity_type_id, callback) {
|
||||
|
@ -149,7 +149,16 @@ function make_message (data) {
|
||||
_.each(_.keys(emoji_substitutions), function (key) {
|
||||
var escaped_key = String(key).replace(/([.*+?=^!:${}()|[\]\/\\])/g, '\\$1');
|
||||
var regexp = new RegExp("(?:^|\\s|<[a-z]*>)(" + escaped_key + ")(?=\\s|$|</[a-z]*>)", "g");
|
||||
var msg_bak = msg.body;
|
||||
msg.body = msg.body.replace(regexp, ' <span class="o_mail_emoji">'+emoji_substitutions[key]+'</span> ');
|
||||
|
||||
// Idiot-proof limit. If the user had the amazing idea of copy-pasting thousands of emojis,
|
||||
// the image rendering can lead to memory overflow errors on some browsers (e.g. Chrome).
|
||||
// Set an arbitrary limit to 200 from which we simply don't replace them (anyway, they are
|
||||
// already replaced by the unicode counterpart).
|
||||
if (_.str.count(msg.body, 'o_mail_emoji') > 200) {
|
||||
msg.body = msg_bak;
|
||||
}
|
||||
});
|
||||
|
||||
function property_descr(channel) {
|
||||
|
@ -16,7 +16,8 @@ var HEIGHT_FOLDED = '34px';
|
||||
return Widget.extend({
|
||||
template: "mail.ChatWindow",
|
||||
custom_events: {
|
||||
escape_pressed: '_onEscapePressed'
|
||||
escape_pressed: '_onEscapePressed',
|
||||
document_viewer_closed: '_onDocumentViewerClose',
|
||||
},
|
||||
events: {
|
||||
'click .o_chat_composer': '_onComposerClick',
|
||||
@ -180,6 +181,9 @@ return Widget.extend({
|
||||
}
|
||||
this.focus_input();
|
||||
},
|
||||
_onDocumentViewerClose: function (ev) {
|
||||
this.focus_input();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
@ -514,6 +514,9 @@ var BasicComposer = Widget.extend(chat_mixin, {
|
||||
on_click_add_attachment: function () {
|
||||
this.$('input.o_input_file').click();
|
||||
this.$input.focus();
|
||||
// set ignoreEscape to avoid escape_pressed event when file selector dialog is opened
|
||||
// when user press escape to cancel file selector dialog then escape_pressed event should not be trigerred
|
||||
this.ignoreEscape = true;
|
||||
},
|
||||
|
||||
setState: function (state) {
|
||||
@ -565,6 +568,8 @@ var BasicComposer = Widget.extend(chat_mixin, {
|
||||
if (this.mention_manager.is_open()) {
|
||||
event.stopPropagation();
|
||||
this.mention_manager.reset_suggestions();
|
||||
} else if (this.ignoreEscape) {
|
||||
this.ignoreEscape = false;
|
||||
} else {
|
||||
this.trigger_up("escape_pressed");
|
||||
}
|
||||
@ -789,6 +794,7 @@ var BasicComposer = Widget.extend(chat_mixin, {
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
_onAttachmentView: function (event) {
|
||||
event.stopPropagation();
|
||||
var activeAttachmentID = $(event.currentTarget).data('id');
|
||||
var attachments = this.get('attachment_ids');
|
||||
if (activeAttachmentID) {
|
||||
|
@ -25,6 +25,7 @@ var DocumentViewer = Widget.extend({
|
||||
'DOMMouseScroll .o_viewer_content': '_onScroll', // Firefox
|
||||
'mousewheel .o_viewer_content': '_onScroll', // Chrome, Safari, IE
|
||||
'keydown': '_onKeydown',
|
||||
'keyup': '_onKeyUp',
|
||||
'mousedown .o_viewer_img': '_onStartDrag',
|
||||
'mousemove .o_viewer_content': '_onDrag',
|
||||
'mouseup .o_viewer_content': '_onEndDrag'
|
||||
@ -152,6 +153,7 @@ var DocumentViewer = Widget.extend({
|
||||
_onClose: function (e) {
|
||||
e.preventDefault();
|
||||
this.$el.modal('hide');
|
||||
this.trigger_up('document_viewer_closed');
|
||||
},
|
||||
/**
|
||||
* When popup close complete destroyed modal even DOM footprint too
|
||||
@ -232,6 +234,20 @@ var DocumentViewer = Widget.extend({
|
||||
break;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Close popup on ESCAPE keyup
|
||||
*
|
||||
* @private
|
||||
* @param {KeyEvent} e
|
||||
*/
|
||||
_onKeyUp: function (e) {
|
||||
switch (e.which) {
|
||||
case $.ui.keyCode.ESCAPE:
|
||||
e.preventDefault();
|
||||
this._onClose(e);
|
||||
break;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
|
@ -122,7 +122,7 @@ var MessagingMenu = Widget.extend({
|
||||
if (channelID === 'channel_inbox') {
|
||||
var resID = $(event.currentTarget).data('res_id');
|
||||
var resModel = $(event.currentTarget).data('res_model');
|
||||
if (resModel && resID) {
|
||||
if (resModel && resModel !== 'mail.channel' && resID) {
|
||||
this.do_action({
|
||||
type: 'ir.actions.act_window',
|
||||
res_model: resModel,
|
||||
@ -130,7 +130,11 @@ var MessagingMenu = Widget.extend({
|
||||
res_id: resID
|
||||
});
|
||||
} else {
|
||||
this.do_action('mail.mail_channel_action_client_chat', {clear_breadcrumbs: true})
|
||||
var clientChatOptions = {clear_breadcrumbs: true};
|
||||
if (resModel && resModel === 'mail.channel' && resID) {
|
||||
clientChatOptions.active_id = resID;
|
||||
}
|
||||
this.do_action('mail.mail_channel_action_client_chat', clientChatOptions)
|
||||
.then(function () {
|
||||
self.trigger_up('hide_app_switcher');
|
||||
core.bus.trigger('change_menu_section', chat_manager.get_discuss_menu_id());
|
||||
|
@ -328,6 +328,7 @@ var Thread = Widget.extend({
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
_onAttachmentView: function (event) {
|
||||
event.stopPropagation();
|
||||
var activeAttachmentID = $(event.currentTarget).data('id');
|
||||
if (activeAttachmentID) {
|
||||
var attachmentViewer = new DocumentViewer(this, this.attachments, activeAttachmentID);
|
||||
|
@ -60,7 +60,7 @@ function _parse_and_transform(nodes, transform_function) {
|
||||
|
||||
// Suggested URL Javascript regex of http://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url
|
||||
// Adapted to make http(s):// not required if (and only if) www. is given. So `should.notmatch` does not match.
|
||||
var url_regexp = /\b(?:https?:\/\/|(www\.))[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,13}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/gi;
|
||||
var url_regexp = /\b(?:https?:\/\/\d{1,3}(?:\.\d{1,3}){3}|(?:https?:\/\/|(?:www\.))[-a-z0-9@:%._\+~#=]{2,256}\.[a-z]{2,13})\b(?:[-a-z0-9@:%_\+.~#?&'$//=]*)/gi;
|
||||
function linkify(text, attrs) {
|
||||
attrs = attrs || {};
|
||||
if (attrs.target === undefined) {
|
||||
@ -70,7 +70,7 @@ function linkify(text, attrs) {
|
||||
return key + '="' + _.escape(value) + '"';
|
||||
}).join(' ');
|
||||
return text.replace(url_regexp, function (url) {
|
||||
var href = (!/^(f|ht)tps?:\/\//i.test(url)) ? "http://" + url : url;
|
||||
var href = (!/^https?:\/\//i.test(url)) ? "http://" + url : url;
|
||||
return '<a ' + attrs + ' href="' + href + '">' + url + '</a>';
|
||||
});
|
||||
}
|
||||
@ -92,6 +92,7 @@ function strip_html (node, transform_children) {
|
||||
|
||||
function inline (node, transform_children) {
|
||||
if (node.nodeType === 3) return node.data;
|
||||
if (node.nodeType === 8) return "";
|
||||
if (node.tagName === "BR") return " ";
|
||||
if (node.tagName.match(/^(A|P|DIV|PRE|BLOCKQUOTE)$/)) return transform_children();
|
||||
node.innerHTML = transform_children();
|
||||
@ -100,16 +101,23 @@ function inline (node, transform_children) {
|
||||
|
||||
// Parses text to find email: Tagada <address@mail.fr> -> [Tagada, address@mail.fr] or False
|
||||
function parse_email (text) {
|
||||
var result = text.match(/(.*)<(.*@.*)>/);
|
||||
if (result) {
|
||||
return [_.str.trim(result[1]), _.str.trim(result[2])];
|
||||
if (text){
|
||||
var result = text.match(/(.*)<(.*@.*)>/);
|
||||
if (result) {
|
||||
return [_.str.trim(result[1]), _.str.trim(result[2])];
|
||||
}
|
||||
result = text.match(/(.*@.*)/);
|
||||
if (result) {
|
||||
return [_.str.trim(result[1]), _.str.trim(result[1])];
|
||||
}
|
||||
return [text, false];
|
||||
}
|
||||
result = text.match(/(.*@.*)/);
|
||||
/* result = text.match(/(.*@.*)/);
|
||||
if (result) {
|
||||
return [_.str.trim(result[1]), _.str.trim(result[1])];
|
||||
}
|
||||
return [text, false];
|
||||
}
|
||||
}*/
|
||||
|
||||
// Replaces textarea text into html text (add <p>, <a>)
|
||||
// TDE note : should be done server-side, in Python -> use mail.compose.message ?
|
||||
|
@ -51,7 +51,7 @@
|
||||
border: none;
|
||||
}
|
||||
.o_composer_button_full_composer {
|
||||
.o-position-absolute(0, 0);
|
||||
.o-position-absolute(auto, 0);
|
||||
}
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.o_composer_button_send {
|
||||
@ -136,7 +136,7 @@
|
||||
|
||||
&.o_chat_inline_composer {
|
||||
.o_composer_container {
|
||||
.o-flex(1, 0, auto);
|
||||
.o-flex(1, 1, auto);
|
||||
}
|
||||
.o_composer {
|
||||
padding: @o-mail-chatter-gap @o-mail-chatter-gap 0 @o-mail-chatter-gap;
|
||||
@ -339,6 +339,7 @@
|
||||
}
|
||||
|
||||
.o_modal_fullscreen {
|
||||
z-index: @o-chat-window-zindex + 1; // To overlap chat window
|
||||
.o_viewer_content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -107,7 +107,7 @@
|
||||
&.o_mail_note {
|
||||
background-color: @mail-thread-note;
|
||||
padding-left: @grid-gutter-width*0.3;
|
||||
border-bottom: 1px solid @gray-lighter-dark;
|
||||
border-bottom: 1px solid @gray-lighter-darker;
|
||||
}
|
||||
|
||||
.o_mail_subject {
|
||||
|
@ -76,7 +76,7 @@
|
||||
</t>
|
||||
|
||||
<t t-name="DocumentViewer">
|
||||
<div class="modal o_modal_fullscreen" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal o_modal_fullscreen" tabindex="-1" data-keyboard="false" role="dialog" aria-hidden="true">
|
||||
<t t-call="DocumentViewer.Content"/>
|
||||
|
||||
<t t-if="widget.attachment.length != 1">
|
||||
|
@ -50,6 +50,84 @@ QUnit.module('mail', {}, function () {
|
||||
parent.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('open document viewer and close using ESCAPE key should reset focus to chat window', function (assert) {
|
||||
assert.expect(6);
|
||||
|
||||
function createParent(params) {
|
||||
var widget = new Widget();
|
||||
|
||||
testUtils.addMockEnvironment(widget, params);
|
||||
return widget;
|
||||
}
|
||||
var messages = [{
|
||||
attachment_ids: [{
|
||||
filename: 'image1.jpg',
|
||||
id:1,
|
||||
mimetype: 'image/jpeg',
|
||||
name: 'Test Image 1',
|
||||
url: '/web/content/1?download=true'
|
||||
}],
|
||||
author_id: ["1", "John Doe"],
|
||||
body: "A message",
|
||||
date: moment("2016-12-20 09:35:40"),
|
||||
displayed_author: "John Doe",
|
||||
id: 1,
|
||||
is_note: false,
|
||||
is_starred: false,
|
||||
model: 'partner',
|
||||
res_id: 2
|
||||
}];
|
||||
var parent = createParent({
|
||||
mockRPC: function (route, args) {
|
||||
if(_.str.contains(route, '/mail/attachment/preview/') ||
|
||||
_.str.contains(route, '/web/static/lib/pdfjs/web/viewer.html')){
|
||||
var canvas = document.createElement('canvas');
|
||||
return $.when(canvas.toDataURL());
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
data: {},
|
||||
});
|
||||
|
||||
var chatWindow = new ChatWindow(parent, 1, "user", false, messages.length, {});
|
||||
chatWindow.appendTo($('#qunit-fixture'));
|
||||
chatWindow.render(messages);
|
||||
|
||||
testUtils.intercept(chatWindow, 'get_messages', function(event) {
|
||||
event.stopPropagation();
|
||||
var requested_msgs = _.filter(messages, function (msg) {
|
||||
return _.contains(event.data.options.ids, msg.id);
|
||||
});
|
||||
event.data.callback($.when(requested_msgs));
|
||||
}, true);
|
||||
|
||||
testUtils.intercept(chatWindow, 'get_bus', function(event) {
|
||||
event.stopPropagation();
|
||||
event.data.callback(new Bus());
|
||||
}, true);
|
||||
|
||||
chatWindow.on('document_viewer_closed', null, function () {
|
||||
assert.ok(true, "chat window should trigger a close document viewer event");
|
||||
});
|
||||
assert.strictEqual(chatWindow.$('.o_thread_message .o_attachment').length, 1,
|
||||
"there should be three attachment on message");
|
||||
// click on first image attachement
|
||||
chatWindow.$('.o_thread_message .o_attachment .o_image_box .o_image_overlay').first().click();
|
||||
// check focus is on document viewer popup and then press escape to close it
|
||||
assert.strictEqual(document.activeElement, $('.o_modal_fullscreen')[0], "Modal popup should have focus");
|
||||
assert.strictEqual($('.o_modal_fullscreen img.o_viewer_img[src*="/web/image/1?unique=1"]').length, 1,
|
||||
"Modal popup should open with first image src");
|
||||
// trigger ESCAPE keyup on document viewer popup
|
||||
var upKeyEvent = jQuery.Event("keyup", {which: 27});
|
||||
$('.o_modal_fullscreen').trigger(upKeyEvent);
|
||||
assert.strictEqual(document.activeElement, chatWindow.$input[0],
|
||||
"input should be focused");
|
||||
var upKeyEvent = jQuery.Event( "keyup", {which: 27});
|
||||
chatWindow.$('.o_composer_input').trigger(upKeyEvent);
|
||||
assert.strictEqual(chatWindow.folded, false, "Closed chat Window");
|
||||
parent.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('chat window\'s input can still be focused when the UI is blocked', function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
|
@ -8,7 +8,7 @@ QUnit.module('mail', {}, function () {
|
||||
QUnit.module('Mail utils');
|
||||
|
||||
QUnit.test('add_link utility function', function (assert) {
|
||||
assert.expect(7);
|
||||
assert.expect(15);
|
||||
|
||||
var testInputs = {
|
||||
'http://admin:password@example.com:8/%2020': true,
|
||||
@ -24,6 +24,7 @@ QUnit.test('add_link utility function', function (assert) {
|
||||
var output = utils.parse_and_transform(content, utils.add_link);
|
||||
if (willLinkify) {
|
||||
assert.strictEqual(output.indexOf('<a '), 0, "There should be a link");
|
||||
assert.strictEqual(output.indexOf('</a>'), (output.length - 4), "Link should match the whole text");
|
||||
} else {
|
||||
assert.strictEqual(output.indexOf('<a '), -1, "There should be no link");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import socket
|
||||
|
||||
@ -10,7 +10,7 @@ from flectra.tools import mute_logger
|
||||
MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com>
|
||||
To: {to}
|
||||
cc: {cc}
|
||||
Received: by mail1.flectra.com (Postfix, from userid 10002)
|
||||
Received: by mail1.openerp.com (Postfix, from userid 10002)
|
||||
id 5DF9ABFB2A; Fri, 10 Aug 2012 16:16:39 +0200 (CEST)
|
||||
From: {email_from}
|
||||
Subject: {subject}
|
||||
@ -51,7 +51,7 @@ Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
MAIL_TEMPLATE_PLAINTEXT = """Return-Path: <whatever-2a840@postmaster.twitter.com>
|
||||
To: {to}
|
||||
Received: by mail1.flectra.com (Postfix, from userid 10002)
|
||||
Received: by mail1.openerp.com (Postfix, from userid 10002)
|
||||
id 5DF9ABFB2A; Fri, 10 Aug 2012 16:16:39 +0200 (CEST)
|
||||
From: Sylvie Lelitre <test.sylvie.lelitre@agrolait.com>
|
||||
Subject: {subject}
|
||||
@ -78,7 +78,7 @@ X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,FREEMAIL_FROM,
|
||||
HTML_MESSAGE,RCVD_IN_DNSWL_LOW autolearn=unavailable version=3.3.1
|
||||
Received: from mail-ie0-f173.google.com (mail-ie0-f173.google.com [209.85.223.173])
|
||||
by mail1.grosbedon.com (Postfix) with ESMTPS id 9BBD7BFAAA
|
||||
for <raoul@flectra.fr>; Fri, 23 Aug 2013 13:17:55 +0200 (CEST)
|
||||
for <raoul@openerp.fr>; Fri, 23 Aug 2013 13:17:55 +0200 (CEST)
|
||||
Received: by mail-ie0-f173.google.com with SMTP id qd12so575130ieb.4
|
||||
for <raoul@grosbedon.fr>; Fri, 23 Aug 2013 04:17:54 -0700 (PDT)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
@ -298,6 +298,630 @@ AAAAACwAAAAAAgACAAAEA3DJFQA7
|
||||
--001a11416b9e9b229a05272b7052--
|
||||
"""
|
||||
|
||||
MAIL_EML_ATTACHMENT = """Subject: Re: test attac
|
||||
From: Anon <anon@flectrahq.com>
|
||||
To: anon@gmail.com
|
||||
References: <f3b9f8f8-28fa-2543-cab2-7aa68f679ebb@flectrahq.com>
|
||||
Message-ID: <cb7eaf62-58dc-2017-148c-305d0c78892f@flectrahq.com>
|
||||
Date: Wed, 14 Mar 2018 14:26:58 +0100
|
||||
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101
|
||||
Thunderbird/52.6.0
|
||||
MIME-Version: 1.0
|
||||
In-Reply-To: <f3b9f8f8-28fa-2543-cab2-7aa68f679ebb@flectrahq.com>
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="------------A6B5FD5F68F4D73ECD739009"
|
||||
Content-Language: en-US
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------A6B5FD5F68F4D73ECD739009
|
||||
Content-Type: text/plain; charset=utf-8; format=flowed
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
|
||||
|
||||
On 14/03/18 14:20, Anon wrote:
|
||||
> Some nice content
|
||||
>
|
||||
|
||||
|
||||
--------------A6B5FD5F68F4D73ECD739009
|
||||
Content-Type: message/rfc822;
|
||||
name="original_msg.eml"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: attachment;
|
||||
filename="original_msg.eml"
|
||||
|
||||
Delivered-To: anon2@gmail1.openerp.com
|
||||
Received: by 10.46.1.170 with SMTP id f42csp2379722lji;
|
||||
Mon, 5 Mar 2018 01:19:23 -0800 (PST)
|
||||
X-Google-Smtp-Source: AG47ELsYTlAcblMxfnaEENQuF+MFoac5Q07wieyw0cybq/qOX4+DmayqoQILkiWT+NiTOcnr/ACO
|
||||
X-Received: by 10.28.154.213 with SMTP id c204mr7237750wme.64.1520241563503;
|
||||
Mon, 05 Mar 2018 01:19:23 -0800 (PST)
|
||||
ARC-Seal: i=1; a=rsa-sha256; t=1520241563; cv=none;
|
||||
d=google.com; s=arc-20160816;
|
||||
b=BqgMSbqmbpYW1ZtfGTVjj/654MBmabw4XadNZEaI96hDaub6N6cP8Guu3PoxscI9os
|
||||
0OLYVP1s/B+Vv9rIzulCwHyHsgnX+aTxGYepTDN6x8SA9Qeb9aQoNSVvQLryTAoGpaFr
|
||||
vXhw8aPWyr28edE03TDFA/s7X65Bf6dV5zJdMiUPVqGkfYfcTHMf3nDER5vk8vQj7tve
|
||||
Cfyy0h9vLU9RSEtdFwmlEkLmgT9NQ3GDf0jQ97eMXPgR2q6duCPoMcz15KlWOno53xgH
|
||||
EiV7aIZ5ZMN/m+/2xt3br/ubJ5euFojWhDnHUZoaqd08TCSQPd4fFCCx75MjDeCnwYMn
|
||||
iKSg==
|
||||
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
|
||||
h=content-language:mime-version:user-agent:date:message-id:subject
|
||||
:from:to:dkim-signature:arc-authentication-results;
|
||||
bh=/UIFqhjCCbwBLsI4w7YY98QH6G/wxe+2W4bbMDCskjM=;
|
||||
b=Wv5jt+usnSgWI96GaZWUN8/VKl1drueDpU/4gkyX/iK4d6S4CuSDjwYAc3guz/TjeW
|
||||
GoKCqT30IGZoStpXQbuLry7ezXNK+Fp8MJKN2n/x5ClJWHxIsxIGlP2QC3TO8RI0P5o0
|
||||
GXG9izW93q1ubkdPJFt3unSjjwSYf5XVQAZQtRm9xKjqA+lbtFbsnbjJ4wgYBURnD8ma
|
||||
Qxb2xsxXDelaZvtdlzHRDn5SEkbqhcCclEYw6oRLpVQFZeYtPxcCleVybtj2owJxdaLp
|
||||
7wXuo/gpYe6E2cPuS2opei8AzjEhYTNzlYXTPvaoxCCTTjfGTaPv22TeRDehuIXngSEl
|
||||
Nmmw==
|
||||
ARC-Authentication-Results: i=1; mx.google.com;
|
||||
dkim=pass header.i=@flectrahq.com header.s=mail header.b=MCzhjB9b;
|
||||
spf=pass (google.com: domain of soup@flectrahq.com designates 149.202.180.44 as permitted sender) smtp.mailfrom=soup@flectrahq.com;
|
||||
dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=flectrahq.com
|
||||
Return-Path: <soup@flectrahq.com>
|
||||
Received: from mail2.flectrahq.com (mail2.flectrahq.com. [149.202.180.44])
|
||||
by mx.google.com with ESMTPS id y4si4279200wmy.148.2018.03.05.01.19.22
|
||||
(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
|
||||
Mon, 05 Mar 2018 01:19:23 -0800 (PST)
|
||||
Received-SPF: pass (google.com: domain of soup@flectrahq.com designates 149.202.180.44 as permitted sender) client-ip=149.202.180.44;
|
||||
Authentication-Results: mx.google.com;
|
||||
dkim=pass header.i=@flectrahq.com header.s=mail header.b=MCzhjB9b;
|
||||
spf=pass (google.com: domain of soup@flectrahq.com designates 149.202.180.44 as permitted sender) smtp.mailfrom=soup@flectrahq.com;
|
||||
dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=flectrahq.com
|
||||
Received: from [10.10.31.24] (unknown [91.183.114.50])
|
||||
(Authenticated sender: soup)
|
||||
by mail2.flectrahq.com (Postfix) with ESMTPSA id 7B571A4085
|
||||
for <what@flectrahq.com>; Mon, 5 Mar 2018 10:19:21 +0100 (CET)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=flectrahq.com; s=mail;
|
||||
t=1520241562; bh=L2r7Sp/vjogIdM1k8H9zDGDjnhKolsTTLLjndnFC4Jc=;
|
||||
h=To:From:Subject:Date:From;
|
||||
b=MCzhjB9bnsrJ3uKjq+GjujFxmtrq3fc7Vv7Vg2C72EPKnkxgqy6yPjWKtXbBlaiT3
|
||||
YjKI24aiSQlOeOPQiqFgiDzeqqemNDp+CRuhoYz1Vbz+ESRaHtkWRLb7ZjvohS2k7e
|
||||
RTq7tUxY2nUL2YrNHV7DFYtJVBwiTuyLP6eAiJdE=
|
||||
To: what@flectrahq.com
|
||||
From: Soup <soup@flectrahq.com>
|
||||
Subject: =?UTF-8?Q?Soupe_du_jour_:_Pois_cass=c3=a9s?=
|
||||
Message-ID: <a05d8334-7b7c-df68-c96a-4a88ed19f31b@flectrahq.com>
|
||||
Date: Mon, 5 Mar 2018 10:19:21 +0100
|
||||
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101
|
||||
Thunderbird/52.6.0
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="------------1F2D18B1129FC2F0B9EECF50"
|
||||
Content-Language: en-US
|
||||
X-Spam-Status: No, score=-1.2 required=5.0 tests=ALL_TRUSTED,BAYES_00,
|
||||
HTML_IMAGE_ONLY_08,HTML_MESSAGE,T_REMOTE_IMAGE autolearn=no
|
||||
autolearn_force=no version=3.4.0
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail2.flectrahq.com
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------1F2D18B1129FC2F0B9EECF50
|
||||
Content-Type: text/plain; charset=utf-8; format=flowed
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Résultat de recherche d'images pour "dessin la princesse au petit pois"
|
||||
|
||||
--
|
||||
Soup
|
||||
|
||||
Odoo S.A.
|
||||
Chaussée de Namur, 40
|
||||
B-1367 Grand Rosière
|
||||
Web: http://www.flectrahq.com
|
||||
|
||||
|
||||
--------------1F2D18B1129FC2F0B9EECF50
|
||||
Content-Type: text/html; charset=utf-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#FFFFFF">
|
||||
<p><img
|
||||
src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjCNAadd3NDM8g9w0P_-gAVYrrqC0wmBNYKGsTZ2Pst5SsNxTRnA"
|
||||
alt="Résultat de recherche d'images pour "dessin la
|
||||
princesse au petit pois""></p>
|
||||
<pre class="moz-signature" cols="72">--
|
||||
Soup
|
||||
|
||||
Odoo S.A.
|
||||
Chaussée de Namur, 40
|
||||
B-1367 Grand Rosière
|
||||
Web: <a class="moz-txt-link-freetext" href="http://www.flectrahq.com">http://www.flectrahq.com</a> </pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
--------------1F2D18B1129FC2F0B9EECF50--
|
||||
|
||||
--------------A6B5FD5F68F4D73ECD739009--"""
|
||||
|
||||
|
||||
MAIL_XHTML = """Return-Path: <xxxx@xxxx.com>
|
||||
Received: from xxxx.internal (xxxx.xxxx.internal [1.1.1.1])
|
||||
by xxxx (xxxx 1.1.1-111-g972eecc-slipenbois) with LMTPA;
|
||||
Fri, 13 Apr 2018 22:11:52 -0400
|
||||
X-Cyrus-Session-Id: sloti35d1t38-1111111-11111111111-5-11111111111111111111
|
||||
X-Sieve: CMU Sieve 1.0
|
||||
X-Spam-known-sender: no ("Email failed DMARC policy for domain"); in-addressbook
|
||||
X-Spam-score: 0.0
|
||||
X-Spam-hits: ALL_TRUSTED -1, BAYES_00 -1.9, FREEMAIL_FROM 0.001,
|
||||
HTML_FONT_LOW_CONTRAST 0.001, HTML_MESSAGE 0.001, SPF_SOFTFAIL 0.665,
|
||||
LANGUAGES en, BAYES_USED global, SA_VERSION 1.1.0
|
||||
X-Spam-source: IP='1.1.1.1', Host='unk', Country='unk', FromHeader='com',
|
||||
MailFrom='com'
|
||||
X-Spam-charsets: plain='utf-8', html='utf-8'
|
||||
X-IgnoreVacation: yes ("Email failed DMARC policy for domain")
|
||||
X-Resolved-to: catchall@xxxx.xxxx
|
||||
X-Delivered-to: catchall@xxxx.xxxx
|
||||
X-Mail-from: xxxx@xxxx.com
|
||||
Received: from mx4 ([1.1.1.1])
|
||||
by xxxx.internal (LMTPProxy); Fri, 13 Apr 2018 22:11:52 -0400
|
||||
Received: from xxxx.xxxx.com (localhost [127.0.0.1])
|
||||
by xxxx.xxxx.internal (Postfix) with ESMTP id E1111C1111;
|
||||
Fri, 13 Apr 2018 22:11:51 -0400 (EDT)
|
||||
Received: from xxxx.xxxx.internal (localhost [127.0.0.1])
|
||||
by xxxx.xxxx.com (Authentication Milter) with ESMTP
|
||||
id BBDD1111D1A;
|
||||
Fri, 13 Apr 2018 22:11:51 -0400
|
||||
ARC-Authentication-Results: i=1; xxxx.xxxx.com; arc=none (no signatures found);
|
||||
dkim=pass (2048-bit rsa key sha256) header.d=xxxx.com header.i=@xxxx.com header.b=P1aaAAaa x-bits=2048 x-keytype=rsa x-algorithm=sha256 x-selector=fm2;
|
||||
dmarc=fail (p=none,d=none) header.from=xxxx.com;
|
||||
iprev=pass policy.iprev=1.1.1.1 (out1-smtp.xxxx.com);
|
||||
spf=softfail smtp.mailfrom=xxxx@xxxx.com smtp.helo=out1-smtp.xxxx.com;
|
||||
x-aligned-from=pass (Address match);
|
||||
x-cm=none score=0;
|
||||
x-ptr=pass x-ptr-helo=out1-smtp.xxxx.com x-ptr-lookup=out1-smtp.xxxx.com;
|
||||
x-return-mx=pass smtp.domain=xxxx.com smtp.result=pass smtp_is_org_domain=yes header.domain=xxxx.com header.result=pass header_is_org_domain=yes;
|
||||
x-tls=pass version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128;
|
||||
x-vs=clean score=0 state=0
|
||||
Authentication-Results: xxxx.xxxx.com;
|
||||
arc=none (no signatures found);
|
||||
dkim=pass (2048-bit rsa key sha256) header.d=xxxx.com header.i=@xxxx.com header.b=P1awJPiy x-bits=2048 x-keytype=rsa x-algorithm=sha256 x-selector=fm2;
|
||||
dmarc=fail (p=none,d=none) header.from=xxxx.com;
|
||||
iprev=pass policy.iprev=66.111.4.25 (out1-smtp.xxxx.com);
|
||||
spf=softfail smtp.mailfrom=xxxx@xxxx.com smtp.helo=out1-smtp.xxxx.com;
|
||||
x-aligned-from=pass (Address match);
|
||||
x-cm=none score=0;
|
||||
x-ptr=pass x-ptr-helo=out1-smtp.xxxx.com x-ptr-lookup=out1-smtp.xxxx.com;
|
||||
x-return-mx=pass smtp.domain=xxxx.com smtp.result=pass smtp_is_org_domain=yes header.domain=xxxx.com header.result=pass header_is_org_domain=yes;
|
||||
x-tls=pass version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128;
|
||||
x-vs=clean score=0 state=0
|
||||
X-ME-VSCategory: clean
|
||||
X-ME-CMScore: 0
|
||||
X-ME-CMCategory: none
|
||||
Received-SPF: softfail
|
||||
(gmail.com ... _spf.xxxx.com: Sender is not authorized by default to use 'xxxx@xxxx.com' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched))
|
||||
receiver=xxxx.xxxx.com;
|
||||
identity=mailfrom;
|
||||
envelope-from="xxxx@xxxx.com";
|
||||
helo=out1-smtp.xxxx.com;
|
||||
client-ip=1.1.1.1
|
||||
Received: from xxxx.xxxx.internal (gateway1.xxxx.internal [1.1.1.1])
|
||||
(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
|
||||
(No client certificate requested)
|
||||
by xxxx.xxxx.internal (Postfix) with ESMTPS;
|
||||
Fri, 13 Apr 2018 22:11:51 -0400 (EDT)
|
||||
Received: from compute3.internal (xxxx.xxxx.internal [10.202.2.43])
|
||||
by xxxx.xxxx.internal (Postfix) with ESMTP id 8BD5B21BBD;
|
||||
Fri, 13 Apr 2018 22:11:51 -0400 (EDT)
|
||||
Received: from xxxx ([10.202.2.163])
|
||||
by xxxx.internal (MEProxy); Fri, 13 Apr 2018 22:11:51 -0400
|
||||
X-ME-Sender: <xms:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
|
||||
Received: from [1.1.1.1] (unknown [1.1.1.1])
|
||||
by mail.xxxx.com (Postfix) with ESMTPA id BF5E1111D
|
||||
for <catchall@xxxx.xxxx>; Fri, 13 Apr 2018 22:11:50 -0400 (EDT)
|
||||
From: "xxxx xxxx" <xxxx@xxxx.com>
|
||||
To: "xxxx" <catchall@xxxx.xxxx>
|
||||
Subject: Re: xxxx (Ref PO1)
|
||||
Date: Sat, 14 Apr 2018 02:11:42 +0000
|
||||
Message-Id: <em67f5c44a-xxxx-xxxx-xxxx-69f56d618a94@wswin7hg4n4l1ce>
|
||||
In-Reply-To: <829228111124527.1111111602.256611118262939-openerp-129-xxxx.xxxx@ip-1-1-1-1>
|
||||
References: <867911111953277.1523671337.187951111160400-openerp-129-xxxx.xxxx@ip-1-1-1-1>
|
||||
<867911111953277.1523671337.256611118262939-openerp-129-xxxx.xxxx@ip-1-1-1-1>
|
||||
Reply-To: "xxxx xxxx" <xxxx@xxxx.com>
|
||||
User-Agent: eM_Client/7.0.26687.0
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="------=_MB48E455BD-1111-42EC-1111-886CDF48905E"
|
||||
|
||||
--------=_MB48E455BD-1111-42EC-1111-886CDF48905E
|
||||
Content-Type: text/plain; format=flowed; charset=utf-8
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
xxxx
|
||||
|
||||
|
||||
------ Original Message ------
|
||||
From: "xxxx" <xxxx@xxxx.com>
|
||||
To: "xxxx" <xxxx@xxxx.com>
|
||||
Sent: 4/13/2018 7:06:43 PM
|
||||
Subject: xxxx
|
||||
|
||||
>xxxx
|
||||
|
||||
--------=_MB48E455BD-1111-42EC-1111-886CDF48905E
|
||||
Content-Type: text/html; charset=utf-8
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
<?xml version=3D"1.0" encoding=3D"utf-16"?><html><head><style type=3D"text/=
|
||||
css"><!--blockquote.cite
|
||||
{margin-left: 5px; margin-right: 0px; padding-left: 10px; padding-right:=
|
||||
0px; border-left-width: 1px; border-left-style: solid; border-left-color:=
|
||||
rgb(204, 204, 204);}
|
||||
blockquote.cite2
|
||||
{margin-left: 5px; margin-right: 0px; padding-left: 10px; padding-right:=
|
||||
0px; border-left-width: 1px; border-left-style: solid; border-left-color:=
|
||||
rgb(204, 204, 204); margin-top: 3px; padding-top: 0px;}
|
||||
a img
|
||||
{border: 0px;}
|
||||
body
|
||||
{font-family: Tahoma; font-size: 12pt;}
|
||||
--></style></head><body><div>this is a reply to PO200109 from emClient</div=
|
||||
><div id=3D"signature_old"><div style=3D"font-family: Tahoma; font-size:=
|
||||
12 pt;">-- <br /><span><span class=3D"__postbox-detected-content __postbox=
|
||||
-detected-address" style=3D"TEXT-DECORATION: underline; COLOR: rgb(115,133,=
|
||||
172); PADDING-BOTTOM: 0pt; PADDING-TOP: 0pt; PADDING-LEFT: 0pt; DISPLAY:=
|
||||
inline; PADDING-RIGHT: 0pt" __postbox-detected-content=3D"__postbox-detect=
|
||||
ed-address"></span>xxxx<br />xxxx<br /><b=
|
||||
r />xxxx</span></=
|
||||
div></div><div><br /></div><div><br /></div><div><br /></div>
|
||||
<div>------ Original Message ------</div>
|
||||
<div>From: "xxxx" <<a href=3D"mailto:xxxx@xxxx.com">xxxx=
|
||||
@xxxx.com</a>></div>
|
||||
<div>To: "xxxx" <<a href=3D"mailto:xxxx@xxxx.com">a=
|
||||
xxxx@xxxx.com</a>></div>
|
||||
<div>Sent: 4/13/2018 7:06:43 PM</div>
|
||||
<div>Subject: xxxx</div><div><br /></div=
|
||||
>
|
||||
<div id=3D"x00b4101ba6e64ce"><blockquote cite=3D"829228972724527.1523671602=
|
||||
.256660938262939-openerp-129-xxxx.xxxx@ip-1-1-1-1" type=3D"cite"=
|
||||
class=3D"cite2">
|
||||
<table border=3D"0" width=3D"100%" cellpadding=3D"0" bgcolor=3D"#ededed"=
|
||||
style=3D"padding: 20px; background-color: #ededed" summary=3D"o_mail_notif=
|
||||
ication">
|
||||
<tbody>
|
||||
|
||||
<!-- HEADER -->
|
||||
<tr>
|
||||
<td align=3D"center" style=3D"min-width: 590px;">
|
||||
<table width=3D"590" border=3D"0" cellpadding=3D=
|
||||
"0" bgcolor=3D"#875A7B" style=3D"min-width: 590px; background-color: rgb(13=
|
||||
5,90,123); padding: 20px;">
|
||||
<tbody><tr>
|
||||
<td valign=3D"middle">
|
||||
<span style=3D"font-size:20px; color:whit=
|
||||
e; font-weight: bold;">
|
||||
mangez des saucisses
|
||||
</span>
|
||||
</td>
|
||||
<td valign=3D"middle" align=3D"right">
|
||||
<img src=3D"http://erp.xxxx.xxxx/logo.png=
|
||||
" style=3D"padding: 0px; margin: 0px; height: auto; width: 80px;" alt=3D=
|
||||
"xxxx" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- CONTENT -->
|
||||
<tr>
|
||||
<td align=3D"center" style=3D"min-width: 590px;">
|
||||
<table width=3D"590" border=3D"0" cellpadding=3D=
|
||||
"0" bgcolor=3D"#ffffff" style=3D"min-width: 590px; background-color: rgb(25=
|
||||
5, 255, 255); padding: 20px;">
|
||||
<tbody>
|
||||
<tr><td valign=3D"top" style=3D"font-family:A=
|
||||
rial,Helvetica,sans-serif; color: #555; font-size: 14px;">
|
||||
<p style=3D"margin: 0px 0px 9px 0px; font-s=
|
||||
ize: 13px; font-family: "Lucida Grande", Helvetica, Verdana, Aria=
|
||||
l, sans-serif">xxxx.=20
|
||||
,</p>
|
||||
<p style=3D"margin: 0px 0px 9px 0px; font-size: 13px; font-family: "Lu=
|
||||
cida Grande", Helvetica, Verdana, Arial, sans-serif">
|
||||
xxxx.
|
||||
</p>
|
||||
|
||||
<p style=3D"margin: 0px 0px 9px 0px; font-size: 13px; font-family: "Lu=
|
||||
cida Grande", Helvetica, Verdana, Arial, sans-serif">You can reply =
|
||||
to this email if you have any questions.</p>
|
||||
<p style=3D"margin: 0px 0px 9px 0px; font-size: 13px; font-family: "Lu=
|
||||
cida Grande", Helvetica, Verdana, Arial, sans-serif">Thank you,</p>
|
||||
</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<tr>
|
||||
<td align=3D"center" style=3D"min-width: 590px;">
|
||||
<table width=3D"590" border=3D"0" cellpadding=3D=
|
||||
"0" bgcolor=3D"#875A7B" style=3D"min-width: 590px; background-color: rgb(13=
|
||||
5,90,123); padding: 20px;">
|
||||
<tbody><tr>
|
||||
<td valign=3D"middle" align=3D"left" style=
|
||||
=3D"color: #fff; padding-top: 10px; padding-bottom: 10px; font-size: 12px;"=
|
||||
>
|
||||
xxxx<br />
|
||||
+1-801-980-4240
|
||||
</td>
|
||||
<td valign=3D"middle" align=3D"right" style=
|
||||
=3D"color: #fff; padding-top: 10px; padding-bottom: 10px; font-size: 12px;"=
|
||||
>
|
||||
<a href=3D"http://erp.xxxx.xxxx/info@xxxx-a=
|
||||
aa.com" style=3D"text-decoration:none; color: white;">info@aust-mfg.com</a>=
|
||||
<br />
|
||||
<a href=3D"http://www.xxxx=
|
||||
.com" style=3D"text-decoration:none; color: white;">
|
||||
http://www.xxxx.com
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=3D"center">
|
||||
Powered by <a href=3D"https://www.flectrahq.com">Odo=
|
||||
o</a>.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
=20
|
||||
<pre style=3D"white-space: pre-wrap">xxxx.
|
||||
</pre>
|
||||
</blockquote></div>
|
||||
</body></html>
|
||||
--------=_MB48E455BD-2850-42EC-B1CA-886CDF48905E--"""
|
||||
|
||||
|
||||
|
||||
MAIL_XHTML = """Return-Path: <xxxx@xxxx.com>
|
||||
Received: from xxxx.internal (xxxx.xxxx.internal [1.1.1.1])
|
||||
by xxxx (xxxx 1.1.1-111-g972eecc-slipenbois) with LMTPA;
|
||||
Fri, 13 Apr 2018 22:11:52 -0400
|
||||
X-Cyrus-Session-Id: sloti35d1t38-1111111-11111111111-5-11111111111111111111
|
||||
X-Sieve: CMU Sieve 1.0
|
||||
X-Spam-known-sender: no ("Email failed DMARC policy for domain"); in-addressbook
|
||||
X-Spam-score: 0.0
|
||||
X-Spam-hits: ALL_TRUSTED -1, BAYES_00 -1.9, FREEMAIL_FROM 0.001,
|
||||
HTML_FONT_LOW_CONTRAST 0.001, HTML_MESSAGE 0.001, SPF_SOFTFAIL 0.665,
|
||||
LANGUAGES en, BAYES_USED global, SA_VERSION 1.1.0
|
||||
X-Spam-source: IP='1.1.1.1', Host='unk', Country='unk', FromHeader='com',
|
||||
MailFrom='com'
|
||||
X-Spam-charsets: plain='utf-8', html='utf-8'
|
||||
X-IgnoreVacation: yes ("Email failed DMARC policy for domain")
|
||||
X-Resolved-to: catchall@xxxx.xxxx
|
||||
X-Delivered-to: catchall@xxxx.xxxx
|
||||
X-Mail-from: xxxx@xxxx.com
|
||||
Received: from mx4 ([1.1.1.1])
|
||||
by xxxx.internal (LMTPProxy); Fri, 13 Apr 2018 22:11:52 -0400
|
||||
Received: from xxxx.xxxx.com (localhost [127.0.0.1])
|
||||
by xxxx.xxxx.internal (Postfix) with ESMTP id E1111C1111;
|
||||
Fri, 13 Apr 2018 22:11:51 -0400 (EDT)
|
||||
Received: from xxxx.xxxx.internal (localhost [127.0.0.1])
|
||||
by xxxx.xxxx.com (Authentication Milter) with ESMTP
|
||||
id BBDD1111D1A;
|
||||
Fri, 13 Apr 2018 22:11:51 -0400
|
||||
ARC-Authentication-Results: i=1; xxxx.xxxx.com; arc=none (no signatures found);
|
||||
dkim=pass (2048-bit rsa key sha256) header.d=xxxx.com header.i=@xxxx.com header.b=P1aaAAaa x-bits=2048 x-keytype=rsa x-algorithm=sha256 x-selector=fm2;
|
||||
dmarc=fail (p=none,d=none) header.from=xxxx.com;
|
||||
iprev=pass policy.iprev=1.1.1.1 (out1-smtp.xxxx.com);
|
||||
spf=softfail smtp.mailfrom=xxxx@xxxx.com smtp.helo=out1-smtp.xxxx.com;
|
||||
x-aligned-from=pass (Address match);
|
||||
x-cm=none score=0;
|
||||
x-ptr=pass x-ptr-helo=out1-smtp.xxxx.com x-ptr-lookup=out1-smtp.xxxx.com;
|
||||
x-return-mx=pass smtp.domain=xxxx.com smtp.result=pass smtp_is_org_domain=yes header.domain=xxxx.com header.result=pass header_is_org_domain=yes;
|
||||
x-tls=pass version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128;
|
||||
x-vs=clean score=0 state=0
|
||||
Authentication-Results: xxxx.xxxx.com;
|
||||
arc=none (no signatures found);
|
||||
dkim=pass (2048-bit rsa key sha256) header.d=xxxx.com header.i=@xxxx.com header.b=P1awJPiy x-bits=2048 x-keytype=rsa x-algorithm=sha256 x-selector=fm2;
|
||||
dmarc=fail (p=none,d=none) header.from=xxxx.com;
|
||||
iprev=pass policy.iprev=66.111.4.25 (out1-smtp.xxxx.com);
|
||||
spf=softfail smtp.mailfrom=xxxx@xxxx.com smtp.helo=out1-smtp.xxxx.com;
|
||||
x-aligned-from=pass (Address match);
|
||||
x-cm=none score=0;
|
||||
x-ptr=pass x-ptr-helo=out1-smtp.xxxx.com x-ptr-lookup=out1-smtp.xxxx.com;
|
||||
x-return-mx=pass smtp.domain=xxxx.com smtp.result=pass smtp_is_org_domain=yes header.domain=xxxx.com header.result=pass header_is_org_domain=yes;
|
||||
x-tls=pass version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128;
|
||||
x-vs=clean score=0 state=0
|
||||
X-ME-VSCategory: clean
|
||||
X-ME-CMScore: 0
|
||||
X-ME-CMCategory: none
|
||||
Received-SPF: softfail
|
||||
(gmail.com ... _spf.xxxx.com: Sender is not authorized by default to use 'xxxx@xxxx.com' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched))
|
||||
receiver=xxxx.xxxx.com;
|
||||
identity=mailfrom;
|
||||
envelope-from="xxxx@xxxx.com";
|
||||
helo=out1-smtp.xxxx.com;
|
||||
client-ip=1.1.1.1
|
||||
Received: from xxxx.xxxx.internal (gateway1.xxxx.internal [1.1.1.1])
|
||||
(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
|
||||
(No client certificate requested)
|
||||
by xxxx.xxxx.internal (Postfix) with ESMTPS;
|
||||
Fri, 13 Apr 2018 22:11:51 -0400 (EDT)
|
||||
Received: from compute3.internal (xxxx.xxxx.internal [10.202.2.43])
|
||||
by xxxx.xxxx.internal (Postfix) with ESMTP id 8BD5B21BBD;
|
||||
Fri, 13 Apr 2018 22:11:51 -0400 (EDT)
|
||||
Received: from xxxx ([10.202.2.163])
|
||||
by xxxx.internal (MEProxy); Fri, 13 Apr 2018 22:11:51 -0400
|
||||
X-ME-Sender: <xms:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
|
||||
Received: from [1.1.1.1] (unknown [1.1.1.1])
|
||||
by mail.xxxx.com (Postfix) with ESMTPA id BF5E1111D
|
||||
for <catchall@xxxx.xxxx>; Fri, 13 Apr 2018 22:11:50 -0400 (EDT)
|
||||
From: "xxxx xxxx" <xxxx@xxxx.com>
|
||||
To: "xxxx" <catchall@xxxx.xxxx>
|
||||
Subject: Re: xxxx (Ref PO1)
|
||||
Date: Sat, 14 Apr 2018 02:11:42 +0000
|
||||
Message-Id: <em67f5c44a-xxxx-xxxx-xxxx-69f56d618a94@wswin7hg4n4l1ce>
|
||||
In-Reply-To: <829228111124527.1111111602.256611118262939-openerp-129-xxxx.xxxx@ip-1-1-1-1>
|
||||
References: <867911111953277.1523671337.187951111160400-openerp-129-xxxx.xxxx@ip-1-1-1-1>
|
||||
<867911111953277.1523671337.256611118262939-openerp-129-xxxx.xxxx@ip-1-1-1-1>
|
||||
Reply-To: "xxxx xxxx" <xxxx@xxxx.com>
|
||||
User-Agent: eM_Client/7.0.26687.0
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="------=_MB48E455BD-1111-42EC-1111-886CDF48905E"
|
||||
|
||||
--------=_MB48E455BD-1111-42EC-1111-886CDF48905E
|
||||
Content-Type: text/plain; format=flowed; charset=utf-8
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
xxxx
|
||||
|
||||
|
||||
------ Original Message ------
|
||||
From: "xxxx" <xxxx@xxxx.com>
|
||||
To: "xxxx" <xxxx@xxxx.com>
|
||||
Sent: 4/13/2018 7:06:43 PM
|
||||
Subject: xxxx
|
||||
|
||||
>xxxx
|
||||
|
||||
--------=_MB48E455BD-1111-42EC-1111-886CDF48905E
|
||||
Content-Type: text/html; charset=utf-8
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
<?xml version=3D"1.0" encoding=3D"utf-16"?><html><head><style type=3D"text/=
|
||||
css"><!--blockquote.cite
|
||||
{margin-left: 5px; margin-right: 0px; padding-left: 10px; padding-right:=
|
||||
0px; border-left-width: 1px; border-left-style: solid; border-left-color:=
|
||||
rgb(204, 204, 204);}
|
||||
blockquote.cite2
|
||||
{margin-left: 5px; margin-right: 0px; padding-left: 10px; padding-right:=
|
||||
0px; border-left-width: 1px; border-left-style: solid; border-left-color:=
|
||||
rgb(204, 204, 204); margin-top: 3px; padding-top: 0px;}
|
||||
a img
|
||||
{border: 0px;}
|
||||
body
|
||||
{font-family: Tahoma; font-size: 12pt;}
|
||||
--></style></head><body><div>this is a reply to PO200109 from emClient</div=
|
||||
><div id=3D"signature_old"><div style=3D"font-family: Tahoma; font-size:=
|
||||
12 pt;">-- <br /><span><span class=3D"__postbox-detected-content __postbox=
|
||||
-detected-address" style=3D"TEXT-DECORATION: underline; COLOR: rgb(115,133,=
|
||||
172); PADDING-BOTTOM: 0pt; PADDING-TOP: 0pt; PADDING-LEFT: 0pt; DISPLAY:=
|
||||
inline; PADDING-RIGHT: 0pt" __postbox-detected-content=3D"__postbox-detect=
|
||||
ed-address"></span>xxxx<br />xxxx<br /><b=
|
||||
r />xxxx</span></=
|
||||
div></div><div><br /></div><div><br /></div><div><br /></div>
|
||||
<div>------ Original Message ------</div>
|
||||
<div>From: "xxxx" <<a href=3D"mailto:xxxx@xxxx.com">xxxx=
|
||||
@xxxx.com</a>></div>
|
||||
<div>To: "xxxx" <<a href=3D"mailto:xxxx@xxxx.com">a=
|
||||
xxxx@xxxx.com</a>></div>
|
||||
<div>Sent: 4/13/2018 7:06:43 PM</div>
|
||||
<div>Subject: xxxx</div><div><br /></div=
|
||||
>
|
||||
<div id=3D"x00b4101ba6e64ce"><blockquote cite=3D"829228972724527.1523671602=
|
||||
.256660938262939-openerp-129-xxxx.xxxx@ip-1-1-1-1" type=3D"cite"=
|
||||
class=3D"cite2">
|
||||
<table border=3D"0" width=3D"100%" cellpadding=3D"0" bgcolor=3D"#ededed"=
|
||||
style=3D"padding: 20px; background-color: #ededed" summary=3D"o_mail_notif=
|
||||
ication">
|
||||
<tbody>
|
||||
|
||||
<!-- HEADER -->
|
||||
<tr>
|
||||
<td align=3D"center" style=3D"min-width: 590px;">
|
||||
<table width=3D"590" border=3D"0" cellpadding=3D=
|
||||
"0" bgcolor=3D"#875A7B" style=3D"min-width: 590px; background-color: rgb(13=
|
||||
5,90,123); padding: 20px;">
|
||||
<tbody><tr>
|
||||
<td valign=3D"middle">
|
||||
<span style=3D"font-size:20px; color:whit=
|
||||
e; font-weight: bold;">
|
||||
mangez des saucisses
|
||||
</span>
|
||||
</td>
|
||||
<td valign=3D"middle" align=3D"right">
|
||||
<img src=3D"http://erp.xxxx.xxxx/logo.png=
|
||||
" style=3D"padding: 0px; margin: 0px; height: auto; width: 80px;" alt=3D=
|
||||
"xxxx" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- CONTENT -->
|
||||
<tr>
|
||||
<td align=3D"center" style=3D"min-width: 590px;">
|
||||
<table width=3D"590" border=3D"0" cellpadding=3D=
|
||||
"0" bgcolor=3D"#ffffff" style=3D"min-width: 590px; background-color: rgb(25=
|
||||
5, 255, 255); padding: 20px;">
|
||||
<tbody>
|
||||
<tr><td valign=3D"top" style=3D"font-family:A=
|
||||
rial,Helvetica,sans-serif; color: #555; font-size: 14px;">
|
||||
<p style=3D"margin: 0px 0px 9px 0px; font-s=
|
||||
ize: 13px; font-family: "Lucida Grande", Helvetica, Verdana, Aria=
|
||||
l, sans-serif">xxxx.=20
|
||||
,</p>
|
||||
<p style=3D"margin: 0px 0px 9px 0px; font-size: 13px; font-family: "Lu=
|
||||
cida Grande", Helvetica, Verdana, Arial, sans-serif">
|
||||
xxxx.
|
||||
</p>
|
||||
|
||||
<p style=3D"margin: 0px 0px 9px 0px; font-size: 13px; font-family: "Lu=
|
||||
cida Grande", Helvetica, Verdana, Arial, sans-serif">You can reply =
|
||||
to this email if you have any questions.</p>
|
||||
<p style=3D"margin: 0px 0px 9px 0px; font-size: 13px; font-family: "Lu=
|
||||
cida Grande", Helvetica, Verdana, Arial, sans-serif">Thank you,</p>
|
||||
</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<tr>
|
||||
<td align=3D"center" style=3D"min-width: 590px;">
|
||||
<table width=3D"590" border=3D"0" cellpadding=3D=
|
||||
"0" bgcolor=3D"#875A7B" style=3D"min-width: 590px; background-color: rgb(13=
|
||||
5,90,123); padding: 20px;">
|
||||
<tbody><tr>
|
||||
<td valign=3D"middle" align=3D"left" style=
|
||||
=3D"color: #fff; padding-top: 10px; padding-bottom: 10px; font-size: 12px;"=
|
||||
>
|
||||
xxxx<br />
|
||||
+1-801-980-4240
|
||||
</td>
|
||||
<td valign=3D"middle" align=3D"right" style=
|
||||
=3D"color: #fff; padding-top: 10px; padding-bottom: 10px; font-size: 12px;"=
|
||||
>
|
||||
<a href=3D"http://erp.xxxx.xxxx/info@xxxx-a=
|
||||
aa.com" style=3D"text-decoration:none; color: white;">info@aust-mfg.com</a>=
|
||||
<br />
|
||||
<a href=3D"http://www.xxxx=
|
||||
.com" style=3D"text-decoration:none; color: white;">
|
||||
http://www.xxxx.com
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=3D"center">
|
||||
Powered by <a href=3D"https://www.flectrahq.com">Odo=
|
||||
o</a>.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
=20
|
||||
<pre style=3D"white-space: pre-wrap">xxxx.
|
||||
</pre>
|
||||
</blockquote></div>
|
||||
</body></html>
|
||||
--------=_MB48E455BD-2850-42EC-B1CA-886CDF48905E--"""
|
||||
|
||||
|
||||
class TestMailgateway(TestMail):
|
||||
|
||||
@ -327,7 +951,7 @@ class TestMailgateway(TestMail):
|
||||
'subject': 'Public Discussion',
|
||||
'message_type': 'email',
|
||||
'author_id': self.partner_1.id,
|
||||
'message_id': '<123456-flectra-%s-mail.test@%s>' % (self.test_public.id, socket.gethostname()),
|
||||
'message_id': '<123456-openerp-%s-mail.test@%s>' % (self.test_public.id, socket.gethostname()),
|
||||
})
|
||||
|
||||
@mute_logger('flectra.addons.mail.models.mail_thread')
|
||||
@ -366,6 +990,12 @@ class TestMailgateway(TestMail):
|
||||
self.assertEqual(res['body'], '')
|
||||
self.assertEqual(res['attachments'][0][0], 'thetruth.pdf')
|
||||
|
||||
@mute_logger('flectra.addons.mail.models.mail_thread')
|
||||
def test_message_parse_xhtml(self):
|
||||
""" Test that the parsing of mail with embedded emails as eml(msg) which generates empty attachments, can be processed.
|
||||
"""
|
||||
self.env['mail.thread'].message_process('mail.channel', MAIL_XHTML)
|
||||
|
||||
@mute_logger('flectra.addons.mail.models.mail_thread')
|
||||
def test_message_process_cid(self):
|
||||
new_groups = self.format_and_process(MAIL_MULTIPART_IMAGE, subject='My Frogs', to='groups@example.com')
|
||||
@ -528,13 +1158,7 @@ class TestMailgateway(TestMail):
|
||||
'message_process: email should be sent to Sylvie')
|
||||
|
||||
# TODO : the author of a message post on mail.test should not be added as follower
|
||||
# FAIL ON 'message_process: after reply, group should have 2 followers') ` AssertionError: res.partner(104,) != res.partner(104, 105) : message_process: after reply, group should have 2 followers
|
||||
|
||||
# Test: author (and not recipient) added as follower
|
||||
# self.assertEqual(self.test_public.message_partner_ids, self.partner_1 | self.partner_2,
|
||||
# 'message_process: after reply, group should have 2 followers')
|
||||
# self.assertEqual(self.test_public.message_channel_ids, self.env['mail.test'],
|
||||
# 'message_process: after reply, group should have 2 followers (0 channels)')
|
||||
|
||||
@mute_logger('flectra.addons.mail.models.mail_thread', 'flectra.models')
|
||||
def test_message_process_in_reply_to(self):
|
||||
@ -569,6 +1193,7 @@ class TestMailgateway(TestMail):
|
||||
MAIL_TEMPLATE, to='erroneous@example.com',
|
||||
extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % self.fake_email.message_id,
|
||||
msg_id='<1198923581.41972151344608186800.JavaMail.4@agrolait.com>')
|
||||
|
||||
self.assertEqual(len(self.test_public.message_ids), 2, 'message_process: group should contain one new message')
|
||||
self.assertEqual(len(self.fake_email.child_ids), 1, 'message_process: new message should be children of the existing one')
|
||||
|
||||
@ -581,10 +1206,10 @@ class TestMailgateway(TestMail):
|
||||
extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % self.fake_email.message_id,
|
||||
msg_id='<1198923581.41972151344608186800.JavaMail.4@agrolait.com>',
|
||||
target_model='mail.channel')
|
||||
self.assertEqual(len(self.test_public.message_ids), 1, 'message_process: group should not contain new message')
|
||||
self.assertEqual(len(self.fake_email.child_ids), 0, 'message_process: original email should not contain childs')
|
||||
self.assertEqual(res_test.name, 'My Dear Forward')
|
||||
self.assertEqual(len(res_test.message_ids), 1)
|
||||
|
||||
self.assertEqual(len(self.test_public.message_ids), 2, 'message_process: group should not contain new message')
|
||||
self.assertEqual(len(self.fake_email.child_ids), 1, 'message_process: original email should not contain childs')
|
||||
self.assertEqual(len(res_test.message_ids), 0)
|
||||
|
||||
@mute_logger('flectra.addons.mail.models.mail_thread', 'flectra.models')
|
||||
def test_message_process_references_forward_cc(self):
|
||||
@ -606,11 +1231,11 @@ class TestMailgateway(TestMail):
|
||||
self.format_and_process,
|
||||
MAIL_TEMPLATE, email_from='valid.lelitre@agrolait.com',
|
||||
to='noone@example.com', subject='spam',
|
||||
extra='In-Reply-To: <12321321-flectra-%d-mail.test@%s>' % (self.test_public.id, socket.gethostname()),
|
||||
extra='In-Reply-To: <12321321-openerp-%d-mail.test@%s>' % (self.test_public.id, socket.gethostname()),
|
||||
msg_id='<1198923581.41972151344608186802.JavaMail.diff1@agrolait.com>')
|
||||
|
||||
# when 6.1 messages are present, compat mode is available
|
||||
# Flectra 10 update: compat mode has been removed and should not work anymore
|
||||
# Odoo 10 update: compat mode has been removed and should not work anymore
|
||||
self.fake_email.write({'message_id': False})
|
||||
# Do: compat mode accepts partial-matching emails
|
||||
self.assertRaises(
|
||||
@ -619,16 +1244,16 @@ class TestMailgateway(TestMail):
|
||||
MAIL_TEMPLATE, email_from='other5@gmail.com',
|
||||
msg_id='<1.2.JavaMail.new@agrolait.com>',
|
||||
to='noone@example.com>', subject='spam',
|
||||
extra='In-Reply-To: <12321321-flectra-%d-mail.test@%s>' % (self.test_public.id, socket.gethostname()))
|
||||
extra='In-Reply-To: <12321321-openerp-%d-mail.test@%s>' % (self.test_public.id, socket.gethostname()))
|
||||
|
||||
# 3''. 6.1 compat mode should not work if hostname does not match!
|
||||
# Flectra 10 update: compat mode has been removed and should not work anymore and does not depend from hostname
|
||||
# Odoo 10 update: compat mode has been removed and should not work anymore and does not depend from hostname
|
||||
self.assertRaises(ValueError,
|
||||
self.format_and_process,
|
||||
MAIL_TEMPLATE, email_from='other5@gmail.com',
|
||||
msg_id='<1.3.JavaMail.new@agrolait.com>',
|
||||
to='noone@example.com>', subject='spam',
|
||||
extra='In-Reply-To: <12321321-flectra-%d-mail.test@neighbor.com>' % self.test_public.id)
|
||||
extra='In-Reply-To: <12321321-openerp-%d-mail.test@neighbor.com>' % self.test_public.id)
|
||||
|
||||
# Test created messages
|
||||
self.assertEqual(len(self.test_public.message_ids), 1)
|
||||
|
@ -23,7 +23,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" title="Using your own email server is required to send/receive emails in Community and Enterprise versions. Online users already benefit from a ready-to-use email server (@mycompany.flectra.com).">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" title="Using your own email server is required to send/receive emails in Community versions. Online users already benefit from a ready-to-use email server (@mycompany.flectrahq.com).">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="default_external_email_server"/>
|
||||
</div>
|
||||
|
@ -11,6 +11,11 @@ from flectra.tools import consteq
|
||||
|
||||
class MassMailController(http.Controller):
|
||||
|
||||
@http.route(['/unsubscribe_from_list'], type='http', website=True, multilang=False, auth='public')
|
||||
def unsubscribe_placeholder_link(self, **post):
|
||||
"""Dummy route so placeholder is not prefixed by language, MUST have multilang=False"""
|
||||
raise werkzeug.exceptions.NotFound()
|
||||
|
||||
@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['mail.mass_mailing'].sudo().browse(mailing_id)
|
||||
|
@ -92,7 +92,7 @@ class MailMail(models.Model):
|
||||
def send_get_email_dict(self, partner=None):
|
||||
# TDE: temporary addition (mail was parameter) due to semi-new-API
|
||||
res = super(MailMail, self).send_get_email_dict(partner)
|
||||
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
|
||||
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url').rstrip('/')
|
||||
if self.mailing_id and res.get('body') and res.get('email_to'):
|
||||
emails = tools.email_split(res.get('email_to')[0])
|
||||
email_to = emails and emails[0] or False
|
||||
|
@ -681,6 +681,7 @@ class MassMailing(models.Model):
|
||||
'mass_mailing_id': mailing.id,
|
||||
'mailing_list_ids': [(4, l.id) for l in mailing.contact_list_ids],
|
||||
'no_auto_thread': mailing.reply_to_mode != 'thread',
|
||||
'template_id': None,
|
||||
}
|
||||
if mailing.reply_to_mode == 'email':
|
||||
composer_values['reply_to'] = mailing.reply_to
|
||||
|
@ -38,7 +38,7 @@ FieldTextHtml.include({
|
||||
var datarecord = this._super();
|
||||
if (this.model === 'mail.mass_mailing') {
|
||||
// these fields can potentially get very long, let's remove them
|
||||
datarecord = _.omit(datarecord, ['mailing_domain', 'contact_list_ids', 'body_html']);
|
||||
datarecord = _.omit(datarecord, ['mailing_domain', 'contact_list_ids', 'body_html', 'attachment_ids']);
|
||||
}
|
||||
return datarecord;
|
||||
},
|
||||
|
@ -46,6 +46,11 @@
|
||||
background-color: @o_mm_def_color_alpha;
|
||||
}
|
||||
|
||||
td {
|
||||
// Default browser style but needed so that alignment works on some mail
|
||||
// clients (see transcoder)
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
// ===== Layout =====
|
||||
.o_layout {
|
||||
|
@ -26,7 +26,7 @@ class TestMassMailing(models.TransientModel):
|
||||
'reply_to': mailing.reply_to,
|
||||
'email_to': test_mail,
|
||||
'subject': mailing.name,
|
||||
'body_html': mailing.body_html,
|
||||
'body_html': tools.html_sanitize(mailing.body_html, sanitize_attributes=True, sanitize_style=True, strip_classes=True),
|
||||
'notification': True,
|
||||
'mailing_id': mailing.id,
|
||||
'attachment_ids': [(4, attachment.id) for attachment in mailing.attachment_ids],
|
||||
|
@ -10,7 +10,9 @@
|
||||
name="action_mass_mailing_attendees"
|
||||
icon="fa-envelope-o"
|
||||
attrs="{'invisible': [('seats_expected', '=', 0)]}">
|
||||
Mail Attendees
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_text">Mail Attendees</span>
|
||||
</div>
|
||||
</button>
|
||||
</button>
|
||||
</field>
|
||||
|
@ -16,7 +16,7 @@ class Event(models.Model):
|
||||
view_mode='form',
|
||||
target='current',
|
||||
context=dict(
|
||||
default_mailing_model=self.env.ref('website_event_track.model_event_track').id,
|
||||
default_mailing_model_id=self.env.ref('website_event_track.model_event_track').id,
|
||||
default_mailing_domain="[('event_id', 'in', %s), ('stage_id.is_cancel', '!=', True)]" % self.ids,
|
||||
),
|
||||
)
|
||||
|
@ -100,7 +100,7 @@ class PortalChatter(http.Controller):
|
||||
raise Forbidden()
|
||||
# Non-employee see only messages with not internal subtype (aka, no internal logs)
|
||||
if not request.env['res.users'].has_group('base.group_user'):
|
||||
domain = expression.AND([['&', '&', ('subtype_id', '!=', False), ('subtype_id.internal', '=', False)], domain])
|
||||
domain = expression.AND([['&', ('subtype_id', '!=', False), ('subtype_id.internal', '=', False)], domain])
|
||||
Message = request.env['mail.message'].sudo()
|
||||
return {
|
||||
'messages': Message.search(domain, limit=limit, offset=offset).portal_message_format(),
|
||||
|
@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import ir_http
|
||||
from . import mail_thread
|
||||
from . import mail_message
|
||||
from . import portal_mixin
|
16
addons/portal/models/ir_http.py
Normal file
16
addons/portal/models/ir_http.py
Normal file
@ -0,0 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
|
||||
from flectra import api, fields, models
|
||||
from flectra.osv import expression
|
||||
|
||||
|
||||
class IrHttp(models.AbstractModel):
|
||||
_inherit = 'ir.http'
|
||||
|
||||
@classmethod
|
||||
def _get_translation_frontend_modules_domain(cls):
|
||||
domain = super(IrHttp, cls)._get_translation_frontend_modules_domain()
|
||||
return expression.OR([domain, [('name', '=', 'portal')]])
|
||||
|
@ -10,6 +10,7 @@
|
||||
is_website_user: <t t-esc="json.dumps(request.env.user._is_public())"/>,
|
||||
user_id: <t t-esc="json.dumps(request.env.user.id)" />,
|
||||
is_frontend: true,
|
||||
translationURL: '/website/translations',
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -194,6 +195,21 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div t-if="searchbar_groupby" class="dropdown pull-right mr4">
|
||||
<button id="portal_searchbar_groupby" class="o_portal_search_panel_fixed_width btn btn-default" type="button" data-toggle="dropdown">
|
||||
<span class="fa fa-bars fa-lg" />
|
||||
<span class='hidden-xs hidden-sm hidden-md' t-esc="searchbar_groupby[groupby].get('label', 'None')"/>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="portal_searchbar_groupby">
|
||||
<li t-foreach="searchbar_groupby" t-as="option" t-att-class="groupby == option and 'active'">
|
||||
<a t-att-href="default_url + '?' + keep_query('*', groupby=option)">
|
||||
<span t-esc="searchbar_groupby[option].get('label')"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<template id="portal_contact" name="Contact">
|
||||
|
@ -140,7 +140,7 @@ class PortalWizardUser(models.TransientModel):
|
||||
if wizard_user.partner_id.company_id:
|
||||
company_id = wizard_user.partner_id.company_id.id
|
||||
else:
|
||||
company_id = self.env['res.company']._company_default_get('res.users')
|
||||
company_id = self.env['res.company']._company_default_get('res.users').id
|
||||
user_portal = wizard_user.sudo().with_context(company_id=company_id)._create_user()
|
||||
else:
|
||||
user_portal = user
|
||||
|
Loading…
Reference in New Issue
Block a user