forked from extern/django-helpdesk
parent
d57f11f40a
commit
d7ebc8e1c2
@ -21,11 +21,6 @@ import email
|
|||||||
from email.message import Message
|
from email.message import Message
|
||||||
from email.utils import getaddresses
|
from email.utils import getaddresses
|
||||||
from email_reply_parser import EmailReplyParser
|
from email_reply_parser import EmailReplyParser
|
||||||
|
|
||||||
# Add OAUTH Libraries
|
|
||||||
from oauthlib.oauth2 import BackendApplicationClient
|
|
||||||
from requests_oauthlib import OAuth2Session
|
|
||||||
|
|
||||||
from helpdesk import settings
|
from helpdesk import settings
|
||||||
from helpdesk.exceptions import DeleteIgnoredTicketException, IgnoreTicketException
|
from helpdesk.exceptions import DeleteIgnoredTicketException, IgnoreTicketException
|
||||||
from helpdesk.lib import process_attachments, safe_template_context
|
from helpdesk.lib import process_attachments, safe_template_context
|
||||||
@ -230,101 +225,6 @@ def imap_sync(q, logger, server):
|
|||||||
server.logout()
|
server.logout()
|
||||||
|
|
||||||
|
|
||||||
def imap_oauth_sync(q, logger, server):
|
|
||||||
"""
|
|
||||||
IMAP eMail server with OAUTH authentication.
|
|
||||||
Only tested against O365 implementation
|
|
||||||
|
|
||||||
Uses OAUTH Dict in Settings.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
logger.debug("Start Mailbox polling via IMAP OAUTH")
|
|
||||||
|
|
||||||
client = BackendApplicationClient(
|
|
||||||
client_id=django_settings.HELPDESK_OAUTH["client_id"],
|
|
||||||
scope=django_settings.HELPDESK_OAUTH["scope"],
|
|
||||||
)
|
|
||||||
|
|
||||||
oauth = OAuth2Session(client=client)
|
|
||||||
token = oauth.fetch_token(
|
|
||||||
token_url=django_settings.HELPDESK_OAUTH["token_url"],
|
|
||||||
client_id=django_settings.HELPDESK_OAUTH["client_id"],
|
|
||||||
client_secret=django_settings.HELPDESK_OAUTH["secret"],
|
|
||||||
include_client_id=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO: Somehow link this to the debug level set within Django settings logging
|
|
||||||
server.debug = 4
|
|
||||||
|
|
||||||
# TODO: Perhaps store the authentication string template externally? Settings? Queue Table?
|
|
||||||
server.authenticate(
|
|
||||||
"XOAUTH2",
|
|
||||||
lambda x: f"user={q.email_box_user}\x01auth=Bearer {token['access_token']}\x01\x01".encode(),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Select the Inbound Mailbox folder
|
|
||||||
server.select(q.email_box_imap_folder)
|
|
||||||
|
|
||||||
except imaplib.IMAP4.abort:
|
|
||||||
logger.error("IMAP authentication failed.")
|
|
||||||
server.logout()
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
except ssl.SSLError:
|
|
||||||
logger.error(
|
|
||||||
"IMAP login failed due to SSL error. This is often due to a timeout. "
|
|
||||||
"Please check your connection and try again."
|
|
||||||
)
|
|
||||||
server.logout()
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
try:
|
|
||||||
data = server.search(None, 'NOT', 'DELETED')[1]
|
|
||||||
if data:
|
|
||||||
msgnums = data[0].split()
|
|
||||||
logger.info(f"Found {len(msgnums)} message(s) on IMAP server" )
|
|
||||||
for num in msgnums:
|
|
||||||
logger.info(f"Processing message {num}")
|
|
||||||
data = server.fetch(num, '(RFC822)')[1]
|
|
||||||
full_message = encoding.force_str(data[0][1], errors='replace')
|
|
||||||
|
|
||||||
try:
|
|
||||||
ticket = object_from_message(message=full_message, queue=q, logger=logger)
|
|
||||||
|
|
||||||
except IgnoreTicketException as itex:
|
|
||||||
logger.warn(f"Message {num} was ignored. {itex}")
|
|
||||||
|
|
||||||
except DeleteIgnoredTicketException:
|
|
||||||
server.store(num, '+FLAGS', '\\Deleted')
|
|
||||||
logger.warn("Message %s was ignored and deleted from IMAP server" % num)
|
|
||||||
|
|
||||||
except TypeError as te:
|
|
||||||
# Log the error with stacktrace to help identify what went wrong
|
|
||||||
logger.error(f"Unexpected error processing message: {te}", exc_info=True)
|
|
||||||
|
|
||||||
else:
|
|
||||||
if ticket:
|
|
||||||
server.store(num, '+FLAGS', '\\Deleted')
|
|
||||||
logger.info(
|
|
||||||
"Successfully processed message %s, deleted from IMAP server" % num)
|
|
||||||
else:
|
|
||||||
logger.warn(
|
|
||||||
"Message %s was not successfully processed, and will be left on IMAP server" % num)
|
|
||||||
|
|
||||||
except imaplib.IMAP4.error:
|
|
||||||
logger.error(
|
|
||||||
"IMAP retrieve failed. Is the folder '%s' spelled correctly, and does it exist on the server?",
|
|
||||||
q.email_box_imap_folder
|
|
||||||
)
|
|
||||||
|
|
||||||
# Purged Flagged Messages & Logout
|
|
||||||
server.expunge()
|
|
||||||
server.close()
|
|
||||||
server.logout()
|
|
||||||
|
|
||||||
|
|
||||||
def process_queue(q, logger):
|
def process_queue(q, logger):
|
||||||
logger.info("***** %s: Begin processing mail for django-helpdesk" % ctime())
|
logger.info("***** %s: Begin processing mail for django-helpdesk" % ctime())
|
||||||
|
|
||||||
@ -372,18 +272,7 @@ def process_queue(q, logger):
|
|||||||
'init': imaplib.IMAP4,
|
'init': imaplib.IMAP4,
|
||||||
},
|
},
|
||||||
'sync': imap_sync
|
'sync': imap_sync
|
||||||
},
|
}
|
||||||
'oauth': {
|
|
||||||
'ssl': {
|
|
||||||
'port': 993,
|
|
||||||
'init': imaplib.IMAP4_SSL,
|
|
||||||
},
|
|
||||||
'insecure': {
|
|
||||||
'port': 143,
|
|
||||||
'init': imaplib.IMAP4,
|
|
||||||
},
|
|
||||||
'sync': imap_oauth_sync
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
if email_box_type in mail_defaults:
|
if email_box_type in mail_defaults:
|
||||||
encryption = 'insecure'
|
encryption = 'insecure'
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
# Generated by Django 3.2.16 on 2023-03-25 15:45
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('helpdesk', '0036_add_attachment_validator'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='queue',
|
|
||||||
name='email_box_type',
|
|
||||||
field=models.CharField(blank=True, choices=[('pop3', 'POP 3'), ('imap', 'IMAP'), ('oauth', 'IMAP OAUTH'), ('local', 'Local Directory')], help_text='E-Mail server type for creating tickets automatically from a mailbox - both POP3 and IMAP are supported, as well as reading from a local directory.', max_length=5, null=True, verbose_name='E-Mail Box Type'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -175,9 +175,7 @@ class Queue(models.Model):
|
|||||||
email_box_type = models.CharField(
|
email_box_type = models.CharField(
|
||||||
_('E-Mail Box Type'),
|
_('E-Mail Box Type'),
|
||||||
max_length=5,
|
max_length=5,
|
||||||
choices=(('pop3', _('POP 3')),
|
choices=(('pop3', _('POP 3')), ('imap', _('IMAP')),
|
||||||
('imap', _('IMAP')),
|
|
||||||
('oauth', _('IMAP OAUTH')),
|
|
||||||
('local', _('Local Directory'))),
|
('local', _('Local Directory'))),
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
|
@ -249,14 +249,3 @@ HELPDESK_FULL_FIRST_MESSAGE_FROM_EMAIL = getattr(
|
|||||||
# (which gets stripped/corrupted otherwise)
|
# (which gets stripped/corrupted otherwise)
|
||||||
HELPDESK_ALWAYS_SAVE_INCOMING_EMAIL_MESSAGE = getattr(
|
HELPDESK_ALWAYS_SAVE_INCOMING_EMAIL_MESSAGE = getattr(
|
||||||
settings, "HELPDESK_ALWAYS_SAVE_INCOMING_EMAIL_MESSAGE", False)
|
settings, "HELPDESK_ALWAYS_SAVE_INCOMING_EMAIL_MESSAGE", False)
|
||||||
|
|
||||||
#######################
|
|
||||||
# email OAUTH #
|
|
||||||
#######################
|
|
||||||
|
|
||||||
HELPDESK_OAUTH = {
|
|
||||||
"token_url": "",
|
|
||||||
"client_id": "",
|
|
||||||
"secret": "",
|
|
||||||
"scope": [""]
|
|
||||||
}
|
|
||||||
|
@ -12,5 +12,3 @@ pinax_teams
|
|||||||
djangorestframework
|
djangorestframework
|
||||||
django-model-utils
|
django-model-utils
|
||||||
django-cleanup
|
django-cleanup
|
||||||
requests
|
|
||||||
requests_oauthlib
|
|
||||||
|
Loading…
Reference in New Issue
Block a user