k9mail源码分析.docx

上传人:b****8 文档编号:10334991 上传时间:2023-02-10 格式:DOCX 页数:31 大小:398.51KB
下载 相关 举报
k9mail源码分析.docx_第1页
第1页 / 共31页
k9mail源码分析.docx_第2页
第2页 / 共31页
k9mail源码分析.docx_第3页
第3页 / 共31页
k9mail源码分析.docx_第4页
第4页 / 共31页
k9mail源码分析.docx_第5页
第5页 / 共31页
点击查看更多>>
下载资源
资源描述

k9mail源码分析.docx

《k9mail源码分析.docx》由会员分享,可在线阅读,更多相关《k9mail源码分析.docx(31页珍藏版)》请在冰豆网上搜索。

k9mail源码分析.docx

k9mail源码分析

privatevoidfinishAutoSetup(){

Stringemail=mEmailView.getText().toString();

Stringpassword=mPasswordView.getText().toString();

String[]emailParts=splitEmail(email);

Stringuser=emailParts[0];

Stringdomain=emailParts[1];

URIincomingUri=null;

URIoutgoingUri=null;

try{

StringuserEnc=URLEncoder.encode(user,"UTF-8");

StringpasswordEnc=URLEncoder.encode(password,"UTF-8");

StringincomingUsername=mProvider.incomingUsernameTemplate;

incomingUsername=incomingUsername.replaceAll("\\$email",email);

incomingUsername=incomingUsername.replaceAll("\\$user",userEnc);

incomingUsername=incomingUsername.replaceAll("\\$domain",domain);

URIincomingUriTemplate=mProvider.incomingUriTemplate;

incomingUri=newURI(incomingUriTemplate.getScheme(),incomingUsername+":

"

+passwordEnc,incomingUriTemplate.getHost(),incomingUriTemplate.getPort(),null,

null,null);

StringoutgoingUsername=mProvider.outgoingUsernameTemplate;

URIoutgoingUriTemplate=mProvider.outgoingUriTemplate;

 

if(outgoingUsername!

=null){

outgoingUsername=outgoingUsername.replaceAll("\\$email",email);

outgoingUsername=outgoingUsername.replaceAll("\\$user",userEnc);

outgoingUsername=outgoingUsername.replaceAll("\\$domain",domain);

outgoingUri=newURI(outgoingUriTemplate.getScheme(),outgoingUsername+":

"

+passwordEnc,outgoingUriTemplate.getHost(),outgoingUriTemplate.getPort(),null,

null,null);

}else{

outgoingUri=newURI(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!

hasaspecialfolderforSpam,called"BulkMail".

if(incomingUriTemplate.getHost().toLowerCase().endsWith("")){

mAccount.setSpamFolderName("BulkMail");

}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);

}elseif(incomingUri.toString().startsWith("pop3")){

mAccount.setDeletePolicy(Account.DELETE_POLICY_NEVER);

}

//Checkincominghere.ThencheckoutgoinginonActivityResult()

AccountSetupCheckSettings.actionCheckSettings(this,mAccount,CheckDirection.INCOMING);

}catch(UnsupportedEncodingExceptionenc){

//Thisreallyshouldn'thappensincetheencodingishardcodedtoUTF-8

Log.e(K9.LOG_TAG,"Couldn'turlencodeusernameorpassword.",enc);

}catch(URISyntaxExceptionuse){

/*

*IfthereissomeproblemwiththeURIwegiveupandgoonto

*manualsetup.

*/

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.804\src\com\fsck\k9\mail

地址:

address.java

地址和通讯录名字之间的转换

身份认证:

Authentication.java

函数作用:

计算对CRAM-MD5认证机制的响应,给用户提供认证信息和服务器提供随机数。

packagecom.fsck.k9.mail;

importjava.security.MessageDigest;

importcom.fsck.k9.mail.filter.Base64;

importcom.fsck.k9.mail.filter.Hex;

publicclassAuthentication{

privatestaticfinalStringUS_ASCII="US-ASCII";

/**

*ComputestheresponseforCRAM-MD5authenticationmechanismgiventheusercredentialsand

*theserver-providednonce.

*

*@paramusernameTheusername.

*@parampasswordThepassword.

*@paramb64NonceThenonceasbase64-encodedstring.

*@returnTheCRAM-MD5response.

*

*@throwsAuthenticationFailedExceptionIfsomethingwentwrong.

*

*@seeAuthentication#computeCramMd5Bytes(String,String,byte[])

*/

publicstaticStringcomputeCramMd5(Stringusername,Stringpassword,Stringb64Nonce)

throwsAuthenticationFailedException{

try{

byte[]b64NonceBytes=b64Nonce.getBytes(US_ASCII);

byte[]b64CRAM=computeCramMd5Bytes(username,password,b64NonceBytes);

returnnewString(b64CRAM,US_ASCII);

}catch(AuthenticationFailedExceptione){

throwe;

}catch(Exceptione){

thrownewAuthenticationFailedException("Thisshouldn'thappen",e);

}

}

/**

*ComputestheresponseforCRAM-MD5authenticationmechanismgiventheusercredentialsand

*theserver-providednonce.

*

*@paramusernameTheusername.

*@parampasswordThepassword.

*@paramb64NonceThenonceasbase64-encodedbytearray.

*@returnTheCRAM-MD5responseasbytearray.

*

*@throwsAuthenticationFailedExceptionIfsomethingwentwrong.

*

*@see

//tools.ietf.org/html/rfc2195">RFC2195

*/

publicstaticbyte[]computeCramMd5Bytes(Stringusername,Stringpassword,byte[]b64Nonce)

throwsAuthenticationFailedException{

try{

byte[]nonce=Base64.decodeBase64(b64Nonce);

byte[]secretBytes=password.getBytes(US_ASCII);

MessageDigestmd=MessageDigest.getInstance("MD5");

if(secretBytes.length>64){

secretBytes=md.digest(secretBytes);

}

byte[]ipad=newbyte[64];

byte[]opad=newbyte[64];

System.arraycopy(secretBytes,0,ipad,0,secretBytes.length);

System.arraycopy(secretBytes,0,opad,0,secretBytes.length);

for(inti=0;i

for(inti=0;i

md.update(ipad);

byte[]firstPass=md.digest(nonce);

md.update(opad);

byte[]result=md.digest(firstPass);

StringplainCRAM=username+""+newString(Hex.encodeHex(result));

byte[]b64CRAM=Base64.encodeBase64(plainCRAM.getBytes(US_ASCII));

returnb64CRAM;

}catch(Exceptione){

thrownewAuthenticationFailedException("SomethingwentwrongduringCRAM-MD5computation",e);

}

}

}

 

k-9-.fsck.k9.mail.transport;

SmtpTransport.java

WebDavTransport.java

k-9-4.804\src\com\fsck\k9\mail\transport\imap

ImapSettings.java

com.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配置文件中。

该类存储了一个账号的所有信息。

Accountstoresallofthesettingsforasingleaccountdefinedbytheuser.ItisabletosaveanddeleteitselfgivenaPreferencestoworkwith.EachaccountisdefinedbyaUUID.

(1)Account的默认信息:

收发件箱、删除策略、网络类型、消息类型、键值、颜色、排序类、数据库ID等等

(2)protectedAccount(Contextcontext)

设置账户的基本信息:

(3)privateintpickColor(Contextcontext)

*PickaniceAndroidguidelinescolorifwehaven'tusedthemallyet.

(4)protectedAccount(Preferencespreferences,Stringuuid){

this.mUuid=uuid;

loadAccount(preferences);

}

(5)privatesynchronizedvoidloadAccount(Preferencespreferences)

*Loadstoredsettingsforthisaccount.

(6)protectedsynchronizedvoiddelete(Preferencespreferences)

删除一个账户

(7)publicstaticintfindNewAccountNumber(ListaccountNumbers)

为新账户建立一个AccountNumber

(8)publicstaticListgetExistingAccountNumbers(Preferencespreferences)

获得存在的所有帐户的AccountNumber列表

(9)publicstaticintgenerateAccountNumber(Preferencespreferences)

生成一个AccountNumber

(10)publicvoidmove(Preferencespreferences,booleanmoveUp)

移动账户的位置,上移或下移一位

(11)publicsynchronizedvoidsave(Preferencespreferences)

保存账户的配置信息。

当账户被创建时,我们会为其分配一个唯一的AccountNumber

(12)publicvoidresetVisibleLimits()

重置可以显示的账户的个数

(13)publicAccountStatsgetStats(Contextcontext)throwsMessagingException

获得帐户状态

(14)颜色相关的函数

publicsynchronizedvoidsetChipColor(intcolor)

publicsynchronizedvoidcacheChips()

publicColorChipgetCheckmarkChip(){

returnmCheckmarkChip;

}

publicsynchronizedintgetChipColor(){

returnmChipColor;

}

publicColorChipgenerateColorChip(booleanmessageRead,booleantoMe,booleanccMe,booleanfromMe,booleanmessageFlagged)

publicColorChipgenerateColorChip(){

returnnewColorChip(mChipColor,false,ColorChip.CIRCULAR);

}

(15)publicStringgetUuid(){

returnmUuid;

}

获得当前账户的Uuid

(16)publicUrigetContentUri(){

returnUri.parse("content:

//accounts/"+getUuid());

}

获得当前账户的ContentUri

(16)publicsynchronizedStringgetStoreUri(){

returnmStoreUri;

}

获得当前账户的StoreUri

(17)publicsynchronizedvoidsetStoreUri(StringstoreUri){

this.mStoreUri=storeUri;

}

设置当前账户的Store

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 简洁抽象

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1