Search in sources :

Example 81 with Body

use of com.fsck.k9.mail.Body in project k-9 by k9mail.

the class MessageViewInfoExtractorTest method testSimpleHtmlMessage.

@Test
public void testSimpleHtmlMessage() throws MessagingException {
    String bodyText = "<strong>K-9 Mail</strong> rocks :&gt;";
    // Create text/plain body
    TextBody body = new TextBody(bodyText);
    // Create message
    MimeMessage message = new MimeMessage();
    message.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/html");
    MimeMessageHelper.setBody(message, body);
    // Extract text
    ArrayList<Viewable> outputViewableParts = new ArrayList<>();
    MessageExtractor.findViewablesAndAttachments(message, outputViewableParts, null);
    assertEquals(outputViewableParts.size(), 1);
    ViewableExtractedText container = messageViewInfoExtractor.extractTextFromViewables(outputViewableParts);
    assertEquals(BODY_TEXT, container.text);
    assertEquals(bodyText, container.html);
}
Also used : TextBody(com.fsck.k9.mail.internet.TextBody) MimeMessage(com.fsck.k9.mail.internet.MimeMessage) Viewable(com.fsck.k9.mail.internet.Viewable) ArrayList(java.util.ArrayList) ViewableExtractedText(com.fsck.k9.mailstore.MessageViewInfoExtractor.ViewableExtractedText) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) K9RobolectricTest(com.fsck.k9.K9RobolectricTest) Test(org.junit.Test)

Example 82 with Body

use of com.fsck.k9.mail.Body in project k-9 by k9mail.

the class MessageCreationHelper method createMessage.

private static Message createMessage(String mimeType, Body body) {
    MimeMessage message = new MimeMessage();
    message.setBody(body);
    message.setHeader(MimeHeader.HEADER_CONTENT_TYPE, mimeType);
    return message;
}
Also used : MimeMessage(com.fsck.k9.mail.internet.MimeMessage)

Example 83 with Body

use of com.fsck.k9.mail.Body in project k-9 by k9mail.

the class MessageCompose method initFromIntent.

/**
 * Handle external intents that trigger the message compose activity.
 *
 * <p>
 * Supported external intents:
 * <ul>
 *   <li>{@link Intent#ACTION_VIEW}</li>
 *   <li>{@link Intent#ACTION_SENDTO}</li>
 *   <li>{@link Intent#ACTION_SEND}</li>
 *   <li>{@link Intent#ACTION_SEND_MULTIPLE}</li>
 * </ul>
 * </p>
 *
 * @param intent
 *         The (external) intent that started the activity.
 *
 * @return {@code true}, if this activity was started by an external intent. {@code false},
 *         otherwise.
 */
private boolean initFromIntent(final Intent intent) {
    boolean startedByExternalIntent = false;
    final String action = intent.getAction();
    if (Intent.ACTION_VIEW.equals(action) || Intent.ACTION_SENDTO.equals(action)) {
        /*
             * Someone has clicked a mailto: link. The address is in the URI.
             */
        if (intent.getData() != null) {
            Uri uri = intent.getData();
            if (MailTo.isMailTo(uri)) {
                MailTo mailTo = MailTo.parse(uri);
                initializeFromMailto(mailTo);
            }
        }
    /*
             * Note: According to the documentation ACTION_VIEW and ACTION_SENDTO don't accept
             * EXTRA_* parameters.
             * And previously we didn't process these EXTRAs. But it looks like nobody bothers to
             * read the official documentation and just copies wrong sample code that happens to
             * work with the AOSP Email application. And because even big players get this wrong,
             * we're now finally giving in and read the EXTRAs for those actions (below).
             */
    }
    if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action) || Intent.ACTION_SENDTO.equals(action) || Intent.ACTION_VIEW.equals(action)) {
        startedByExternalIntent = true;
        /*
             * Note: Here we allow a slight deviation from the documented behavior.
             * EXTRA_TEXT is used as message body (if available) regardless of the MIME
             * type of the intent. In addition one or multiple attachments can be added
             * using EXTRA_STREAM.
             */
        CharSequence text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT);
        // Only use EXTRA_TEXT if the body hasn't already been set by the mailto URI
        if (text != null && messageContentView.getText().length() == 0) {
            messageContentView.setText(CrLfConverter.toLf(text));
        }
        String type = intent.getType();
        if (Intent.ACTION_SEND.equals(action)) {
            Uri stream = intent.getParcelableExtra(Intent.EXTRA_STREAM);
            if (stream != null) {
                attachmentPresenter.addExternalAttachment(stream, type);
            }
        } else {
            List<Parcelable> list = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
            if (list != null) {
                for (Parcelable parcelable : list) {
                    Uri stream = (Uri) parcelable;
                    if (stream != null) {
                        attachmentPresenter.addExternalAttachment(stream, type);
                    }
                }
            }
        }
        String subject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
        // Only use EXTRA_SUBJECT if the subject hasn't already been set by the mailto URI
        if (subject != null && subjectView.getText().length() == 0) {
            subjectView.setText(subject);
        }
        recipientPresenter.initFromSendOrViewIntent(intent);
    }
    if (ACTION_AUTOCRYPT_PEER.equals(action)) {
        String trustId = intent.getStringExtra(OpenPgpApi.EXTRA_AUTOCRYPT_PEER_ID);
        if (trustId != null) {
            recipientPresenter.initFromTrustIdAction(trustId);
            startedByExternalIntent = true;
        }
    }
    return startedByExternalIntent;
}
Also used : Parcelable(android.os.Parcelable) Uri(android.net.Uri) MailTo(com.fsck.k9.helper.MailTo)

Example 84 with Body

use of com.fsck.k9.mail.Body in project k-9 by k9mail.

the class MessageCompose method onCreate.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (UpgradeDatabases.actionUpgradeDatabases(this, getIntent())) {
        finish();
        return;
    }
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    setLayout(R.layout.message_compose);
    ViewStub contentContainer = findViewById(R.id.message_compose_content);
    sizeFormatter = new SizeFormatter(getResources());
    ThemeManager themeManager = getThemeManager();
    int messageComposeThemeResourceId = themeManager.getMessageComposeThemeResourceId();
    ContextThemeWrapper themeContext = new ContextThemeWrapper(this, messageComposeThemeResourceId);
    LayoutInflater themedLayoutInflater = LayoutInflater.from(themeContext);
    contentContainer.setLayoutInflater(themedLayoutInflater);
    View contentView = contentContainer.inflate();
    // background color needs to be forced
    // TODO: Change themes to use appropriate background colors that don't need overriding.
    TypedValue outValue = new TypedValue();
    themeContext.getTheme().resolveAttribute(R.attr.messageViewBackgroundColor, outValue, true);
    contentView.setBackgroundColor(outValue.data);
    initializeActionBar();
    // on api level 15, setContentView() shows the progress bar for some reason...
    setProgressBarIndeterminateVisibility(false);
    final Intent intent = getIntent();
    String messageReferenceString = intent.getStringExtra(EXTRA_MESSAGE_REFERENCE);
    relatedMessageReference = MessageReference.parse(messageReferenceString);
    final String accountUuid = (relatedMessageReference != null) ? relatedMessageReference.getAccountUuid() : intent.getStringExtra(EXTRA_ACCOUNT);
    if (accountUuid != null) {
        account = preferences.getAccount(accountUuid);
    }
    if (account == null) {
        account = preferences.getDefaultAccount();
    }
    if (account == null) {
        /*
             * There are no accounts set up. This should not have happened. Prompt the
             * user to set up an account as an acceptable bailout.
             */
        MessageList.launch(this);
        changesMadeSinceLastSave = false;
        finish();
        return;
    }
    contacts = Contacts.getInstance(MessageCompose.this);
    chooseIdentityButton = findViewById(R.id.identity);
    chooseIdentityButton.setOnClickListener(this);
    ReplyToView replyToView = new ReplyToView(this);
    replyToPresenter = new ReplyToPresenter(replyToView);
    RecipientMvpView recipientMvpView = new RecipientMvpView(this);
    ComposePgpInlineDecider composePgpInlineDecider = new ComposePgpInlineDecider();
    ComposePgpEnableByDefaultDecider composePgpEnableByDefaultDecider = new ComposePgpEnableByDefaultDecider();
    OpenPgpApiManager openPgpApiManager = new OpenPgpApiManager(getApplicationContext(), this);
    recipientPresenter = new RecipientPresenter(getApplicationContext(), getSupportLoaderManager(), openPgpApiManager, recipientMvpView, account, composePgpInlineDecider, composePgpEnableByDefaultDecider, AutocryptStatusInteractor.getInstance(), new ReplyToParser(), DI.get(AutocryptDraftStateHeaderParser.class));
    recipientPresenter.asyncUpdateCryptoStatus();
    subjectView = findViewById(R.id.subject);
    subjectView.getInputExtras(true).putBoolean("allowEmoji", true);
    EditText upperSignature = findViewById(R.id.upper_signature);
    EditText lowerSignature = findViewById(R.id.lower_signature);
    QuotedMessageMvpView quotedMessageMvpView = new QuotedMessageMvpView(this);
    quotedMessagePresenter = new QuotedMessagePresenter(this, quotedMessageMvpView, account);
    attachmentPresenter = new AttachmentPresenter(getApplicationContext(), attachmentMvpView, getSupportLoaderManager(), this);
    messageContentView = findViewById(R.id.message_content);
    messageContentView.getInputExtras(true).putBoolean("allowEmoji", true);
    attachmentsView = findViewById(R.id.attachments);
    TextWatcher draftNeedsChangingTextWatcher = new SimpleTextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            changesMadeSinceLastSave = true;
        }
    };
    TextWatcher signTextWatcher = new SimpleTextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            changesMadeSinceLastSave = true;
            signatureChanged = true;
        }
    };
    replyToView.addTextChangedListener(draftNeedsChangingTextWatcher);
    recipientMvpView.addTextChangedListener(draftNeedsChangingTextWatcher);
    quotedMessageMvpView.addTextChangedListener(draftNeedsChangingTextWatcher);
    subjectView.addTextChangedListener(draftNeedsChangingTextWatcher);
    messageContentView.addTextChangedListener(draftNeedsChangingTextWatcher);
    /*
         * We set this to invisible by default. Other methods will turn it back on if it's
         * needed.
         */
    quotedMessagePresenter.showOrHideQuotedText(QuotedTextMode.NONE);
    subjectView.setOnFocusChangeListener(this);
    messageContentView.setOnFocusChangeListener(this);
    if (savedInstanceState != null) {
        /*
             * This data gets used in onCreate, so grab it here instead of onRestoreInstanceState
             */
        relatedMessageProcessed = savedInstanceState.getBoolean(STATE_KEY_SOURCE_MESSAGE_PROCED, false);
    }
    if (initFromIntent(intent)) {
        action = Action.COMPOSE;
        changesMadeSinceLastSave = true;
    } else {
        String action = intent.getAction();
        if (ACTION_COMPOSE.equals(action)) {
            this.action = Action.COMPOSE;
        } else if (ACTION_REPLY.equals(action)) {
            this.action = Action.REPLY;
        } else if (ACTION_REPLY_ALL.equals(action)) {
            this.action = Action.REPLY_ALL;
        } else if (ACTION_FORWARD.equals(action)) {
            this.action = Action.FORWARD;
        } else if (ACTION_FORWARD_AS_ATTACHMENT.equals(action)) {
            this.action = Action.FORWARD_AS_ATTACHMENT;
        } else if (ACTION_EDIT_DRAFT.equals(action)) {
            this.action = Action.EDIT_DRAFT;
        } else {
            // This shouldn't happen
            Timber.w("MessageCompose was started with an unsupported action");
            this.action = Action.COMPOSE;
        }
    }
    if (identity == null) {
        identity = account.getIdentity(0);
    }
    if (account.isSignatureBeforeQuotedText()) {
        signatureView = upperSignature;
        lowerSignature.setVisibility(View.GONE);
    } else {
        signatureView = lowerSignature;
        upperSignature.setVisibility(View.GONE);
    }
    updateSignature();
    signatureView.addTextChangedListener(signTextWatcher);
    if (!identity.getSignatureUse()) {
        signatureView.setVisibility(View.GONE);
    }
    requestReadReceipt = account.isMessageReadReceipt();
    updateFrom();
    replyToPresenter.setIdentity(identity);
    if (!relatedMessageProcessed) {
        if (action == Action.REPLY || action == Action.REPLY_ALL || action == Action.FORWARD || action == Action.FORWARD_AS_ATTACHMENT || action == Action.EDIT_DRAFT) {
            messageLoaderHelper = messageLoaderHelperFactory.createForMessageCompose(this, getSupportLoaderManager(), getSupportFragmentManager(), messageLoaderCallbacks);
            internalMessageHandler.sendEmptyMessage(MSG_PROGRESS_ON);
            if (action == Action.FORWARD_AS_ATTACHMENT) {
                messageLoaderHelper.asyncStartOrResumeLoadingMessageMetadata(relatedMessageReference);
            } else {
                Parcelable cachedDecryptionResult = intent.getParcelableExtra(EXTRA_MESSAGE_DECRYPTION_RESULT);
                messageLoaderHelper.asyncStartOrResumeLoadingMessage(relatedMessageReference, cachedDecryptionResult);
            }
        }
    }
    if (action == Action.REPLY || action == Action.REPLY_ALL) {
        relatedFlag = Flag.ANSWERED;
    } else if (action == Action.FORWARD || action == Action.FORWARD_AS_ATTACHMENT) {
        relatedFlag = Flag.FORWARDED;
    }
    if (action == Action.REPLY || action == Action.REPLY_ALL || action == Action.EDIT_DRAFT) {
        // change focus to message body.
        messageContentView.requestFocus();
    } else {
        // Explicitly set focus to "To:" input field (see issue 2998)
        recipientMvpView.requestFocusOnToField();
    }
    updateMessageFormat();
    // Set font size of input controls
    int fontSize = K9.getFontSizes().getMessageComposeInput();
    replyToView.setFontSizes(K9.getFontSizes(), fontSize);
    recipientMvpView.setFontSizes(K9.getFontSizes(), fontSize);
    quotedMessageMvpView.setFontSizes(K9.getFontSizes(), fontSize);
    K9.getFontSizes().setViewTextSize(subjectView, fontSize);
    K9.getFontSizes().setViewTextSize(messageContentView, fontSize);
    K9.getFontSizes().setViewTextSize(signatureView, fontSize);
    updateMessageFormat();
    setTitle();
    currentMessageBuilder = (MessageBuilder) getLastCustomNonConfigurationInstance();
    if (currentMessageBuilder != null) {
        setProgressBarIndeterminateVisibility(true);
        currentMessageBuilder.reattachCallback(this);
    }
    if (savedInstanceState == null) {
        checkAndRequestPermissions();
    }
}
Also used : ComposePgpInlineDecider(com.fsck.k9.message.ComposePgpInlineDecider) SizeFormatter(com.fsck.k9.ui.helper.SizeFormatter) ReplyToParser(com.fsck.k9.helper.ReplyToParser) RecipientMvpView(com.fsck.k9.activity.compose.RecipientMvpView) TextWatcher(android.text.TextWatcher) SimpleTextWatcher(com.fsck.k9.helper.SimpleTextWatcher) AttachmentPresenter(com.fsck.k9.activity.compose.AttachmentPresenter) ComposePgpEnableByDefaultDecider(com.fsck.k9.message.ComposePgpEnableByDefaultDecider) TypedValue(android.util.TypedValue) EditText(android.widget.EditText) RecipientPresenter(com.fsck.k9.activity.compose.RecipientPresenter) OpenPgpApiManager(org.openintents.openpgp.OpenPgpApiManager) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) Parcelable(android.os.Parcelable) ThemeManager(com.fsck.k9.ui.base.ThemeManager) QuotedMessageMvpView(com.fsck.k9.ui.compose.QuotedMessageMvpView) ImageView(android.widget.ImageView) RecipientMvpView(com.fsck.k9.activity.compose.RecipientMvpView) View(android.view.View) QuotedMessageMvpView(com.fsck.k9.ui.compose.QuotedMessageMvpView) TextView(android.widget.TextView) ReplyToView(com.fsck.k9.activity.compose.ReplyToView) AttachmentMvpView(com.fsck.k9.activity.compose.AttachmentPresenter.AttachmentMvpView) SuppressLint(android.annotation.SuppressLint) ViewStub(android.view.ViewStub) ReplyToView(com.fsck.k9.activity.compose.ReplyToView) ReplyToPresenter(com.fsck.k9.activity.compose.ReplyToPresenter) QuotedMessagePresenter(com.fsck.k9.ui.compose.QuotedMessagePresenter) SimpleTextWatcher(com.fsck.k9.helper.SimpleTextWatcher) ContextThemeWrapper(android.view.ContextThemeWrapper) LayoutInflater(android.view.LayoutInflater)

Example 85 with Body

use of com.fsck.k9.mail.Body in project k-9 by k9mail.

the class AttachmentInfoExtractorTest method extractInfo__withDeferredFileBody.

@Test
public void extractInfo__withDeferredFileBody() throws Exception {
    attachmentInfoExtractor = new AttachmentInfoExtractor(context) {

        @Nullable
        @Override
        protected Uri getDecryptedFileProviderUri(DeferredFileBody decryptedTempFileBody, String mimeType) {
            return TEST_URI;
        }
    };
    DeferredFileBody body = mock(DeferredFileBody.class);
    when(body.getSize()).thenReturn(TEST_SIZE);
    MimeBodyPart part = new MimeBodyPart();
    part.setBody(body);
    part.setHeader(MimeHeader.HEADER_CONTENT_TYPE, TEST_MIME_TYPE);
    AttachmentViewInfo attachmentViewInfo = attachmentInfoExtractor.extractAttachmentInfo(part);
    assertEquals(TEST_URI, attachmentViewInfo.internalUri);
    assertEquals(TEST_SIZE, attachmentViewInfo.size);
    assertEquals(TEST_MIME_TYPE, attachmentViewInfo.mimeType);
    assertFalse(attachmentViewInfo.inlineAttachment);
    assertTrue(attachmentViewInfo.isContentAvailable());
}
Also used : MimeBodyPart(com.fsck.k9.mail.internet.MimeBodyPart) Uri(android.net.Uri) Nullable(androidx.annotation.Nullable) DeferredFileBody(com.fsck.k9.mailstore.DeferredFileBody) AttachmentViewInfo(com.fsck.k9.mailstore.AttachmentViewInfo) RobolectricTest(com.fsck.k9.RobolectricTest) Test(org.junit.Test)

Aggregations

Body (com.fsck.k9.mail.Body)44 BodyPart (com.fsck.k9.mail.BodyPart)35 Multipart (com.fsck.k9.mail.Multipart)32 MimeBodyPart (com.fsck.k9.mail.internet.MimeBodyPart)32 Part (com.fsck.k9.mail.Part)29 Test (org.junit.Test)29 TextBody (com.fsck.k9.mail.internet.TextBody)23 MimeMessage (com.fsck.k9.mail.internet.MimeMessage)21 MimeMultipart (com.fsck.k9.mail.internet.MimeMultipart)19 ArrayList (java.util.ArrayList)16 MessagingException (com.fsck.k9.mail.MessagingException)14 BinaryTempFileBody (com.fsck.k9.mail.internet.BinaryTempFileBody)10 ByteArrayOutputStream (java.io.ByteArrayOutputStream)10 Message (com.fsck.k9.mail.Message)9 OutputStream (java.io.OutputStream)9 Stack (java.util.Stack)9 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)9 K9RobolectricTest (com.fsck.k9.K9RobolectricTest)7 BinaryMemoryBody (com.fsck.k9.mailstore.BinaryMemoryBody)7 InputStream (java.io.InputStream)7