发送email

来源:互联网 发布:python json encode 编辑:程序博客网 时间:2024/05/17 23:34

sendOrSaveMessage:调用updateMessage方法更新displayname

sendMessage and save:发送邮件同时保存邮件时调用message.save()方法;

sendPendingMessagesSynchronous:更新mailboxId将邮件从发件箱移到已发送邮件

代码详细分析:

MessageCompose.java

当用户编辑完成后点击发送按钮,则触发MessageCompose.javaonsend()方法:

    privatevoid onSend() {

        if (!isAddressAllValid()) {

            Toast.makeText(this, getString(R.string.message_compose_error_invalid_email),

                           Toast.LENGTH_LONG).show();

        } elseif (getAddresses(mToView).length == 0 &&

                getAddresses(mCcView).length == 0 &&

                getAddresses(mBccView).length == 0) {

            mToView.setError(getString(R.string.message_compose_error_no_recipients));

            Toast.makeText(this, getString(R.string.message_compose_error_no_recipients),

                    Toast.LENGTH_LONG).show();

        } else {

            sendOrSaveMessage(true);

            setDraftNeedsSaving(false);

            finish();

        }

    }

首先对收件人地址的合法性进行判断,不合法则弹出toast消息提示用户。接着调用sendOrSaveMessage()进行发送,发送完毕后执行setDraftNeedsSaving(false)表示不用保存草稿(因为发送过程中会将邮件保存在发件箱或者已发送),然后finishActivity

sendOrSaveMessage()中先对mMessageLoaded进行判断,该值用于判断回复或者转发邮件时上一封邮件是否加载完毕,没有加载完毕是不会发送的。然后将当前邮件保存在数据库。然后调用Controller.java进行发送。

Controller.java

sendMessage()完成发送前的准备工作,将邮件移至发件箱(Outbox),这里是exchange的邮件发送过程与pop/imap的分岔点。

    publicvoidsendMessage(long messageId,long accountId) {

        ContentResolver resolver = mProviderContext.getContentResolver();

        if (accountId == -1) {

            accountId = lookupAccountForMessage(messageId);

        }

        if (accountId == -1) {

            // probably the message was not found

            if (Email.LOGD) {

                Email.log("no account found for message " + messageId);

            }

            return;

        }

 

        // Move toOutbox

        long outboxId = findOrCreateMailboxOfType(accountId, Mailbox.TYPE_OUTBOX);

        ContentValues cv = new ContentValues();

        cv.put(EmailContent.MessageColumns.MAILBOX_KEY, outboxId);

 

        // does this need to be SYNCED_CONTENT_URI instead?

        Uri uri = ContentUris.withAppendedId(EmailContent.Message.CONTENT_URI, messageId);

        resolver.update(uri, cv, null,null);

 

        // Split here for target type (Service or MessagingController)

        IEmailService service = getServiceForMessage(messageId);

        if (service !=null) {

            // We just need to be sure thecallback is installed, if this is the first call

            // to the service.

            try {

                service.setCallback(mServiceCallback);

            } catch (RemoteException re) {

                // OK - not a criticalcallback here

            }

        } else {

            // for IMAP & POP only, (attempt to) send the message now

            final EmailContent.Account account =

                    EmailContent.Account.restoreAccountWithId(mProviderContext, accountId);

            if (account ==null) {

                return;

            }

            finallong sentboxId = findOrCreateMailboxOfType(accountId, Mailbox.TYPE_SENT);

            /*DTS2012042101715yangjinri 20120417 begin */

            finallong msgId = messageId;

            new Thread() {

                @Override

                publicvoid run() {

                    boolean sendCurrentMessageOnly = (1 == Settings.Systemex.getInt(mContext.getContentResolver(),

                                        "send_current_message_only", 0));

                    if (sendCurrentMessageOnly) {

                        mLegacyController.sendCurrentMessage(account, sentboxId,mLegacyListener, msgId);

                    } else {

                        mLegacyController.sendPendingMessages(account, sentboxId,mLegacyListener);

                    }

            /*DTS2012042101715yangjinri 20120417 end */

                }

            }.start();

        }

    }

MessagingController.java

sendPendingMessages()方法将发件箱中的每封邮件都发送出去,并且开启一个线程来尝试完成。

    publicvoid sendPendingMessages(final EmailContent.Account account, finallong sentFolderId,

            MessagingListener listener) {

        put("sendPendingMessages", listener,new Runnable() {

            publicvoid run() {

                sendPendingMessagesSynchronous(account, sentFolderId);

            }

        });

    }

线程中的实现方法如下:

1.outbox中循环查找需要发送的邮件

2.如果需要发送的邮件数量为0,则return

3.创建sender对象(通用的sender entries存放在senders.xml)和store对象()和store对象(通用的store entries存放在stores.xml)。

4.循环发送邮件,若一封发送失败,会continue发送下一封

5.发送成功,会将邮件转移至已发送,或者删除

publicvoidsendPendingMessagesSynchronous(final EmailContent.Account account,

            long sentFolderId) {

        // 1.  Loop through all messages in the account's outbox

        long outboxId = Mailbox.findMailboxOfType(mContext, account.mId, Mailbox.TYPE_OUTBOX);

        if (outboxId == Mailbox.NO_MAILBOX) {

            return;

        }

        ContentResolver resolver = mContext.getContentResolver();

        Cursor c = resolver.query(EmailContent.Message.CONTENT_URI,

                EmailContent.Message.ID_COLUMN_PROJECTION,

                EmailContent.Message.MAILBOX_KEY +"=?",new String[] { Long.toString(outboxId) },

                null);

        try {

            // 2. exit early

            if (c.getCount() <= 0) {

                return;

            }

            // 3. do one-time setup of the Sender & other stuff

            mListeners.sendPendingMessagesStarted(account.mId, -1);

 

            Sender sender = Sender.getInstance(mContext, account.getSenderUri(mContext));

            Store remoteStore = Store.getInstance(account.getStoreUri(mContext),mContext,null);

            boolean requireMoveMessageToSentFolder = remoteStore.requireCopyMessageToSentFolder();

            ContentValues moveToSentValues = null;

            if (requireMoveMessageToSentFolder) {

                moveToSentValues = new ContentValues();

                moveToSentValues.put(MessageColumns.MAILBOX_KEY, sentFolderId);

            }

 

            // 4. loop through the available messages and send them

            /* DTS2012042101715 yangjinri 20120417 begin*/

            boolean sendCurrentMessageOnly = (1 == Settings.Systemex.getInt(mContext.getContentResolver(),

                                        "send_current_message_only", 0));

            while (c.moveToNext()) {

                long messageId = -1;

                try {

                    messageId = c.getLong(0);

                    if (sendCurrentMessageOnly) {

                        if (messageId ==mMessageId) {

                            mListeners.sendPendingMessagesStarted(account.mId, messageId);

                            sender.sendMessage(messageId);

                        } else {

                            continue;

                        }

                    } else {

                        mListeners.sendPendingMessagesStarted(account.mId, messageId);

                        sender.sendMessage(messageId);

                    }                

            /* DTS2012042101715 yangjinri 20120417 end*/

                } catch (MessagingException me) {

                    // report error for this message, but keep trying others

                    mListeners.sendPendingMessagesFailed(account.mId, messageId, me);

                    continue;

                }

                // 5. move to sent, or delete

                Uri syncedUri =

                    ContentUris.withAppendedId(EmailContent.Message.SYNCED_CONTENT_URI, messageId);

                if (requireMoveMessageToSentFolder) {

                    resolver.update(syncedUri, moveToSentValues,null,null);

                } else {

                    AttachmentProvider.deleteAllAttachmentFiles(mContext, account.mId, messageId);

                    Uri uri =

                        ContentUris.withAppendedId(EmailContent.Message.CONTENT_URI, messageId);

                    resolver.delete(uri, null, null);

                    resolver.delete(syncedUri,null,null);

                }

            }

            // 6. report completion/success

            mListeners.sendPendingMessagesCompleted(account.mId);

 

        } catch (MessagingException me) {

            mListeners.sendPendingMessagesFailed(account.mId, -1, me);

        } finally {

            c.close();

        }

    }

SmtpSender.java

SmtpSender类继承于Sender类,实现了其sendMessage()抽象方法:

然后通过MAIL TORCPT TODATA等命令与服务器进行交互。然后将邮件用Rfc822Output.writeTo()将邮件打包成标准格式后上传给服务器。executeSimpleCommand("\r\n.")表示这次发送结束。

@Override

    publicvoidsendMessage(long messageId)throws MessagingException {

        close();

        open();

 

        Message message = Message.restoreMessageWithId(mContext, messageId);

        if (message ==null) {

            thrownew MessagingException("Trying to send non-existent message id="

                    + Long.toString(messageId));

        }

        Address from = Address.unpackFirst(message.mFrom);

        Address[] to = Address.unpack(message.mTo);

        Address[] cc = Address.unpack(message.mCc);

        Address[] bcc = Address.unpack(message.mBcc);

 

        try {

            executeSimpleCommand("MAIL FROM: " +"<" + from.getAddress() +">");

            for (Address address : to) {

                executeSimpleCommand("RCPT TO: " +"<" + address.getAddress() +">");

            }

            for (Address address : cc) {

                executeSimpleCommand("RCPT TO: " +"<" + address.getAddress() +">");

            }

            for (Address address : bcc) {

                executeSimpleCommand("RCPT TO: " +"<" + address.getAddress() +">");

            }

            executeSimpleCommand("DATA");

            // TODO byte stuffing

            Rfc822Output.writeTo(mContext, messageId,

                    new EOLConvertingOutputStream(mTransport.getOutputStream()),true,false);

            executeSimpleCommand("\r\n.");

        } catch (IOException ioe) {

            thrownew MessagingException("Unable to send message", ioe);

        }

    }

 

0 0
原创粉丝点击