k9mail源码分析.docx_第1页
k9mail源码分析.docx_第2页
k9mail源码分析.docx_第3页
k9mail源码分析.docx_第4页
k9mail源码分析.docx_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

private void finishAutoSetup() String email = mEmailView.getText().toString(); String password = mPasswordView.getText().toString(); String emailParts = splitEmail(email); String user = emailParts0; String domain = emailParts1; URI incomingUri = null; URI outgoingUri = null; try String userEnc = URLEncoder.encode(user, UTF-8); String passwordEnc = URLEncoder.encode(password, UTF-8); String incomingUsername = mProvider.incomingUsernameTemplate; incomingUsername = incomingUsername.replaceAll($email, email); incomingUsername = incomingUsername.replaceAll($user, userEnc); incomingUsername = incomingUsername.replaceAll($domain, domain); URI incomingUriTemplate = mProvider.incomingUriTemplate; incomingUri = new URI(incomingUriTemplate.getScheme(), incomingUsername + : + passwordEnc, incomingUriTemplate.getHost(), incomingUriTemplate.getPort(), null, null, null); String outgoingUsername = mProvider.outgoingUsernameTemplate; URI outgoingUriTemplate = mProvider.outgoingUriTemplate; if (outgoingUsername != null) outgoingUsername = outgoingUsername.replaceAll($email, email); outgoingUsername = outgoingUsername.replaceAll($user, userEnc); outgoingUsername = outgoingUsername.replaceAll($domain, domain); outgoingUri = new URI(outgoingUriTemplate.getScheme(), outgoingUsername + : + passwordEnc, outgoingUriTemplate.getHost(), outgoingUriTemplate.getPort(), null, null, null); else outgoingUri = new URI(outgoingUriTemplate.getScheme(), null, outgoingUriTemplate.getHost(), outgoingUriTemplate.getPort(), null, null, null); if (mAccount = null) mAccount = Preferences.getPreferences(this).newAccount(); mAccount.setName(getOwnerName(); mAccount.setEmail(email); mAccount.setStoreUri(incomingUri.toString(); mAccount.setTransportUri(outgoingUri.toString(); mAccount.setDraftsFolderName(getString(R.string.special_mailbox_name_drafts); mAccount.setTrashFolderName(getString(R.string.special_mailbox_name_trash); mAccount.setArchiveFolderName(getString(R.string.special_mailbox_name_archive); / Yahoo! has a special folder for Spam, called Bulk Mail. if (incomingUriTemplate.getHost().toLowerCase().endsWith(.) mAccount.setSpamFolderName(Bulk Mail); else mAccount.setSpamFolderName(getString(R.string.special_mailbox_name_spam); mAccount.setSentFolderName(getString(R.string.special_mailbox_name_sent); if (incomingUri.toString().startsWith(imap) mAccount.setDeletePolicy(Account.DELETE_POLICY_ON_DELETE); else if (incomingUri.toString().startsWith(pop3) mAccount.setDeletePolicy(Account.DELETE_POLICY_NEVER); / Check incoming here. Then check outgoing in onActivityResult() AccountSetupCheckSettings.actionCheckSettings(this, mAccount, CheckDirection.INCOMING); catch (UnsupportedEncodingException enc) / This really shouldnt happen since the encoding is hardcoded to UTF-8 Log.e(K9.LOG_TAG, Couldnt urlencode username or password., enc); catch (URISyntaxException use) /* * If there is some problem with the URI we give up and go on to * manual setup. */ onManualSetup(); MIME邮件的构成MIME消息(邮件,对应 k9mail 的 MimeMessage 类),由消息头 (对应 k9mai的 MimeHeader 类)和消息体(body对应k9mail的Body 接口)两大部分组成。邮件头中不允许出现空行。邮件头包含了发件人、收件人、主题、时间、MIME 版本、邮件内容的类型等重要信息。每条信息称为一个域,由域名后加“: ”和信息的内容构成,可以是一行,较长的也可以占用多行。域的首行必须“顶头”写,即左边不能有空白字符(空格和制表符);续行则必须以空白字符打头,且第一个空白字符不是信息本身固有的,解码时要过滤掉。邮件头信息中各个字段及其含义的说明如下表:邮件体(body)指的是邮件的内容,它的类型由邮件头的“Content-Type”域指出,常见的简单类型有 text/plain(纯文本)和 text/html(超文本)。multipart 类型是 MIME 邮件的精髓,对应 k9mail 的 MultiPart 类。邮件体被分为多个段或者多个部分,对应 k9mail 的 Part 接口,每个段又包含段头和段体两部分,这两部分之间也以空行分隔。常见的 multipart 类 型 有 三 种 : multipart/mixed, multipart/related 和multipart/alternative。从它们的名称,不难推知这些类型各自的含义和用处。它们之间的层次关系如下图所示,从中可以看出,如果在邮件中要添加附件,必须定义 multipart/mixed 段;如果存在内嵌资源,至少要定义 multipart/related 段;如果纯文本与超文本共存,至少要定义 multipart/alternative 段。 为什么说是“至少”?举个例子说,如果只有纯文本与超文本正文,那么在邮件头中将类型扩大化,定义为 multipart/related,甚至 multipart/mixed,都是允许的。k-9-4.804srccomfsckk9mail地址:address.java地址和通讯录名字之间的转换身份认证:Authentication.java函数作用:计算对CRAM-MD5认证机制的响应,给用户提供认证信息和服务器提供随机数。package com.fsck.k9.mail;import java.security.MessageDigest;import com.fsck.k9.mail.filter.Base64;import com.fsck.k9.mail.filter.Hex;public class Authentication private static final String US_ASCII = US-ASCII; /* * Computes the response for CRAM-MD5 authentication mechanism given the user credentials and * the server-provided nonce. * * param username The username. * param password The password. * param b64Nonce The nonce as base64-encoded string. * return The CRAM-MD5 response. * * throws AuthenticationFailedException If something went wrong. * * see Authentication#computeCramMd5Bytes(String, String, byte) */ public static String computeCramMd5(String username, String password, String b64Nonce) throws AuthenticationFailedException try byte b64NonceBytes = b64Nonce.getBytes(US_ASCII); byte b64CRAM = computeCramMd5Bytes(username, password, b64NonceBytes); return new String(b64CRAM, US_ASCII); catch (AuthenticationFailedException e) throw e; catch (Exception e) throw new AuthenticationFailedException(This shouldnt happen, e); /* * Computes the response for CRAM-MD5 authentication mechanism given the user credentials and * the server-provided nonce. * * param username The username. * param password The password. * param b64Nonce The nonce as base64-encoded byte array. * return The CRAM-MD5 response as byte array. * * throws AuthenticationFailedException If something went wrong. * * see RFC 2195 */ public static byte computeCramMd5Bytes(String username, String password, byte b64Nonce) throws AuthenticationFailedException try byte nonce = Base64.decodeBase64(b64Nonce); byte secretBytes = password.getBytes(US_ASCII); MessageDigest md = MessageDigest.getInstance(MD5); if (secretBytes.length 64) secretBytes = md.digest(secretBytes); byte ipad = new byte64; byte opad = new byte64; System.arraycopy(secretBytes, 0, ipad, 0, secretBytes.length); System.arraycopy(secretBytes, 0, opad, 0, secretBytes.length); for (int i = 0; i ipad.length; i+) ipadi = 0x36; for (int i = 0; i opad.length; i+) opadi = 0x5c; md.update(ipad); byte firstPass = md.digest(nonce); md.update(opad); byte result = md.digest(firstPass); String plainCRAM = username + + new String(Hex.encodeHex(result); byte b64CRAM = Base64.encodeBase64(plainCRAM.getBytes(US_ASCII); return b64CRAM; catch (Exception e) throw new AuthenticationFailedException(Something went wrong during CRAM-MD5 computation, e); .fsck.k9.mail.transport;SmtpTransport.javaWebDavTransport.javak-9-4.804srccomfsckk9mailtransportimapImapSettings.javacom.fsck.k9:Account.java这是个实体类,也是 android 平台上 MVC 模式中的 Model 类,它除了封装Email 账户的信息外,还被设计用于保存账户的各种设置,包括账户身份认证设置 Identity、字体设置 FontSizes、通知设置 NotificationSetting 和邮件收发地址、草稿箱、垃圾箱、总是密送到的账户、反垃圾用的文件夹、各种网络(3g、WiFi等 ) 连 接 下 是 否 启 用 压 缩 等 , 这些数据使用android平台的SharedPreferences 保存,SharedPreferences 是平台下除了SQLite 外另外一种方便好用的数据持久化方式,应该是 android 平台上最简单的读写外部数据的方法,特别适用于保存客户端不同用户的个性化设置信息。一个账户用一个 UUID 定义,可以通过 mUuid 属性的值来区分两个账户。Accou 类实现了接口 BaseAccount,这个接口定义了获取、设置 Email 账户的及其描述的 String 类型的数据,还定义了获取账户 UUID 值的方法。通过 Account 可以获得账户对应的 LocalStore 实例,然后可以进一步获得该账户在 SQLite 数据库里面保存的一切信息,包括邮件文件夹、邮件等,还可以获得远程邮件服务器的代理( RemoteStore ,包括 ImapStore 、 Pop3Store 和WebDavStore,这些组件封装了对远程服务器的访问) ,并进一步获得其内部类(例如 ImapStore 的内部类 ImapFolder),实现对远程服务器上相应对象的操作。Account 的类型怎么区分的?通过 Account 类的属性 mStoreUri, 不同类型的 Account 的 mStoreUri 的值以不同的前缀开头,k9mail 分别使用 pop3、imap 和 webdav 表示相应的三种 Email 账户类型,该属性的值的形式如下:imap:/PLAIN:帐号:密码:143/1%7C这些数据变化后,k9mail会调用Account 类的save方法通过SharedPreferences.Editor 把这些数据保存到 xml 配置文件中。该类存储了一个账号的所有信息。Account stores all of the settings for a single account defined by the user. It is able to save and delete itself given a Preferences to work with. Each account is defined by a UUID.(1)Account的默认信息:收发件箱、删除策略、网络类型、消息类型、键值、颜色、排序类、数据库ID等等(2)protected Account(Context context) 设置账户的基本信息:(3)private int pickColor(Context context)* Pick a nice Android guidelines color if we havent used them all yet.(4)protected Account(Preferences preferences, String uuid) this.mUuid = uuid; loadAccount(preferences); (5)private synchronized void loadAccount(Preferences preferences)* Load stored settings for this account.(6)protected synchronized void delete(Preferences preferences)删除一个账户(7)public static int findNewAccountNumber(List accountNumbers) 为新账户建立一个AccountNumber(8)public static List getExistingAccountNumbers(Preferences preferences)获得存在的所有帐户的Account Number列表(9)public static int generateAccountNumber(Preferences preferences) 生成一个AccountNumber(10)public void move(Preferences preferences, boolean moveUp) 移动账户的位置,上移或下移一位(11)public synchronized void save(Preferences preferences)保存账户的配置信息。当账户被创建时,我们会为其分配一个唯一的Account Number(12)public void resetVisibleLimits()重置可以显示的账户的个数(13)public AccountStats getStats(Context context) throws MessagingException 获得帐户状态(14)颜色相关的函数public synchronized void setChipColor(int color) public synchronized void cacheChips() public ColorChip getCheckmarkChip() return mCheckmarkChip; public synchronized int getChipColor() return mChipColor; public ColorChip generateColorChip(boolean messageRead, boolean toMe, boolean ccMe, boolean fromMe, boolean messageFlagged) public ColorChip generateColorChip() return new ColorChip(mChipColor, false, ColorChip.CIRCULAR); (15)public String getUuid() return mUuid; 获得当前账户的Uuid(16)public Uri getContentUri() return Uri.parse(content:/accounts/ + getUuid(); 获得当前账户的ContentUri(16)public synchronized String getStoreUri() return mStoreUri; 获得当前账户的StoreUri(17)public synchronized void setStoreUri(String storeUri) this.mStoreUri = storeUri;设置当前账户的StoreUri(18)public synchronized String getTransportUri() return mTransportUri; 获得当前账户的TransportUri(19)public synchronized void setTransportUri(String transportUri) this.mTransportUri = transportUri; 设置当前账户的TransportUri Override(20)public synchronized String getDescription() return mDescription; Override(21)public synchronized void setDescription(String description) this.mDescription = description; (22)public synchronized String getName() return identities.get(0).getName(); (22)public synchronized void setName(String name) identities.get(0).setName(name); (23)public synchronized boolean getSignatureUse() return identities.get(0).getSignatureUse(); (24)public synchronized void setSignatureUse(boolean signatureUse) identities.get(0).setSignatureUse(signatureUse); (25)public synchronized String getSignature() return identities.get(0).getSignature(); (26)public synchronized void setSignature(String signature) identities.get(0).setSignature(signature); (27)public synchronized String getEmail() return identities.get(0).getEmail(); (28)public synchronized void setEmail(String email) identities.get(0).setEmail(email); (29)public synchronized String getAlwaysBcc() return mAlwaysBcc; (30)public synchronized void setAlwaysBcc(String alwaysBcc) this.mAlwaysBcc = alwaysBcc; /* Have we sent a new mail notification on this account */(31)public boolean isRingNotified() return mRingNotified; (32)public void setRingNotified(boolean ringNotified) mRingNotified = ringNotified; (33)public String getLocalStorageProviderId() return mLocalStorageProviderId;(34)public void setLocalStorageProviderId(String id) (35)public synchronized int getAutomaticCheckIntervalMinutes() return mAutomaticCheckIntervalMinutes; * Returns -1 for never.(36)public synchronized boolean setAutomaticCheckIntervalMinutes(int automaticCheckIntervalMinutes) * param automaticCheckIntervalMinutes or -1 for never. (37)public synchronized int getDisplayCount() return mDisplayCount; (38)public synchronized void setDisplayCount(int displayCount) if (displayCount != -1) this.mDisplayCount = displayCount; else this.mDisplayCount = K9.DEFAULT_VISIBLE_LIMIT; resetVisibleLimits(); (39)public synchronized long getLastAutomaticCheckTime() return mLastAutomaticCheckTime; (40)public synchronized void setLastAutomaticCheckTime(long lastAutomaticCheckTime) this.mLastAutomaticCheckTime = lastAutomaticCheckTime; (41)public synchronized long getLatestOldMessageSeenTime() return mLatestOldMessageSeenTime; (42)public synchronized void setLatestOldMessageSeenTime(long latestOldMessageSeenTime) this.mLatestOldMessageSeenTime = latestOldMessageSeenTime; (43)public synchronized boolean isNotifyNewMail() return mNotifyNewMail; (44)public synchronized void setNotifyNewMail(boolean notifyNewMail) this.mNotifyNewMail = notifyNewMail; (45)public synchronized int getDeletePolicy() return mDeletePolicy; (46)public synchronized void setDeletePolicy(int deletePolicy) this.mDeletePolicy = deletePolicy; (47)public boolean isSpecialFolder(String folderName)(48)public synchronized String getDraftsFolderName() return mDraftsFolderName; (49)public synchronized void setDraftsFolderName(String draftsFolderName) mDraftsFolderName = draftsFolderName; (50)public synchronized boolean hasDraftsFolder() return !K9.FOLDER_NONE.equalsIgnoreCase(mDraftsFolderName); * Checks if this account has a drafts folder set. * return true if account has a drafts folder set.(51)public synchronized String getSentFolderName() return mSentFolderName; (52)public synchronized String getErrorFolderName() return K9.ERROR_FOLDER_NAME; (53)public synchronized void setSentFolderName(String sentFolderName) mSentFolderName = sentFolderName; (54)public synchronized boolean hasSentFolder() return !K9.FOLDER_NONE.equalsIgnoreCase(mSentFolderName); * Checks if this account has a sent folder set. * return true if account has a sent folder set. (55)public synchronized String getTrashFolderName() return mTrashFolderName; (56)public synchronized void setTrashFolderName(String trashFolderName) mTrashFolderName = trashFolderName; (57)public synchronized boolean hasTrashFolder() return !K9.FOLDER_NONE.equalsIgnoreCase(mTrashFolderName); * Checks if this account has a trash folder set. * return true if account has a trash folder set.(58)public synchronized String getArchiveFolderName() return mArchiveFolderName; (59)public synchronized void setArchiveFolderName(String archiveFolderName) mArchiveFolderName = archiveFolderName; (60)public synchronized boolean hasArchiveFolder() return !K9.FOLDER_NONE.equalsIgnoreCase(mArchiveFolderName); * Checks if this account has an archive folder set. * return true if account has an archive folder set.(61)public synchronized String getSpamFolderName() return mSpamFolderName; (62)public synchronized void setSpamFolderName(String spamFolderName) mSpamFolderName = spamFolderName; (63)public synchronized boolean hasSpamFolder() return !K9.FOLDER_NONE.equalsIgnoreCase(mSpamFolderName); * Checks if this account has a spam folder set. * return true if account has a spam folder set.(64)public synchronized String getOutboxFolderName() return OUTBOX; (65

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论