mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Add test mail account
This commit is contained in:
		| @@ -995,7 +995,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">24</context> | ||||
|           <context context-type="linenumber">34</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context> | ||||
| @@ -1046,7 +1046,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">25</context> | ||||
|           <context context-type="linenumber">35</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context> | ||||
| @@ -1231,6 +1231,56 @@ | ||||
|           <context context-type="linenumber">19</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3894950702316166331" datatype="html"> | ||||
|         <source>Loading...</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">30</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/permissions-dialog/permissions-dialog.component.html</context> | ||||
|           <context context-type="linenumber">18</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/dashboard/dashboard.component.html</context> | ||||
|           <context context-type="linenumber">26</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/dashboard/widgets/widget-frame/widget-frame.component.html</context> | ||||
|           <context context-type="linenumber">7</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">95</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> | ||||
|           <context context-type="linenumber">230</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> | ||||
|           <context context-type="linenumber">320</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> | ||||
|           <context context-type="linenumber">406</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">19</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">27</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6563391987554512024" datatype="html"> | ||||
|         <source>Test</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">32</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="451418349275958054" datatype="html"> | ||||
|         <source>No encryption</source> | ||||
|         <context-group purpose="location"> | ||||
| @@ -1256,14 +1306,28 @@ | ||||
|         <source>Create new mail account</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">33</context> | ||||
|           <context context-type="linenumber">39</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5559445021532852612" datatype="html"> | ||||
|         <source>Edit mail account</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">37</context> | ||||
|           <context context-type="linenumber">43</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7726734777863565313" datatype="html"> | ||||
|         <source>Successfully connected to the mail server</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">88</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6533084895896956145" datatype="html"> | ||||
|         <source>Unable to connect to the mail server</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">89</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4086606389696938932" datatype="html"> | ||||
| @@ -2024,45 +2088,6 @@ | ||||
|           <context context-type="linenumber">12</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3894950702316166331" datatype="html"> | ||||
|         <source>Loading...</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/permissions-dialog/permissions-dialog.component.html</context> | ||||
|           <context context-type="linenumber">18</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/dashboard/dashboard.component.html</context> | ||||
|           <context context-type="linenumber">26</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/dashboard/widgets/widget-frame/widget-frame.component.html</context> | ||||
|           <context context-type="linenumber">7</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">95</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> | ||||
|           <context context-type="linenumber">230</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> | ||||
|           <context context-type="linenumber">320</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> | ||||
|           <context context-type="linenumber">406</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">19</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">27</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8105421668262723483" datatype="html"> | ||||
|         <source>Set Permissions</source> | ||||
|         <context-group purpose="location"> | ||||
|   | ||||
| @@ -20,7 +20,7 @@ export abstract class EditDialogComponent< | ||||
| > implements OnInit | ||||
| { | ||||
|   constructor( | ||||
|     private service: AbstractPaperlessService<T>, | ||||
|     protected service: AbstractPaperlessService<T>, | ||||
|     private activeModal: NgbActiveModal, | ||||
|     private userService: UserService | ||||
|   ) {} | ||||
|   | ||||
| @@ -21,6 +21,16 @@ | ||||
|     </div> | ||||
|   </div> | ||||
|   <div class="modal-footer"> | ||||
|     <div class="m-0 me-2"> | ||||
|       <ngb-alert #testResultAlert *ngIf="testResult" [type]="testResult" class="mb-0 py-2" (closed)="testResult = null">{{testResultMessage}}</ngb-alert> | ||||
|     </div> | ||||
|     <button type="button" class="btn btn-outline-primary" (click)="test()" [disabled]="networkActive || testActive"> | ||||
|       <ng-container *ngIf="testActive"> | ||||
|         <div class="spinner-border spinner-border-sm me-2" role="status"></div> | ||||
|         <span class="visually-hidden mr-1" i18n>Loading...</span> | ||||
|       </ng-container> | ||||
|       <ng-container i18n>Test</ng-container> | ||||
|     </button> | ||||
|     <button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button> | ||||
|     <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button> | ||||
|   </div> | ||||
|   | ||||
| @@ -0,0 +1,4 @@ | ||||
| ::ng-deep .alert-dismissible .btn-close { | ||||
|     padding-top: 0.75rem !important; | ||||
|     padding-bottom: 0.75rem !important; | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { Component } from '@angular/core' | ||||
| import { Component, ViewChild } from '@angular/core' | ||||
| import { FormControl, FormGroup } from '@angular/forms' | ||||
| import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' | ||||
| import { NgbActiveModal, NgbAlert } from '@ng-bootstrap/ng-bootstrap' | ||||
| import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-dialog.component' | ||||
| import { | ||||
|   IMAPSecurity, | ||||
| @@ -21,6 +21,12 @@ const IMAP_SECURITY_OPTIONS = [ | ||||
|   styleUrls: ['./mail-account-edit-dialog.component.scss'], | ||||
| }) | ||||
| export class MailAccountEditDialogComponent extends EditDialogComponent<PaperlessMailAccount> { | ||||
|   testActive: boolean = false | ||||
|   testResult: string | ||||
|   alertTimeout | ||||
|  | ||||
|   @ViewChild('testResultAlert', { static: false }) testResultAlert: NgbAlert | ||||
|  | ||||
|   constructor( | ||||
|     service: MailAccountService, | ||||
|     activeModal: NgbActiveModal, | ||||
| @@ -53,4 +59,33 @@ export class MailAccountEditDialogComponent extends EditDialogComponent<Paperles | ||||
|   get imapSecurityOptions() { | ||||
|     return IMAP_SECURITY_OPTIONS | ||||
|   } | ||||
|  | ||||
|   test() { | ||||
|     this.testActive = true | ||||
|     this.testResult = null | ||||
|     clearTimeout(this.alertTimeout) | ||||
|     const mailService = this.service as MailAccountService | ||||
|     const newObject = Object.assign( | ||||
|       Object.assign({}, this.object), | ||||
|       this.objectForm.value | ||||
|     ) | ||||
|     mailService.test(newObject).subscribe({ | ||||
|       next: (result: { success: boolean }) => { | ||||
|         this.testActive = false | ||||
|         this.testResult = result.success ? 'success' : 'danger' | ||||
|         this.alertTimeout = setTimeout(() => this.testResultAlert.close(), 5000) | ||||
|       }, | ||||
|       error: (e) => { | ||||
|         this.testActive = false | ||||
|         this.testResult = 'danger' | ||||
|         this.alertTimeout = setTimeout(() => this.testResultAlert.close(), 5000) | ||||
|       }, | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   get testResultMessage() { | ||||
|     return this.testResult === 'success' | ||||
|       ? $localize`Successfully connected to the mail server` | ||||
|       : $localize`Unable to connect to the mail server` | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -48,4 +48,8 @@ export class MailAccountService extends AbstractPaperlessService<PaperlessMailAc | ||||
|   delete(o: PaperlessMailAccount) { | ||||
|     return super.delete(o).pipe(tap(() => this.reload())) | ||||
|   } | ||||
|  | ||||
|   test(o: PaperlessMailAccount) { | ||||
|     return this.http.post(this.getResourceUrl() + 'test/', o) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -16,6 +16,7 @@ body { | ||||
|   --pngx-primary-darken-15: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 15%)); | ||||
|   --pngx-primary-darken-18: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 18%)); | ||||
|   --pngx-primary-darken-27: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 27%)); | ||||
|   --pngx-success-darken-10: hsl(152, 69%, 11%); // based on success #198754 | ||||
|   --pngx-bg-alt: #fff; | ||||
|   --pngx-bg-darker: var(--bs-gray-100); | ||||
|   --pngx-focus-alpha: 0.3; | ||||
| @@ -205,6 +206,12 @@ $form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='htt | ||||
|     --bs-alert-border-color: var(--pngx-bg-darker); | ||||
|   } | ||||
|  | ||||
|   .alert-success { | ||||
|     --bs-alert-color: var(--pngx-body-color-accent); | ||||
|     --bs-alert-bg: var(--pngx-success-darken-10); | ||||
|     --bs-alert-border-color: var(--pngx-bg-darker); | ||||
|   } | ||||
|  | ||||
|   .table-striped > tbody > tr:nth-of-type(odd) > * { | ||||
|     color: var(--pngx-body-color-accent); | ||||
|   } | ||||
|   | ||||
| @@ -29,6 +29,7 @@ from paperless.consumers import StatusConsumer | ||||
| from paperless.views import FaviconView | ||||
| from paperless.views import GroupViewSet | ||||
| from paperless.views import UserViewSet | ||||
| from paperless_mail.views import MailAccountTestView | ||||
| from paperless_mail.views import MailAccountViewSet | ||||
| from paperless_mail.views import MailRuleViewSet | ||||
| from rest_framework.authtoken import views | ||||
| @@ -102,6 +103,11 @@ urlpatterns = [ | ||||
|                     AcknowledgeTasksView.as_view(), | ||||
|                     name="acknowledge_tasks", | ||||
|                 ), | ||||
|                 re_path( | ||||
|                     r"^mail_accounts/test/", | ||||
|                     MailAccountTestView.as_view(), | ||||
|                     name="mail_accounts_test", | ||||
|                 ), | ||||
|                 path("token/", views.obtain_auth_token), | ||||
|             ] | ||||
|             + api_router.urls, | ||||
|   | ||||
| @@ -1,10 +1,19 @@ | ||||
| import datetime | ||||
| import logging | ||||
|  | ||||
| from django.http import HttpResponseBadRequest | ||||
| from documents.views import PassUserMixin | ||||
| from paperless.views import StandardPagination | ||||
| from paperless_mail.mail import get_mailbox | ||||
| from paperless_mail.mail import mailbox_login | ||||
| from paperless_mail.mail import MailError | ||||
| from paperless_mail.models import MailAccount | ||||
| from paperless_mail.models import MailRule | ||||
| from paperless_mail.serialisers import MailAccountSerializer | ||||
| from paperless_mail.serialisers import MailRuleSerializer | ||||
| from rest_framework.generics import GenericAPIView | ||||
| from rest_framework.permissions import IsAuthenticated | ||||
| from rest_framework.response import Response | ||||
| from rest_framework.viewsets import ModelViewSet | ||||
|  | ||||
|  | ||||
| @@ -24,3 +33,41 @@ class MailRuleViewSet(ModelViewSet, PassUserMixin): | ||||
|     serializer_class = MailRuleSerializer | ||||
|     pagination_class = StandardPagination | ||||
|     permission_classes = (IsAuthenticated,) | ||||
|  | ||||
|  | ||||
| class MailAccountTestView(GenericAPIView): | ||||
|  | ||||
|     permission_classes = (IsAuthenticated,) | ||||
|     serializer_class = MailAccountSerializer | ||||
|  | ||||
|     def post(self, request, *args, **kwargs): | ||||
|         logger = logging.getLogger("paperless_mail") | ||||
|         request.data["name"] = datetime.datetime.now().isoformat() | ||||
|         serializer = self.get_serializer(data=request.data) | ||||
|         serializer.is_valid(raise_exception=True) | ||||
|  | ||||
|         # account exists, use the password from there instead of *** | ||||
|         if ( | ||||
|             len(serializer.validated_data.get("password").replace("*", "")) == 0 | ||||
|             and request.data["id"] is not None | ||||
|         ): | ||||
|             serializer.validated_data["password"] = MailAccount.objects.get( | ||||
|                 pk=request.data["id"], | ||||
|             ).password | ||||
|  | ||||
|         account = MailAccount(**serializer.validated_data) | ||||
|  | ||||
|         with get_mailbox( | ||||
|             account.imap_server, | ||||
|             account.imap_port, | ||||
|             account.imap_security, | ||||
|         ) as M: | ||||
|             try: | ||||
|                 mailbox_login(M, account) | ||||
|                 return Response({"success": True}) | ||||
|             except MailError as e: | ||||
|                 logger.error( | ||||
|                     f"Mail account {account} test failed: {e}", | ||||
|                     exc_info=False, | ||||
|                 ) | ||||
|                 return HttpResponseBadRequest("Unable to connect to server") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 shamoon
					shamoon