2014-08-19 17:31:01 +02:00
|
|
|
# The COPYRIGHT file at the top level of this repository contains the full
|
|
|
|
# copyright notices and license terms.
|
|
|
|
from trytond.pool import Pool, PoolMeta
|
2014-09-01 22:11:20 +02:00
|
|
|
from trytond.model import fields, ModelView
|
|
|
|
from trytond.transaction import Transaction
|
|
|
|
from trytond.wizard import Wizard, StateAction
|
2021-03-23 09:49:03 +01:00
|
|
|
from trytond.pyson import Eval, Bool
|
2021-04-01 12:46:27 +02:00
|
|
|
from email.utils import formataddr, formatdate, make_msgid, parseaddr
|
|
|
|
from email import encoders, message_from_bytes
|
2014-09-01 22:11:20 +02:00
|
|
|
from email.mime.multipart import MIMEMultipart
|
|
|
|
from email.mime.text import MIMEText
|
|
|
|
from email.mime.base import MIMEBase
|
|
|
|
import mimetypes
|
2019-05-23 12:14:43 +02:00
|
|
|
from trytond.modules.electronic_mail.electronic_mail import _make_header
|
2014-09-01 22:11:20 +02:00
|
|
|
import logging
|
|
|
|
import datetime
|
2019-04-14 08:31:18 +02:00
|
|
|
from trytond.i18n import gettext
|
|
|
|
from trytond.exceptions import UserError
|
|
|
|
|
2014-09-01 22:11:20 +02:00
|
|
|
try:
|
|
|
|
from html2text import html2text
|
|
|
|
except ImportError:
|
|
|
|
message = "Unable to import html2text and it's needed."
|
|
|
|
logging.getLogger('MailObj').error(message)
|
|
|
|
raise Exception(message)
|
2014-08-19 17:31:01 +02:00
|
|
|
|
2014-09-01 22:11:20 +02:00
|
|
|
__all__ = ['Activity', 'ActivityReplyMail']
|
2014-08-19 17:31:01 +02:00
|
|
|
|
|
|
|
|
2021-03-23 09:49:03 +01:00
|
|
|
class Cron(metaclass=PoolMeta):
|
|
|
|
__name__ = 'ir.cron'
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def __setup__(cls):
|
|
|
|
super().__setup__()
|
|
|
|
cls.method.selection.extend([
|
|
|
|
('activity.activity|create_activity', "Create Activity")])
|
|
|
|
|
|
|
|
|
2018-08-17 18:35:06 +02:00
|
|
|
class Activity(metaclass=PoolMeta):
|
2014-08-19 17:31:01 +02:00
|
|
|
__name__ = 'activity.activity'
|
|
|
|
|
2014-09-01 22:11:20 +02:00
|
|
|
mail = fields.Many2One('electronic.mail', "Related Mail", readonly=True,
|
2014-10-30 09:27:56 +01:00
|
|
|
ondelete='CASCADE')
|
2014-09-01 22:11:20 +02:00
|
|
|
have_mail = fields.Function(fields.Boolean('Have mail'), 'get_have_mail')
|
|
|
|
#related_activity = fields.Many2One('activity.activity', 'Related activity',
|
|
|
|
# domain=[('id', 'in', Eval('resource.activities', []))], depends=['resource'])
|
|
|
|
related_activity = fields.Many2One('activity.activity', 'Related activity')
|
2014-08-19 17:31:01 +02:00
|
|
|
|
|
|
|
@classmethod
|
2014-09-01 22:11:20 +02:00
|
|
|
def __setup__(cls):
|
|
|
|
super(Activity, cls).__setup__()
|
|
|
|
cls._buttons.update({
|
2021-03-23 09:49:03 +01:00
|
|
|
'new': {
|
|
|
|
'icon': 'tryton-email',
|
|
|
|
},
|
|
|
|
'reply': {
|
|
|
|
'icon': 'tryton-forward',
|
|
|
|
},
|
|
|
|
'guess': {
|
|
|
|
'icon': 'tryton-forward',
|
|
|
|
'invisible': Bool(Eval('resource', -1)),
|
|
|
|
'depends': ['resource'],
|
|
|
|
},
|
2014-09-01 22:11:20 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
@property
|
|
|
|
def message_id(self):
|
|
|
|
return self.mail and self.mail.message_id or make_msgid()
|
|
|
|
|
|
|
|
@property
|
|
|
|
def in_reply_to(self):
|
|
|
|
return self.mail and self.mail.in_reply_to or (self.related_activity
|
|
|
|
and self.related_activity.mail and
|
|
|
|
self.related_activity.mail.message_id or "")
|
|
|
|
|
2021-03-23 09:49:03 +01:00
|
|
|
@classmethod
|
|
|
|
def _get_origin(cls):
|
|
|
|
return super()._get_origin() + ['electronic.mail']
|
|
|
|
|
2014-09-01 22:11:20 +02:00
|
|
|
@property
|
|
|
|
def reference(self):
|
|
|
|
result = ""
|
|
|
|
if self.mail and self.mail.reference:
|
|
|
|
result = self.mail.reference
|
|
|
|
elif self.related_activity and self.related_activity.mail:
|
|
|
|
if self.related_activity.mail.reference:
|
|
|
|
result += self.related_activity.mail.reference or ""
|
|
|
|
else:
|
|
|
|
result += self.related_activity.mail.in_reply_to or ""
|
2014-09-08 19:19:15 +02:00
|
|
|
result += self.related_activity.mail.message_id or ""
|
2014-09-01 22:11:20 +02:00
|
|
|
return result
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def get_have_mail(self, activities, name):
|
|
|
|
result = {}
|
|
|
|
for activity in activities:
|
|
|
|
result[activity.id] = activity.mail and True or False
|
|
|
|
return result
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
def new(cls, activities):
|
|
|
|
user = cls.check_activity_user_info()
|
|
|
|
if user:
|
|
|
|
for activity in activities:
|
|
|
|
if activity.mail and activity.mail.flag_received:
|
2019-04-14 08:31:18 +02:00
|
|
|
raise UserError(gettext(
|
|
|
|
'electronic_mail_activity.mail_received',
|
|
|
|
activity=activity.id))
|
2014-10-20 14:45:36 +02:00
|
|
|
cls.send_mail(activity, user)
|
2014-09-01 22:11:20 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button_action('electronic_mail_activity.wizard_replymail')
|
|
|
|
def reply(cls, activities):
|
|
|
|
cls.check_activity_user_info()
|
|
|
|
|
2021-03-23 09:49:03 +01:00
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
def guess(cls, activities):
|
|
|
|
activities = cls.browse(sorted(activities, key=lambda x: x.id))
|
|
|
|
for activity in activities:
|
|
|
|
activity = cls(activity)
|
|
|
|
activity.guess_resource()
|
|
|
|
# Each activity is saved because in this list there
|
|
|
|
# could be a resource of another of the same list
|
|
|
|
activity.save()
|
|
|
|
|
2014-09-01 22:11:20 +02:00
|
|
|
@classmethod
|
|
|
|
def check_activity_user_info(cls):
|
|
|
|
"Check if user have deffined the a server and a mailbox"
|
|
|
|
User = Pool().get('res.user')
|
|
|
|
user = User(Transaction().user)
|
|
|
|
if user and user.smtp_server:
|
|
|
|
if user.mailbox:
|
|
|
|
return user
|
2019-04-14 08:31:18 +02:00
|
|
|
raise UserError(gettext(
|
|
|
|
'electronic_mail_activity.no_mailbox',user=user.name))
|
2014-09-01 22:11:20 +02:00
|
|
|
else:
|
2019-04-14 08:31:18 +02:00
|
|
|
raise UserError(gettext(
|
|
|
|
'electronic_mail_activity.no_smtp_server',user=user.name))
|
2014-09-01 22:11:20 +02:00
|
|
|
|
|
|
|
@classmethod
|
2014-10-20 14:45:36 +02:00
|
|
|
def send_mail(cls, activity, user):
|
2014-09-01 22:11:20 +02:00
|
|
|
"""
|
|
|
|
Send out the given email using the SMTP_CLIENT if configured in the
|
|
|
|
Tryton Server configuration
|
|
|
|
|
|
|
|
:param email_id: Browse record of the email to be sent
|
|
|
|
:param server: Browse Record of the server
|
|
|
|
:param type_: If the mail to send is new or a reply
|
|
|
|
"""
|
|
|
|
ElectronicMail = Pool().get('electronic.mail')
|
|
|
|
|
|
|
|
if activity.mail:
|
|
|
|
mail = activity.mail
|
|
|
|
else:
|
|
|
|
# Prepare the mail strucuture
|
|
|
|
mimetype_mail = activity.create_mimetype(user)
|
|
|
|
# Create the mail
|
2014-10-20 14:45:36 +02:00
|
|
|
mail = ElectronicMail.create_from_mail(mimetype_mail,
|
2021-02-02 10:46:35 +01:00
|
|
|
user.mailbox, activity)
|
2021-06-23 09:26:53 +02:00
|
|
|
if not mail:
|
|
|
|
return
|
2014-09-01 22:11:20 +02:00
|
|
|
|
|
|
|
# Before to send, control if all mails are corrects
|
|
|
|
# If there are no user in main contact or in contacts, we creat And
|
|
|
|
# activity for internal reason and we send the mail to the employee.
|
|
|
|
emails = []
|
2015-03-08 22:34:05 +01:00
|
|
|
email_to = activity.contacts and activity.contacts[0].email or activity.employee.party.email
|
|
|
|
name_to = activity.contacts and activity.contacts[0].name or activity.employee.party.name
|
2016-02-28 07:56:25 +01:00
|
|
|
emails_to = ElectronicMail.validate_emails(email_to)
|
2014-09-01 22:11:20 +02:00
|
|
|
if emails_to:
|
2016-02-28 07:56:25 +01:00
|
|
|
emails.append(emails_to)
|
2014-09-01 22:11:20 +02:00
|
|
|
else:
|
2019-04-14 08:31:18 +02:00
|
|
|
raise UserError(gettext(
|
|
|
|
'electronic_mail_activity.no_valid_mail',
|
|
|
|
email=email_to, party=name_to))
|
2014-09-01 22:11:20 +02:00
|
|
|
if activity.contacts:
|
|
|
|
for c in activity.contacts:
|
2016-02-28 07:56:25 +01:00
|
|
|
emails_cc = ElectronicMail.validate_emails(c.email)
|
2014-09-01 22:11:20 +02:00
|
|
|
if emails_cc:
|
2016-02-28 07:56:25 +01:00
|
|
|
emails.append(emails_cc)
|
2014-09-01 22:11:20 +02:00
|
|
|
else:
|
2019-04-14 08:31:18 +02:00
|
|
|
raise UserError(gettext(
|
|
|
|
'electronic_mail_activity.no_valid_mail',
|
|
|
|
email=activity.contacts[0].email,
|
|
|
|
party=activity.contacts[0].name))
|
2014-09-08 09:10:30 +02:00
|
|
|
if user and user.smtp_server and user.smtp_server.smtp_email:
|
|
|
|
emails.append(user.smtp_server.smtp_email)
|
2014-09-01 22:11:20 +02:00
|
|
|
|
2018-06-12 23:36:24 +02:00
|
|
|
mail_str = ElectronicMail._get_mail(mail)
|
|
|
|
user.smtp_server.send_mail(mail.from_, emails, mail_str)
|
|
|
|
ElectronicMail.write([mail], {
|
|
|
|
'flag_send': True,
|
|
|
|
})
|
|
|
|
cls.write([activity], {
|
|
|
|
'mail': mail.id,
|
|
|
|
})
|
2014-09-01 22:11:20 +02:00
|
|
|
|
|
|
|
logging.getLogger('Activity Mail').info(
|
|
|
|
'Send email %s from activity %s (to %s)' % (mail.id, activity.id,
|
2014-09-07 07:30:03 +02:00
|
|
|
emails))
|
2014-09-01 22:11:20 +02:00
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
def create_mimetype(self, user):
|
|
|
|
'''Create a MIMEtype structure from activity values
|
|
|
|
:param activity: Object of the activity to send mail
|
|
|
|
:param type_: To know if it's a new mail or a reply
|
|
|
|
:return: MIMEtype
|
|
|
|
'''
|
|
|
|
Attachment = Pool().get('ir.attachment')
|
|
|
|
|
|
|
|
message = MIMEMultipart()
|
2014-09-07 11:59:07 +02:00
|
|
|
message['Message-Id'] = self.message_id
|
|
|
|
message['Date'] = formatdate(localtime=True)
|
2014-09-01 22:11:20 +02:00
|
|
|
|
|
|
|
# If reply, take from the related activity the message_id and
|
|
|
|
# reference information
|
|
|
|
if self.related_activity:
|
2014-09-07 11:59:07 +02:00
|
|
|
message['In-Reply-To'] = self.in_reply_to
|
|
|
|
message['Reference'] = self.reference
|
2015-03-08 22:34:05 +01:00
|
|
|
message['From'] = (self.employee and formataddr((
|
2014-09-01 22:11:20 +02:00
|
|
|
_make_header(self.employee.party.name),
|
|
|
|
self.employee.party.email)) or
|
|
|
|
formataddr((user.employee.party.name, user.employee.party.email)))
|
2015-03-08 22:34:05 +01:00
|
|
|
message['To'] = (self.contacts and formataddr((
|
|
|
|
_make_header(self.contacts[0].name),
|
|
|
|
self.contacts[0].email)) or
|
2014-09-01 22:11:20 +02:00
|
|
|
formataddr((self.employee.party.name, self.employee.party.email)))
|
2014-09-07 11:59:07 +02:00
|
|
|
message['Cc'] = ",".join([
|
2014-09-01 22:11:20 +02:00
|
|
|
formataddr((_make_header(c.name), c.email))
|
|
|
|
for c in self.contacts])
|
2014-09-08 09:02:53 +02:00
|
|
|
message['Bcc'] = (user and user.smtp_server and
|
|
|
|
user.smtp_server.smtp_email or "")
|
2014-09-07 11:59:07 +02:00
|
|
|
message['Subject'] = _make_header(self.subject)
|
2014-09-07 07:17:39 +02:00
|
|
|
plain = self.description.encode('utf-8')
|
|
|
|
if user.add_signature and user.signature:
|
|
|
|
signature = user.signature.encode('utf-8')
|
2014-09-01 22:11:20 +02:00
|
|
|
plain = '%s\n--\n%s' % (plain, signature)
|
2015-01-19 21:18:45 +01:00
|
|
|
message.attach(MIMEText(plain, 'plain', _charset='utf-8'))
|
2014-09-01 22:11:20 +02:00
|
|
|
|
|
|
|
# Attach reports
|
|
|
|
attachs = Attachment.search([
|
|
|
|
('resource', '=', str(self)),
|
|
|
|
])
|
|
|
|
if attachs:
|
|
|
|
for attach in attachs:
|
|
|
|
filename = attach.name
|
|
|
|
data = attach.data
|
2014-09-12 10:37:43 +02:00
|
|
|
content_type, encoding = mimetypes.guess_type(filename)
|
2014-09-01 22:11:20 +02:00
|
|
|
maintype, subtype = (
|
|
|
|
content_type or 'application/octet-stream'
|
|
|
|
).split('/', 1)
|
|
|
|
attachment = MIMEBase(maintype, subtype)
|
|
|
|
attachment.set_payload(data)
|
2018-08-17 18:35:06 +02:00
|
|
|
encoders.encode_base64(attachment)
|
2014-09-01 22:11:20 +02:00
|
|
|
attachment.add_header(
|
|
|
|
'Content-Disposition', 'attachment', filename=filename)
|
|
|
|
attachment.add_header(
|
|
|
|
'Content-Transfer-Encoding', 'base64')
|
|
|
|
message.attach(attachment)
|
|
|
|
return message
|
|
|
|
|
2014-09-08 08:35:47 +02:00
|
|
|
@classmethod
|
|
|
|
def get_contact_mechanism(cls, email, parties=None, active=True):
|
|
|
|
""" Get party and contact_mechanism from email.
|
|
|
|
With the possibility to restic some party list
|
|
|
|
and to search for the non active parties
|
|
|
|
"""
|
|
|
|
ContactMechanism = Pool().get('party.contact_mechanism')
|
|
|
|
PartyRelation = Pool().get('party.relation')
|
|
|
|
domain = [
|
|
|
|
('type', '=', 'email'),
|
|
|
|
('active', '=', active),
|
|
|
|
('value', '=', email),
|
|
|
|
]
|
|
|
|
if parties:
|
|
|
|
domain.append(
|
|
|
|
('party', 'in', parties),
|
|
|
|
)
|
|
|
|
contact_mechanisms = ContactMechanism.search(domain)
|
|
|
|
if contact_mechanisms:
|
|
|
|
if len(contact_mechanisms) == 1:
|
|
|
|
return contact_mechanisms[0]
|
2021-04-01 12:49:54 +02:00
|
|
|
contact_mechanisms_copy = contact_mechanisms[:]
|
2014-09-08 08:35:47 +02:00
|
|
|
for contact_mechanism in contact_mechanisms:
|
|
|
|
party_relation = PartyRelation.search([
|
|
|
|
('from_', '=', contact_mechanism.party.id),
|
|
|
|
])
|
|
|
|
if party_relation:
|
|
|
|
contact_mechanisms_copy.remove(contact_mechanism)
|
|
|
|
if not contact_mechanisms_copy or len(contact_mechanisms_copy) > 1:
|
|
|
|
return contact_mechanisms[0]
|
|
|
|
if len(contact_mechanisms_copy) == 1:
|
|
|
|
return contact_mechanisms_copy[0]
|
|
|
|
return None
|
|
|
|
|
2014-09-01 22:11:20 +02:00
|
|
|
@classmethod
|
2021-03-23 09:49:03 +01:00
|
|
|
def create_activity(cls):
|
|
|
|
pool = Pool()
|
|
|
|
ModelData = pool.get('ir.model.data')
|
|
|
|
ElectronicMail = pool.get('electronic.mail')
|
|
|
|
Activity = pool.get('activity.activity')
|
|
|
|
ActivityType = pool.get('activity.type')
|
|
|
|
ActivityConfiguration = pool.get('activity.configuration')
|
2021-04-01 12:46:27 +02:00
|
|
|
Attachment = pool.get('ir.attachment')
|
2021-03-23 15:23:40 +01:00
|
|
|
|
2021-03-23 09:49:03 +01:00
|
|
|
mails = ElectronicMail.search([
|
|
|
|
('mailbox', '=', ActivityConfiguration(0).pending_mailbox)
|
|
|
|
], order=[('date', 'ASC'), ('id', 'ASC')])
|
|
|
|
activity_type = ActivityType(ModelData.get_id('activity',
|
|
|
|
'incoming_email_type'))
|
2021-03-23 15:23:40 +01:00
|
|
|
|
2021-03-23 09:49:03 +01:00
|
|
|
employee = ActivityConfiguration(0).employee
|
|
|
|
processed_mailbox = ActivityConfiguration(0).processed_mailbox
|
|
|
|
activities = []
|
2021-04-01 12:46:27 +02:00
|
|
|
activity_attachments = []
|
2021-03-23 09:49:03 +01:00
|
|
|
for mail in mails:
|
|
|
|
activity = Activity()
|
2021-04-08 12:04:27 +02:00
|
|
|
if mail.subject:
|
|
|
|
activity.subject = mail.subject.replace('\r', '')
|
2021-03-23 09:49:03 +01:00
|
|
|
activity.activity_type = activity_type
|
|
|
|
activity.employee = employee
|
|
|
|
activity.dtstart = mail.date
|
2021-04-01 09:50:11 +02:00
|
|
|
if mail.body_plain:
|
2021-04-08 12:04:27 +02:00
|
|
|
description = mail.body_plain
|
2021-04-01 09:50:11 +02:00
|
|
|
elif mail.body_html:
|
2021-04-08 12:04:27 +02:00
|
|
|
description = html2text(mail.body_html)
|
|
|
|
else:
|
|
|
|
description = None
|
|
|
|
if description:
|
|
|
|
activity.description = description.replace('\r', '').replace(
|
|
|
|
'<br/>', '\n')
|
2021-03-23 09:49:03 +01:00
|
|
|
activity.mail = mail
|
|
|
|
activity.state = 'planned'
|
|
|
|
activity.resource = None
|
|
|
|
activity.origin = mail
|
2021-04-01 12:46:27 +02:00
|
|
|
|
2021-07-12 13:24:39 +02:00
|
|
|
if mail.mail_file:
|
|
|
|
msg = message_from_bytes(mail.mail_file)
|
|
|
|
attachments = []
|
|
|
|
for attachment in ElectronicMail.get_attachments(msg):
|
|
|
|
attachments.append(Attachment(
|
|
|
|
name = attachment.get('filename', mail.subject),
|
|
|
|
type = 'data',
|
|
|
|
data = attachment.get('data')))
|
|
|
|
activity_attachments.append(attachments)
|
2021-03-23 09:49:03 +01:00
|
|
|
activities.append(activity)
|
|
|
|
mail.mailbox = processed_mailbox
|
2021-04-01 12:46:27 +02:00
|
|
|
|
|
|
|
if activities:
|
|
|
|
cls.save(activities)
|
|
|
|
to_save = []
|
|
|
|
for activity, attachments in zip(activities, activity_attachments):
|
|
|
|
for attachment in attachments:
|
|
|
|
attachment.resource = str(activity)
|
|
|
|
to_save += attachments
|
|
|
|
Attachment.save(to_save)
|
|
|
|
ElectronicMail.save(mails)
|
|
|
|
cls.guess(activities)
|
2021-03-23 09:49:03 +01:00
|
|
|
|
|
|
|
def get_previous_activity(self):
|
2014-09-01 22:11:20 +02:00
|
|
|
ElectronicMail = Pool().get('electronic.mail')
|
2021-03-23 09:49:03 +01:00
|
|
|
if not isinstance(self.origin, ElectronicMail):
|
|
|
|
return
|
|
|
|
parent = self.origin.parent
|
|
|
|
if not parent:
|
|
|
|
return
|
|
|
|
activities = self.search([
|
|
|
|
('origin', '=', parent)
|
|
|
|
], limit=1)
|
|
|
|
if activities:
|
|
|
|
return activities[0]
|
|
|
|
|
2021-04-01 12:49:54 +02:00
|
|
|
@classmethod
|
|
|
|
def emails_to_reject(cls):
|
|
|
|
pool = Pool()
|
|
|
|
Employee = pool.get('company.employee')
|
|
|
|
Company = pool.get('company.company')
|
|
|
|
ContactMechanism = pool.get('party.contact_mechanism')
|
|
|
|
User = pool.get('res.user')
|
|
|
|
|
|
|
|
employees = Employee.search([])
|
|
|
|
parties = [x.party for x in employees]
|
|
|
|
parties += [x.party for x in Company.search([])]
|
|
|
|
contact_mechanisms = ContactMechanism.search([
|
|
|
|
('type', '=', 'email'),
|
|
|
|
('party', 'in', parties)
|
|
|
|
])
|
|
|
|
mails = [x.value.lower() for x in contact_mechanisms]
|
|
|
|
return set(mails)
|
|
|
|
|
2021-03-23 09:49:03 +01:00
|
|
|
def guess_resource(self):
|
2021-04-01 12:49:54 +02:00
|
|
|
pool = Pool()
|
|
|
|
ElectronicMail = pool.get('electronic.mail')
|
|
|
|
Activity = pool.get('activity.activity')
|
|
|
|
Party = pool.get('party.party')
|
|
|
|
|
2021-03-23 09:49:03 +01:00
|
|
|
previous_activity = self.get_previous_activity()
|
|
|
|
if previous_activity:
|
|
|
|
if previous_activity.resource:
|
|
|
|
self.resource = previous_activity.resource
|
|
|
|
self.party = previous_activity.resource.party
|
2021-04-01 12:49:54 +02:00
|
|
|
elif self.origin and isinstance(self.origin, ElectronicMail):
|
|
|
|
_, email = parseaddr(self.origin.from_)
|
|
|
|
rejected_emails = self.emails_to_reject()
|
|
|
|
if email in rejected_emails:
|
|
|
|
addresses = [x[1] for x in self.origin.all_to
|
|
|
|
if x[1] not in rejected_emails]
|
|
|
|
if not addresses:
|
|
|
|
return
|
|
|
|
email = addresses[0]
|
|
|
|
|
|
|
|
activities = Activity.search([
|
|
|
|
('party', '!=', None),
|
|
|
|
('origin.from_', 'ilike', '%' + email + '%',
|
|
|
|
'electronic.mail'),
|
|
|
|
], limit=1, order=[('dtstart', 'DESC')])
|
|
|
|
if activities:
|
|
|
|
self.party = activities[0].party
|
|
|
|
return
|
|
|
|
|
|
|
|
activities = Activity.search([
|
|
|
|
('party', '!=', None),
|
|
|
|
('origin.to', 'ilike', '%' + email + '%',
|
|
|
|
'electronic.mail'),
|
|
|
|
], limit=1, order=[('dtstart', 'DESC')])
|
|
|
|
if activities:
|
|
|
|
self.party = activities[0].party
|
|
|
|
return
|
|
|
|
|
|
|
|
parties = Party.search([
|
|
|
|
('contact_mechanisms.value', 'ilike', email),
|
|
|
|
], limit=1)
|
|
|
|
if parties:
|
|
|
|
self.party = parties[0]
|
2014-09-01 22:11:20 +02:00
|
|
|
|
|
|
|
|
2018-08-17 18:35:06 +02:00
|
|
|
class ActivityReplyMail(Wizard, metaclass=PoolMeta):
|
2014-09-01 22:11:20 +02:00
|
|
|
'Activity Reply Mail'
|
|
|
|
__name__ = 'activity.activity.replymail'
|
|
|
|
start_state = 'open_'
|
|
|
|
open_ = StateAction('activity.act_activity_activity')
|
|
|
|
|
|
|
|
def do_open_(self, action):
|
|
|
|
Activity = Pool().get('activity.activity')
|
|
|
|
|
|
|
|
activities = Activity.browse([Transaction().context['active_id']])
|
|
|
|
re = "Re: "
|
|
|
|
return_activities = []
|
|
|
|
for activity in activities:
|
|
|
|
return_activity = Activity.copy([activity])[0]
|
|
|
|
if return_activity.subject[:3].lower() != re[:3].lower():
|
|
|
|
return_activity.subject = "%s%s" % (re, return_activity.subject)
|
|
|
|
return_activity.direction = 'outgoing'
|
|
|
|
return_activity.dtstart = datetime.datetime.now()
|
|
|
|
return_activity.mail = None
|
|
|
|
return_activity.description = '\n'.join("> %s" % l.strip()
|
|
|
|
for l in return_activity.description.split('\n'))
|
|
|
|
return_activity.related_activity = activity.id
|
|
|
|
return_activity.save()
|
|
|
|
return_activities.append(return_activity.id)
|
|
|
|
|
|
|
|
data = {'res_id': return_activities}
|
|
|
|
if len(return_activities) == 1:
|
|
|
|
action['views'].reverse()
|
|
|
|
return action, data
|