Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

forward a message as attachment #1728

Closed
wants to merge 3 commits into from

Conversation

the0ne
Copy link
Contributor

@the0ne the0ne commented Oct 18, 2016

enables the user to forward a message as attachment of mime type "message/rfc822".
this is often required to avoid the original message headers being changed.

@the0ne the0ne mentioned this pull request Oct 18, 2016
} else {
if (K9.DEBUG) {
Log.d(K9.LOG_TAG, "could not get Message-ID.");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Collapse this else { if { into else if. And print something about the message you do know in the debug line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i didn't want to modify the code, its copied from a few lines above - see function processMessageToForward.

if we need to change it, then we should also modify it above.
what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be bold. :)

Copy link
Contributor

@philipwhiuk philipwhiuk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some feedback based on visual review. I'll try and load it on my device for testing later.

attachments.put(attachment.uri, attachment);
attachmentMvpView.addAttachmentView(attachment);
} catch (java.io.IOException e) {
throw new IllegalStateException("Error storing the message to a temporary file: " + e.getMessage());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass the original exception instead of swallowing it.

} catch (java.io.IOException e) {
throw new IllegalStateException("Error storing the message to a temporary file: " + e.getMessage());
} catch (MessagingException e) {
throw new IllegalStateException("Received the same attachmentViewInfo twice!");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass the original exception instead of swallowing it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at what level should the exception be caught, then? could you propose a solution, please?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean throw new IllegalStateException("....",e)

else {
try {
File tempFile = File.createTempFile("pre", ".tmp");
tempFile.deleteOnExit();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fairly sure we have a better mechanism for temporary files than deleteOnExit. K-9 is unlikely to ever exit. Nor is the JVM.

Also, code style: else { on the same line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleteOnExit is used throughout the whole K-9 code.
didn't find anything else so this must be it.

@@ -467,7 +471,7 @@ public void onTextChanged(CharSequence s, int start, int before, int count) {

if (!mSourceMessageProcessed) {
if (mAction == Action.REPLY || mAction == Action.REPLY_ALL ||
mAction == Action.FORWARD || mAction == Action.EDIT_DRAFT) {
mAction == Action.FORWARD || mAction == Action.FORWARD_AS_ATTACHMENT || mAction == Action.EDIT_DRAFT) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap this line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you describe in detail what you mean?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line is too long. Put mAction == Action.EDIT_DRAFT on the next line.

}

return allPartsAvailable;
}

public boolean loadNonInlineAttachments(MessageViewInfo messageViewInfo) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code style generally prefers the public function above the private functions it uses.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will switch order

@@ -73,6 +73,7 @@ Bitte senden Sie Fehlerberichte, Ideen für neue Funktionen und stellen Sie Frag
<string name="compose_title_reply">Antworten</string>
<string name="compose_title_reply_all">Allen antworten</string>
<string name="compose_title_forward">Weiterleiten</string>
<string name="compose_title_forward_as_attachment">Weiterleiten als Anhang</string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these will be overwritten by Transifex as an FYI

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

@the0ne
Copy link
Contributor Author

the0ne commented Oct 18, 2016

i moved the exception handling out to processSourceMessage.
seems that's the better place.

@philipwhiuk
Copy link
Contributor

philipwhiuk commented Oct 19, 2016

This seems to allow viewing of forwarded messages and I have no issue with the changes. Roundcube can parse the forwarded messages we send so it is fine.

But I do have a case where I forwarded an email (which had an attachment itself) as an attachment via Outlook. And that is still displayed as an unparsed attachment. Incidentally Roundcube gets confused here too - it displays the inner attachment as an attachment and the outer forwarded email as content - I think correct behaviour is to display and offer for download the attachment.

In our case it's not possible to save the email forwarded as an attachment in K-9. I think we should be able to save the attachment - similar to how I'm doing with the iCal stuff in #930

I don't know whether that was something you intended to fix as well with this PR.

@the0ne
Copy link
Contributor Author

the0ne commented Oct 19, 2016

fixing issues with viewing attachments is out of scope for this fix.
the direction i'm going is the following: https://github.com/the0ne/k-9/tree/report_as_spam

@the0ne
Copy link
Contributor Author

the0ne commented Oct 19, 2016

@philipwhiuk would you please also review
https://github.com/the0ne/k-9/tree/report_as_spam
which is based upon this pull?

@philipwhiuk
Copy link
Contributor

See #1736 for comments for that @the0ne

@the0ne
Copy link
Contributor Author

the0ne commented Oct 20, 2016

@philipwhiuk please also review #1739 for the implementation of #622

Copy link
Contributor

@Valodim Valodim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but the 7bit reencoding thing (see below) might turn out to be quite the showstopper here :\

attachmentPresenter.processMessageToForward(messageViewInfo);
}

private void processMessageToForwardAsAttachment(MessageViewInfo messageViewInfo) throws IOException, MessagingException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is very similar to processMessageToForward, a boolean forwardAsAttachment parameter seems more suitable for the small difference in behavior

@@ -162,7 +170,9 @@ public boolean loadNonInlineAttachments(MessageViewInfo messageViewInfo) {
allPartsAvailable = false;
continue;
}
addAttachment(attachmentViewInfo);
if(loadNonInlineAttachments) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code style

attachmentMvpView.showMissingAttachmentsPartialMessageForwardWarning();
} else {
File tempFile = File.createTempFile("pre", ".tmp");
tempFile.deleteOnExit();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleteOnExit should be considered an almost-noop on android, since apps rarely if ever "exit"

Copy link
Contributor Author

@the0ne the0ne Oct 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This exact scheme is found throughout the existing code.
Please let me know what else to use.
But I'd prefer to stick with what you used before as it has been in use and tested for quite a while.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, you're right AttachmentContentLoader does this as well. Ugh. We really shouldn't be doing this, but I'm not sure what a good way to deal with this is.. @cketti ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should pick one of the strategies outlined here: https://developer.android.com/reference/java/io/File.html#deleteOnExit()

I think the Unix trick is too low level. The list idea may work, but the finally strategy is neatest if we can refactor the code accordingly.

This probably wants an audit issue?

File tempFile = File.createTempFile("pre", ".tmp");
tempFile.deleteOnExit();
FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
messageViewInfo.message.writeTo(fileOutputStream);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should not be done on the UI thread but rather in a loader. check out AttachmentContentLoader

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm. i'm actually using a loader to analyze the attachment after writing.
do you think writing the binary data to the temporary folder is an issue?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At any rate, it definitely should be kept out of the UI thread

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm.
maybe someone could help out a little?
i understand that one must use the loader for an Attachment object with a link to the MessageViewInfo so that the AttachmentContentLoader can do it's job but i'm not deep enough into K-9 code to do that myself.

Copy link
Contributor Author

@the0ne the0ne Nov 4, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify how this can be improved using an AttachmentContentLoader.
Will it be necessary to add code to SafeContentResolver as well?

"attachment;\r\n filename=\"%s\";\r\n size=%d",
attachment.name, attachment.size));
if (!MimeUtil.isMessage(attachment.contentType)) {
bp.setEncoding(MimeUtility.getEncodingforType(attachment.contentType));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attaching the data as is opens up the whole rabbit hole that is 7bit eencoding. iinm, we would ideally have a magic method MimeMessage Message7BitReencoder.reencode(LocalMessage) that does this, but there are a lot of things that can go wrong with that :\

@cketti what's the plan for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Valodim I actually use this functionality already and I don't see any issues forwarding text mail nor mail with binary attachments. might it be that the encoding issue doesn't apply here?
Please also note that the bp.setEncoding is not called for attachments that are rfc822 messages.
Can you provide any means of creating mail to demonstrate the issue you expect?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is related to #1034. Although reading how qmail and exim handle this issue (source) we might want to rethink this.

We need to come up with a concept on 8bit messages sooner or later, let's continue the discussion over there

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, got your point.
Two workarounds would be:

  1. take the newly created attachment name, strip out anything other than numbers and letters, replace space by underscore, limit length to a max of ~78
  2. use a pre-defined string as the attachment name as thunderbird does, e.g. "forwarded message"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this is about 8 bit encoding of emails in general, not just the filename. Have you looked at the issue I linked above?

Copy link
Contributor Author

@the0ne the0ne Nov 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Valodim not in detail - can you give a short summary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually the following code applies:
`

    } else if (MimeUtil.isMessage(type)) {
        return (MimeUtil.ENC_8BIT);

`
and hence the encoding will be set to 8bit.
according to all i read there's no 7bit encoding nowadays, right?

@cketti cketti added the status: needs work Issues that are pending further action or development label Dec 12, 2016
Copy link
Member

@cketti cketti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@the0ne: This branch is a bit of a mess. Please clean it up so it only contains your changes.

@the0ne
Copy link
Contributor Author

the0ne commented Dec 13, 2016

after cleanup, will you also answer the questions about 8bit and AttachmentContentLoader above?

@the0ne
Copy link
Contributor Author

the0ne commented Dec 29, 2016

@cketti The branch has been cleaned up as requested - please review.

@cketti cketti self-assigned this Feb 20, 2017
@the0ne
Copy link
Contributor Author

the0ne commented Dec 29, 2017

@cketti if you want to have this feature feel free to let me know and i'll think about again fixing the conflicts that have been introduced in the mean time.

i won't again do all the work like with #1736 and #1739 only so that you will say "well, good job but now that it's ready we don't want the feature". what you did there was disrespecting developer's time and that was rude.

so once you decided please either let me know or just close this.

@cketti
Copy link
Member

cketti commented Jan 8, 2018

@the0ne: Thanks for your work. I used your code as base for PR #3063. Most notable difference is that there happens no (additional) file I/O in the main thread and that we still don't allow external apps to provide attachments with a MIME type of message/*.

@cketti cketti closed this Jan 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: needs work Issues that are pending further action or development
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants