diff --git a/mayan/apps/sources/__init__.py b/mayan/apps/sources/__init__.py index fbbba9ce0b..d0ef0458d9 100644 --- a/mayan/apps/sources/__init__.py +++ b/mayan/apps/sources/__init__.py @@ -10,6 +10,7 @@ from rest_api.classes import APIEndPoint from .classes import StagingFile from .links import (document_create_multiple, document_create_siblings, + setup_imap_email_list, setup_pop3_email_list, setup_sources, setup_web_form_list, setup_source_create, setup_source_delete, setup_source_edit, setup_source_transformation_create, @@ -18,8 +19,8 @@ from .links import (document_create_multiple, document_create_siblings, setup_source_transformation_list, setup_staging_folder_list, setup_watch_folder_list, staging_file_delete, upload_version) -from .models import (SourceTransformation, StagingFolderSource, - WatchFolderSource, WebFormSource) +from .models import (IMAPEmail, POP3Email, SourceTransformation, + StagingFolderSource, WatchFolderSource, WebFormSource) from .urls import api_urls from .widgets import staging_file_thumbnail @@ -27,17 +28,23 @@ register_links([StagingFile], [staging_file_delete]) register_links(SourceTransformation, [setup_source_transformation_edit, setup_source_transformation_delete]) -register_links(['sources:setup_web_form_list', 'sources:setup_staging_folder_list', 'sources:setup_watch_folder_list', 'sources:setup_source_create'], [setup_web_form_list, setup_staging_folder_list], menu_name='form_header') +register_links(['sources:setup_imap_email_list', 'sources:setup_pop3_email_list', 'sources:setup_web_form_list', 'sources:setup_staging_folder_list', 'sources:setup_watch_folder_list', 'sources:setup_source_create'], [setup_web_form_list, setup_staging_folder_list, setup_pop3_email_list, setup_imap_email_list], menu_name='form_header') -register_links(WebFormSource, [setup_web_form_list, setup_staging_folder_list], menu_name='form_header') +register_links(WebFormSource, [setup_web_form_list, setup_staging_folder_list, setup_pop3_email_list, setup_imap_email_list], menu_name='form_header') register_links(WebFormSource, [setup_source_transformation_list, setup_source_edit, setup_source_delete]) -register_links(['sources:setup_web_form_list', 'sources:setup_staging_folder_list', 'sources:setup_watch_folder_list', 'sources:setup_source_edit', 'sources:setup_source_delete', 'sources:setup_source_create'], [setup_sources, setup_source_create], menu_name='sidebar') +register_links(['sources:setup_imap_email_list', 'sources:setup_pop3_email_list', 'sources:setup_web_form_list', 'sources:setup_staging_folder_list', 'sources:setup_watch_folder_list', 'sources:setup_source_edit', 'sources:setup_source_delete', 'sources:setup_source_create'], [setup_sources, setup_source_create], menu_name='sidebar') -register_links(StagingFolderSource, [setup_web_form_list, setup_staging_folder_list], menu_name='form_header') +register_links(StagingFolderSource, [setup_web_form_list, setup_staging_folder_list, setup_pop3_email_list, setup_imap_email_list], menu_name='form_header') register_links(StagingFolderSource, [setup_source_transformation_list, setup_source_edit, setup_source_delete]) -register_links(WatchFolderSource, [setup_web_form_list, setup_staging_folder_list, setup_watch_folder_list], menu_name='form_header') +register_links(POP3Email, [setup_web_form_list, setup_staging_folder_list, setup_pop3_email_list, setup_imap_email_list], menu_name='form_header') +register_links(POP3Email, [setup_source_transformation_list, setup_source_edit, setup_source_delete]) + +register_links(IMAPEmail, [setup_web_form_list, setup_staging_folder_list, setup_pop3_email_list, setup_imap_email_list], menu_name='form_header') +register_links(IMAPEmail, [setup_source_transformation_list, setup_source_edit, setup_source_delete]) + +register_links(WatchFolderSource, [setup_web_form_list, setup_staging_folder_list, setup_pop3_email_list, setup_imap_email_list], menu_name='form_header') register_links(WatchFolderSource, [setup_source_transformation_list, setup_source_edit, setup_source_delete]) # Document version @@ -45,7 +52,7 @@ register_links(['documents:document_version_list', 'documents:upload_version', ' register_links(['sources:setup_source_transformation_create', 'sources:setup_source_transformation_edit', 'sources:setup_source_transformation_delete', 'sources:setup_source_transformation_list'], [setup_source_transformation_create], menu_name='sidebar') -source_views = ['sources:setup_web_form_list', 'sources:setup_staging_folder_list', 'sources:setup_watch_folder_list', 'sources:setup_source_edit', 'sources:setup_source_delete', 'sources:setup_source_create', 'sources:setup_source_transformation_list', 'sources:setup_source_transformation_edit', 'sources:setup_source_transformation_delete', 'sources:setup_source_transformation_create'] +source_views = ['sources:setup_imap_email_list', 'sources:setup_pop3_email_list', 'sources:setup_web_form_list', 'sources:setup_staging_folder_list', 'sources:setup_watch_folder_list', 'sources:setup_source_edit', 'sources:setup_source_delete', 'sources:setup_source_create', 'sources:setup_source_transformation_list', 'sources:setup_source_transformation_edit', 'sources:setup_source_transformation_delete', 'sources:setup_source_transformation_create'] register_model_list_columns(StagingFile, [ { diff --git a/mayan/apps/sources/forms.py b/mayan/apps/sources/forms.py index 938e168384..ac2104fbd7 100644 --- a/mayan/apps/sources/forms.py +++ b/mayan/apps/sources/forms.py @@ -8,8 +8,8 @@ from django.utils.translation import ugettext_lazy as _ from documents.forms import DocumentForm -from .models import (SourceTransformation, StagingFolderSource, WebFormSource, - WatchFolderSource) +from .models import (IMAPEmail, POP3Email, SourceTransformation, + StagingFolderSource, WebFormSource, WatchFolderSource) from .utils import validate_whitelist_blacklist logger = logging.getLogger(__name__) @@ -85,6 +85,16 @@ class StagingFolderSetupForm(forms.ModelForm): model = StagingFolderSource +class POP3EmailSetupForm(forms.ModelForm): + class Meta: + model = POP3Email + + +class IMAPEmailSetupForm(forms.ModelForm): + class Meta: + model = IMAPEmail + + class WatchFolderSetupForm(forms.ModelForm): class Meta: model = WatchFolderSource diff --git a/mayan/apps/sources/links.py b/mayan/apps/sources/links.py index 8327bc48e8..730b9228a8 100644 --- a/mayan/apps/sources/links.py +++ b/mayan/apps/sources/links.py @@ -5,7 +5,8 @@ from django.utils.translation import ugettext_lazy as _ from documents.permissions import (PERMISSION_DOCUMENT_CREATE, PERMISSION_DOCUMENT_NEW_VERSION) -from .models import StagingFolderSource, WatchFolderSource, WebFormSource +from .models import (IMAPEmail, POP3Email, StagingFolderSource, + WatchFolderSource, WebFormSource) from .permissions import (PERMISSION_SOURCES_SETUP_CREATE, PERMISSION_SOURCES_SETUP_DELETE, PERMISSION_SOURCES_SETUP_EDIT, @@ -20,6 +21,8 @@ setup_sources = {'text': _(u'Sources'), 'view': 'sources:setup_web_form_list', ' setup_web_form_list = {'text': _(u'Web forms'), 'view': 'sources:setup_web_form_list', 'famfam': 'application_form', 'icon': 'application_form.png', 'children_classes': [WebFormSource], 'permissions': [PERMISSION_SOURCES_SETUP_VIEW]} setup_staging_folder_list = {'text': _(u'Staging folders'), 'view': 'sources:setup_staging_folder_list', 'famfam': 'folder_camera', 'children_classes': [StagingFolderSource], 'permissions': [PERMISSION_SOURCES_SETUP_VIEW]} setup_watch_folder_list = {'text': _(u'Watch folders'), 'view': 'sources:setup_watch_folder_list', 'famfam': 'folder_magnify', 'children_classes': [WatchFolderSource], 'permissions': [PERMISSION_SOURCES_SETUP_VIEW]} +setup_pop3_email_list = {'text': _(u'POP3 emails'), 'view': 'sources:setup_pop3_email_list', 'famfam': 'email', 'children_classes': [POP3Email], 'permissions': [PERMISSION_SOURCES_SETUP_VIEW]} +setup_imap_email_list = {'text': _(u'IMAP emails'), 'view': 'sources:setup_imap_email_list', 'famfam': 'email', 'children_classes': [IMAPEmail], 'permissions': [PERMISSION_SOURCES_SETUP_VIEW]} setup_source_edit = {'text': _(u'Edit'), 'view': 'sources:setup_source_edit', 'args': ['source.pk'], 'famfam': 'application_form_edit', 'permissions': [PERMISSION_SOURCES_SETUP_EDIT]} setup_source_delete = {'text': _(u'Delete'), 'view': 'sources:setup_source_delete', 'args': ['source.pk'], 'famfam': 'application_form_delete', 'permissions': [PERMISSION_SOURCES_SETUP_DELETE]} diff --git a/mayan/apps/sources/models.py b/mayan/apps/sources/models.py index 6292575c3b..9b204388d2 100644 --- a/mayan/apps/sources/models.py +++ b/mayan/apps/sources/models.py @@ -204,13 +204,13 @@ class IntervalBaseModel(OutOfProcessSource): super(IntervalBaseModel, self).save(*args, **kwargs) periodic_task_name = 'check_interval_source-%i' % self.pk if new_source: - interval_instance = IntervalSchedule.objects.create(every=self.interval) + interval_instance = IntervalSchedule.objects.create(every=self.interval, period='seconds') PeriodicTask.objects.create( name=periodic_task_name, interval=interval_instance, task='sources.tasks.task_check_interval_source', queue='mailing', - args=json.dump({'source_id': self.pk}) + kwargs=json.dumps({'source_id': self.pk}) ) else: periodic_task = PeriodicTask.objects.get(name=periodic_task_name) @@ -219,8 +219,8 @@ class IntervalBaseModel(OutOfProcessSource): periodic_task.save() def delete(self, *args, **kwargs): - super(IntervalBaseModel, self).delete(*args, **kwargs) periodic_task_name = 'check_interval_source-%i' % self.pk + super(IntervalBaseModel, self).delete(*args, **kwargs) periodic_task = PeriodicTask.objects.get(name=periodic_task_name) interval_instance = periodic_task.interval periodic_task.delete() @@ -303,11 +303,9 @@ class POP3Email(EmailBaseModel): mailbox.dele(message_number) mailbox.quit() - #SourceLog.objects.save_status(source=self, status='Successful connection.') - except Exception as exception: logger.error('Unhandled exception: %s' % exception) - #SourceLog.objects.save_status(source=self, status='Error: %s' % exc) + # TODO: Add user notification class Meta: verbose_name = _('POP email') @@ -348,10 +346,9 @@ class IMAPEmail(EmailBaseModel): mailbox.expunge() mailbox.close() mailbox.logout() - #SourceLog.objects.save_status(source=self, status='Successful connection.') except Exception as exception: logger.error('Unhandled exception: %s' % exc) - #SourceLog.objects.save_status(source=self, status='Error: %s' % exc) + # TODO: Add user notification class Meta: verbose_name = _('IMAP email') diff --git a/mayan/apps/sources/tasks.py b/mayan/apps/sources/tasks.py index 98cf19e9ad..0dc6c6258d 100644 --- a/mayan/apps/sources/tasks.py +++ b/mayan/apps/sources/tasks.py @@ -13,6 +13,12 @@ from .models import Source logger = logging.getLogger(__name__) +@app.task(ignore_result=True) +def task_check_interval_source(source_id): + source = Source.objects.get_subclass(pk=source_id) + source.fetch_mail() + + @app.task(ignore_result=True) def task_upload_document(source_id, file_path, filename=None, use_file_name=False, document_type_id=None, expand=False, metadata_dict_list=None, user_id=None, document_id=None, new_version_data=None, command_line=False, description=None): source = Source.objects.get_subclass(pk=source_id) diff --git a/mayan/apps/sources/urls.py b/mayan/apps/sources/urls.py index 13edaa5f4d..382cff78f4 100644 --- a/mayan/apps/sources/urls.py +++ b/mayan/apps/sources/urls.py @@ -5,7 +5,8 @@ from django.conf.urls import patterns, url from .api_views import (APIDocumentCreateView, APIStagingSourceFileView, APIStagingSourceFileImageView, APIStagingSourceListView, APIStagingSourceView) -from .literals import (SOURCE_CHOICE_STAGING, SOURCE_CHOICE_WATCH, +from .literals import (SOURCE_CHOICE_EMAIL_POP3, SOURCE_CHOICE_EMAIL_IMAP, + SOURCE_CHOICE_STAGING, SOURCE_CHOICE_WATCH, SOURCE_CHOICE_WEB_FORM) from .wizards import DocumentCreateWizard @@ -23,6 +24,8 @@ urlpatterns = patterns('sources.views', url(r'^setup/interactive/%s/list/$' % SOURCE_CHOICE_WEB_FORM, 'setup_source_list', {'source_type': SOURCE_CHOICE_WEB_FORM}, 'setup_web_form_list'), url(r'^setup/interactive/%s/list/$' % SOURCE_CHOICE_STAGING, 'setup_source_list', {'source_type': SOURCE_CHOICE_STAGING}, 'setup_staging_folder_list'), url(r'^setup/interactive/%s/list/$' % SOURCE_CHOICE_WATCH, 'setup_source_list', {'source_type': SOURCE_CHOICE_WATCH}, 'setup_watch_folder_list'), + url(r'^setup/interactive/%s/list/$' % SOURCE_CHOICE_EMAIL_POP3, 'setup_source_list', {'source_type': SOURCE_CHOICE_EMAIL_POP3}, 'setup_pop3_email_list'), + url(r'^setup/interactive/%s/list/$' % SOURCE_CHOICE_EMAIL_IMAP, 'setup_source_list', {'source_type': SOURCE_CHOICE_EMAIL_IMAP}, 'setup_imap_email_list'), url(r'^setup/interactive/(?P\w+)/list/$', 'setup_source_list', (), 'setup_source_list'), url(r'^setup/interactive/(?P\d+)/edit/$', 'setup_source_edit', (), 'setup_source_edit'), diff --git a/mayan/apps/sources/views.py b/mayan/apps/sources/views.py index ef0ed99ef0..819e3c9a4c 100644 --- a/mayan/apps/sources/views.py +++ b/mayan/apps/sources/views.py @@ -23,14 +23,16 @@ from documents.permissions import (PERMISSION_DOCUMENT_CREATE, from metadata.api import decode_metadata_from_url, metadata_repr_as_list from permissions.models import Permission -from .forms import (StagingDocumentForm, StagingFolderSetupForm, - SourceTransformationForm, SourceTransformationForm_create, - WatchFolderSetupForm, WebFormForm, WebFormSetupForm) -from .literals import (SOURCE_CHOICE_STAGING, SOURCE_CHOICE_WATCH, +from .forms import (POP3EmailSetupForm, IMAPEmailSetupForm, StagingDocumentForm, + StagingFolderSetupForm, SourceTransformationForm, + SourceTransformationForm_create, WatchFolderSetupForm, + WebFormForm, WebFormSetupForm) +from .literals import (SOURCE_CHOICE_EMAIL_IMAP, SOURCE_CHOICE_EMAIL_POP3, + SOURCE_CHOICE_STAGING, SOURCE_CHOICE_WATCH, SOURCE_CHOICE_WEB_FORM, SOURCE_UNCOMPRESS_CHOICE_ASK, SOURCE_UNCOMPRESS_CHOICE_Y) -from .models import (Source, StagingFolderSource, SourceTransformation, - WatchFolderSource, WebFormSource) +from .models import (IMAPEmail, POP3Email, Source, StagingFolderSource, + SourceTransformation, WatchFolderSource, WebFormSource) from .permissions import (PERMISSION_SOURCES_SETUP_CREATE, PERMISSION_SOURCES_SETUP_DELETE, PERMISSION_SOURCES_SETUP_EDIT, @@ -38,6 +40,32 @@ from .permissions import (PERMISSION_SOURCES_SETUP_CREATE, from .tasks import task_upload_document +def get_class(source_type): + if source_type == SOURCE_CHOICE_WEB_FORM: + return WebFormSource + elif source_type == SOURCE_CHOICE_STAGING: + return StagingFolderSource + elif source_type == SOURCE_CHOICE_WATCH: + return WatchFolderSource + elif source_type == SOURCE_CHOICE_EMAIL_POP3: + return POP3Email + elif source_type == SOURCE_CHOICE_EMAIL_IMAP: + return IMAPEmail + + +def get_form_class(source_type): + if source_type == SOURCE_CHOICE_WEB_FORM: + return WebFormSetupForm + elif source_type == SOURCE_CHOICE_STAGING: + return StagingFolderSetupForm + elif source_type == SOURCE_CHOICE_WATCH: + return WatchFolderSetupForm + elif source_type == SOURCE_CHOICE_EMAIL_POP3: + return POP3EmailSetupForm + elif source_type == SOURCE_CHOICE_EMAIL_IMAP: + return IMAPEmailSetupForm + + def document_create_siblings(request, document_id): Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE]) @@ -86,10 +114,20 @@ def get_active_tab_links(document=None): for staging_folder in staging_folders: tab_links.append(get_tab_link_for_source(staging_folder, document)) + pop3_emails = POP3Email.objects.filter(enabled=True) + for source_instance in pop3_emails: + tab_links.append(get_tab_link_for_source(source_instance, document)) + + imap_emails = IMAPEmail.objects.filter(enabled=True) + for source_instance in imap_emails: + tab_links.append(get_tab_link_for_source(source_instance, document)) + return { 'tab_links': tab_links, SOURCE_CHOICE_WEB_FORM: web_forms, - SOURCE_CHOICE_STAGING: staging_folders + SOURCE_CHOICE_STAGING: staging_folders, + SOURCE_CHOICE_EMAIL_POP3: pop3_emails, + SOURCE_CHOICE_EMAIL_IMAP: imap_emails } @@ -370,13 +408,9 @@ def staging_file_delete(request, staging_folder_pk, encoded_filename): def setup_source_list(request, source_type): Permission.objects.check_permissions(request.user, [PERMISSION_SOURCES_SETUP_VIEW]) - if source_type == SOURCE_CHOICE_WEB_FORM: - cls = WebFormSource - elif source_type == SOURCE_CHOICE_STAGING: - cls = StagingFolderSource - elif source_type == SOURCE_CHOICE_WATCH: - cls = WatchFolderSource + cls = get_class(source_type) + # TODO: remove plurals context = { 'object_list': cls.objects.all(), 'title': cls.class_fullname_plural(), @@ -393,12 +427,7 @@ def setup_source_edit(request, source_id): Permission.objects.check_permissions(request.user, [PERMISSION_SOURCES_SETUP_EDIT]) source = get_object_or_404(Source.objects.select_subclasses(), pk=source_id) - if isinstance(source, WebFormSource): - form_class = WebFormSetupForm - elif isinstance(source, StagingFolderSource): - form_class = StagingFolderSetupForm - elif isinstance(source, WatchFolderSource): - form_class = WatchFolderSetupForm + form_class = get_form_class(source.source_type) next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))) @@ -439,6 +468,12 @@ def setup_source_delete(request, source_id): elif isinstance(source, WatchFolderSource): form_icon = u'folder_delete.png' redirect_view = 'sources:setup_watch_folder_list' + elif isinstance(source, POP3Email): + form_icon = u'folder_delete.png' + redirect_view = 'sources:setup_pop3_email_list' + elif isinstance(source, IMAPEmail): + form_icon = u'folder_delete.png' + redirect_view = 'sources:setup_imap_email_list' previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', redirect_view))) @@ -450,8 +485,7 @@ def setup_source_delete(request, source_id): messages.error(request, _(u'Error deleting source "%(source)s": %(error)s') % { 'source': source, 'error': exception }) - - return HttpResponseRedirect(redirect_view) + return HttpResponseRedirect(reverse(redirect_view)) context = { 'title': _(u'Are you sure you wish to delete the source: %s?') % source.fullname(), @@ -471,15 +505,8 @@ def setup_source_delete(request, source_id): def setup_source_create(request, source_type): Permission.objects.check_permissions(request.user, [PERMISSION_SOURCES_SETUP_CREATE]) - if source_type == SOURCE_CHOICE_WEB_FORM: - cls = WebFormSource - form_class = WebFormSetupForm - elif source_type == SOURCE_CHOICE_STAGING: - cls = WebFormSource - form_class = StagingFolderSetupForm - elif source_type == SOURCE_CHOICE_WATCH: - cls = WebFormSource - form_class = WatchFolderSetupForm + cls = get_class(source_type) + form_class = get_form_class(source_type) if request.method == 'POST': form = form_class(data=request.POST)