Search in sources :

Example 1 with InsertableHtmlContent

use of com.fsck.k9.message.quote.InsertableHtmlContent in project k-9 by k9mail.

the class PgpMessageBuilderTest method createDefaultPgpMessageBuilder.

private static PgpMessageBuilder createDefaultPgpMessageBuilder(OpenPgpApi openPgpApi) {
    PgpMessageBuilder builder = new PgpMessageBuilder(RuntimeEnvironment.application, MessageIdGenerator.getInstance(), BoundaryGenerator.getInstance());
    builder.setOpenPgpApi(openPgpApi);
    Identity identity = new Identity();
    identity.setName("tester");
    identity.setEmail("test@example.org");
    identity.setDescription("test identity");
    identity.setSignatureUse(false);
    builder.setSubject("subject").setSentDate(new Date()).setHideTimeZone(false).setTo(new ArrayList<Address>()).setCc(new ArrayList<Address>()).setBcc(new ArrayList<Address>()).setInReplyTo("inreplyto").setReferences("references").setRequestReadReceipt(false).setIdentity(identity).setMessageFormat(SimpleMessageFormat.TEXT).setText(TEST_MESSAGE_TEXT).setAttachments(new ArrayList<Attachment>()).setSignature("signature").setQuoteStyle(QuoteStyle.PREFIX).setQuotedTextMode(QuotedTextMode.NONE).setQuotedText("quoted text").setQuotedHtmlContent(new InsertableHtmlContent()).setReplyAfterQuote(false).setSignatureBeforeQuotedText(false).setIdentityChanged(false).setSignatureChanged(false).setCursorPosition(0).setMessageReference(null).setDraft(false);
    return builder;
}
Also used : Address(com.fsck.k9.mail.Address) ArrayList(java.util.ArrayList) Attachment(com.fsck.k9.activity.misc.Attachment) InsertableHtmlContent(com.fsck.k9.message.quote.InsertableHtmlContent) Identity(com.fsck.k9.Identity) Date(java.util.Date)

Example 2 with InsertableHtmlContent

use of com.fsck.k9.message.quote.InsertableHtmlContent in project k-9 by k9mail.

the class QuotedMessagePresenter method processDraftMessage.

public void processDraftMessage(MessageViewInfo messageViewInfo, Map<IdentityField, String> k9identity) {
    quoteStyle = k9identity.get(IdentityField.QUOTE_STYLE) != null ? QuoteStyle.valueOf(k9identity.get(IdentityField.QUOTE_STYLE)) : account.getQuoteStyle();
    int cursorPosition = 0;
    if (k9identity.containsKey(IdentityField.CURSOR_POSITION)) {
        try {
            cursorPosition = Integer.parseInt(k9identity.get(IdentityField.CURSOR_POSITION));
        } catch (Exception e) {
            Timber.e(e, "Could not parse cursor position for MessageCompose; continuing.");
        }
    }
    String showQuotedTextMode;
    if (k9identity.containsKey(IdentityField.QUOTED_TEXT_MODE)) {
        showQuotedTextMode = k9identity.get(IdentityField.QUOTED_TEXT_MODE);
    } else {
        showQuotedTextMode = "NONE";
    }
    int bodyLength = k9identity.get(IdentityField.LENGTH) != null ? Integer.valueOf(k9identity.get(IdentityField.LENGTH)) : UNKNOWN_LENGTH;
    int bodyOffset = k9identity.get(IdentityField.OFFSET) != null ? Integer.valueOf(k9identity.get(IdentityField.OFFSET)) : UNKNOWN_LENGTH;
    Integer bodyFooterOffset = k9identity.get(IdentityField.FOOTER_OFFSET) != null ? Integer.valueOf(k9identity.get(IdentityField.FOOTER_OFFSET)) : null;
    Integer bodyPlainLength = k9identity.get(IdentityField.PLAIN_LENGTH) != null ? Integer.valueOf(k9identity.get(IdentityField.PLAIN_LENGTH)) : null;
    Integer bodyPlainOffset = k9identity.get(IdentityField.PLAIN_OFFSET) != null ? Integer.valueOf(k9identity.get(IdentityField.PLAIN_OFFSET)) : null;
    QuotedTextMode quotedMode;
    try {
        quotedMode = QuotedTextMode.valueOf(showQuotedTextMode);
    } catch (Exception e) {
        quotedMode = QuotedTextMode.NONE;
    }
    // Always respect the user's current composition format preference, even if the
    // draft was saved in a different format.
    // TODO - The current implementation doesn't allow a user in HTML mode to edit a draft that wasn't saved with K9mail.
    String messageFormatString = k9identity.get(IdentityField.MESSAGE_FORMAT);
    MessageFormat messageFormat = null;
    if (messageFormatString != null) {
        try {
            messageFormat = MessageFormat.valueOf(messageFormatString);
        } catch (Exception e) {
        /* do nothing */
        }
    }
    if (messageFormat == null) {
        // This message probably wasn't created by us. The exception is legacy
        // drafts created before the advent of HTML composition. In those cases,
        // we'll display the whole message (including the quoted part) in the
        // composition window. If that's the case, try and convert it to text to
        // match the behavior in text mode.
        view.setMessageContentCharacters(BodyTextExtractor.getBodyTextFromMessage(messageViewInfo.rootPart, SimpleMessageFormat.TEXT));
        forcePlainText = true;
        showOrHideQuotedText(quotedMode);
        return;
    }
    if (messageFormat == MessageFormat.HTML) {
        // defaults to null
        String bodyText;
        Part part = MimeUtility.findFirstPartByMimeType(messageViewInfo.rootPart, "text/html");
        if (part != null) {
            // Shouldn't happen if we were the one who saved it.
            quotedTextFormat = SimpleMessageFormat.HTML;
            String text = MessageExtractor.getTextFromPart(part);
            if (text == null) {
                Timber.d("Empty message; skipping.");
                bodyText = "";
            } else {
                Timber.d("Loading message with offset %d, length %d. Text length is %d.", bodyOffset, bodyLength, text.length());
                if (bodyOffset + bodyLength > text.length()) {
                    // The draft was edited outside of K-9 Mail?
                    Timber.d("The identity field from the draft contains an invalid LENGTH/OFFSET");
                    bodyOffset = 0;
                    bodyLength = 0;
                }
                // Grab our reply text.
                bodyText = text.substring(bodyOffset, bodyOffset + bodyLength);
            }
            view.setMessageContentCharacters(HtmlConverter.htmlToText(bodyText));
            // Regenerate the quoted html without our user content in it.
            StringBuilder quotedHTML = new StringBuilder();
            // stuff before the reply
            quotedHTML.append(text.substring(0, bodyOffset));
            quotedHTML.append(text.substring(bodyOffset + bodyLength));
            if (quotedHTML.length() > 0) {
                quotedHtmlContent = new InsertableHtmlContent();
                quotedHtmlContent.setQuotedContent(quotedHTML);
                // We don't know if bodyOffset refers to the header or to the footer
                quotedHtmlContent.setHeaderInsertionPoint(bodyOffset);
                if (bodyFooterOffset != null) {
                    quotedHtmlContent.setFooterInsertionPoint(bodyFooterOffset);
                } else {
                    quotedHtmlContent.setFooterInsertionPoint(bodyOffset);
                }
                // TODO replace with MessageViewInfo data
                view.setQuotedHtml(quotedHtmlContent.getQuotedContent(), AttachmentResolver.createFromPart(messageViewInfo.rootPart));
            }
        }
        if (bodyPlainOffset != null && bodyPlainLength != null) {
            processSourceMessageText(messageViewInfo.rootPart, bodyPlainOffset, bodyPlainLength, false);
        }
    } else if (messageFormat == MessageFormat.TEXT) {
        quotedTextFormat = SimpleMessageFormat.TEXT;
        processSourceMessageText(messageViewInfo.rootPart, bodyOffset, bodyLength, true);
    } else {
        Timber.e("Unhandled message format.");
    }
    // Set the cursor position if we have it.
    try {
        view.setMessageContentCursorPosition(cursorPosition);
    } catch (Exception e) {
        Timber.e(e, "Could not set cursor position in MessageCompose; ignoring.");
    }
    showOrHideQuotedText(quotedMode);
}
Also used : SimpleMessageFormat(com.fsck.k9.message.SimpleMessageFormat) MessageFormat(com.fsck.k9.Account.MessageFormat) Part(com.fsck.k9.mail.Part) QuotedTextMode(com.fsck.k9.message.QuotedTextMode) InsertableHtmlContent(com.fsck.k9.message.quote.InsertableHtmlContent) MessagingException(com.fsck.k9.mail.MessagingException)

Example 3 with InsertableHtmlContent

use of com.fsck.k9.message.quote.InsertableHtmlContent in project k-9 by k9mail.

the class TextBodyBuilderTest method testBuildTextHtml.

@Theory
public void testBuildTextHtml(boolean includeQuotedText, QuoteStyle quoteStyle, boolean isReplyAfterQuote, boolean isSignatureUse, boolean isSignatureBeforeQuotedText, boolean isDraft) {
    String expectedText;
    int expectedMessageLength;
    int expectedMessagePosition = 0;
    String expectedHtmlContent;
    String expectedPrefix = "";
    if (includeQuotedText && quoteStyle == QuoteStyle.PREFIX && isReplyAfterQuote && !isDraft) {
        expectedPrefix = "<br clear=\"all\">";
    }
    String expectedPostfix = "";
    if (!isDraft && includeQuotedText) {
        expectedPostfix = "<br><br>";
    }
    // 3.signature
    if (quoteStyle == QuoteStyle.PREFIX && isReplyAfterQuote) {
        expectedText = expectedPrefix + "<html>message content";
        if (!isDraft && isSignatureUse) {
            expectedText += "\r\n" + "signature";
        }
        expectedText += "</html>";
        expectedMessageLength = expectedText.length();
        String quotedContent = "quoted text";
        if (isDraft || includeQuotedText) {
            expectedHtmlContent = makeExpectedHtmlContent(expectedText, quotedContent, 0, false, expectedText, expectedText + quotedContent);
            expectedText += quotedContent;
        } else {
            expectedHtmlContent = makeExpectedHtmlContent(expectedText, quotedContent, 0, true, "", quotedContent);
        // expectedText += quotedContent;
        }
    } else // 3.quoted text
    if (isSignatureBeforeQuotedText) {
        expectedText = expectedPrefix + "<html>message content";
        if (!isDraft && isSignatureUse) {
            expectedText += "\r\n" + "signature";
        }
        expectedText += "</html>";
        expectedText += expectedPostfix;
        expectedMessageLength = expectedText.length();
        String quotedContent = "quoted text";
        if (isDraft || includeQuotedText) {
            expectedHtmlContent = makeExpectedHtmlContent(expectedText, quotedContent, 0, true, expectedText, expectedText + quotedContent);
            expectedText += quotedContent;
        } else {
            expectedHtmlContent = makeExpectedHtmlContent(expectedText, quotedContent, 0, true, "", quotedContent);
        // expectedText += quotedContent;
        }
    } else // 1.message content
    // 2.quoted text
    // 3.signature
    {
        String expectedSignature = "";
        expectedText = expectedPrefix + "<html>message content";
        if (!isDraft && isSignatureUse) {
            if (!includeQuotedText) {
                expectedText += "\r\n" + "signature";
            } else {
                expectedSignature = "<html>\r\nsignature</html>";
            }
        }
        expectedText += "</html>";
        expectedText += expectedPostfix;
        expectedMessageLength = expectedText.length();
        String quotedContent = "quoted text";
        if (isDraft || includeQuotedText) {
            expectedHtmlContent = makeExpectedHtmlContent(expectedText, expectedSignature + quotedContent, expectedSignature.length(), true, expectedText, expectedText + expectedSignature + quotedContent);
            expectedText += expectedSignature + quotedContent;
        } else {
            expectedHtmlContent = makeExpectedHtmlContent(expectedText, quotedContent, 0, true, "", quotedContent);
        // expectedText += quotedContent;
        }
    }
    InsertableHtmlContent insertableHtmlContent = new InsertableHtmlContent();
    String quotedText = "quoted text";
    insertableHtmlContent.setQuotedContent(new StringBuilder(quotedText));
    String messageText = "message content";
    String signatureText = "signature";
    TestingTextBodyBuilder textBodyBuilder = new TestingTextBodyBuilder(includeQuotedText, isDraft, quoteStyle, isReplyAfterQuote, isSignatureBeforeQuotedText, isSignatureUse, messageText, signatureText);
    textBodyBuilder.setQuotedTextHtml(insertableHtmlContent);
    TextBody textBody = textBodyBuilder.buildTextHtml();
    assertThat(textBody, instanceOf(TextBody.class));
    assertThat(textBody.getRawText(), is(expectedText));
    assertThat(textBody.getComposedMessageLength(), is(expectedMessageLength));
    assertThat(textBody.getComposedMessageOffset(), is(expectedMessagePosition));
    assertThat(insertableHtmlContent.toDebugString(), is(expectedHtmlContent));
}
Also used : TextBody(com.fsck.k9.mail.internet.TextBody) InsertableHtmlContent(com.fsck.k9.message.quote.InsertableHtmlContent) Theory(org.junit.experimental.theories.Theory)

Example 4 with InsertableHtmlContent

use of com.fsck.k9.message.quote.InsertableHtmlContent in project k-9 by k9mail.

the class TextBodyBuilder method buildTextHtml.

/**
 * Build the {@link Body} that will contain the text of the message.
 *
 * @return {@link com.fsck.k9.mail.internet.TextBody} instance that contains the entered text and
 *         possibly the quoted original message.
 */
public TextBody buildTextHtml() {
    // The length of the formatted version of the user-supplied text/reply
    int composedMessageLength;
    // The offset of the user-supplied text/reply in the final text body
    int composedMessageOffset = 0;
    // Get the user-supplied text
    String text = mMessageContent;
    // Do we have to modify an existing message to include our reply?
    if (mIncludeQuotedText) {
        InsertableHtmlContent quotedHtmlContent = getQuotedTextHtml();
        if (K9.isDebugLoggingEnabled()) {
            Timber.d("insertable: %s", quotedHtmlContent.toDebugString());
        }
        // Convert the text to HTML
        text = textToHtmlFragment(text);
        // Save length of the body. This is used when thawing drafts.
        composedMessageLength = text.length();
        // Append signature to the reply
        if (mAppendSignature && (mReplyAfterQuote || mSignatureBeforeQuotedText)) {
            text += getSignatureHtml();
        }
        /*
             * Set the insertion location based upon our reply after quote
             * setting. Additionally, add some extra separators between the
             * composed message and quoted message depending on the quote
             * location. We only add the extra separators when we're
             * sending, that way when we load a draft, we don't have to know
             * the length of the separators to remove them before editing.
             */
        if (mReplyAfterQuote) {
            quotedHtmlContent.setInsertionLocation(InsertableHtmlContent.InsertionLocation.AFTER_QUOTE);
            if (mInsertSeparator) {
                final String separator = "<br clear=\"all\">";
                text = separator + text;
                composedMessageOffset = separator.length();
            }
        } else {
            quotedHtmlContent.setInsertionLocation(InsertableHtmlContent.InsertionLocation.BEFORE_QUOTE);
            if (mInsertSeparator) {
                text += "<br><br>";
            }
        }
        // Place signature immediately after the quoted text
        if (mAppendSignature && !(mReplyAfterQuote || mSignatureBeforeQuotedText)) {
            quotedHtmlContent.insertIntoQuotedFooter(getSignatureHtml());
        }
        quotedHtmlContent.setUserContent(text);
        // Save the body's offset. This is used when thawing drafts.
        composedMessageOffset += quotedHtmlContent.getInsertionPoint();
        text = quotedHtmlContent.toString();
    } else {
        // Convert the text to HTML
        text = textToHtmlFragment(text);
        composedMessageLength = text.length();
        composedMessageOffset = HTML_AND_BODY_START.length();
        // There is no text to quote so simply append the signature if available
        if (mAppendSignature) {
            text += getSignatureHtml();
        }
        text = HTML_AND_BODY_START + text + HTML_AND_BODY_END;
    }
    TextBody body = new TextBody(text);
    body.setComposedMessageLength(composedMessageLength);
    body.setComposedMessageOffset(composedMessageOffset);
    return body;
}
Also used : TextBody(com.fsck.k9.mail.internet.TextBody) InsertableHtmlContent(com.fsck.k9.message.quote.InsertableHtmlContent)

Example 5 with InsertableHtmlContent

use of com.fsck.k9.message.quote.InsertableHtmlContent in project k-9 by k9mail.

the class HtmlQuoteCreator method quoteOriginalHtmlMessage.

/**
 * Add quoting markup to a HTML message.
 * @param originalMessage Metadata for message being quoted.
 * @param messageBody Text of the message to be quoted.
 * @param quoteStyle Style of quoting.
 * @return Modified insertable message.
 */
public static InsertableHtmlContent quoteOriginalHtmlMessage(Message originalMessage, String messageBody, QuoteStyle quoteStyle) {
    CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class);
    InsertableHtmlContent insertable = findInsertionPoints(messageBody);
    String sentDate = new QuoteDateFormatter().format(originalMessage.getSentDate());
    String fromAddress = Address.toString(originalMessage.getFrom());
    if (quoteStyle == QuoteStyle.PREFIX) {
        StringBuilder header = new StringBuilder();
        header.append("<div class=\"gmail_quote\">");
        if (sentDate.length() != 0) {
            String replyHeader = resourceProvider.replyHeader(fromAddress, sentDate);
            header.append(HtmlConverter.textToHtmlFragment(replyHeader));
        } else {
            String replyHeader = resourceProvider.replyHeader(fromAddress);
            header.append(HtmlConverter.textToHtmlFragment(replyHeader));
        }
        header.append("<blockquote class=\"gmail_quote\" " + "style=\"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;\">\r\n");
        String footer = "</blockquote></div>";
        insertable.insertIntoQuotedHeader(header.toString());
        insertable.insertIntoQuotedFooter(footer);
    } else if (quoteStyle == QuoteStyle.HEADER) {
        StringBuilder header = new StringBuilder();
        header.append("<div style='font-size:10.0pt;font-family:\"Tahoma\",\"sans-serif\";padding:3.0pt 0in 0in 0in'>\r\n");
        // This gets converted into a horizontal line during html to text conversion.
        header.append("<hr style='border:none;border-top:solid #E1E1E1 1.0pt'>\r\n");
        if (originalMessage.getFrom() != null && fromAddress.length() != 0) {
            header.append("<b>").append(resourceProvider.messageHeaderFrom()).append("</b> ").append(HtmlConverter.textToHtmlFragment(fromAddress)).append("<br>\r\n");
        }
        if (sentDate.length() != 0) {
            header.append("<b>").append(resourceProvider.messageHeaderDate()).append("</b> ").append(sentDate).append("<br>\r\n");
        }
        if (originalMessage.getRecipients(RecipientType.TO) != null && originalMessage.getRecipients(RecipientType.TO).length != 0) {
            header.append("<b>").append(resourceProvider.messageHeaderTo()).append("</b> ").append(HtmlConverter.textToHtmlFragment(Address.toString(originalMessage.getRecipients(RecipientType.TO)))).append("<br>\r\n");
        }
        if (originalMessage.getRecipients(RecipientType.CC) != null && originalMessage.getRecipients(RecipientType.CC).length != 0) {
            header.append("<b>").append(resourceProvider.messageHeaderCc()).append("</b> ").append(HtmlConverter.textToHtmlFragment(Address.toString(originalMessage.getRecipients(RecipientType.CC)))).append("<br>\r\n");
        }
        if (originalMessage.getSubject() != null) {
            header.append("<b>").append(resourceProvider.messageHeaderSubject()).append("</b> ").append(HtmlConverter.textToHtmlFragment(originalMessage.getSubject())).append("<br>\r\n");
        }
        header.append("</div>\r\n");
        header.append("<br>\r\n");
        insertable.insertIntoQuotedHeader(header.toString());
    }
    return insertable;
}
Also used : CoreResourceProvider(com.fsck.k9.CoreResourceProvider)

Aggregations

InsertableHtmlContent (com.fsck.k9.message.quote.InsertableHtmlContent)4 TextBody (com.fsck.k9.mail.internet.TextBody)2 MessageFormat (com.fsck.k9.Account.MessageFormat)1 CoreResourceProvider (com.fsck.k9.CoreResourceProvider)1 Identity (com.fsck.k9.Identity)1 Attachment (com.fsck.k9.activity.misc.Attachment)1 Address (com.fsck.k9.mail.Address)1 MessagingException (com.fsck.k9.mail.MessagingException)1 Part (com.fsck.k9.mail.Part)1 QuotedTextMode (com.fsck.k9.message.QuotedTextMode)1 SimpleMessageFormat (com.fsck.k9.message.SimpleMessageFormat)1 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 Theory (org.junit.experimental.theories.Theory)1