81 lines
2.7 KiB
Python
81 lines
2.7 KiB
Python
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
# this repository contains the full copyright notices and license terms.
|
|
|
|
import email.parser
|
|
import email.policy
|
|
import itertools
|
|
import re
|
|
from email.utils import getaddresses
|
|
|
|
import trytond.config as config
|
|
from trytond.i18n import gettext
|
|
from trytond.pool import PoolMeta
|
|
from trytond.transaction import Transaction
|
|
|
|
REPLY_LINE = '\N{EM DASH}' * 80
|
|
DESTINATION_RE = re.compile(r"^[^@]*\+([0-9a-f]{32})@", re.IGNORECASE)
|
|
|
|
|
|
def _get_channel_identifier(email):
|
|
base = config.get(
|
|
'inbound_email', 'chat_reply_to',
|
|
default=config.get('email', 'from'))
|
|
_, our_domain = base.split('@', 1)
|
|
|
|
for key in ('To', 'Cc'):
|
|
if key not in email:
|
|
continue
|
|
addresses = [a for _, a in getaddresses(email.get_all(key))]
|
|
for address in addresses:
|
|
_, domain = address.split('@', 1)
|
|
if domain != our_domain:
|
|
continue
|
|
if (m := DESTINATION_RE.match(address)):
|
|
channel_id, = m.groups()
|
|
return channel_id
|
|
return None
|
|
|
|
|
|
class Channel(metaclass=PoolMeta):
|
|
__name__ = 'ir.chat.channel'
|
|
|
|
@classmethod
|
|
def _email_channel(cls, email):
|
|
channel = super()._email_channel(email)
|
|
channels = []
|
|
if (channel_id := _get_channel_identifier(email)):
|
|
channels = cls.search([('identifier', '=', channel_id)])
|
|
return channel if len(channels) != 1 else channels[0]
|
|
|
|
@classmethod
|
|
def _email_content(cls, body):
|
|
body = super()._email_content(body)
|
|
return '\n'.join(itertools.takewhile(
|
|
lambda l: REPLY_LINE not in l,
|
|
body.splitlines()))
|
|
|
|
@classmethod
|
|
def post_inbound_email(cls, inbound_email, rule):
|
|
parser = email.parser.BytesParser(policy=email.policy.default)
|
|
message = parser.parsebytes(inbound_email.data)
|
|
return cls.post_from_email(message)
|
|
|
|
@classmethod
|
|
def _email_reply_to(cls, message):
|
|
reply_to = super()._email_reply_to(message)
|
|
base = config.get(
|
|
'inbound_email', 'chat_reply_to',
|
|
default=reply_to or config.get('email', 'from'))
|
|
local_part, domain_part = base.split('@', 1)
|
|
if '+' in local_part:
|
|
local_part, _ = local_part.split('+', 1)
|
|
local_part += f'+{message.channel.identifier}'
|
|
return '@'.join((local_part, domain_part))
|
|
|
|
@classmethod
|
|
def _email_body(cls, message):
|
|
body = super()._email_body(message)
|
|
with Transaction().set_context(language=message.channel.language):
|
|
above_msg = gettext('inbound_email.msg_reply_above')
|
|
return f'{REPLY_LINE}\n{above_msg}\n\n{body}'
|