Files

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}'