mail icon indicating copy to clipboard operation
mail copied to clipboard

feature: mail provider backend

Open SebastianKrupinski opened this issue 1 year ago • 17 comments

Initial Mail Provider Implementation

https://github.com/nextcloud/server/issues/5080

SebastianKrupinski avatar May 16 '24 23:05 SebastianKrupinski

Todo:

  • Copyright
  • Comments
  • Minor code improvements

SebastianKrupinski avatar May 16 '24 23:05 SebastianKrupinski

This PR requires the server PR first...

https://github.com/nextcloud/server/pull/45383

SebastianKrupinski avatar May 24 '24 18:05 SebastianKrupinski

TODO: Separate attachment handling for file system files (saved on the system) and string data files (created or loaded in memory)

SebastianKrupinski avatar May 24 '24 18:05 SebastianKrupinski

TODO: unit tests

SebastianKrupinski avatar May 28 '24 13:05 SebastianKrupinski

Hello there, Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

github-actions[bot] avatar Jun 02 '24 02:06 github-actions[bot]

Testing process:

Pull this PR and server PR - https://github.com/nextcloud/server/pull/45383

Make sure you have an email account setup in the mail app.

Then create calendar event with an attendee.

Invitation email should be sent from personal mail account

SebastianKrupinski avatar Jul 09 '24 15:07 SebastianKrupinski

"OCA\\Mail\\Controller\\OutboxController::update(): Argument #5 ($editorBody) must be of type string, null given, called in /var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php on line 208 in file '/var/www/nextcloud/apps/mail/lib/Controller/OutboxController.php' line 178" when using "Send now" from the Outbox

@miaulalala

So setting the editor body in the message does let the message be opened in the GUI.

BUT there is a side effect...

  1. After opening the message pressing send destroys the formatting of the original message.
  2. After opening the message pressing close destroys the attachment and prevents the message from sending.

I would recommend we disable this for now.

SebastianKrupinski avatar Aug 22 '24 13:08 SebastianKrupinski

"OCA\\Mail\\Controller\\OutboxController::update(): Argument #5 ($editorBody) must be of type string, null given, called in /var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php on line 208 in file '/var/www/nextcloud/apps/mail/lib/Controller/OutboxController.php' line 178" when using "Send now" from the Outbox

@miaulalala

So setting the editor body in the message does let the message be opened in the GUI.

BUT there is a side effect...

1. After opening the message pressing send destroys the formatting of the original message.

2. After opening the message pressing close destroys the attachment and prevents the message from sending.

I would recommend we disable this for now.

this is not about opening the message in the gui - it's about the "Send now" button in the three dot menu in the outbox.

A message that is sent through the outbox should behave exactly as a message sent through mail would. Disabling features is not an option.

miaulalala avatar Aug 22 '24 13:08 miaulalala

@SebastianKrupinski as discussed in our team call, please use fixup commits. It's much easier to review your changes than because GitHub shows only the new changes. I'm aware that I actually asked you for the opposite, sorry about that.

kesselb avatar Aug 22 '24 13:08 kesselb

@SebastianKrupinski as discussed in our team call, please use fixup commits. It's much easier to review your changes than because GitHub shows only the new changes. I'm aware that I actually asked you for the opposite, sorry about that.

Yes, I re based and squashed out of habit, which wiped the previous commits. Appologies.

SebastianKrupinski avatar Aug 22 '24 14:08 SebastianKrupinski

"OCA\\Mail\\Controller\\OutboxController::update(): Argument #5 ($editorBody) must be of type string, null given, called in /var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php on line 208 in file '/var/www/nextcloud/apps/mail/lib/Controller/OutboxController.php' line 178" when using "Send now" from the Outbox

@miaulalala So setting the editor body in the message does let the message be opened in the GUI. BUT there is a side effect...

1. After opening the message pressing send destroys the formatting of the original message.

2. After opening the message pressing close destroys the attachment and prevents the message from sending.

I would recommend we disable this for now.

this is not about opening the message in the gui - it's about the "Send now" button in the three dot menu in the outbox.

A message that is sent through the outbox should behave exactly as a message sent through mail would. Disabling features is not an option.

@miaulalala I agree the "Send now" should work. But these messages are different, because they are automated.

The problem is that this API is used by the server and other apps to send automated messages, that do NOT use the front end editor, therefor there is no editorBody.

So forcing the editorBody to contain content that it can not handle properly causes more issues, as I have stated above. The better solution to this is to fix the "Send Now" action to properly handle automated messages in a followup PR.

SebastianKrupinski avatar Aug 22 '24 16:08 SebastianKrupinski

It's new that we have messages in the outbox that were not created by a user, and therefore we don't have an editor body.

That we store the editor body in addition to the actual message has the reasoning that CKEditor is an HTML editor for websites and documents, but we are using it for composing emails. The generated HTML is then "transformed" to an HTML for emails. That only works one-way, and therefore we store the actual source as well to make editing possible.

For our current use case, sending the calendar invitation from the user account, it seems unnecessary/unwanted to edit the outgoing message. I assume we need to extend our outbox logic to have mutable and immutable messages. As a start, it might be enough to hide messages in the outbox view with editor body = null. A bit nicer would be to show at least our usual message preview instead of the editor, but I cannot tell how much work that is.

Please align the final approach with Anna and Christoph.

kesselb avatar Aug 23 '24 10:08 kesselb

It's new that we have messages in the outbox that were not created by a user, and therefore we don't have an editor body.

That we store the editor body in addition to the actual message has the reasoning that CKEditor is an HTML editor for websites and documents, but we are using it for composing emails. The generated HTML is then "transformed" to an HTML for emails. That only works one-way, and therefore we store the actual source as well to make editing possible.

For our current use case, sending the calendar invitation from the user account, it seems unnecessary/unwanted to edit the outgoing message. I assume we need to extend our outbox logic to have mutable and immutable messages. As a start, it might be enough to hide messages in the outbox view with editor body = null. A bit nicer would be to show at least our usual message preview instead of the editor, but I cannot tell how much work that is.

Please align the final approach with Anna and Christoph.

I agree.

SebastianKrupinski avatar Aug 23 '24 12:08 SebastianKrupinski

Keeping editorBody null and not allowing edits for automated emails is an acceptable workaround for me :+1:

ChristophWurst avatar Aug 23 '24 12:08 ChristophWurst

@ChristophWurst

Done. I will create a separate ticket to alter the outbox logic.

SebastianKrupinski avatar Aug 23 '24 14:08 SebastianKrupinski

@miaulalala

Outbox send logic was broken. Its fixed now.

https://github.com/nextcloud/mail/pull/10059

SebastianKrupinski avatar Aug 27 '24 18:08 SebastianKrupinski

https://github.com/nextcloud/mail/pull/9651#discussion_r1733025515

ChristophWurst avatar Aug 28 '24 09:08 ChristophWurst

Tested and works. @miaulalala @kesselb ok for you too?

ChristophWurst avatar Aug 30 '24 09:08 ChristophWurst

The downside is that it take up to 5 minutes until the invitation is delivered. Invite someone to your Google Calendar, Outlook, etc. and the invitation is right there.

I agree this is a downside but at the moment I don't see a better option for a better balance between performance and functionality.

A) I'm not aware about performance issues with many attendees. I assume calendar and external clients do have a loading >animation to signal back that the request is beeing processed.

There are a couple of tickets stating that inviting 10+ attendees fails. At the moment our UI does not show a "Processing animation" or even disable the save buttons, when I insert a debug break point, to stop the save process you can actually re-click and start another save process.

B) Filing the invitation into the outbox is nice because a user could retry if sending failed for temporary reasons. However I don't >see how a failing mail delivery would make the entire PUT command fail.

We can talk about this in a call, but a general overview of the save process (PUT Request) is this...

-> User Generates a PUT Request (Clicks Save) -> Server Validates Data -> Server Compares Events (On update) -> Server Finds Attendees -> Server Generates iTip Messages for Attendees -> Server Saves Event for Attendees (Local NC Users Only) -> Server Generates Emails (For all attendees) -> Server Sends Emails (For all attendees) -> Server Saves Event for Organizer -> Server Returns Response

So the issue of a response that takes too long is to fold, A) the user might re-click B) the client might give up waiting for a response and re-try.

The other issue is that an error during the SMTP send process, on one of the accounts might actual cause the event save process to fail and the event is never saved for the organizer.

Ultimately its @ChristophWurst that has to make the choice... Attempt to send instantly or no

SebastianKrupinski avatar Aug 30 '24 15:08 SebastianKrupinski

There are a couple of tickets stating that inviting 10+ attendees fails.

Link?

At the moment our UI does not show a "Processing animation" or even disable the save buttons, when I insert a debug break point, to stop the save process you can actually re-click and start another save process.

We should have one, plase log an issue for calendar: https://github.com/nextcloud/calendar

The other issue is that an error during the SMTP send process, on one of the accounts might actual cause the event save process to fail and the event is never saved for the organizer.

An SMTP error should not interrupt the process. Please make sure the mail provider part for the imip plugin handle such a situation properly. I recommend another test case for IMipPluginTest to make sure the code works as expected if an exception is thrown.

kesselb avatar Aug 30 '24 16:08 kesselb

Please don't rebase/squash this pull request until approved because that may rewrite the commit hashes. GitHub cannot show the incoming changes then and I have to review everything from the start. If you need to pull the latest changes from main, merge main into this branch.

kesselb avatar Aug 30 '24 17:08 kesselb

An SMTP error should not interrupt the process. Please make sure the mail provider part for the imip plugin handle such a situation properly. I recommend another test case for IMipPluginTest to make sure the code works as expected if an exception is thrown.

Sure I can do that, but that will be a separate PR on the server. This is not in scope for the mail app

SebastianKrupinski avatar Aug 30 '24 19:08 SebastianKrupinski

We should have one, please log an issue for calendar.

Sure

SebastianKrupinski avatar Aug 30 '24 19:08 SebastianKrupinski

@kesselb

The downside is that it take up to 5 minutes until the invitation is delivered. Invite someone to your Google Calendar, Outlook, etc. and the invitation is right there.

What if we make this a configurable option? In the mail app settings... we can add a "Bypass outbox for system messages" or "Send system messages instantly"

SebastianKrupinski avatar Aug 31 '24 17:08 SebastianKrupinski

The other issue is that an error during the SMTP send process, on one of the accounts might actual cause the event save process to fail and the event is never saved for the organizer.

Ultimately its @ChristophWurst that has to make the choice... Attempt to send instantly or no

We currently send instantly, so let's keep this behavior for the Mail provider too.

For fault tolerance I suggest we first add all the emails to the outbox, then we trigger sending. Any messages that run into an (recoverable) error will remain in the outbox and get retried by cron.

In the future we can discuss async sending. With many attendees and slow SMTP it's indeed a bit of a bad UX and potential for a timeout. But fixing this here is out of scope.

ChristophWurst avatar Sep 02 '24 05:09 ChristophWurst

The branch is a bit behind main. Please merge main (no rebase, no squash) to have a CI run against the latest main.

kesselb avatar Sep 06 '24 16:09 kesselb

Please merge main (no rebase, no squash) to have a CI run against the latest main.

@SebastianKrupinski to provide the reason for this: it allows us to follow your changes. Every time you change the git history with an amend or a rebase, github is no longer able to diff the changes between our last visit and your last push. Every time you change history, we have to review the full diff. In this PR, that's 1200 LOC.

Hope this makes sense.

Please avoid rebases in PRs like this where reviewers left request for changes.

ChristophWurst avatar Sep 09 '24 06:09 ChristophWurst

Please merge main (no rebase, no squash) to have a CI run against the latest main.

@SebastianKrupinski to provide the reason for this: it allows us to follow your changes. Every time you change the git history with an amend or a rebase, github is no longer able to diff the changes between our last visit and your last push. Every time you change history, we have to review the full diff. In this PR, that's 1200 LOC.

Hope this makes sense.

Please avoid rebases in PRs like this where reviewers left request for changes.

Sorry, i did a merge the first time and it messed up the app, couldn't get it to run, so after trying to fix it, I had to delete it re-clone it and redo the changes.

SebastianKrupinski avatar Sep 09 '24 13:09 SebastianKrupinski

@ChristophWurst

These two comments...

https://github.com/nextcloud/mail/pull/9651#discussion_r1750300381 https://github.com/nextcloud/mail/pull/9651#discussion_r1750301662

From the selected code block, I think you are looking at a old version of the PR the code was already changed in this commit.

https://github.com/nextcloud/mail/pull/9651/commits/7f85f0d8408c8336de4b5f9d09723f66a2bc1bb9#diff-b2fd4b9c63f5641101d4ec474c50008f95fc16af2c64ae2972a22e607f88932d

image

SebastianKrupinski avatar Sep 09 '24 15:09 SebastianKrupinski

From the selected code block, I think you are looking at a old version of the PR the code was already changed in this commit.

See https://github.com/nextcloud/mail/actions/runs/10755754956/job/29827858067?pr=9651. This is the latest CI run.

ChristophWurst avatar Sep 09 '24 15:09 ChristophWurst